Commit d0ca7b09 authored by Shakti Sahu's avatar Shakti Sahu Committed by Commit Bot

MVC for NTP fake search box

This CL attempts to create MVC for the fake search box. Fake search box
is used from NTP and TasksView as well. Extracted most of the view
details into properties. There are still a few issues specific to
NewTabPageLayout where we directly try to set padding on the fake box.

Bug: 1069194
Change-Id: Icaa919e2de302a8d398eb8fd42cb0afd1f6c7040
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2141200
Commit-Queue: Shakti Sahu <shaktisahu@chromium.org>
Reviewed-by: default avatarDavid Trainor <dtrainor@chromium.org>
Cr-Commit-Position: refs/heads/master@{#758722}
parent 15889160
...@@ -1059,6 +1059,11 @@ chrome_java_sources = [ ...@@ -1059,6 +1059,11 @@ chrome_java_sources = [
"java/src/org/chromium/chrome/browser/ntp/cards/StatusItem.java", "java/src/org/chromium/chrome/browser/ntp/cards/StatusItem.java",
"java/src/org/chromium/chrome/browser/ntp/cards/SuggestionsCategoryInfo.java", "java/src/org/chromium/chrome/browser/ntp/cards/SuggestionsCategoryInfo.java",
"java/src/org/chromium/chrome/browser/ntp/cards/SuggestionsSection.java", "java/src/org/chromium/chrome/browser/ntp/cards/SuggestionsSection.java",
"java/src/org/chromium/chrome/browser/ntp/search/SearchBoxContainerView.java",
"java/src/org/chromium/chrome/browser/ntp/search/SearchBoxCoordinator.java",
"java/src/org/chromium/chrome/browser/ntp/search/SearchBoxMediator.java",
"java/src/org/chromium/chrome/browser/ntp/search/SearchBoxProperties.java",
"java/src/org/chromium/chrome/browser/ntp/search/SearchBoxViewBinder.java",
"java/src/org/chromium/chrome/browser/ntp/snippets/CategoryInt.java", "java/src/org/chromium/chrome/browser/ntp/snippets/CategoryInt.java",
"java/src/org/chromium/chrome/browser/ntp/snippets/EmptySuggestionsSource.java", "java/src/org/chromium/chrome/browser/ntp/snippets/EmptySuggestionsSource.java",
"java/src/org/chromium/chrome/browser/ntp/snippets/SectionHeader.java", "java/src/org/chromium/chrome/browser/ntp/snippets/SectionHeader.java",
......
...@@ -6,16 +6,15 @@ package org.chromium.chrome.browser.tasks; ...@@ -6,16 +6,15 @@ package org.chromium.chrome.browser.tasks;
import android.content.Context; import android.content.Context;
import android.content.res.Resources; import android.content.res.Resources;
import android.text.TextWatcher;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.view.ViewStub; import android.view.ViewStub;
import android.widget.CompoundButton.OnCheckedChangeListener; import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.FrameLayout; import android.widget.FrameLayout;
import android.widget.TextView;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.appcompat.content.res.AppCompatResources;
import com.google.android.material.appbar.AppBarLayout; import com.google.android.material.appbar.AppBarLayout;
...@@ -23,7 +22,7 @@ import org.chromium.base.ApiCompatibilityUtils; ...@@ -23,7 +22,7 @@ import org.chromium.base.ApiCompatibilityUtils;
import org.chromium.chrome.browser.coordinator.CoordinatorLayoutForPointer; import org.chromium.chrome.browser.coordinator.CoordinatorLayoutForPointer;
import org.chromium.chrome.browser.lifecycle.ActivityLifecycleDispatcher; import org.chromium.chrome.browser.lifecycle.ActivityLifecycleDispatcher;
import org.chromium.chrome.browser.ntp.IncognitoDescriptionView; import org.chromium.chrome.browser.ntp.IncognitoDescriptionView;
import org.chromium.chrome.browser.ntp.NewTabPageLayout.SearchBoxContainerView; import org.chromium.chrome.browser.ntp.search.SearchBoxCoordinator;
import org.chromium.chrome.tab_ui.R; import org.chromium.chrome.tab_ui.R;
import org.chromium.components.browser_ui.styles.ChromeColors; import org.chromium.components.browser_ui.styles.ChromeColors;
import org.chromium.components.content_settings.CookieControlsEnforcement; import org.chromium.components.content_settings.CookieControlsEnforcement;
...@@ -34,8 +33,7 @@ class TasksView extends CoordinatorLayoutForPointer { ...@@ -34,8 +33,7 @@ class TasksView extends CoordinatorLayoutForPointer {
private FrameLayout mBodyViewContainer; private FrameLayout mBodyViewContainer;
private FrameLayout mCarouselTabSwitcherContainer; private FrameLayout mCarouselTabSwitcherContainer;
private AppBarLayout mHeaderView; private AppBarLayout mHeaderView;
private SearchBoxContainerView mSearchBoxContainerView; private SearchBoxCoordinator mSearchBoxCoordinator;
private TextView mSearchBoxText;
private IncognitoDescriptionView mIncognitoDescriptionView; private IncognitoDescriptionView mIncognitoDescriptionView;
private View.OnClickListener mIncognitoDescriptionLearnMoreListener; private View.OnClickListener mIncognitoDescriptionLearnMoreListener;
private boolean mIncognitoCookieControlsCardIsVisible; private boolean mIncognitoCookieControlsCardIsVisible;
...@@ -52,10 +50,10 @@ class TasksView extends CoordinatorLayoutForPointer { ...@@ -52,10 +50,10 @@ class TasksView extends CoordinatorLayoutForPointer {
} }
public void initialize(ActivityLifecycleDispatcher activityLifecycleDispatcher) { public void initialize(ActivityLifecycleDispatcher activityLifecycleDispatcher) {
assert mSearchBoxContainerView assert mSearchBoxCoordinator
!= null : "#onFinishInflate should be completed before the call to initialize."; != null : "#onFinishInflate should be completed before the call to initialize.";
mSearchBoxContainerView.initialize(activityLifecycleDispatcher); mSearchBoxCoordinator.initialize(activityLifecycleDispatcher);
} }
@Override @Override
...@@ -64,12 +62,11 @@ class TasksView extends CoordinatorLayoutForPointer { ...@@ -64,12 +62,11 @@ class TasksView extends CoordinatorLayoutForPointer {
mCarouselTabSwitcherContainer = mCarouselTabSwitcherContainer =
(FrameLayout) findViewById(R.id.carousel_tab_switcher_container); (FrameLayout) findViewById(R.id.carousel_tab_switcher_container);
mSearchBoxContainerView = findViewById(R.id.search_box); mSearchBoxCoordinator = new SearchBoxCoordinator(getContext(), this);
mHeaderView = (AppBarLayout) findViewById(R.id.task_surface_header); mHeaderView = (AppBarLayout) findViewById(R.id.task_surface_header);
AppBarLayout.LayoutParams layoutParams = AppBarLayout.LayoutParams layoutParams =
(AppBarLayout.LayoutParams) mSearchBoxContainerView.getLayoutParams(); (AppBarLayout.LayoutParams) mSearchBoxCoordinator.getView().getLayoutParams();
layoutParams.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL); layoutParams.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL);
mSearchBoxText = (TextView) mSearchBoxContainerView.findViewById(R.id.search_box_text);
} }
ViewGroup getCarouselTabSwitcherContainer() { ViewGroup getCarouselTabSwitcherContainer() {
...@@ -90,43 +87,10 @@ class TasksView extends CoordinatorLayoutForPointer { ...@@ -90,43 +87,10 @@ class TasksView extends CoordinatorLayoutForPointer {
} }
/** /**
* Set the given listener for the fake search box. * @return The {@link SearchBoxCoordinator} representing the fake search box.
* @param listener The given listener.
*/ */
void setFakeSearchBoxClickListener(@Nullable View.OnClickListener listener) { SearchBoxCoordinator getSearchBoxCoordinator() {
mSearchBoxText.setOnClickListener(listener); return mSearchBoxCoordinator;
}
/**
* Set the given watcher for the fake search box.
* @param textWatcher The given {@link TextWatcher}.
*/
void setFakeSearchBoxTextWatcher(TextWatcher textWatcher) {
mSearchBoxText.addTextChangedListener(textWatcher);
}
/**
* Set the visibility of the fake search box.
* @param isVisible Whether it's visible.
*/
void setFakeSearchBoxVisibility(boolean isVisible) {
mSearchBoxContainerView.setVisibility(isVisible ? View.VISIBLE : View.GONE);
}
/**
* Set the visibility of the voice recognition button.
* @param isVisible Whether it's visible.
*/
void setVoiceRecognitionButtonVisibility(boolean isVisible) {
findViewById(R.id.voice_search_button).setVisibility(isVisible ? View.VISIBLE : View.GONE);
}
/**
* Set the voice recognition button click listener.
* @param listener The given listener.
*/
void setVoiceRecognitionButtonClickListener(@Nullable View.OnClickListener listener) {
findViewById(R.id.voice_search_button).setOnClickListener(listener);
} }
/** /**
...@@ -152,12 +116,13 @@ class TasksView extends CoordinatorLayoutForPointer { ...@@ -152,12 +116,13 @@ class TasksView extends CoordinatorLayoutForPointer {
int backgroundColor = ChromeColors.getPrimaryBackgroundColor(resources, isIncognito); int backgroundColor = ChromeColors.getPrimaryBackgroundColor(resources, isIncognito);
setBackgroundColor(backgroundColor); setBackgroundColor(backgroundColor);
mHeaderView.setBackgroundColor(backgroundColor); mHeaderView.setBackgroundColor(backgroundColor);
mSearchBoxContainerView.setBackgroundResource(
isIncognito ? R.drawable.fake_search_box_bg_incognito : R.drawable.ntp_search_box); mSearchBoxCoordinator.setBackground(AppCompatResources.getDrawable(mContext,
isIncognito ? R.drawable.fake_search_box_bg_incognito : R.drawable.ntp_search_box));
int hintTextColor = isIncognito int hintTextColor = isIncognito
? ApiCompatibilityUtils.getColor(resources, R.color.locationbar_light_hint_text) ? ApiCompatibilityUtils.getColor(resources, R.color.locationbar_light_hint_text)
: ApiCompatibilityUtils.getColor(resources, R.color.locationbar_dark_hint_text); : ApiCompatibilityUtils.getColor(resources, R.color.locationbar_dark_hint_text);
mSearchBoxText.setHintTextColor(hintTextColor); mSearchBoxCoordinator.setSearchBoxHintColor(hintTextColor);
} }
/** /**
......
...@@ -32,9 +32,11 @@ import org.chromium.ui.modelutil.PropertyModel; ...@@ -32,9 +32,11 @@ import org.chromium.ui.modelutil.PropertyModel;
class TasksViewBinder { class TasksViewBinder {
public static void bind(PropertyModel model, TasksView view, PropertyKey propertyKey) { public static void bind(PropertyModel model, TasksView view, PropertyKey propertyKey) {
if (propertyKey == FAKE_SEARCH_BOX_CLICK_LISTENER) { if (propertyKey == FAKE_SEARCH_BOX_CLICK_LISTENER) {
view.setFakeSearchBoxClickListener(model.get(FAKE_SEARCH_BOX_CLICK_LISTENER)); view.getSearchBoxCoordinator().setSearchBoxClickListener(
model.get(FAKE_SEARCH_BOX_CLICK_LISTENER));
} else if (propertyKey == FAKE_SEARCH_BOX_TEXT_WATCHER) { } else if (propertyKey == FAKE_SEARCH_BOX_TEXT_WATCHER) {
view.setFakeSearchBoxTextWatcher(model.get(FAKE_SEARCH_BOX_TEXT_WATCHER)); view.getSearchBoxCoordinator().setSearchBoxTextWatcher(
model.get(FAKE_SEARCH_BOX_TEXT_WATCHER));
} else if (propertyKey == INCOGNITO_COOKIE_CONTROLS_CARD_VISIBILITY) { } else if (propertyKey == INCOGNITO_COOKIE_CONTROLS_CARD_VISIBILITY) {
view.setIncognitoCookieControlsCardVisibility( view.setIncognitoCookieControlsCardVisibility(
model.get(INCOGNITO_COOKIE_CONTROLS_CARD_VISIBILITY)); model.get(INCOGNITO_COOKIE_CONTROLS_CARD_VISIBILITY));
...@@ -54,7 +56,7 @@ class TasksViewBinder { ...@@ -54,7 +56,7 @@ class TasksViewBinder {
view.setIncognitoDescriptionLearnMoreClickListener( view.setIncognitoDescriptionLearnMoreClickListener(
model.get(INCOGNITO_LEARN_MORE_CLICK_LISTENER)); model.get(INCOGNITO_LEARN_MORE_CLICK_LISTENER));
} else if (propertyKey == IS_FAKE_SEARCH_BOX_VISIBLE) { } else if (propertyKey == IS_FAKE_SEARCH_BOX_VISIBLE) {
view.setFakeSearchBoxVisibility(model.get(IS_FAKE_SEARCH_BOX_VISIBLE)); view.getSearchBoxCoordinator().setVisibility(model.get(IS_FAKE_SEARCH_BOX_VISIBLE));
} else if (propertyKey == IS_INCOGNITO) { } else if (propertyKey == IS_INCOGNITO) {
view.setIncognitoMode(model.get(IS_INCOGNITO)); view.setIncognitoMode(model.get(IS_INCOGNITO));
} else if (propertyKey == IS_INCOGNITO_DESCRIPTION_INITIALIZED) { } else if (propertyKey == IS_INCOGNITO_DESCRIPTION_INITIALIZED) {
...@@ -72,14 +74,14 @@ class TasksViewBinder { ...@@ -72,14 +74,14 @@ class TasksViewBinder {
} else if (propertyKey == IS_TAB_CAROUSEL_VISIBLE) { } else if (propertyKey == IS_TAB_CAROUSEL_VISIBLE) {
view.setTabCarouselVisibility(model.get(IS_TAB_CAROUSEL_VISIBLE)); view.setTabCarouselVisibility(model.get(IS_TAB_CAROUSEL_VISIBLE));
} else if (propertyKey == IS_VOICE_RECOGNITION_BUTTON_VISIBLE) { } else if (propertyKey == IS_VOICE_RECOGNITION_BUTTON_VISIBLE) {
view.setVoiceRecognitionButtonVisibility( view.getSearchBoxCoordinator().setVoiceSearchButtonVisibility(
model.get(IS_VOICE_RECOGNITION_BUTTON_VISIBLE)); model.get(IS_VOICE_RECOGNITION_BUTTON_VISIBLE));
} else if (propertyKey == MORE_TABS_CLICK_LISTENER) { } else if (propertyKey == MORE_TABS_CLICK_LISTENER) {
view.setMoreTabsOnClickListener(model.get(MORE_TABS_CLICK_LISTENER)); view.setMoreTabsOnClickListener(model.get(MORE_TABS_CLICK_LISTENER));
} else if (propertyKey == MV_TILES_VISIBLE) { } else if (propertyKey == MV_TILES_VISIBLE) {
view.setMostVisitedVisibility(model.get(MV_TILES_VISIBLE) ? View.VISIBLE : View.GONE); view.setMostVisitedVisibility(model.get(MV_TILES_VISIBLE) ? View.VISIBLE : View.GONE);
} else if (propertyKey == VOICE_SEARCH_BUTTON_CLICK_LISTENER) { } else if (propertyKey == VOICE_SEARCH_BUTTON_CLICK_LISTENER) {
view.setVoiceRecognitionButtonClickListener( view.getSearchBoxCoordinator().setVoiceSearchButtonClickListener(
model.get(VOICE_SEARCH_BUTTON_CLICK_LISTENER)); model.get(VOICE_SEARCH_BUTTON_CLICK_LISTENER));
} }
} }
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
found in the LICENSE file. --> found in the LICENSE file. -->
<view <view
class="org.chromium.chrome.browser.ntp.NewTabPageLayout$SearchBoxContainerView" class="org.chromium.chrome.browser.ntp.search.SearchBoxContainerView"
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
......
// Copyright 2020 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.search;
import android.content.Context;
import android.graphics.drawable.RippleDrawable;
import android.os.Build;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.LinearLayout;
/**
* Provides the additional capabilities needed for the SearchBox container layout.
*/
public class SearchBoxContainerView extends LinearLayout {
/** Constructor for inflating from XML. */
public SearchBoxContainerView(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP
&& ev.getActionMasked() == MotionEvent.ACTION_DOWN) {
if (getBackground() instanceof RippleDrawable) {
((RippleDrawable) getBackground()).setHotspot(ev.getX(), ev.getY());
}
}
return super.onInterceptTouchEvent(ev);
}
}
// Copyright 2020 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.search;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.text.TextWatcher;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.lifecycle.ActivityLifecycleDispatcher;
import org.chromium.ui.modelutil.PropertyModel;
/**
* This class is responsible for reacting to events from the outside world, interacting with other
* coordinators, running most of the business logic associated with the fake search box component,
* and updating the model accordingly.
*/
public class SearchBoxCoordinator {
private final PropertyModel mModel;
private final ViewGroup mView;
private final SearchBoxMediator mMediator;
/** Constructor. */
public SearchBoxCoordinator(Context context, ViewGroup parent) {
mModel = new PropertyModel(SearchBoxProperties.ALL_KEYS);
mView = parent.findViewById(R.id.search_box);
mMediator = new SearchBoxMediator(context, mModel, mView);
}
public void initialize(ActivityLifecycleDispatcher activityLifecycleDispatcher) {
mMediator.initialize(activityLifecycleDispatcher);
}
public View getView() {
return mView;
}
public void destroy() {
mMediator.destroy();
}
public void setAlpha(float alpha) {
mModel.set(SearchBoxProperties.ALPHA, alpha);
}
public void setBackground(Drawable background) {
mModel.set(SearchBoxProperties.BACKGROUND, background);
}
public void setVisibility(boolean visible) {
mModel.set(SearchBoxProperties.VISIBILITY, visible);
}
public void setSearchText(String text) {
mModel.set(SearchBoxProperties.SEARCH_TEXT, text);
}
public void setSearchBoxClickListener(OnClickListener listener) {
mModel.set(SearchBoxProperties.SEARCH_BOX_CLICK_CALLBACK, listener);
}
public void setSearchBoxTextWatcher(TextWatcher textWatcher) {
mModel.set(SearchBoxProperties.SEARCH_BOX_TEXT_WATCHER, textWatcher);
}
public void setSearchBoxHintColor(int hintTextColor) {
mModel.set(SearchBoxProperties.SEARCH_BOX_HINT_COLOR, hintTextColor);
}
public void setVoiceSearchButtonVisibility(boolean visible) {
mModel.set(SearchBoxProperties.VOICE_SEARCH_VISIBILITY, visible);
}
public void setVoiceSearchButtonClickListener(OnClickListener listener) {
mModel.set(SearchBoxProperties.VOICE_SEARCH_CLICK_CALLBACK, listener);
}
}
// Copyright 2020 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.search;
import android.content.Context;
import android.content.res.ColorStateList;
import android.graphics.drawable.Drawable;
import android.view.ViewGroup;
import androidx.annotation.ColorRes;
import org.chromium.chrome.browser.externalauth.ExternalAuthUtils;
import org.chromium.chrome.browser.gsa.GSAState;
import org.chromium.chrome.browser.lifecycle.ActivityLifecycleDispatcher;
import org.chromium.chrome.browser.lifecycle.Destroyable;
import org.chromium.chrome.browser.lifecycle.NativeInitObserver;
import org.chromium.chrome.browser.omnibox.voice.AssistantVoiceSearchService;
import org.chromium.chrome.browser.search_engines.TemplateUrlServiceFactory;
import org.chromium.components.browser_ui.styles.ChromeColors;
import org.chromium.ui.modelutil.PropertyModel;
import org.chromium.ui.modelutil.PropertyModelChangeProcessor;
class SearchBoxMediator
implements Destroyable, NativeInitObserver, AssistantVoiceSearchService.Observer {
private final Context mContext;
private final PropertyModel mModel;
private final ViewGroup mView;
private ActivityLifecycleDispatcher mActivityLifecycleDispatcher;
private AssistantVoiceSearchService mAssistantVoiceSearchService;
public SearchBoxMediator(Context context, PropertyModel model, ViewGroup view) {
mContext = context;
mModel = model;
mView = view;
PropertyModelChangeProcessor.create(mModel, mView, new SearchBoxViewBinder());
}
/**
* Initializes the SearchBoxContainerView with the given params. This must be called for
* classes that use the SearchBoxContainerView.
*
* @param activityLifecycleDispatcher Used to register for lifecycle events.
*/
public void initialize(ActivityLifecycleDispatcher activityLifecycleDispatcher) {
assert mActivityLifecycleDispatcher == null;
mActivityLifecycleDispatcher = activityLifecycleDispatcher;
mActivityLifecycleDispatcher.register(this);
if (mActivityLifecycleDispatcher.isNativeInitializationFinished()) {
onFinishNativeInitialization();
}
}
@Override
public void destroy() {
if (mAssistantVoiceSearchService != null) {
mAssistantVoiceSearchService.destroy();
mAssistantVoiceSearchService = null;
}
if (mActivityLifecycleDispatcher != null) {
mActivityLifecycleDispatcher.unregister(this);
mActivityLifecycleDispatcher = null;
}
}
@Override
public void onFinishNativeInitialization() {
mAssistantVoiceSearchService =
new AssistantVoiceSearchService(mContext, ExternalAuthUtils.getInstance(),
TemplateUrlServiceFactory.get(), GSAState.getInstance(mContext), this);
onAssistantVoiceSearchServiceChanged();
}
@Override
public void onAssistantVoiceSearchServiceChanged() {
// Potential race condition between destroy and the observer, see crbug.com/1055274.
if (mAssistantVoiceSearchService == null) return;
Drawable drawable = mAssistantVoiceSearchService.getCurrentMicDrawable();
mModel.set(SearchBoxProperties.VOICE_SEARCH_DRAWABLE, drawable);
final @ColorRes int primaryColor = ChromeColors.getDefaultThemeColor(
mContext.getResources(), false /* forceDarkBgColor= */);
ColorStateList colorStateList =
mAssistantVoiceSearchService.getMicButtonColorStateList(primaryColor, mContext);
mModel.set(SearchBoxProperties.VOICE_SEARCH_COLOR_STATE_LIST, colorStateList);
}
}
// Copyright 2020 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.search;
import android.content.res.ColorStateList;
import android.graphics.drawable.Drawable;
import android.text.TextWatcher;
import android.view.View.OnClickListener;
import org.chromium.ui.modelutil.PropertyKey;
import org.chromium.ui.modelutil.PropertyModel.WritableBooleanPropertyKey;
import org.chromium.ui.modelutil.PropertyModel.WritableFloatPropertyKey;
import org.chromium.ui.modelutil.PropertyModel.WritableIntPropertyKey;
import org.chromium.ui.modelutil.PropertyModel.WritableObjectPropertyKey;
/**
* The properties required to build the fake search box on new tab page.
*/
interface SearchBoxProperties {
WritableFloatPropertyKey ALPHA = new WritableFloatPropertyKey();
WritableObjectPropertyKey<Drawable> BACKGROUND = new WritableObjectPropertyKey<>();
WritableBooleanPropertyKey VISIBILITY = new WritableBooleanPropertyKey();
WritableBooleanPropertyKey VOICE_SEARCH_VISIBILITY = new WritableBooleanPropertyKey();
WritableObjectPropertyKey<Drawable> VOICE_SEARCH_DRAWABLE = new WritableObjectPropertyKey<>();
WritableObjectPropertyKey<ColorStateList> VOICE_SEARCH_COLOR_STATE_LIST =
new WritableObjectPropertyKey<>();
WritableObjectPropertyKey<OnClickListener> VOICE_SEARCH_CLICK_CALLBACK =
new WritableObjectPropertyKey<>();
WritableObjectPropertyKey<String> SEARCH_TEXT = new WritableObjectPropertyKey<>();
WritableObjectPropertyKey<OnClickListener> SEARCH_BOX_CLICK_CALLBACK =
new WritableObjectPropertyKey<>();
WritableObjectPropertyKey<TextWatcher> SEARCH_BOX_TEXT_WATCHER =
new WritableObjectPropertyKey<>();
WritableIntPropertyKey SEARCH_BOX_HINT_COLOR = new WritableIntPropertyKey();
PropertyKey[] ALL_KEYS = new PropertyKey[] {ALPHA, BACKGROUND, VISIBILITY,
VOICE_SEARCH_VISIBILITY, VOICE_SEARCH_DRAWABLE, VOICE_SEARCH_COLOR_STATE_LIST,
VOICE_SEARCH_CLICK_CALLBACK, SEARCH_TEXT, SEARCH_BOX_CLICK_CALLBACK,
SEARCH_BOX_TEXT_WATCHER, SEARCH_BOX_HINT_COLOR};
}
// Copyright 2020 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.search;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import org.chromium.base.ApiCompatibilityUtils;
import org.chromium.ui.base.ViewUtils;
import org.chromium.ui.modelutil.PropertyKey;
import org.chromium.ui.modelutil.PropertyModel;
import org.chromium.ui.modelutil.PropertyModelChangeProcessor;
/**
* Responsible for building and setting properties on the search box on new tab page.
*/
class SearchBoxViewBinder
implements PropertyModelChangeProcessor.ViewBinder<PropertyModel, View, PropertyKey> {
@Override
public final void bind(PropertyModel model, View view, PropertyKey propertyKey) {
ImageView voiceSearchButton =
view.findViewById(org.chromium.chrome.R.id.voice_search_button);
View searchBoxContainer = view;
final TextView searchBoxTextView =
searchBoxContainer.findViewById(org.chromium.chrome.R.id.search_box_text);
if (SearchBoxProperties.VISIBILITY == propertyKey) {
searchBoxContainer.setVisibility(
model.get(SearchBoxProperties.VISIBILITY) ? View.VISIBLE : View.GONE);
} else if (SearchBoxProperties.ALPHA == propertyKey) {
searchBoxContainer.setAlpha(model.get(SearchBoxProperties.ALPHA));
// Disable the search box contents if it is the process of being animated away.
ViewUtils.setEnabledRecursive(
searchBoxContainer, searchBoxContainer.getAlpha() == 1.0f);
} else if (SearchBoxProperties.BACKGROUND == propertyKey) {
searchBoxContainer.setBackground(model.get(SearchBoxProperties.BACKGROUND));
} else if (SearchBoxProperties.VOICE_SEARCH_COLOR_STATE_LIST == propertyKey) {
ApiCompatibilityUtils.setImageTintList(voiceSearchButton,
model.get(SearchBoxProperties.VOICE_SEARCH_COLOR_STATE_LIST));
} else if (SearchBoxProperties.VOICE_SEARCH_DRAWABLE == propertyKey) {
voiceSearchButton.setImageDrawable(
model.get(SearchBoxProperties.VOICE_SEARCH_DRAWABLE));
} else if (SearchBoxProperties.VOICE_SEARCH_VISIBILITY == propertyKey) {
voiceSearchButton.setVisibility(model.get(SearchBoxProperties.VOICE_SEARCH_VISIBILITY)
? View.VISIBLE
: View.GONE);
} else if (SearchBoxProperties.SEARCH_BOX_CLICK_CALLBACK == propertyKey) {
searchBoxTextView.setOnClickListener(
model.get(SearchBoxProperties.SEARCH_BOX_CLICK_CALLBACK));
} else if (SearchBoxProperties.SEARCH_BOX_TEXT_WATCHER == propertyKey) {
searchBoxTextView.addTextChangedListener(
model.get(SearchBoxProperties.SEARCH_BOX_TEXT_WATCHER));
} else if (SearchBoxProperties.SEARCH_TEXT == propertyKey) {
searchBoxTextView.setText(model.get(SearchBoxProperties.SEARCH_TEXT));
} else if (SearchBoxProperties.VOICE_SEARCH_CLICK_CALLBACK == propertyKey) {
voiceSearchButton.setOnClickListener(
model.get(SearchBoxProperties.VOICE_SEARCH_CLICK_CALLBACK));
} else if (SearchBoxProperties.SEARCH_BOX_HINT_COLOR == propertyKey) {
searchBoxTextView.setHintTextColor(
model.get(SearchBoxProperties.SEARCH_BOX_HINT_COLOR));
} else {
assert false : "Unhandled property detected in SearchBoxViewBinder!";
}
}
}
...@@ -8,10 +8,10 @@ import android.graphics.Bitmap; ...@@ -8,10 +8,10 @@ import android.graphics.Bitmap;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams; import android.view.ViewGroup.LayoutParams;
import android.widget.TextView;
import org.chromium.base.Callback; import org.chromium.base.Callback;
import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.flags.ChromeFeatureList;
import org.chromium.chrome.browser.ntp.search.SearchBoxCoordinator;
import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.profiles.Profile;
import java.util.List; import java.util.List;
...@@ -23,15 +23,15 @@ import java.util.List; ...@@ -23,15 +23,15 @@ import java.util.List;
*/ */
public class QueryTileSection { public class QueryTileSection {
private final ViewGroup mQueryTileSectionView; private final ViewGroup mQueryTileSectionView;
private final TextView mSearchBox; private final SearchBoxCoordinator mSearchBoxCoordinator;
private QueryTileCoordinator mQueryTileCoordinator; private QueryTileCoordinator mQueryTileCoordinator;
private TileProvider mTileProvider; private TileProvider mTileProvider;
/** Constructor. */ /** Constructor. */
public QueryTileSection( public QueryTileSection(ViewGroup queryTileSectionView,
ViewGroup queryTileSectionView, TextView searchTextView, Profile profile) { SearchBoxCoordinator searchBoxCoordinator, Profile profile) {
mQueryTileSectionView = queryTileSectionView; mQueryTileSectionView = queryTileSectionView;
mSearchBox = searchTextView; mSearchBoxCoordinator = searchBoxCoordinator;
if (!ChromeFeatureList.isEnabled(ChromeFeatureList.QUERY_TILES)) return; if (!ChromeFeatureList.isEnabled(ChromeFeatureList.QUERY_TILES)) return;
mTileProvider = TileProviderFactory.getForProfile(profile); mTileProvider = TileProviderFactory.getForProfile(profile);
...@@ -48,7 +48,7 @@ public class QueryTileSection { ...@@ -48,7 +48,7 @@ public class QueryTileSection {
mQueryTileSectionView.setVisibility(tiles.isEmpty() ? View.GONE : View.VISIBLE); mQueryTileSectionView.setVisibility(tiles.isEmpty() ? View.GONE : View.VISIBLE);
}); });
if (tile != null) mSearchBox.setText(tile.queryText); if (tile != null) mSearchBoxCoordinator.setSearchText(tile.queryText);
} }
private void getVisuals(Tile tile, Callback<List<Bitmap>> callback) { private void getVisuals(Tile tile, Callback<List<Bitmap>> callback) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment