// Copyright 2016 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. package org.chromium.chrome.browser.ntp; import android.annotation.SuppressLint; import android.content.Context; import android.support.annotation.IntDef; import android.view.View; import org.chromium.base.Log; import org.chromium.base.VisibleForTesting; import org.chromium.ui.widget.Toast; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.List; /** * Exposes general configuration info about the NTP UI. */ public class UiConfig { /** The different supported UI setups. Observers can register to be notified of changes.*/ @Retention(RetentionPolicy.SOURCE) @IntDef({DISPLAY_STYLE_UNDEFINED, DISPLAY_STYLE_NARROW, DISPLAY_STYLE_REGULAR, DISPLAY_STYLE_WIDE}) public @interface DisplayStyle {} public static final int DISPLAY_STYLE_UNDEFINED = -1; public static final int DISPLAY_STYLE_NARROW = 0; public static final int DISPLAY_STYLE_REGULAR = 1; public static final int DISPLAY_STYLE_WIDE = 2; private static final int REGULAR_CARD_MIN_WIDTH_DP = 360; private static final int WIDE_CARD_MIN_WIDTH_DP = 600; private static final String TAG = "Ntp"; private static final boolean DEBUG = false; @DisplayStyle private int mCurrentDisplayStyle; private final List<DisplayStyleObserver> mObservers = new ArrayList<>(); private final Context mContext; /** * @param referenceView the View we observe to deduce the configuration from. */ public UiConfig(View referenceView) { mContext = referenceView.getContext(); mCurrentDisplayStyle = computeDisplayStyleForCurrentConfig(); referenceView.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() { @Override public void onViewAttachedToWindow(View v) { updateDisplayStyle(); } @Override public void onViewDetachedFromWindow(View v) {} }); } /** * Registers a {@link DisplayStyleObserver}. It will be notified right away with the current * display style. */ public void addObserver(DisplayStyleObserver observer) { mObservers.add(observer); observer.onDisplayStyleChanged(mCurrentDisplayStyle); } /** * Refresh the display style, notify observers of changes. */ public void updateDisplayStyle() { updateDisplayStyle(computeDisplayStyleForCurrentConfig()); } /** * Sets the display style, notifying observers of changes. Should only be used in testing. */ @VisibleForTesting public void setDisplayStyleForTesting(@DisplayStyle int displayStyle) { updateDisplayStyle(displayStyle); } private void updateDisplayStyle(@DisplayStyle int displayStyle) { if (displayStyle == mCurrentDisplayStyle) return; mCurrentDisplayStyle = displayStyle; for (DisplayStyleObserver observer : mObservers) { observer.onDisplayStyleChanged(displayStyle); } } /** * Returns the currently used display style. */ @DisplayStyle public int getCurrentDisplayStyle() { return mCurrentDisplayStyle; } @DisplayStyle // TODO(crbug.com/635567): Fix this properly. @SuppressLint("DefaultLocale") private int computeDisplayStyleForCurrentConfig() { int widthDp = mContext.getResources().getConfiguration().screenWidthDp; String debugString; @DisplayStyle int newDisplayStyle; if (widthDp < REGULAR_CARD_MIN_WIDTH_DP) { newDisplayStyle = DISPLAY_STYLE_NARROW; if (DEBUG) debugString = String.format("DISPLAY_STYLE_NARROW (w=%ddp)", widthDp); } else if (widthDp >= WIDE_CARD_MIN_WIDTH_DP) { newDisplayStyle = DISPLAY_STYLE_WIDE; if (DEBUG) debugString = String.format("DISPLAY_STYLE_WIDE (w=%ddp)", widthDp); } else { newDisplayStyle = DISPLAY_STYLE_REGULAR; if (DEBUG) debugString = String.format("DISPLAY_STYLE_REGULAR (w=%ddp)", widthDp); } if (DEBUG) { Log.d(TAG, debugString); Toast.makeText(mContext, debugString, Toast.LENGTH_SHORT).show(); } return newDisplayStyle; } }