| // Copyright 2018 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.omnibox.status; |
| |
| import android.support.annotation.ColorRes; |
| import android.support.annotation.DrawableRes; |
| import android.support.annotation.StringRes; |
| import android.view.View; |
| |
| import org.chromium.chrome.R; |
| import org.chromium.ui.modelutil.PropertyModel; |
| |
| /** |
| * Contains the controller logic of the Status component. |
| */ |
| class StatusMediator { |
| private final PropertyModel mModel; |
| private boolean mDarkTheme; |
| private boolean mUrlHasFocus; |
| private boolean mVerboseStatusAllowed; |
| private boolean mVerboseStatusSpaceAvailable; |
| private boolean mPageIsPreview; |
| private boolean mPageIsOffline; |
| |
| private int mUrlMinWidth; |
| private int mSeparatorMinWidth; |
| private int mVerboseStatusTextMinWidth; |
| |
| private @DrawableRes int mSecurityIconRes; |
| private @DrawableRes int mSecurityIconTintRes; |
| private @StringRes int mSecurityIconDescriptionRes; |
| private @DrawableRes int mNavigationIconRes; |
| private @DrawableRes int mNavigationIconTintRes; |
| |
| private boolean mTestingIsSecurityButtonShown; |
| |
| StatusMediator(PropertyModel model) { |
| mModel = model; |
| } |
| |
| /** |
| * Toggle animations of icon changes. |
| */ |
| void setAnimationsEnabled(boolean enabled) { |
| mModel.set(StatusProperties.ANIMATIONS_ENABLED, enabled); |
| } |
| |
| /** |
| * Specify navigation button image type. |
| */ |
| void setNavigationButtonType(@DrawableRes int imageRes) { |
| mNavigationIconRes = imageRes; |
| updateLocationBarIcon(); |
| } |
| |
| /** |
| * Specify whether displayed page is an offline page. |
| */ |
| void setPageIsOffline(boolean pageIsOffline) { |
| if (mPageIsOffline != pageIsOffline) { |
| mPageIsOffline = pageIsOffline; |
| updateStatusVisibility(); |
| updateColorTheme(); |
| } |
| } |
| |
| /** |
| * Specify whether displayed page is a preview page. |
| */ |
| void setPageIsPreview(boolean pageIsPreview) { |
| if (mPageIsPreview != pageIsPreview) { |
| mPageIsPreview = pageIsPreview; |
| updateStatusVisibility(); |
| updateColorTheme(); |
| } |
| } |
| |
| /** |
| * Specify icon displayed by the security chip. |
| */ |
| void setSecurityIconResource(@DrawableRes int securityIcon) { |
| mSecurityIconRes = securityIcon; |
| updateLocationBarIcon(); |
| } |
| |
| /** |
| * Specify tint of icon displayed by the security chip. |
| */ |
| void setSecurityIconTint(@ColorRes int tintList) { |
| mSecurityIconTintRes = tintList; |
| updateLocationBarIcon(); |
| } |
| |
| /** |
| * Specify tint of icon displayed by the security chip. |
| */ |
| void setSecurityIconDescription(@StringRes int desc) { |
| mSecurityIconDescriptionRes = desc; |
| updateLocationBarIcon(); |
| } |
| |
| /** |
| * Specify minimum width of the separator field. |
| */ |
| void setSeparatorFieldMinWidth(int width) { |
| mSeparatorMinWidth = width; |
| } |
| |
| /** |
| * Specify object to receive status click events. |
| * |
| * @param listener Specifies target object to receive events. |
| */ |
| void setStatusClickListener(View.OnClickListener listener) { |
| mModel.set(StatusProperties.STATUS_CLICK_LISTENER, listener); |
| } |
| |
| /** |
| * Update unfocused location bar width to determine shape and content of the |
| * Status view. |
| */ |
| void setUnfocusedLocationBarWidth(int width) { |
| // This unfocused width is used rather than observing #onMeasure() to avoid showing the |
| // verbose status when the animation to unfocus the URL bar has finished. There is a call to |
| // LocationBarLayout#onMeasure() after the URL focus animation has finished and before the |
| // location bar has received its updated width layout param. |
| int computedSpace = width - mUrlMinWidth - mSeparatorMinWidth; |
| boolean hasSpaceForStatus = width >= mVerboseStatusTextMinWidth; |
| |
| if (hasSpaceForStatus) { |
| mModel.set(StatusProperties.VERBOSE_STATUS_TEXT_WIDTH, computedSpace); |
| } |
| |
| if (hasSpaceForStatus != mVerboseStatusSpaceAvailable) { |
| mVerboseStatusSpaceAvailable = hasSpaceForStatus; |
| updateStatusVisibility(); |
| } |
| } |
| |
| /** |
| * Report URL focus change. |
| */ |
| void setUrlHasFocus(boolean urlHasFocus) { |
| if (mUrlHasFocus == urlHasFocus) return; |
| |
| mUrlHasFocus = urlHasFocus; |
| updateStatusVisibility(); |
| updateLocationBarIcon(); |
| } |
| |
| /** |
| * Specify minimum width of an URL field. |
| */ |
| void setUrlMinWidth(int width) { |
| mUrlMinWidth = width; |
| } |
| |
| /** |
| * Toggle between dark and light UI color theme. |
| */ |
| void setUseDarkColors(boolean useDarkColors) { |
| if (mDarkTheme != useDarkColors) { |
| mDarkTheme = useDarkColors; |
| updateColorTheme(); |
| } |
| } |
| |
| /** |
| * Specify whether parent allows verbose status text. |
| */ |
| void setVerboseStatusTextAllowed(boolean isVerboseStatusTextAllowed) { |
| mVerboseStatusAllowed = isVerboseStatusTextAllowed; |
| updateStatusVisibility(); |
| } |
| |
| /** |
| * Specify minimum width of the verbose status text field. |
| */ |
| void setVerboseStatusTextMinWidth(int width) { |
| mVerboseStatusTextMinWidth = width; |
| } |
| |
| /** |
| * Update visibility of the verbose status text field. |
| */ |
| private void updateStatusVisibility() { |
| @StringRes |
| int statusText = 0; |
| |
| if (mPageIsPreview) { |
| statusText = R.string.location_bar_preview_lite_page_status; |
| } else if (mPageIsOffline) { |
| statusText = R.string.location_bar_verbose_status_offline; |
| } |
| |
| // Decide whether presenting verbose status text makes sense. |
| boolean newVisibility = mVerboseStatusAllowed && mVerboseStatusSpaceAvailable |
| && (!mUrlHasFocus) && (statusText != 0); |
| |
| // Update status content only if it is visible. |
| // Note: PropertyModel will help us avoid duplicate updates with the |
| // same value. |
| if (newVisibility) { |
| mModel.set(StatusProperties.VERBOSE_STATUS_TEXT_STRING_RES, statusText); |
| } |
| |
| mModel.set(StatusProperties.VERBOSE_STATUS_TEXT_VISIBLE, newVisibility); |
| } |
| |
| /** |
| * Update color theme for all status components. |
| */ |
| private void updateColorTheme() { |
| @ColorRes |
| int separatorColor = mDarkTheme ? R.color.locationbar_status_separator_color |
| : R.color.locationbar_status_separator_color_light; |
| |
| @ColorRes |
| int textColor = 0; |
| if (mPageIsPreview) { |
| // There will never be a Preview in Incognito and the site theme color is not used. So |
| // ignore useDarkColors. |
| textColor = R.color.locationbar_status_preview_color; |
| } else if (mPageIsOffline) { |
| textColor = mDarkTheme ? R.color.locationbar_status_offline_color |
| : R.color.locationbar_status_offline_color_light; |
| } |
| |
| @ColorRes |
| int tintColor = mDarkTheme ? R.color.dark_mode_tint : R.color.light_mode_tint; |
| |
| mModel.set(StatusProperties.SEPARATOR_COLOR_RES, separatorColor); |
| mNavigationIconTintRes = tintColor; |
| if (textColor != 0) mModel.set(StatusProperties.VERBOSE_STATUS_TEXT_COLOR_RES, textColor); |
| |
| updateLocationBarIcon(); |
| } |
| |
| /** |
| * Reports whether security icon is shown. |
| */ |
| boolean testIsSecurityButtonShown() { |
| return mTestingIsSecurityButtonShown; |
| } |
| |
| /** |
| * Update selection of icon presented on the location bar. |
| * |
| * - Navigation button is: |
| * - shown only on large form factor devices (tablets and up), |
| * - shown only if URL is focused. |
| * |
| * - Security icon is: |
| * - shown only if specified, |
| * - not shown if URL is focused. |
| */ |
| private void updateLocationBarIcon() { |
| if (mUrlHasFocus) { |
| mModel.set(StatusProperties.STATUS_ICON_RES, mNavigationIconRes); |
| mModel.set(StatusProperties.STATUS_ICON_TINT_RES, mNavigationIconTintRes); |
| mModel.set(StatusProperties.STATUS_ICON_DESCRIPTION_RES, |
| R.string.accessibility_toolbar_btn_site_info); |
| mModel.set(StatusProperties.STATUS_ICON_ACCESSIBILITY_TOAST_RES, 0); |
| mTestingIsSecurityButtonShown = false; |
| return; |
| } |
| |
| if (!mUrlHasFocus && mSecurityIconRes != 0) { |
| mModel.set(StatusProperties.STATUS_ICON_RES, mSecurityIconRes); |
| mModel.set(StatusProperties.STATUS_ICON_TINT_RES, mSecurityIconTintRes); |
| mModel.set(StatusProperties.STATUS_ICON_DESCRIPTION_RES, mSecurityIconDescriptionRes); |
| mModel.set( |
| StatusProperties.STATUS_ICON_ACCESSIBILITY_TOAST_RES, R.string.menu_page_info); |
| mTestingIsSecurityButtonShown = true; |
| return; |
| } |
| |
| mTestingIsSecurityButtonShown = false; |
| mModel.set(StatusProperties.STATUS_ICON_RES, 0); |
| } |
| } |