File: feature_tile.h

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (378 lines) | stat: -rw-r--r-- 15,930 bytes parent folder | download | duplicates (6)
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
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
// Copyright 2022 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_SYSTEM_UNIFIED_FEATURE_TILE_H_
#define ASH_SYSTEM_UNIFIED_FEATURE_TILE_H_

#include "ash/ash_export.h"
#include "base/functional/callback_forward.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "base/observer_list_types.h"
#include "ui/base/metadata/metadata_header_macros.h"
#include "ui/color/color_id.h"
#include "ui/views/background.h"
#include "ui/views/controls/button/button.h"

namespace gfx {
struct VectorIcon;
class Insets;
}  // namespace gfx

namespace views {
class FlexLayoutView;
class ImageButton;
class ImageView;
class InkDropContainerView;
class Label;
}  // namespace views

namespace ash {

// The main button used in FeatureTilesContainerView, which acts as an entry
// point for features in QuickSettingsView.
//
// Note: Once http://b/298692153 is complete then this will be the type of tile
// used in the VC controls bubble as well.
//
// There are two TileTypes: Primary and Compact.
//
// The primary tile has an icon and title, and may have a subtitle. The icon may
// or may not be separately clickable. The tile has one of the following
// behaviors:
// 1. Launch surface        (e.g. Screen Capture)
// 2. Toggle                (e.g. Toggle Dark Theme)
// 3. Drill-in              (e.g. Go to Accessibility detailed view)
// 4. Toggle with drill-in  (e.g. Toggle Wi-Fi | Go to Network details)
// 5. Togglable tile with decorative drill-in (e.g. Selecting a VPN network)
//
// The compact tile has an icon and a single title, which may be
// multi-line. They are always placed in pairs side by side to take up the
// space of a regular FeatureTile. Regular tiles may switch to their compact
// version when necessary, e.g. when entering TabletMode. It presents one
// of the following behaviors:
// 1. Launch surface        (e.g. Screen Capture)
// 2. Toggle                (e.g. Toggle Auto-rotate)
// 3. Drill-in              (e.g. Go to Cast detailed view)
//
// Support for download UI is in the process of being added. This will allow a
// compact tile to indicate the progress of a download it is associated with.
// The initial use-case will be DLC downloading for the "Live caption" feature
// tile in the VC controls bubble, though the API for setting download state
// should be general enough that it can be used for anything download-related.
// See http://b/298692153 for details.
class ASH_EXPORT FeatureTile : public views::Button {
  METADATA_HEADER(FeatureTile, views::Button)

 public:
  // Used in the FeatureTile constructor to set the tile view type.
  enum class TileType {
    kPrimary = 0,
    kCompact = 1,
    kMaxValue = kCompact,
  };

  // The possible states the download progress UI can be in. The download
  // progress UI is currently only supported for compact tiles.
  //
  // TODO(b/315188874): Add full support for all download states.
  enum class DownloadState {
    kNone,         // The default state, e.g. this tile is not associated
                   // with a download. If this tile is of type
                   // `TileType::kPrimary` then it should always be in this
                   // download state.
    kPending,      // The download has not yet started. The tile's label is
                   // changed to "Download pending". The tile is not
                   // interactable while in this state.
    kDownloading,  // The download is in progress. The tile's label is changed
                   // to "Downloading X%" and a download progress indicator is
                   // made visible. The tile is not interactable while in this
                   // state.
    kDownloaded,   // The download finished successfully.
    kError,        // The download finished with an error. The tile is not
                   // interactable while in this state.
  };

  // Constructor for FeatureTiles. `callback` will be called when interacting
  // with the main part of the button, which accounts for the whole tile.
  // If the icon is not separately clickable (the default), `callback` will
  // also be called when clicking on the icon.
  explicit FeatureTile(PressedCallback callback,
                       bool is_togglable = true,
                       TileType type = TileType::kPrimary);
  FeatureTile(const FeatureTile&) = delete;
  FeatureTile& operator=(const FeatureTile&) = delete;
  ~FeatureTile() override;

  // Implement this class to get notified of certain state changes to this tile.
  // Currently this only exists for testing purposes.
  class Observer : public base::CheckedObserver {
   public:
    // Called when this tile's download state changes. `download_state` is the
    // new download state, and `progress` is the new download progress
    // (currently only meaningful when the download state is
    // `DownloadState::kDownloading`).
    virtual void OnDownloadStateChanged(DownloadState download_state,
                                        int progress) = 0;
  };

  // Adds/removes an observer of this tile.
  void AddObserver(Observer* observer);
  void RemoveObserver(Observer* observer);

  // Sets whether the icon on the left is clickable, separate from clicking on
  // the tile itself. Use SetIconClickCallback() to set the callback. This
  // function is separate from SetIconClickCallback() because it's likely that
  // FeatureTile users will want to set the callback once but may want to switch
  // the icon between being clickable or not (e.g. the network icon based on
  // Ethernet vs. Wi-Fi).
  void SetIconClickable(bool clickable);

  // Sets the `callback` for clicks on `icon_button_`.
  void SetIconClickCallback(base::RepeatingCallback<void()> callback);

  // Sets the `on_title_container_bounds_changed_` callback.
  void SetOnTitleBoundsChangedCallback(
      base::RepeatingCallback<void()> callback);

  // Creates a decorative `drill_in_arrow_` on the right side of the tile. This
  // indicates to the user that the tile shows a detailed view when pressed.
  void CreateDecorativeDrillInArrow();

  // Updates the colors of the background and elements of the button.
  void UpdateColors();

  // Updates the `toggled_` state of the tile. If the tile is not togglable,
  // `toggled_` will always be false.
  void SetToggled(bool toggled);
  bool IsToggled() const;

  // Sets the vector icon.
  void SetVectorIcon(const gfx::VectorIcon& icon);

  // Sets margins for 'title_container_' in the tile.
  void SetTitleContainerMargins(const gfx::Insets& insets);

  // Setters to apply custom background colors.
  void SetBackgroundColorId(ui::ColorId background_color_id);
  void SetBackgroundToggledColorId(ui::ColorId background_toggled_color_id);
  void SetBackgroundDisabledColorId(ui::ColorId background_disabled_color_id);

  // Sets the radius determining the tile's curved edges.
  void SetButtonCornerRadius(const int radius);

  // Setters to apply custom foreground colors.
  void SetForegroundColorId(ui::ColorId foreground_color_id);
  void SetForegroundToggledColorId(ui::ColorId foreground_toggled_color_id);
  void SetForegroundDisabledColorId(ui::ColorId foreground_disabled_color_id);
  void SetForegroundOptionalColorId(ui::ColorId foreground_optional_color_id);
  void SetForegroundOptionalToggledColorId(
      ui::ColorId foreground_optional_toggled_color_id);

  // Sets a custom color for the tile's ink drop, when its toggled.
  void SetInkDropToggledBaseColorId(ui::ColorId ink_drop_toggled_base_color_id);

  // Sets the tile icon from an ImageSkia.
  void SetImage(gfx::ImageSkia image);

  // Sets the tooltip text of `icon_button_`.
  void SetIconButtonTooltipText(const std::u16string& text);

  // Sets the text of `label_`. If `VcDlcUi` is enabled and there is an on-going
  // download associated with this tile then the new label won't be reflected in
  // the UI until the download finishes. Also note that download-related labels
  // (like "Downloading 7%" or "Download pending") should not be specified using
  // this method - those labels are automatically set when the download state
  // changes.
  void SetLabel(const std::u16string& label);

  // Returns the maximum width for `sub_label_`.
  int GetSubLabelMaxWidth() const;

  // Sets the text of the `sub_label_`.
  void SetSubLabel(const std::u16string& sub_label);

  // Sets visibility of `sub_label_`.
  void SetSubLabelVisibility(bool visible);

  // Sets the state of this tile's download progress UI. See the documentation
  // for the `DownloadState` enum for more details on how a particular download
  // state affects the tile. `progress` is an integer in the range [0, 100], and
  // is ignored when `state` is not `DownloadState::kDownloading`.
  void SetDownloadState(DownloadState state, int progress);

  // views::View:
  void AddLayerToRegion(ui::Layer* layer, views::LayerRegion region) override;
  void RemoveLayerFromRegions(ui::Layer* layer) override;

  // views::ViewObserver:
  void OnViewBoundsChanged(views::View* observed_view) override;

  base::WeakPtr<FeatureTile> GetWeakPtr() {
    return weak_ptr_factory_.GetWeakPtr();
  }

  TileType tile_type() { return type_; }
  bool is_icon_clickable() const { return is_icon_clickable_; }
  views::ImageButton* icon_button() { return icon_button_; }
  views::Label* label() { return label_; }
  views::Label* sub_label() { return sub_label_; }
  views::ImageView* drill_in_arrow() { return drill_in_arrow_; }
  int corner_radius() const { return corner_radius_; }

  DownloadState download_state_for_testing() const { return download_state_; }
  int download_progress_for_testing() const {
    return download_progress_percent_;
  }

 private:
  friend class BluetoothFeaturePodControllerTest;
  friend class HotspotFeaturePodControllerTest;
  friend class NotificationCounterViewTest;

  // A `views::Background` that visually indicates download progress.
  // Automatically handles both LTR and RTL layouts.
  class ProgressBackground : public views::Background {
   public:
    ProgressBackground(ui::ColorId progress_color_id,
                       ui::ColorId background_color_id);
    ProgressBackground(const ProgressBackground&) = delete;
    ProgressBackground& operator=(const ProgressBackground&) = delete;
    ~ProgressBackground() override = default;

    // views::Background:
    void Paint(gfx::Canvas* canvas, views::View* view) const override;

   private:
    // The `ui::ColorId`s for both the progress- and non-progress-(i.e.
    // "background-") portions of the background.
    const ui::ColorId progress_color_id_;
    const ui::ColorId background_color_id_;
  };

  // views::Button:
  void OnSetTooltipText(const std::u16string& tooltip_text) override;

  // Creates child views of Feature Tile. The constructed view will vary
  // depending on the button's `type_`.
  void CreateChildViews();

  // Returns the color id to use for the `icon_button_` and `drill_in_arrow_`
  // based on the tile's enabled and toggled state.
  ui::ColorId GetIconColorId() const;

  // Updates the ink drop hover color and ripple color for `icon_button_`.
  void UpdateIconButtonRippleColors();

  // Updates the focus ring color for `icon_button_` for better visibility.
  void UpdateIconButtonFocusRingColor();

  // Updates the color of `drill_in_arrow_` for better visibility.
  void UpdateDrillInArrowColor();

  // Updates the accessibility properties directly in the cache, like the role
  // and the toggle state.
  void UpdateAccessibilityProperties();

  // Updates `label_` attributes depending on whether a sub-label will be
  // visible.
  void SetCompactTileLabelPreferences(bool has_sub_label);

  // Sets the tile's label to its download-related version (e.g. "Downloading
  // 7%" or "Download pending"). This is different from `SetLabel()` because
  // `SetLabel()` is intended to be used externally for setting the tile's
  // non-download-related label (i.e. the "client-specified" label), whereas
  // this method is only used internally by this class to temporarily switch to
  // a different label during download. An optional tooltip can be included if
  // the tooltip should differ from the `download_label`.
  void SetDownloadLabel(const std::u16string& download_label,
                        std::optional<std::u16string> tooltip = std::nullopt);

  // Updates the tile's label according to the current download state. Note that
  // this method assumes the download-related state (e.g. `download_state_` and
  // `download_progress_percent_`) is current, so it is up to the client to
  // perform any download-related state changes prior to calling this.
  void UpdateLabelForDownloadState();

  // Notifies all observers of this tile's current download state. Should only
  // be called when the download state actually changes.
  void NotifyDownloadStateChanged();

  // A list of this tile's observers.
  base::ObserverList<Observer> observers_;

  // Ensures the ink drop is painted above the button's background.
  raw_ptr<views::InkDropContainerView> ink_drop_container_ = nullptr;

  // The vector icon for the tile, if one is set.
  raw_ptr<const gfx::VectorIcon> vector_icon_ = nullptr;

  // Customized value for the tile's background color and foreground color.
  std::optional<ui::ColorId> background_color_;
  std::optional<ui::ColorId> background_toggled_color_;
  std::optional<ui::ColorId> background_disabled_color_;
  std::optional<ui::ColorId> foreground_color_;
  std::optional<ui::ColorId> foreground_toggled_color_;
  std::optional<ui::ColorId> foreground_optional_color_;
  std::optional<ui::ColorId> foreground_optional_toggled_color_;
  std::optional<ui::ColorId> foreground_disabled_color_;

  // Customized value for the tile's ink drop color.
  std::optional<ui::ColorId> ink_drop_toggled_base_color_;

  // Owned by views hierarchy.
  raw_ptr<views::ImageButton> icon_button_ = nullptr;
  raw_ptr<views::Label> label_ = nullptr;
  raw_ptr<views::Label> sub_label_ = nullptr;
  raw_ptr<views::ImageView> drill_in_arrow_ = nullptr;
  raw_ptr<views::FlexLayoutView> title_container_ = nullptr;

  // The radius of the tile's curved edges.
  int corner_radius_;

  // Whether the icon is separately clickable.
  bool is_icon_clickable_ = false;

  // Whether this button is togglable.
  const bool is_togglable_ = false;

  // Whether the button is currently toggled.
  bool toggled_ = false;

  // The non-download-related (a.k.a. "client-specified") text of this tile's
  // label/tooltip. The tile's label/tooltip may change when its downloading
  // state changes, so this is used to store the original, client-specified
  // label/tooltip for later reference (e.g. when a download finishes and the
  // tile needs to show the original label again).
  std::u16string client_specified_label_text_;
  std::u16string client_specified_tooltip_text_;

  // The type of the feature tile that determines how it lays out its view.
  TileType type_;

  // Used to update tile colors and to set the drill-in button enabled state
  // when the button state changes.
  base::CallbackListSubscription enabled_changed_subscription_;

  // The download state this tile is in. A tile is not associated with a
  // download by default.
  DownloadState download_state_ = DownloadState::kNone;

  // True when `UpdateLabelForDownloadState()` is happening.
  bool updating_download_state_labels_ = false;

  // The download progress, as an integer percentage in the range [0, 100]. Only
  // has meaning when the tile is in an active download state.
  int download_progress_percent_ = 0;

  // Runs when `title_container_`'s bounds is changed.
  base::RepeatingClosure on_title_container_bounds_changed_;

  base::WeakPtrFactory<FeatureTile> weak_ptr_factory_{this};
};

}  // namespace ash

#endif  // ASH_SYSTEM_UNIFIED_FEATURE_TILE_H_