Commit 7bd63cba authored by Tomasz Wiszkowski's avatar Tomasz Wiszkowski Committed by Commit Bot

Use Base suggestion view with Answer suggestions.

This change removes custom Refinable icon from AnswerSuggestions
in favor of base suggestion view.

Change-Id: If460ec749cfd3786388b0423da2f61c805ec0c6f
Doc: http://doc/1aL_UcW1gdeSLqNzuJZlQPBqMG0XAwVaoa05UTyVulp8
Bug: 982818
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1848391
Commit-Queue: Ender <ender@google.com>
Reviewed-by: default avatarTed Choc <tedchoc@chromium.org>
Reviewed-by: default avatarBrandon Wylie <wylieb@chromium.org>
Cr-Commit-Position: refs/heads/master@{#706599}
parent 7c2af342
...@@ -670,6 +670,7 @@ junit_binary("chrome_junit_tests") { ...@@ -670,6 +670,7 @@ junit_binary("chrome_junit_tests") {
"//chrome/android/webapk/libs/client:client_java", "//chrome/android/webapk/libs/client:client_java",
"//chrome/android/webapk/libs/common:common_java", "//chrome/android/webapk/libs/common:common_java",
"//chrome/android/webapk/test:junit_test_support", "//chrome/android/webapk/test:junit_test_support",
"//chrome/browser/image_fetcher:java",
"//chrome/browser/ui/android/widget:ui_widget_junit_tests", "//chrome/browser/ui/android/widget:ui_widget_junit_tests",
"//chrome/test/android:chrome_java_test_support", "//chrome/test/android:chrome_java_test_support",
"//components/background_task_scheduler:background_task_scheduler_java", "//components/background_task_scheduler:background_task_scheduler_java",
......
...@@ -1128,7 +1128,6 @@ chrome_java_sources = [ ...@@ -1128,7 +1128,6 @@ chrome_java_sources = [
"java/src/org/chromium/chrome/browser/omnibox/suggestions/SuggestionProcessor.java", "java/src/org/chromium/chrome/browser/omnibox/suggestions/SuggestionProcessor.java",
"java/src/org/chromium/chrome/browser/omnibox/suggestions/VoiceSuggestionProvider.java", "java/src/org/chromium/chrome/browser/omnibox/suggestions/VoiceSuggestionProvider.java",
"java/src/org/chromium/chrome/browser/omnibox/suggestions/answer/AnswerSuggestionProcessor.java", "java/src/org/chromium/chrome/browser/omnibox/suggestions/answer/AnswerSuggestionProcessor.java",
"java/src/org/chromium/chrome/browser/omnibox/suggestions/answer/AnswerSuggestionView.java",
"java/src/org/chromium/chrome/browser/omnibox/suggestions/answer/AnswerSuggestionViewBinder.java", "java/src/org/chromium/chrome/browser/omnibox/suggestions/answer/AnswerSuggestionViewBinder.java",
"java/src/org/chromium/chrome/browser/omnibox/suggestions/answer/AnswerSuggestionViewProperties.java", "java/src/org/chromium/chrome/browser/omnibox/suggestions/answer/AnswerSuggestionViewProperties.java",
"java/src/org/chromium/chrome/browser/omnibox/suggestions/answer/AnswerText.java", "java/src/org/chromium/chrome/browser/omnibox/suggestions/answer/AnswerText.java",
......
...@@ -154,6 +154,7 @@ chrome_junit_test_java_sources = [ ...@@ -154,6 +154,7 @@ chrome_junit_test_java_sources = [
"junit/src/org/chromium/chrome/browser/omnibox/geo/VisibleNetworksTest.java", "junit/src/org/chromium/chrome/browser/omnibox/geo/VisibleNetworksTest.java",
"junit/src/org/chromium/chrome/browser/omnibox/geo/VisibleNetworksTrackerTest.java", "junit/src/org/chromium/chrome/browser/omnibox/geo/VisibleNetworksTrackerTest.java",
"junit/src/org/chromium/chrome/browser/omnibox/status/StatusMediatorUnitTest.java", "junit/src/org/chromium/chrome/browser/omnibox/status/StatusMediatorUnitTest.java",
"junit/src/org/chromium/chrome/browser/omnibox/suggestions/answer/AnswerSuggestionProcessorUnitTest.java",
"junit/src/org/chromium/chrome/browser/omnibox/suggestions/base/BaseSuggestionViewTest.java", "junit/src/org/chromium/chrome/browser/omnibox/suggestions/base/BaseSuggestionViewTest.java",
"junit/src/org/chromium/chrome/browser/omnibox/suggestions/base/SimpleHorizontalLayoutViewTest.java", "junit/src/org/chromium/chrome/browser/omnibox/suggestions/base/SimpleHorizontalLayoutViewTest.java",
"junit/src/org/chromium/chrome/browser/omnibox/suggestions/basic/BasicSuggestionProcessorTest.java", "junit/src/org/chromium/chrome/browser/omnibox/suggestions/basic/BasicSuggestionProcessorTest.java",
......
...@@ -2,75 +2,32 @@ ...@@ -2,75 +2,32 @@
<!-- Copyright 2019 The Chromium Authors. All rights reserved. <!-- Copyright 2019 The Chromium Authors. All rights reserved.
Use of this source code is governed by a BSD-style license that can be Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file. --> found in the LICENSE file. -->
<org.chromium.chrome.browser.omnibox.suggestions.answer.AnswerSuggestionView <LinearLayout
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"
android:clickable="false" android:id="@+id/omnibox_answer"
android:focusable="false" android:layout_width="match_parent"
android:layout_height="@dimen/omnibox_suggestion_answer_height" android:layout_height="@dimen/omnibox_suggestion_answer_height"
android:layout_width="match_parent"> android:layout_centerVertical="true"
android:orientation="vertical"
android:paddingVertical="10dp">
<view class="org.chromium.chrome.browser.omnibox.suggestions.answer.AnswerSuggestionView$FocusableView" <TextView
android:background="?attr/selectableItemBackground" android:ellipsize="end"
android:clickable="true" android:id="@+id/omnibox_answer_line_1"
android:focusable="true" android:layout_width="match_parent"
android:id="@+id/omnibox_answer"
android:layout_alignParentStart="true"
android:layout_centerVertical="true"
android:paddingVertical="10dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_toStartOf="@+id/omnibox_answer_refine_icon" android:maxLines="1"
android:layout_width="0dp"> android:singleLine="true"
android:textAlignment="viewStart" />
<ImageView <TextView
android:contentDescription="@null" android:ellipsize="end"
android:id="@+id/omnibox_answer_icon" android:id="@+id/omnibox_answer_line_2"
android:layout_centerVertical="true" android:layout_width="match_parent"
android:layout_height="36dp" android:layout_height="wrap_content"
android:layout_marginEnd="@dimen/omnibox_suggestion_36dp_icon_margin_end" android:maxLines="3"
android:layout_marginStart="@dimen/omnibox_suggestion_36dp_icon_margin_start" android:singleLine="false"
android:layout_width="36dp" android:textAlignment="viewStart" />
android:scaleType="fitCenter" />
<TextView
android:ellipsize="end"
android:id="@+id/omnibox_answer_line_1"
android:layout_alignParentEnd="true"
android:layout_height="wrap_content"
android:layout_toEndOf="@id/omnibox_answer_icon"
android:layout_width="0dp"
android:maxLines="1"
android:singleLine="true"
android:textAlignment="viewStart" />
<TextView
android:ellipsize="end"
android:id="@+id/omnibox_answer_line_2"
android:layout_alignEnd="@id/omnibox_answer_line_1"
android:layout_alignStart="@id/omnibox_answer_line_1"
android:layout_below="@id/omnibox_answer_line_1"
android:layout_height="wrap_content"
android:layout_width="0dp"
android:maxLines="3"
android:singleLine="false"
android:textAlignment="viewStart" />
</view>
<ImageView
android:background="?attr/selectableItemBackground"
android:clickable="true"
android:contentDescription="@string/accessibility_omnibox_btn_refine"
android:focusable="true"
android:id="@id/omnibox_answer_refine_icon"
android:layout_alignBottom="@id/omnibox_answer"
android:layout_alignParentEnd="true"
android:layout_alignTop="@id/omnibox_answer"
android:layout_centerVertical="true"
android:layout_height="match_parent"
android:layout_marginEnd="@dimen/omnibox_suggestion_refine_view_modern_end_padding"
android:layout_width="@dimen/omnibox_suggestion_refine_width"
android:scaleType="center"
android:src="@drawable/btn_suggestion_refine" />
</org.chromium.chrome.browser.omnibox.suggestions.answer.AnswerSuggestionView> </LinearLayout>
...@@ -24,8 +24,8 @@ import org.chromium.chrome.browser.omnibox.LocationBarVoiceRecognitionHandler; ...@@ -24,8 +24,8 @@ import org.chromium.chrome.browser.omnibox.LocationBarVoiceRecognitionHandler;
import org.chromium.chrome.browser.omnibox.UrlBarEditingTextStateProvider; import org.chromium.chrome.browser.omnibox.UrlBarEditingTextStateProvider;
import org.chromium.chrome.browser.omnibox.suggestions.AutocompleteController.OnSuggestionsReceivedListener; import org.chromium.chrome.browser.omnibox.suggestions.AutocompleteController.OnSuggestionsReceivedListener;
import org.chromium.chrome.browser.omnibox.suggestions.SuggestionListViewBinder.SuggestionListViewHolder; import org.chromium.chrome.browser.omnibox.suggestions.SuggestionListViewBinder.SuggestionListViewHolder;
import org.chromium.chrome.browser.omnibox.suggestions.answer.AnswerSuggestionView;
import org.chromium.chrome.browser.omnibox.suggestions.answer.AnswerSuggestionViewBinder; import org.chromium.chrome.browser.omnibox.suggestions.answer.AnswerSuggestionViewBinder;
import org.chromium.chrome.browser.omnibox.suggestions.base.BaseSuggestionView;
import org.chromium.chrome.browser.omnibox.suggestions.basic.SuggestionView; import org.chromium.chrome.browser.omnibox.suggestions.basic.SuggestionView;
import org.chromium.chrome.browser.omnibox.suggestions.basic.SuggestionViewViewBinder; import org.chromium.chrome.browser.omnibox.suggestions.basic.SuggestionViewViewBinder;
import org.chromium.chrome.browser.omnibox.suggestions.editurl.EditUrlSuggestionProcessor; import org.chromium.chrome.browser.omnibox.suggestions.editurl.EditUrlSuggestionProcessor;
...@@ -129,9 +129,9 @@ public class AutocompleteCoordinatorImpl implements AutocompleteCoordinator { ...@@ -129,9 +129,9 @@ public class AutocompleteCoordinatorImpl implements AutocompleteCoordinator {
adapter.registerType( adapter.registerType(
OmniboxSuggestionUiType.ANSWER_SUGGESTION, OmniboxSuggestionUiType.ANSWER_SUGGESTION,
() -> (AnswerSuggestionView) LayoutInflater.from(mListView.getContext()) () -> new BaseSuggestionView(mListView.getContext(),
.inflate(R.layout.omnibox_answer_suggestion, null), R.layout.omnibox_answer_suggestion),
AnswerSuggestionViewBinder::bind); new AnswerSuggestionViewBinder());
adapter.registerType( adapter.registerType(
OmniboxSuggestionUiType.ENTITY_SUGGESTION, OmniboxSuggestionUiType.ENTITY_SUGGESTION,
......
...@@ -6,9 +6,11 @@ package org.chromium.chrome.browser.omnibox.suggestions.answer; ...@@ -6,9 +6,11 @@ package org.chromium.chrome.browser.omnibox.suggestions.answer;
import android.content.Context; import android.content.Context;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.support.annotation.DrawableRes;
import org.chromium.base.ThreadUtils; import org.chromium.base.ThreadUtils;
import org.chromium.base.metrics.RecordHistogram; import org.chromium.base.metrics.RecordHistogram;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.GlobalDiscardableReferencePool; import org.chromium.chrome.browser.GlobalDiscardableReferencePool;
import org.chromium.chrome.browser.image_fetcher.ImageFetcher; import org.chromium.chrome.browser.image_fetcher.ImageFetcher;
import org.chromium.chrome.browser.image_fetcher.ImageFetcherConfig; import org.chromium.chrome.browser.image_fetcher.ImageFetcherConfig;
...@@ -17,10 +19,9 @@ import org.chromium.chrome.browser.omnibox.OmniboxSuggestionType; ...@@ -17,10 +19,9 @@ import org.chromium.chrome.browser.omnibox.OmniboxSuggestionType;
import org.chromium.chrome.browser.omnibox.UrlBarEditingTextStateProvider; import org.chromium.chrome.browser.omnibox.UrlBarEditingTextStateProvider;
import org.chromium.chrome.browser.omnibox.suggestions.OmniboxSuggestion; import org.chromium.chrome.browser.omnibox.suggestions.OmniboxSuggestion;
import org.chromium.chrome.browser.omnibox.suggestions.OmniboxSuggestionUiType; import org.chromium.chrome.browser.omnibox.suggestions.OmniboxSuggestionUiType;
import org.chromium.chrome.browser.omnibox.suggestions.SuggestionProcessor; import org.chromium.chrome.browser.omnibox.suggestions.base.BaseSuggestionViewProcessor;
import org.chromium.chrome.browser.omnibox.suggestions.answer.AnswerSuggestionViewProperties.AnswerIcon; import org.chromium.chrome.browser.omnibox.suggestions.base.SuggestionDrawableState;
import org.chromium.chrome.browser.omnibox.suggestions.basic.SuggestionHost; import org.chromium.chrome.browser.omnibox.suggestions.basic.SuggestionHost;
import org.chromium.chrome.browser.omnibox.suggestions.basic.SuggestionViewDelegate;
import org.chromium.chrome.browser.util.ConversionUtils; import org.chromium.chrome.browser.util.ConversionUtils;
import org.chromium.components.omnibox.AnswerType; import org.chromium.components.omnibox.AnswerType;
import org.chromium.components.omnibox.SuggestionAnswer; import org.chromium.components.omnibox.SuggestionAnswer;
...@@ -32,14 +33,13 @@ import java.util.List; ...@@ -32,14 +33,13 @@ import java.util.List;
import java.util.Map; import java.util.Map;
/** A class that handles model and view creation for the most commonly used omnibox suggestion. */ /** A class that handles model and view creation for the most commonly used omnibox suggestion. */
public class AnswerSuggestionProcessor implements SuggestionProcessor { public class AnswerSuggestionProcessor extends BaseSuggestionViewProcessor {
private static final int MAX_CACHE_SIZE = 500 * ConversionUtils.BYTES_PER_KILOBYTE; private static final int MAX_CACHE_SIZE = 500 * ConversionUtils.BYTES_PER_KILOBYTE;
private final Map<String, List<PropertyModel>> mPendingAnswerRequestUrls; private final Map<String, List<PropertyModel>> mPendingAnswerRequestUrls;
private final Context mContext; private final Context mContext;
private final SuggestionHost mSuggestionHost; private final SuggestionHost mSuggestionHost;
private ImageFetcher mImageFetcher;
private final UrlBarEditingTextStateProvider mUrlBarEditingTextProvider; private final UrlBarEditingTextStateProvider mUrlBarEditingTextProvider;
private ImageFetcher mImageFetcher;
/** /**
* @param context An Android context. * @param context An Android context.
...@@ -47,6 +47,7 @@ public class AnswerSuggestionProcessor implements SuggestionProcessor { ...@@ -47,6 +47,7 @@ public class AnswerSuggestionProcessor implements SuggestionProcessor {
*/ */
public AnswerSuggestionProcessor(Context context, SuggestionHost suggestionHost, public AnswerSuggestionProcessor(Context context, SuggestionHost suggestionHost,
UrlBarEditingTextStateProvider editingTextProvider) { UrlBarEditingTextStateProvider editingTextProvider) {
super(suggestionHost);
mContext = context; mContext = context;
mSuggestionHost = suggestionHost; mSuggestionHost = suggestionHost;
mPendingAnswerRequestUrls = new HashMap<>(); mPendingAnswerRequestUrls = new HashMap<>();
...@@ -82,11 +83,8 @@ public class AnswerSuggestionProcessor implements SuggestionProcessor { ...@@ -82,11 +83,8 @@ public class AnswerSuggestionProcessor implements SuggestionProcessor {
@Override @Override
public void populateModel(OmniboxSuggestion suggestion, PropertyModel model, int position) { public void populateModel(OmniboxSuggestion suggestion, PropertyModel model, int position) {
SuggestionViewDelegate delegate = super.populateModel(suggestion, model, position);
mSuggestionHost.createSuggestionViewDelegate(suggestion, position); setStateForSuggestion(model, suggestion);
setStateForNewSuggestion(model, suggestion, delegate);
maybeFetchAnswerIcon(suggestion, model);
} }
@Override @Override
...@@ -114,7 +112,15 @@ public class AnswerSuggestionProcessor implements SuggestionProcessor { ...@@ -114,7 +112,15 @@ public class AnswerSuggestionProcessor implements SuggestionProcessor {
// https://cs.chromium.org/Omnibox.SuggestionUsed.AnswerInSuggest // https://cs.chromium.org/Omnibox.SuggestionUsed.AnswerInSuggest
} }
private void maybeFetchAnswerIcon(OmniboxSuggestion suggestion, PropertyModel model) { /**
* Specify ImageFetcher instance to be used for testing purposes.
* TODO(ender): Create fetcher instance in AutocompleteMediator and pass it to the constructor.
*/
void setImageFetcherForTesting(ImageFetcher fetcher) {
mImageFetcher = fetcher;
}
private void maybeFetchAnswerIcon(PropertyModel model, OmniboxSuggestion suggestion) {
ThreadUtils.assertOnUiThread(); ThreadUtils.assertOnUiThread();
// Attempting to fetch answer data before we have a profile to request it for. // Attempting to fetch answer data before we have a profile to request it for.
...@@ -145,13 +151,19 @@ public class AnswerSuggestionProcessor implements SuggestionProcessor { ...@@ -145,13 +151,19 @@ public class AnswerSuggestionProcessor implements SuggestionProcessor {
mImageFetcher.fetchImage( mImageFetcher.fetchImage(
url, ImageFetcher.ANSWER_SUGGESTIONS_UMA_CLIENT_NAME, (Bitmap bitmap) -> { url, ImageFetcher.ANSWER_SUGGESTIONS_UMA_CLIENT_NAME, (Bitmap bitmap) -> {
ThreadUtils.assertOnUiThread(); ThreadUtils.assertOnUiThread();
// Remove models for the URL ahead of all the checks to ensure we
// do not keep them around waiting in case image fetch failed.
List<PropertyModel> currentModels = mPendingAnswerRequestUrls.remove(url); List<PropertyModel> currentModels = mPendingAnswerRequestUrls.remove(url);
if (currentModels == null || bitmap == null) return;
boolean didUpdate = false; boolean didUpdate = false;
for (int i = 0; i < currentModels.size(); i++) { for (int i = 0; i < currentModels.size(); i++) {
PropertyModel currentModel = currentModels.get(i); PropertyModel currentModel = currentModels.get(i);
if (!mSuggestionHost.isActiveModel(currentModel)) continue; if (!mSuggestionHost.isActiveModel(currentModel)) continue;
model.set(AnswerSuggestionViewProperties.ANSWER_IMAGE, bitmap); setSuggestionDrawableState(currentModel,
SuggestionDrawableState.Builder.forBitmap(bitmap)
.setLarge(true)
.build());
didUpdate = true; didUpdate = true;
} }
if (didUpdate) mSuggestionHost.notifyPropertyModelsChanged(); if (didUpdate) mSuggestionHost.notifyPropertyModelsChanged();
...@@ -161,17 +173,11 @@ public class AnswerSuggestionProcessor implements SuggestionProcessor { ...@@ -161,17 +173,11 @@ public class AnswerSuggestionProcessor implements SuggestionProcessor {
/** /**
* Sets both lines of the Omnibox suggestion based on an Answers in Suggest result. * Sets both lines of the Omnibox suggestion based on an Answers in Suggest result.
*/ */
private void setStateForNewSuggestion( private void setStateForSuggestion(PropertyModel model, OmniboxSuggestion suggestion) {
PropertyModel model, OmniboxSuggestion suggestion, SuggestionViewDelegate delegate) {
SuggestionAnswer answer = suggestion.getAnswer(); SuggestionAnswer answer = suggestion.getAnswer();
AnswerText[] details = AnswerTextNewLayout.from( AnswerText[] details = AnswerTextNewLayout.from(
mContext, suggestion, mUrlBarEditingTextProvider.getTextWithoutAutocomplete()); mContext, suggestion, mUrlBarEditingTextProvider.getTextWithoutAutocomplete());
model.set(AnswerSuggestionViewProperties.DELEGATE, delegate);
model.set(AnswerSuggestionViewProperties.TEXT_LINE_1_SIZE, details[0].mHeightSp);
model.set(AnswerSuggestionViewProperties.TEXT_LINE_2_SIZE, details[1].mHeightSp);
model.set(AnswerSuggestionViewProperties.TEXT_LINE_1_TEXT, details[0].mText); model.set(AnswerSuggestionViewProperties.TEXT_LINE_1_TEXT, details[0].mText);
model.set(AnswerSuggestionViewProperties.TEXT_LINE_2_TEXT, details[1].mText); model.set(AnswerSuggestionViewProperties.TEXT_LINE_2_TEXT, details[1].mText);
...@@ -183,43 +189,49 @@ public class AnswerSuggestionProcessor implements SuggestionProcessor { ...@@ -183,43 +189,49 @@ public class AnswerSuggestionProcessor implements SuggestionProcessor {
model.set(AnswerSuggestionViewProperties.TEXT_LINE_1_MAX_LINES, details[0].mMaxLines); model.set(AnswerSuggestionViewProperties.TEXT_LINE_1_MAX_LINES, details[0].mMaxLines);
model.set(AnswerSuggestionViewProperties.TEXT_LINE_2_MAX_LINES, details[1].mMaxLines); model.set(AnswerSuggestionViewProperties.TEXT_LINE_2_MAX_LINES, details[1].mMaxLines);
@AnswerIcon setSuggestionDrawableState(model,
int icon = AnswerIcon.UNDEFINED; SuggestionDrawableState.Builder
.forDrawableRes(mContext, getSuggestionIcon(suggestion))
.setLarge(true)
.build());
maybeFetchAnswerIcon(model, suggestion);
}
/**
* Get default suggestion icon for supplied suggestion.
*/
@DrawableRes
int getSuggestionIcon(OmniboxSuggestion suggestion) {
SuggestionAnswer answer = suggestion.getAnswer();
if (answer != null) { if (answer != null) {
switch (answer.getType()) { switch (answer.getType()) {
case AnswerType.DICTIONARY: case AnswerType.DICTIONARY:
icon = AnswerIcon.DICTIONARY; return R.drawable.ic_book_round;
break;
case AnswerType.FINANCE: case AnswerType.FINANCE:
icon = AnswerIcon.FINANCE; return R.drawable.ic_swap_vert_round;
break;
case AnswerType.KNOWLEDGE_GRAPH: case AnswerType.KNOWLEDGE_GRAPH:
icon = AnswerIcon.KNOWLEDGE; return R.drawable.ic_google_round;
break;
case AnswerType.SUNRISE: case AnswerType.SUNRISE:
icon = AnswerIcon.SUNRISE; return R.drawable.ic_wb_sunny_round;
break;
case AnswerType.TRANSLATION: case AnswerType.TRANSLATION:
icon = AnswerIcon.TRANSLATION; return R.drawable.logo_translate_round;
break;
case AnswerType.WEATHER: case AnswerType.WEATHER:
icon = AnswerIcon.WEATHER; return R.drawable.logo_partly_cloudy;
break;
case AnswerType.WHEN_IS: case AnswerType.WHEN_IS:
icon = AnswerIcon.EVENT; return R.drawable.ic_event_round;
break;
case AnswerType.CURRENCY: case AnswerType.CURRENCY:
icon = AnswerIcon.CURRENCY; return R.drawable.ic_loop_round;
break;
case AnswerType.SPORTS: case AnswerType.SPORTS:
icon = AnswerIcon.SPORTS; return R.drawable.ic_google_round;
default:
assert false : "Unsupported answer type";
break;
} }
} else { } else {
assert suggestion.getType() == OmniboxSuggestionType.CALCULATOR; assert suggestion.getType() == OmniboxSuggestionType.CALCULATOR;
icon = AnswerIcon.CALCULATOR; return R.drawable.ic_equals_sign_round;
} }
return 0;
model.set(AnswerSuggestionViewProperties.ANSWER_ICON_TYPE, icon);
} }
} }
// Copyright 2019 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.suggestions.answer;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.support.v4.graphics.drawable.DrawableCompat;
import android.text.Spannable;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import androidx.annotation.DrawableRes;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.omnibox.suggestions.basic.SuggestionViewDelegate;
import org.chromium.chrome.browser.util.ColorUtils;
/**
* Container view for omnibox answer suggestions.
*/
public class AnswerSuggestionView extends RelativeLayout {
private SuggestionViewDelegate mSuggestionDelegate;
private View mAnswerView;
private TextView mTextView1;
private TextView mTextView2;
private ImageView mAnswerIconView;
private ImageView mRefineView;
/**
* Container view for omnibox suggestions allowing soft focus from keyboard.
*/
public static class FocusableView extends RelativeLayout {
/** Creates new instance of FocusableView. */
public FocusableView(Context context, AttributeSet attributes) {
super(context, attributes);
}
@Override
public boolean isFocused() {
return super.isFocused() || (isSelected() && !isInTouchMode());
}
}
/** Creates new instance of AnswerSuggestionView. */
public AnswerSuggestionView(Context context, AttributeSet attributes) {
super(context, attributes);
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
mTextView1 = findViewById(R.id.omnibox_answer_line_1);
mTextView2 = findViewById(R.id.omnibox_answer_line_2);
mAnswerIconView = findViewById(R.id.omnibox_answer_icon);
mAnswerView = findViewById(R.id.omnibox_answer);
mRefineView = findViewById(R.id.omnibox_answer_refine_icon);
}
@Override
public void setSelected(boolean selected) {
super.setSelected(selected);
mAnswerView.setSelected(selected);
if (selected && !isInTouchMode()) {
postDelegateAction(() -> mSuggestionDelegate.onSetUrlToSuggestion());
}
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
// Whenever the suggestion dropdown is touched, we dispatch onGestureDown which is
// used to let autocomplete controller know that it should stop updating suggestions.
switch (ev.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
mSuggestionDelegate.onGestureDown();
break;
case MotionEvent.ACTION_UP:
mSuggestionDelegate.onGestureUp(ev.getEventTime());
break;
}
return super.dispatchTouchEvent(ev);
}
/** Specify delegate receiving click/refine events. */
void setDelegate(SuggestionViewDelegate delegate) {
mSuggestionDelegate = delegate;
mAnswerView.setOnClickListener(
(View v) -> postDelegateAction(() -> mSuggestionDelegate.onSelection()));
mAnswerView.setOnLongClickListener((View v) -> {
postDelegateAction(() -> mSuggestionDelegate.onLongPress());
return true;
});
mRefineView.setOnClickListener(
(View v) -> postDelegateAction(() -> mSuggestionDelegate.onRefineSuggestion()));
}
/**
* Toggles theme.
* @param useDarkColors specifies whether UI should use dark theme.
*/
void setUseDarkColors(boolean useDarkColors) {
Drawable drawable = mRefineView.getDrawable();
DrawableCompat.setTint(
drawable, ColorUtils.getIconTint(getContext(), !useDarkColors).getDefaultColor());
}
/**
* Specifies text accessibility description of the first text line.
* @param text Text to be announced.
*/
void setLine1AccessibilityDescription(String text) {
mTextView1.setContentDescription(text);
}
/**
* Specifies text accessibility description of the second text line.
* @param text Text to be announced.
*/
void setLine2AccessibilityDescription(String text) {
mTextView2.setContentDescription(text);
}
/**
* Specifies text content of the first text line.
* @param text Text to be displayed.
*/
void setLine1TextContent(Spannable text) {
mTextView1.setText(text);
}
/**
* Specifies text content of the second text line.
* @param text Text to be displayed.
*/
void setLine2TextContent(Spannable text) {
mTextView2.setText(text);
}
/**
* Specifies image bitmap to be displayed as an answer icon.
* @param bitmap Decoded image to be displayed as an answer icon.
*/
void setIconBitmap(Bitmap bitmap) {
BitmapDrawable drawable = new BitmapDrawable(bitmap);
mAnswerIconView.setImageDrawable(drawable);
}
/**
* Specifies fallback image to be presented if no image is available.
* @param res Drawable resource ID to be used in place of answer image.
*/
void setFallbackIconRes(@DrawableRes int res) {
mAnswerIconView.setImageResource(res);
}
/**
* Post delegate action to main thread. Invoked only if delegate is specified.
* @param action Delegate action to invoke on the UI thread.
*/
private void postDelegateAction(Runnable action) {
if (mSuggestionDelegate == null) return;
if (!post(action)) action.run();
}
}
...@@ -4,81 +4,43 @@ ...@@ -4,81 +4,43 @@
package org.chromium.chrome.browser.omnibox.suggestions.answer; package org.chromium.chrome.browser.omnibox.suggestions.answer;
import android.support.v4.view.ViewCompat; import android.widget.TextView;
import org.chromium.chrome.R; import org.chromium.chrome.R;
import org.chromium.chrome.browser.omnibox.suggestions.SuggestionCommonProperties; import org.chromium.chrome.browser.omnibox.suggestions.base.BaseSuggestionView;
import org.chromium.chrome.browser.omnibox.suggestions.answer.AnswerSuggestionViewProperties.AnswerIcon; import org.chromium.chrome.browser.omnibox.suggestions.base.BaseSuggestionViewBinder;
import org.chromium.ui.modelutil.PropertyKey; import org.chromium.ui.modelutil.PropertyKey;
import org.chromium.ui.modelutil.PropertyModel; import org.chromium.ui.modelutil.PropertyModel;
/** A mechanism binding AnswerSuggestion properties to its view. */ /** A mechanism binding AnswerSuggestion properties to its view. */
public class AnswerSuggestionViewBinder { public class AnswerSuggestionViewBinder extends BaseSuggestionViewBinder {
/** @see PropertyModelChangeProcessor.ViewBinder#bind(Object, Object, Object) */ /** @see PropertyModelChangeProcessor.ViewBinder#bind(Object, Object, Object) */
public static void bind( @Override
PropertyModel model, AnswerSuggestionView view, PropertyKey propertyKey) { public void bind(PropertyModel model, BaseSuggestionView view, PropertyKey propertyKey) {
if (AnswerSuggestionViewProperties.DELEGATE.equals(propertyKey)) { super.bind(model, view, propertyKey);
view.setDelegate(model.get(AnswerSuggestionViewProperties.DELEGATE));
} else if (SuggestionCommonProperties.USE_DARK_COLORS.equals(propertyKey)) { if (AnswerSuggestionViewProperties.TEXT_LINE_1_TEXT == propertyKey) {
view.setUseDarkColors(model.get(SuggestionCommonProperties.USE_DARK_COLORS)); TextView tv = view.findContentView(R.id.omnibox_answer_line_1);
} else if (AnswerSuggestionViewProperties.ANSWER_IMAGE.equals(propertyKey)) { tv.setText(model.get(AnswerSuggestionViewProperties.TEXT_LINE_1_TEXT));
view.setIconBitmap(model.get(AnswerSuggestionViewProperties.ANSWER_IMAGE)); } else if (AnswerSuggestionViewProperties.TEXT_LINE_2_TEXT == propertyKey) {
} else if (AnswerSuggestionViewProperties.ANSWER_ICON_TYPE.equals(propertyKey)) { TextView tv = view.findContentView(R.id.omnibox_answer_line_2);
int type = model.get(AnswerSuggestionViewProperties.ANSWER_ICON_TYPE); tv.setText(model.get(AnswerSuggestionViewProperties.TEXT_LINE_2_TEXT));
if (type == AnswerIcon.UNDEFINED) return; } else if (AnswerSuggestionViewProperties.TEXT_LINE_1_ACCESSIBILITY_DESCRIPTION
view.setFallbackIconRes(getAnswerIcon(type)); == propertyKey) {
} else if (AnswerSuggestionViewProperties.TEXT_LINE_1_TEXT.equals(propertyKey)) { TextView tv = view.findContentView(R.id.omnibox_answer_line_1);
view.setLine1TextContent(model.get(AnswerSuggestionViewProperties.TEXT_LINE_1_TEXT)); tv.setContentDescription(model.get(
} else if (AnswerSuggestionViewProperties.TEXT_LINE_2_TEXT.equals(propertyKey)) {
view.setLine2TextContent(model.get(AnswerSuggestionViewProperties.TEXT_LINE_2_TEXT));
} else if (AnswerSuggestionViewProperties.TEXT_LINE_1_ACCESSIBILITY_DESCRIPTION.equals(
propertyKey)) {
view.setLine1AccessibilityDescription(model.get(
AnswerSuggestionViewProperties.TEXT_LINE_1_ACCESSIBILITY_DESCRIPTION)); AnswerSuggestionViewProperties.TEXT_LINE_1_ACCESSIBILITY_DESCRIPTION));
} else if (AnswerSuggestionViewProperties.TEXT_LINE_2_ACCESSIBILITY_DESCRIPTION.equals( } else if (AnswerSuggestionViewProperties.TEXT_LINE_2_ACCESSIBILITY_DESCRIPTION
propertyKey)) { == propertyKey) {
view.setLine2AccessibilityDescription(model.get( TextView tv = view.findContentView(R.id.omnibox_answer_line_2);
tv.setContentDescription(model.get(
AnswerSuggestionViewProperties.TEXT_LINE_2_ACCESSIBILITY_DESCRIPTION)); AnswerSuggestionViewProperties.TEXT_LINE_2_ACCESSIBILITY_DESCRIPTION));
} else if (SuggestionCommonProperties.LAYOUT_DIRECTION.equals(propertyKey)) { } else if (AnswerSuggestionViewProperties.TEXT_LINE_1_MAX_LINES == propertyKey) {
ViewCompat.setLayoutDirection( TextView tv = view.findContentView(R.id.omnibox_answer_line_1);
view, model.get(SuggestionCommonProperties.LAYOUT_DIRECTION)); tv.setMaxLines(model.get(AnswerSuggestionViewProperties.TEXT_LINE_1_MAX_LINES));
} } else if (AnswerSuggestionViewProperties.TEXT_LINE_2_MAX_LINES == propertyKey) {
} TextView tv = view.findContentView(R.id.omnibox_answer_line_2);
tv.setMaxLines(model.get(AnswerSuggestionViewProperties.TEXT_LINE_2_MAX_LINES));
/**
* Convert AnswerIcon type to drawable resource type representing answer icon.
*
* Answers are not shown when user is in incognito mode, so we can rely on
* configuration UI to define colors for light and dark mode that will be used
* by the icons below.
*
* @param type AnswerIcon type to get drawable for.
*/
private static final int getAnswerIcon(@AnswerIcon int type) {
switch (type) {
case AnswerIcon.CALCULATOR:
return R.drawable.ic_equals_sign_round;
case AnswerIcon.DICTIONARY:
return R.drawable.ic_book_round;
case AnswerIcon.FINANCE:
return R.drawable.ic_swap_vert_round;
case AnswerIcon.KNOWLEDGE:
return R.drawable.ic_google_round;
case AnswerIcon.SUNRISE:
return R.drawable.ic_wb_sunny_round;
case AnswerIcon.TRANSLATION:
return R.drawable.logo_translate_round;
case AnswerIcon.WEATHER:
return R.drawable.logo_partly_cloudy;
case AnswerIcon.EVENT:
return R.drawable.ic_event_round;
case AnswerIcon.CURRENCY:
return R.drawable.ic_loop_round;
case AnswerIcon.SPORTS:
return R.drawable.ic_google_round;
default:
assert false : "Invalid answer type: " + type;
return 0;
} }
} }
} }
...@@ -4,54 +4,18 @@ ...@@ -4,54 +4,18 @@
package org.chromium.chrome.browser.omnibox.suggestions.answer; package org.chromium.chrome.browser.omnibox.suggestions.answer;
import android.graphics.Bitmap;
import android.text.Spannable; import android.text.Spannable;
import androidx.annotation.IntDef; import org.chromium.chrome.browser.omnibox.suggestions.base.BaseSuggestionViewProperties;
import org.chromium.chrome.browser.omnibox.suggestions.SuggestionCommonProperties;
import org.chromium.chrome.browser.omnibox.suggestions.basic.SuggestionViewDelegate;
import org.chromium.ui.modelutil.PropertyKey; import org.chromium.ui.modelutil.PropertyKey;
import org.chromium.ui.modelutil.PropertyModel; import org.chromium.ui.modelutil.PropertyModel;
import org.chromium.ui.modelutil.PropertyModel.WritableIntPropertyKey; import org.chromium.ui.modelutil.PropertyModel.WritableIntPropertyKey;
import org.chromium.ui.modelutil.PropertyModel.WritableObjectPropertyKey; import org.chromium.ui.modelutil.PropertyModel.WritableObjectPropertyKey;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/** /**
* The properties associated with rendering the answer suggestion view. * The properties associated with rendering the answer suggestion view.
*/ */
class AnswerSuggestionViewProperties { class AnswerSuggestionViewProperties {
@IntDef({AnswerIcon.UNDEFINED, AnswerIcon.CALCULATOR, AnswerIcon.DICTIONARY, AnswerIcon.FINANCE,
AnswerIcon.KNOWLEDGE, AnswerIcon.SUNRISE, AnswerIcon.TRANSLATION, AnswerIcon.WEATHER,
AnswerIcon.EVENT, AnswerIcon.CURRENCY, AnswerIcon.SPORTS})
@Retention(RetentionPolicy.SOURCE)
public @interface AnswerIcon {
int UNDEFINED = 0;
int CALCULATOR = 1;
int DICTIONARY = 2;
int FINANCE = 3;
int KNOWLEDGE = 4;
int SUNRISE = 5;
int TRANSLATION = 6;
int WEATHER = 7;
int EVENT = 8;
int CURRENCY = 9;
int SPORTS = 10;
}
/** The delegate to handle actions on the suggestion view. */
public static final WritableObjectPropertyKey<SuggestionViewDelegate> DELEGATE =
new WritableObjectPropertyKey<>();
/** The answer image to be shown. */
public static final WritableObjectPropertyKey<Bitmap> ANSWER_IMAGE =
new WritableObjectPropertyKey<>();
/** The suggestion icon type shown. */
public static final WritableIntPropertyKey ANSWER_ICON_TYPE = new WritableIntPropertyKey();
/** The sizing information for the first line of text. */
public static final WritableIntPropertyKey TEXT_LINE_1_SIZE = new WritableIntPropertyKey();
/** The maximum number of lines to be shown for the first line of text. */ /** The maximum number of lines to be shown for the first line of text. */
public static final WritableIntPropertyKey TEXT_LINE_1_MAX_LINES = new WritableIntPropertyKey(); public static final WritableIntPropertyKey TEXT_LINE_1_MAX_LINES = new WritableIntPropertyKey();
/** The actual text content for the first line of text. */ /** The actual text content for the first line of text. */
...@@ -61,8 +25,6 @@ class AnswerSuggestionViewProperties { ...@@ -61,8 +25,6 @@ class AnswerSuggestionViewProperties {
public static final WritableObjectPropertyKey<String> TEXT_LINE_1_ACCESSIBILITY_DESCRIPTION = public static final WritableObjectPropertyKey<String> TEXT_LINE_1_ACCESSIBILITY_DESCRIPTION =
new WritableObjectPropertyKey<>(); new WritableObjectPropertyKey<>();
/** The sizing information for the second line of text. */
public static final WritableIntPropertyKey TEXT_LINE_2_SIZE = new WritableIntPropertyKey();
/** The maximum number of lines to be shown for the second line of text. */ /** The maximum number of lines to be shown for the second line of text. */
public static final WritableIntPropertyKey TEXT_LINE_2_MAX_LINES = new WritableIntPropertyKey(); public static final WritableIntPropertyKey TEXT_LINE_2_MAX_LINES = new WritableIntPropertyKey();
/** The actual text content for the second line of text. */ /** The actual text content for the second line of text. */
...@@ -72,11 +34,10 @@ class AnswerSuggestionViewProperties { ...@@ -72,11 +34,10 @@ class AnswerSuggestionViewProperties {
public static final WritableObjectPropertyKey<String> TEXT_LINE_2_ACCESSIBILITY_DESCRIPTION = public static final WritableObjectPropertyKey<String> TEXT_LINE_2_ACCESSIBILITY_DESCRIPTION =
new WritableObjectPropertyKey<>(); new WritableObjectPropertyKey<>();
public static final PropertyKey[] ALL_UNIQUE_KEYS = new PropertyKey[] {DELEGATE, ANSWER_IMAGE, public static final PropertyKey[] ALL_UNIQUE_KEYS = new PropertyKey[] {TEXT_LINE_1_TEXT,
ANSWER_ICON_TYPE, TEXT_LINE_1_SIZE, TEXT_LINE_1_MAX_LINES, TEXT_LINE_1_TEXT, TEXT_LINE_1_MAX_LINES, TEXT_LINE_1_ACCESSIBILITY_DESCRIPTION, TEXT_LINE_2_TEXT,
TEXT_LINE_1_ACCESSIBILITY_DESCRIPTION, TEXT_LINE_2_SIZE, TEXT_LINE_2_MAX_LINES, TEXT_LINE_2_MAX_LINES, TEXT_LINE_2_ACCESSIBILITY_DESCRIPTION};
TEXT_LINE_2_TEXT, TEXT_LINE_2_ACCESSIBILITY_DESCRIPTION};
public static final PropertyKey[] ALL_KEYS = public static final PropertyKey[] ALL_KEYS =
PropertyModel.concatKeys(ALL_UNIQUE_KEYS, SuggestionCommonProperties.ALL_KEYS); PropertyModel.concatKeys(ALL_UNIQUE_KEYS, BaseSuggestionViewProperties.ALL_KEYS);
} }
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
package org.chromium.chrome.browser.omnibox.suggestions.base; package org.chromium.chrome.browser.omnibox.suggestions.base;
import android.content.Context; import android.content.Context;
import android.support.annotation.IdRes;
import android.util.TypedValue; import android.util.TypedValue;
import android.view.KeyEvent; import android.view.KeyEvent;
import android.view.LayoutInflater; import android.view.LayoutInflater;
...@@ -145,4 +146,17 @@ public class BaseSuggestionView extends SimpleHorizontalLayoutView { ...@@ -145,4 +146,17 @@ public class BaseSuggestionView extends SimpleHorizontalLayoutView {
ImageView getActionImageView() { ImageView getActionImageView() {
return mActionView; return mActionView;
} }
/**
* Find content view by view id.
*
* Scoped {@link #findViewById(int)} search for the view specified in
* {@link #setContentView(View)}.
*
* @param id View ID of the sought view.
* @return View with the specified ID or null, if view could not be found.
*/
public <T extends View> T findContentView(@IdRes int id) {
return mContentView.findContentView(id);
}
} }
...@@ -52,18 +52,18 @@ public class BaseSuggestionViewBinder ...@@ -52,18 +52,18 @@ public class BaseSuggestionViewBinder
final RoundedCornerImageView view = baseView.getSuggestionImageView(); final RoundedCornerImageView view = baseView.getSuggestionImageView();
final SuggestionDrawableState sds = model.get(BaseSuggestionViewProperties.ICON); final SuggestionDrawableState sds = model.get(BaseSuggestionViewProperties.ICON);
final Resources res = view.getContext().getResources(); final Resources res = view.getContext().getResources();
final int paddingStart = res.getDimensionPixelSize(sds.isLarge() final int paddingStart = res.getDimensionPixelSize(sds.isLarge
? R.dimen.omnibox_suggestion_36dp_icon_margin_start ? R.dimen.omnibox_suggestion_36dp_icon_margin_start
: R.dimen.omnibox_suggestion_24dp_icon_margin_start); : R.dimen.omnibox_suggestion_24dp_icon_margin_start);
final int paddingEnd = res.getDimensionPixelSize(sds.isLarge() final int paddingEnd = res.getDimensionPixelSize(sds.isLarge
? R.dimen.omnibox_suggestion_36dp_icon_margin_end ? R.dimen.omnibox_suggestion_36dp_icon_margin_end
: R.dimen.omnibox_suggestion_24dp_icon_margin_end); : R.dimen.omnibox_suggestion_24dp_icon_margin_end);
// TODO(ender): move logic applying corner rounding to updateIcon when action images use // TODO(ender): move logic applying corner rounding to updateIcon when action images use
// RoundedCornerImageView too. // RoundedCornerImageView too.
RoundedCornerImageView rciv = (RoundedCornerImageView) view; RoundedCornerImageView rciv = (RoundedCornerImageView) view;
int radius = sds.isRounded() int radius = sds.useRoundedCorners
? res.getDimensionPixelSize(R.dimen.default_rounded_corner_radius) ? res.getDimensionPixelSize(R.dimen.default_rounded_corner_radius)
: 0; : 0;
rciv.setRoundedCorners(radius, radius, radius, radius); rciv.setRoundedCorners(radius, radius, radius, radius);
...@@ -91,8 +91,8 @@ public class BaseSuggestionViewBinder ...@@ -91,8 +91,8 @@ public class BaseSuggestionViewBinder
return; return;
} }
view.setImageDrawable(sds.getDrawable()); view.setImageDrawable(sds.drawable);
if (sds.isTintable()) { if (sds.allowTint) {
ApiCompatibilityUtils.setImageTintList( ApiCompatibilityUtils.setImageTintList(
view, ColorUtils.getIconTint(view.getContext(), !useDarkColors)); view, ColorUtils.getIconTint(view.getContext(), !useDarkColors));
} }
......
...@@ -6,6 +6,7 @@ package org.chromium.chrome.browser.omnibox.suggestions.base; ...@@ -6,6 +6,7 @@ package org.chromium.chrome.browser.omnibox.suggestions.base;
import android.content.Context; import android.content.Context;
import android.support.annotation.DrawableRes; import android.support.annotation.DrawableRes;
import android.support.annotation.IdRes;
import android.view.View; import android.view.View;
import android.widget.ImageView; import android.widget.ImageView;
...@@ -59,4 +60,11 @@ class DecoratedSuggestionView extends SimpleHorizontalLayoutView { ...@@ -59,4 +60,11 @@ class DecoratedSuggestionView extends SimpleHorizontalLayoutView {
public boolean isFocused() { public boolean isFocused() {
return super.isFocused() || (isSelected() && !isInTouchMode()); return super.isFocused() || (isSelected() && !isInTouchMode());
} }
<ViewType extends View> ViewType findContentView(@IdRes int id) {
if (mContentView == null) {
return null;
}
return mContentView.findViewById(id);
}
} }
...@@ -7,106 +7,132 @@ package org.chromium.chrome.browser.omnibox.suggestions.base; ...@@ -7,106 +7,132 @@ package org.chromium.chrome.browser.omnibox.suggestions.base;
import android.content.Context; import android.content.Context;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.graphics.drawable.PaintDrawable;
import android.support.annotation.ColorInt; import android.support.annotation.ColorInt;
import android.support.annotation.ColorRes;
import android.support.annotation.DrawableRes; import android.support.annotation.DrawableRes;
import android.support.v4.util.ObjectsCompat; import android.support.v4.util.ObjectsCompat;
import android.support.v7.content.res.AppCompatResources; import android.support.v7.content.res.AppCompatResources;
import org.chromium.chrome.R;
/** Represents graphical decoration for the suggestion components. */ /** Represents graphical decoration for the suggestion components. */
public class SuggestionDrawableState { public class SuggestionDrawableState {
private Drawable mDrawable; /** Embedded drawable object. */
private boolean mAllowTint; public final Drawable drawable;
private boolean mUseRoundedCorners; /** Whether supplied drawable can be tinted */
private boolean mIsLarge; public final boolean allowTint;
/** Whether drawable should be rounded. */
/** public final boolean useRoundedCorners;
* Create new SuggestionDrawableState representing a supplied Drawable object. /** Whether drawable should be displayed as large. */
* public final boolean isLarge;
* @param cxt Current context.
* @param drawable Drawable object to use.
* @param isLarge Whether drawable object should be large (or small).
* @param allowTint Whether supplied drawable can be tinted.
* @param rounded Whether supplied drawable should use rounded corners.
*/
public SuggestionDrawableState(
Context ctx, Drawable drawable, boolean isLarge, boolean allowTint, boolean rounded) {
mDrawable = drawable;
mIsLarge = isLarge;
mAllowTint = allowTint;
mUseRoundedCorners = rounded;
}
/** public static final class Builder {
* Create new SuggestionDrawableState representing a supplied Bitmap. private Drawable mDrawable;
* Bitmap drawables are not tintable. private boolean mAllowTint;
* private boolean mUseRoundedCorners;
* @param cxt Current context. private boolean mIsLarge;
* @param bitmap Bitmap to use.
* @param isLarge Whether drawable object should be large (or small).
* @param rounded Whether supplied drawable should use rounded corners.
*/
public SuggestionDrawableState(Context ctx, Bitmap bitmap, boolean isLarge, boolean rounded) {
this(ctx, new BitmapDrawable(bitmap), isLarge, false, rounded);
}
/** /**
* Create new SuggestionDrawableState representing a supplied Color. * Create new Builder object.
* This instance is not tintable. *
* This method does not utilize ColorDrawables directly, because these are freely resize-able, * @param cxt Current context.
* making it impossible to restrict its aspect ratio to a rectangle. */
* private Builder(Drawable drawable) {
* @param cxt Current context. assert drawable != null : "SuggestionDrawableState needs a Drawable object";
* @param color Color to show. mDrawable = drawable;
* @param isLarge Whether drawable object should be large (or small). }
* @param rounded Whether supplied drawable should use rounded corners.
*/
public SuggestionDrawableState(
Context ctx, @ColorInt int color, boolean isLarge, boolean rounded) {
this(ctx, new PaintDrawable(color), isLarge, false, rounded);
final int edgeSize = ctx.getResources().getDimensionPixelSize(isLarge
? R.dimen.omnibox_suggestion_36dp_icon_size
: R.dimen.omnibox_suggestion_24dp_icon_size);
final PaintDrawable drawable = (PaintDrawable) mDrawable;
drawable.setIntrinsicWidth(edgeSize);
drawable.setIntrinsicHeight(edgeSize);
}
/** /**
* Create new SuggestionDrawableState representing a supplied drawable resource. * Associate Bitmap with built SuggestionDrawableState object.
* *
* @param cxt Current context. * @param bitmap Bitmap to use.
* @param res Drawable resource to use. */
* @param isLarge Whether drawable object should be large (or small). public static Builder forBitmap(Bitmap bitmap) {
* @param allowTint Whether supplied drawable can be tinted. return new Builder(new BitmapDrawable(bitmap));
* @param rounded Whether supplied drawable should use rounded corners. }
*/
public SuggestionDrawableState(Context ctx, @DrawableRes int res, boolean isLarge,
boolean allowTint, boolean rounded) {
this(ctx, AppCompatResources.getDrawable(ctx, res), isLarge, allowTint, rounded);
}
/** Get Drawable associated with this instance. */ /**
Drawable getDrawable() { * Associate Color with built SuggestionDrawableState object.
return mDrawable; *
} * @param color Color to use.
*/
public static Builder forColor(@ColorInt int color) {
return new Builder(new ColorDrawable(color));
}
/** Whether drawable can be tinted. */ /**
boolean isTintable() { * Associate Color with built SuggestionDrawableState object.
return mAllowTint; *
} * @param ctx Current context.
* @param colorRes Color resource to use.
*/
public static Builder forColorRes(Context ctx, @ColorRes int colorRes) {
return new Builder(new ColorDrawable(ctx.getResources().getColor(colorRes)));
}
/** Whether drawable should be drawn as large. */ /**
boolean isLarge() { * Associate Drawable with built SuggestionDrawableState object.
return mIsLarge; *
} * @param ctx Current context.
* @param res Drawable resource to use.
*/
public static Builder forDrawableRes(Context ctx, @DrawableRes int res) {
return new Builder(AppCompatResources.getDrawable(ctx, res));
}
/** Whether drawable should be rounded. */ /**
boolean isRounded() { * Create new SuggestionDrawableState representing a supplied Drawable object.
return mUseRoundedCorners; *
* @param drawable Drawable object to use.
*/
public static Builder forDrawable(Drawable d) {
return new Builder(d);
}
/**
* Specify whether built object should be rounded.
*
* @param useRoundedCorners true, if image should be rounded.
*/
public Builder setUseRoundedCorners(boolean useRoundedCorners) {
mUseRoundedCorners = useRoundedCorners;
return this;
}
/**
* Specify whether build object should receive tint.
*
* @param allowTint true, if built drawable state should be tinted to reflect theme.
*/
public Builder setAllowTint(boolean allowTint) {
mAllowTint = allowTint;
return this;
}
/**
* Specify whether build object should be presented as small (24dp) or large (36dp).
*
* @param isLarge true, if drawable should be shown large (36dp), otherwise 24dp.
*/
public Builder setLarge(boolean isLarge) {
mIsLarge = isLarge;
return this;
}
/**
* Build SuggestionDrawableState object.
*/
public SuggestionDrawableState build() {
return new SuggestionDrawableState(mDrawable, mUseRoundedCorners, mIsLarge, mAllowTint);
}
};
private SuggestionDrawableState(
Drawable drawable, boolean useRoundedCorners, boolean isLarge, boolean allowTint) {
this.drawable = drawable;
this.useRoundedCorners = useRoundedCorners;
this.isLarge = isLarge;
this.allowTint = allowTint;
} }
@Override @Override
...@@ -115,8 +141,7 @@ public class SuggestionDrawableState { ...@@ -115,8 +141,7 @@ public class SuggestionDrawableState {
if (!(object instanceof SuggestionDrawableState)) return false; if (!(object instanceof SuggestionDrawableState)) return false;
SuggestionDrawableState other = (SuggestionDrawableState) object; SuggestionDrawableState other = (SuggestionDrawableState) object;
return mIsLarge == other.mIsLarge && mUseRoundedCorners == other.mUseRoundedCorners return isLarge == other.isLarge && useRoundedCorners == other.useRoundedCorners
&& mAllowTint == other.mAllowTint && allowTint == other.allowTint && ObjectsCompat.equals(drawable, other.drawable);
&& ObjectsCompat.equals(mDrawable, other.mDrawable);
} }
}; };
include_rules = [ include_rules = [
"!clank/java/src/org/chromium/chrome/browser/AppHooksImpl.java", "!clank/java/src/org/chromium/chrome/browser/AppHooksImpl.java",
"+chrome/lib/lifecycle/public", "+chrome/lib/lifecycle/public",
"+chrome/browser/image_fetcher",
"+chrome/browser/ui/android/widget", "+chrome/browser/ui/android/widget",
"+components/autofill/android/java/src/org/chromium/components/autofill", "+components/autofill/android/java/src/org/chromium/components/autofill",
"+components/background_task_scheduler/android", "+components/background_task_scheduler/android",
"+components/bookmarks/common/android", "+components/bookmarks/common/android",
"+components/offline_items_collection/core/android/java/src", "+components/offline_items_collection/core/android/java/src",
"+components/omnibox/browser/android/java/src/org/chromium/components/omnibox",
"+components/payments/content/android/java/src/org/chromium/components/payments", "+components/payments/content/android/java/src/org/chromium/components/payments",
"+components/search_engines/android/java/src/org/chromium/components/search_engines", "+components/search_engines/android/java/src/org/chromium/components/search_engines",
"+components/sync/android/java/src/org/chromium/components/sync", "+components/sync/android/java/src/org/chromium/components/sync",
......
...@@ -7,6 +7,7 @@ package org.chromium.components.omnibox; ...@@ -7,6 +7,7 @@ package org.chromium.components.omnibox;
import android.support.v4.util.ObjectsCompat; import android.support.v4.util.ObjectsCompat;
import android.text.TextUtils; import android.text.TextUtils;
import org.chromium.base.VisibleForTesting;
import org.chromium.base.annotations.CalledByNative; import org.chromium.base.annotations.CalledByNative;
import java.util.ArrayList; import java.util.ArrayList;
...@@ -22,7 +23,8 @@ public class SuggestionAnswer { ...@@ -22,7 +23,8 @@ public class SuggestionAnswer {
private final ImageLine mFirstLine; private final ImageLine mFirstLine;
private final ImageLine mSecondLine; private final ImageLine mSecondLine;
private SuggestionAnswer(@AnswerType int type, ImageLine firstLine, ImageLine secondLine) { @VisibleForTesting
public SuggestionAnswer(@AnswerType int type, ImageLine firstLine, ImageLine secondLine) {
mType = type; mType = type;
mFirstLine = firstLine; mFirstLine = firstLine;
mSecondLine = secondLine; mSecondLine = secondLine;
...@@ -69,8 +71,9 @@ public class SuggestionAnswer { ...@@ -69,8 +71,9 @@ public class SuggestionAnswer {
private final TextField mStatusText; private final TextField mStatusText;
private final String mImage; private final String mImage;
private ImageLine(List<TextField> textFields, TextField additionalText, @VisibleForTesting
TextField statusText, String imageUrl) { public ImageLine(List<TextField> textFields, TextField additionalText, TextField statusText,
String imageUrl) {
mTextFields = textFields; mTextFields = textFields;
mAdditionalText = additionalText; mAdditionalText = additionalText;
mStatusText = statusText; mStatusText = statusText;
...@@ -160,7 +163,8 @@ public class SuggestionAnswer { ...@@ -160,7 +163,8 @@ public class SuggestionAnswer {
private final int mStyle; private final int mStyle;
private final int mNumLines; private final int mNumLines;
private TextField( @VisibleForTesting
public TextField(
@AnswerTextType int type, String text, @AnswerTextStyle int style, int numLines) { @AnswerTextType int type, String text, @AnswerTextStyle int style, int numLines) {
mType = type; mType = type;
mText = text; mText = text;
......
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