1 // Copyright 2018 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 package org.chromium.chrome.browser.omnibox;
6 
7 import android.content.res.Resources;
8 import android.text.Editable;
9 import android.text.Selection;
10 import android.text.TextUtils;
11 import android.view.ActionMode;
12 
13 import androidx.annotation.ColorRes;
14 
15 import org.chromium.base.ApiCompatibilityUtils;
16 import org.chromium.base.Callback;
17 import org.chromium.chrome.R;
18 import org.chromium.chrome.browser.omnibox.UrlBarProperties.AutocompleteText;
19 import org.chromium.chrome.browser.omnibox.UrlBarProperties.UrlBarTextState;
20 import org.chromium.ui.modelutil.PropertyKey;
21 import org.chromium.ui.modelutil.PropertyModel;
22 
23 /**
24  * Handles translating the UrlBar model data to the view state.
25  */
26 class UrlBarViewBinder {
27     /**
28      * @see
29      * PropertyModelChangeProcessor.ViewBinder#bind(Object,
30      * Object, Object)
31      */
bind(PropertyModel model, UrlBar view, PropertyKey propertyKey)32     public static void bind(PropertyModel model, UrlBar view, PropertyKey propertyKey) {
33         if (UrlBarProperties.ACTION_MODE_CALLBACK.equals(propertyKey)) {
34             ActionMode.Callback callback = model.get(UrlBarProperties.ACTION_MODE_CALLBACK);
35             if (callback == null && view.getCustomSelectionActionModeCallback() == null) return;
36             view.setCustomSelectionActionModeCallback(callback);
37         } else if (UrlBarProperties.ALLOW_FOCUS.equals(propertyKey)) {
38             view.setAllowFocus(model.get(UrlBarProperties.ALLOW_FOCUS));
39         } else if (UrlBarProperties.AUTOCOMPLETE_TEXT.equals(propertyKey)) {
40             AutocompleteText autocomplete = model.get(UrlBarProperties.AUTOCOMPLETE_TEXT);
41             if (view.shouldAutocomplete()) {
42                 view.setAutocompleteText(autocomplete.userText, autocomplete.autocompleteText);
43             }
44         } else if (UrlBarProperties.DELEGATE.equals(propertyKey)) {
45             view.setDelegate(model.get(UrlBarProperties.DELEGATE));
46         } else if (UrlBarProperties.FOCUS_CHANGE_CALLBACK.equals(propertyKey)) {
47             final Callback<Boolean> focusChangeCallback =
48                     model.get(UrlBarProperties.FOCUS_CHANGE_CALLBACK);
49             view.setOnFocusChangeListener((v, focused) -> {
50                 if (focused) view.setIgnoreTextChangesForAutocomplete(false);
51                 focusChangeCallback.onResult(focused);
52             });
53         } else if (UrlBarProperties.SHOW_CURSOR.equals(propertyKey)) {
54             view.setCursorVisible(model.get(UrlBarProperties.SHOW_CURSOR));
55         } else if (UrlBarProperties.TEXT_CONTEXT_MENU_DELEGATE.equals(propertyKey)) {
56             view.setTextContextMenuDelegate(model.get(UrlBarProperties.TEXT_CONTEXT_MENU_DELEGATE));
57         } else if (UrlBarProperties.TEXT_STATE.equals(propertyKey)) {
58             UrlBarTextState state = model.get(UrlBarProperties.TEXT_STATE);
59             view.setIgnoreTextChangesForAutocomplete(true);
60             view.setText(state.text);
61             view.setTextForAutofillServices(state.textForAutofillServices);
62             view.setScrollState(state.scrollType, state.scrollToIndex);
63             view.setIgnoreTextChangesForAutocomplete(false);
64 
65             if (view.hasFocus()) {
66                 if (state.selectionState == UrlBarCoordinator.SelectionState.SELECT_ALL) {
67                     view.selectAll();
68                 } else if (state.selectionState == UrlBarCoordinator.SelectionState.SELECT_END) {
69                     view.setSelection(view.getText().length());
70                 }
71             }
72         } else if (UrlBarProperties.USE_DARK_TEXT_COLORS.equals(propertyKey)) {
73             updateTextColors(view, model.get(UrlBarProperties.USE_DARK_TEXT_COLORS));
74         } else if (UrlBarProperties.URL_DIRECTION_LISTENER.equals(propertyKey)) {
75             view.setUrlDirectionListener(model.get(UrlBarProperties.URL_DIRECTION_LISTENER));
76         } else if (UrlBarProperties.URL_TEXT_CHANGE_LISTENER.equals(propertyKey)) {
77             view.setUrlTextChangeListener(model.get(UrlBarProperties.URL_TEXT_CHANGE_LISTENER));
78         } else if (UrlBarProperties.TEXT_CHANGED_LISTENER.equals(propertyKey)) {
79             view.setTextChangedListener(model.get(UrlBarProperties.TEXT_CHANGED_LISTENER));
80         } else if (UrlBarProperties.WINDOW_DELEGATE.equals(propertyKey)) {
81             view.setWindowDelegate(model.get(UrlBarProperties.WINDOW_DELEGATE));
82         }
83     }
84 
updateTextColors(UrlBar view, boolean useDarkTextColors)85     private static void updateTextColors(UrlBar view, boolean useDarkTextColors) {
86         int originalHighlightColor;
87         Object highlightColorObj = view.getTag(R.id.highlight_color);
88         if (highlightColorObj == null || !(highlightColorObj instanceof Integer)) {
89             originalHighlightColor = view.getHighlightColor();
90             view.setTag(R.id.highlight_color, originalHighlightColor);
91         } else {
92             originalHighlightColor = (Integer) highlightColorObj;
93         }
94 
95         Resources resources = view.getResources();
96         int textColor;
97         int hintColor;
98         int highlightColor;
99         if (useDarkTextColors) {
100             textColor = ApiCompatibilityUtils.getColor(resources, R.color.default_text_color_dark);
101             hintColor =
102                     ApiCompatibilityUtils.getColor(resources, R.color.locationbar_dark_hint_text);
103             highlightColor = originalHighlightColor;
104         } else {
105             textColor = ApiCompatibilityUtils.getColor(resources, R.color.default_text_color_light);
106             hintColor =
107                     ApiCompatibilityUtils.getColor(resources, R.color.locationbar_light_hint_text);
108             highlightColor = ApiCompatibilityUtils.getColor(
109                     resources, R.color.highlight_color_on_light_text);
110         }
111 
112         view.setTextColor(textColor);
113         setHintTextColor(view, hintColor);
114         view.setHighlightColor(highlightColor);
115     }
116 
setHintTextColor(UrlBar view, @ColorRes int textColor)117     private static void setHintTextColor(UrlBar view, @ColorRes int textColor) {
118         // Note: Setting the hint text color only takes effect if there is not text in the URL bar.
119         //       To get around this, set the URL to empty before setting the hint color and revert
120         //       back to the previous text after.
121         boolean hasNonEmptyText = false;
122         int selectionStart = 0;
123         int selectionEnd = 0;
124         Editable text = view.getText();
125         if (!TextUtils.isEmpty(text)) {
126             selectionStart = view.getSelectionStart();
127             selectionEnd = view.getSelectionEnd();
128             // Make sure the setText in this block does not affect the suggestions.
129             view.setIgnoreTextChangesForAutocomplete(true);
130             view.setText("");
131             hasNonEmptyText = true;
132         }
133         view.setHintTextColor(textColor);
134         if (hasNonEmptyText) {
135             view.setText(text);
136             if (view.hasFocus()) {
137                 Selection.setSelection(view.getText(), selectionStart, selectionEnd);
138             }
139             view.setIgnoreTextChangesForAutocomplete(false);
140         }
141     }
142 
UrlBarViewBinder()143     private UrlBarViewBinder() {}
144 }
145