1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
ash / search_box / search_box_view_base.h [blame]
// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef ASH_SEARCH_BOX_SEARCH_BOX_VIEW_BASE_H_
#define ASH_SEARCH_BOX_SEARCH_BOX_VIEW_BASE_H_
#include <optional>
#include <string>
#include <vector>
#include "ash/search_box/search_box_constants.h"
#include "base/functional/bind.h"
#include "base/functional/callback_forward.h"
#include "base/memory/raw_ptr.h"
#include "ui/base/metadata/metadata_header_macros.h"
#include "ui/events/types/event_type.h"
#include "ui/gfx/font_list.h"
#include "ui/gfx/geometry/insets.h"
#include "ui/views/background.h"
#include "ui/views/controls/button/image_button.h"
#include "ui/views/controls/textfield/textfield_controller.h"
#include "ui/views/view.h"
#include "ui/views/view_tracker.h"
namespace gfx {
class ImageSkia;
} // namespace gfx
namespace views {
class BoxLayoutView;
class ImageView;
class Label;
class Textfield;
} // namespace views
namespace ash {
class LauncherSearchIphView;
class SearchBoxImageButton;
class SearchIconImageView;
// SearchBoxViewBase consists of icons and a Textfield. The Textfiled is for
// inputting queries and triggering callbacks. The icons include a search icon,
// a close icon and a back icon for different functionalities. This class
// provides common functions for the search box view across Chrome OS.
class SearchBoxViewBase : public views::View,
public views::TextfieldController {
METADATA_HEADER(SearchBoxViewBase, views::View)
public:
SearchBoxViewBase();
SearchBoxViewBase(const SearchBoxViewBase&) = delete;
SearchBoxViewBase& operator=(const SearchBoxViewBase&) = delete;
~SearchBoxViewBase() override;
// Creates the search box close button at the right edge of the search box.
// The close button will initially be hidden. The visibility will be updated
// appropriately when `UpdateButtonsVisibility()` gets called.
views::ImageButton* CreateCloseButton(
const base::RepeatingClosure& button_callback);
// Creates `end_button_container_`, a container view that hosts one or both of
// the `assistant_button_` and `sunfish_button_`.
void CreateEndButtonContainer();
// Creates the sunfish launcher button at the right edge of the search box,
// next to the assistant button. Note that it will only be shown if the close
// button is hidden, as the buttons have the same expected position within the
// search box.
views::ImageButton* CreateSunfishButton(
const base::RepeatingClosure& button_callback);
// Creates the search box assistant button at the right edge of the search
// box. Note that the assistant button will only be shown if close button is
// hidden, as the buttons have the same expected position within the search
// box.
// The assistant button will initially be hidden. The visibility will be
// updated appropriately when `UpdateButtonsVisibility()` gets called.
views::ImageButton* CreateAssistantButton(
const base::RepeatingClosure& button_callback);
// Creates the search box assistant new entry point button at the right edge
// of the search box in LTR layout. The assistant new entry point button will
// initially be hidden. The visibility will be updated appropriately when
// `UpdateButtonsVisibility()` gets called.
views::ImageButton* CreateAssistantNewEntryPointButton(
const base::RepeatingClosure& button_callback);
// Creates the search box category filter button at the right edge of the
// search box, where clicking on it shows a bubble for the users to select
// search categories to show.
// The filter button will initially be hidden and will be shown along with the
// close button. The visibility will be updated appropriately when
// `UpdateButtonsVisibility()` gets called.
views::ImageButton* CreateFilterButton(
const base::RepeatingClosure& button_callback);
bool HasSearch() const;
// Returns the bounds to use for the view (including the shadow) given the
// desired bounds of the search box contents.
gfx::Rect GetViewBoundsForSearchBoxContentsBounds(
const gfx::Rect& rect) const;
views::ImageButton* sunfish_button();
views::ImageButton* assistant_button();
views::ImageButton* assistant_new_entry_point_button();
views::View* edge_button_container();
views::ImageButton* close_button();
views::ImageButton* filter_button();
views::View* filter_and_close_button_container();
views::ImageView* search_icon();
views::Textfield* search_box() { return search_box_; }
void SetIphView(std::unique_ptr<LauncherSearchIphView> iph_view);
LauncherSearchIphView* GetIphView();
void DeleteIphView();
// Called when the query in the search box textfield changes. The search box
// implementation is expected to handle the new query.
// `query` the new search box query.
// `initiated_by_user` whether the query changes was a result of the user
// typing.
virtual void HandleQueryChange(const std::u16string& query,
bool initiated_by_user) = 0;
// Explicitly triggers the search while keeping the same query.
void TriggerSearch();
// Sets contents for the title and category labels used for ghost text
// autocomplete.
void MaybeSetAutocompleteGhostText(const std::u16string& title,
const std::u16string& category);
std::string GetSearchBoxGhostTextForTest();
// Setting the search box active left aligns the placeholder text, changes
// the color of the placeholder text, and enables cursor blink. Setting the
// search box inactive center aligns the placeholder text, sets the color, and
// disables cursor blink.
void SetSearchBoxActive(bool active, ui::EventType event_type);
// Handles Gesture and Mouse Events sent from |search_box_|.
bool OnTextfieldEvent(ui::EventType type);
// Overridden from views::View:
gfx::Size CalculatePreferredSize(
const views::SizeBounds& available_size) const override;
void OnGestureEvent(ui::GestureEvent* event) override;
void OnMouseEvent(ui::MouseEvent* event) override;
void OnThemeChanged() override;
// Allows for search box to be notified of gestures occurring outside, without
// deactivating the searchbox.
void NotifyGestureEvent();
// Whether the search box is active.
bool is_search_box_active() const { return is_search_box_active_; }
void OnSearchBoxFocusedChanged();
// Whether the trimmed query in the search box is empty.
bool IsSearchBoxTrimmedQueryEmpty() const;
virtual void UpdateSearchTextfieldAccessibleActiveDescendantId();
void ClearSearch();
// Called when the search box active state changes.
virtual void OnSearchBoxActiveChanged(bool active);
// Updates the painting if the focus moves to or from the search box.
virtual void UpdateSearchBoxFocusPaint();
protected:
struct InitParams {
InitParams();
~InitParams();
InitParams(const InitParams&) = delete;
InitParams& operator=(const InitParams&) = delete;
// Whether to show close button if the search box is active and empty.
bool show_close_button_when_active = false;
// Whether to create a rounded-rect background.
bool create_background = true;
// Whether to animate the transition when the search icon is changed.
bool animate_changing_search_icon = false;
// Whether we should increase spacing between `search_icon_', 'search_box_',
// and the 'search_box_button_container_'.
bool increase_child_view_padding = false;
// If set, the margins that should be used for the search box text field.
std::optional<gfx::Insets> textfield_margins;
};
void Init(const InitParams& params);
// TODO(http://b/362364735): Fix close button positioning when Sunfish is
// enabled.
// Updates the visibility of the close and assistant buttons.
void UpdateButtonsVisibility();
// When necessary, starts the fade in animation for the button container.
void MaybeFadeContainerIn(views::View* container);
// When necessary, starts the fade out animation for the button container.
void MaybeFadeContainerOut(views::View* container);
// Used as a callback to set the button container's visibility to false.
void SetContainerVisibilityHidden(views::View* container);
// Overridden from views::TextfieldController:
void ContentsChanged(views::Textfield* sender,
const std::u16string& new_contents) override;
bool HandleMouseEvent(views::Textfield* sender,
const ui::MouseEvent& mouse_event) override;
bool HandleGestureEvent(views::Textfield* sender,
const ui::GestureEvent& gesture_event) override;
views::BoxLayoutView* box_layout_view() { return content_container_; }
void SetSearchBoxBackgroundCornerRadius(int corner_radius);
void SetSearchIconImage(gfx::ImageSkia image);
void SetShowAssistantButton(bool show);
void SetShowAssistantNewEntryPointButton(bool show);
void SetShowSunfishButton(bool show);
// Detects |kMousePressed| and |EventType::kGestureTap| events on the white
// background of the search box.
virtual void HandleSearchBoxEvent(ui::LocatedEvent* located_event);
// Updates the search box's background color.
void UpdateBackgroundColor(SkColor color);
// Shows/hides the virtual keyboard if the search box is active.
virtual void UpdateKeyboardVisibility() {}
// Updates the color and alignment of the placeholder text.
virtual void UpdatePlaceholderTextStyle() {}
// Update search box border based on whether the search box is activated.
virtual void UpdateSearchBoxBorder() {}
// Updates the style of the searchbox labels and textfield.
void SetPreferredStyleForAutocompleteText(const gfx::FontList& font_list,
ui::ColorId text_color_id);
void SetPreferredStyleForSearchboxText(const gfx::FontList& font_list,
ui::ColorId text_color_id);
// Initializes `filter_and_close_button_container_` if it has not already been
// done.
void MaybeCreateFilterAndCloseButtonContainer();
private:
void OnEnabledChanged();
// Owned by views hierarchy.
raw_ptr<views::BoxLayoutView> main_container_;
raw_ptr<views::BoxLayoutView> content_container_;
raw_ptr<SearchIconImageView> search_icon_ = nullptr;
raw_ptr<SearchBoxImageButton> assistant_button_ = nullptr;
raw_ptr<SearchBoxImageButton> assistant_new_entry_point_button_ = nullptr;
raw_ptr<SearchBoxImageButton> sunfish_button_ = nullptr;
raw_ptr<SearchBoxImageButton> close_button_ = nullptr;
raw_ptr<SearchBoxImageButton> filter_button_ = nullptr;
raw_ptr<views::BoxLayoutView> end_button_container_ = nullptr;
raw_ptr<views::BoxLayoutView> filter_and_close_button_container_ = nullptr;
raw_ptr<views::BoxLayoutView> text_container_ = nullptr;
raw_ptr<views::Textfield> search_box_;
raw_ptr<views::BoxLayoutView> ghost_text_container_ = nullptr;
raw_ptr<views::Label> separator_label_ = nullptr;
raw_ptr<views::Label> autocomplete_ghost_text_ = nullptr;
raw_ptr<views::Label> category_separator_label_ = nullptr;
raw_ptr<views::Label> category_ghost_text_ = nullptr;
raw_ptr<views::View> search_box_button_container_ = nullptr;
views::ViewTracker iph_view_tracker_;
// Whether the search box is active.
bool is_search_box_active_ = false;
// Whether to show close button if the search box is active and empty.
bool show_close_button_when_active_ = false;
// Whether to show assistant button.
bool show_assistant_button_ = false;
// Whether to show assistant new entry point button.
bool show_assistant_new_entry_point_button_ = false;
// Whether to show sunfish button.
bool show_sunfish_button_ = false;
base::CallbackListSubscription enabled_changed_subscription_ =
AddEnabledChangedCallback(
base::BindRepeating(&SearchBoxViewBase::OnEnabledChanged,
base::Unretained(this)));
base::WeakPtrFactory<SearchBoxViewBase> weak_factory_{this};
};
} // namespace ash
#endif // ASH_SEARCH_BOX_SEARCH_BOX_VIEW_BASE_H_