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
ash / system / progress_indicator / progress_indicator.h [blame]
// Copyright 2021 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_PROGRESS_INDICATOR_PROGRESS_INDICATOR_H_
#define ASH_SYSTEM_PROGRESS_INDICATOR_PROGRESS_INDICATOR_H_
#include <memory>
#include <optional>
#include <vector>
#include "ash/ash_export.h"
#include "ash/system/progress_indicator/progress_indicator_animation_registry.h"
#include "base/callback_list.h"
#include "base/memory/raw_ptr.h"
#include "ui/color/color_provider.h"
#include "ui/compositor/layer_delegate.h"
#include "ui/compositor/layer_owner.h"
namespace ash {
class ProgressIconAnimation;
class ProgressRingAnimation;
// A class owning a `ui::Layer` which paints indication of progress.
// NOTE: The owned `layer()` is not painted if progress == `1.f`, but we can
// paint the `layer()` by setting the progress back to `kForcedShow`.
class ASH_EXPORT ProgressIndicator : public ui::LayerOwner,
public ui::LayerDelegate {
public:
static constexpr char kClassName[] = "ProgressIndicator";
static constexpr float kProgressComplete = 1.f;
static constexpr float kForcedShow = 0.999999f;
ProgressIndicator(const ProgressIndicator&) = delete;
ProgressIndicator& operator=(const ProgressIndicator&) = delete;
~ProgressIndicator() override;
// Returns an instance which paints indication of progress returned by the
// specified `progress_callback`. NOTE: This instance comes pre-wired with an
// `animation_registry_` that will manage progress animations as needed.
static std::unique_ptr<ProgressIndicator> CreateDefaultInstance(
base::RepeatingCallback<std::optional<float>()> progress_callback);
// Adds the specified `callback` to be notified of `progress_` changes. The
// `callback` will continue to receive events so long as both `this` and the
// returned subscription exist.
base::CallbackListSubscription AddProgressChangedCallback(
base::RepeatingClosureList::CallbackType callback);
// Creates and returns the `layer()` which is owned by this progress
// indicator. Note that this may only be called if `layer()` does not exist.
using ColorResolver = base::RepeatingCallback<SkColor(ui::ColorId)>;
ui::Layer* CreateLayer(ColorResolver color_resolver);
// Destroys the `layer()` which is owned by this progress indicator. Note that
// this will no-op if `layer()` does not exist.
void DestroyLayer();
// Invoke to schedule repaint of the entire `layer()`.
void InvalidateLayer();
// Sets the `color_id` to use in lieu of the default when painting progress
// indication. If `color_id` is absent, default colors are used.
void SetColorId(const std::optional<ui::ColorId>& color_id);
// Sets the visibility for this progress indicator's inner icon. Note that
// the inner icon will only be painted while `progress_` is incomplete,
// regardless of the value of `visible` provided.
void SetInnerIconVisible(bool visible);
bool inner_icon_visible() const { return inner_icon_visible_; }
// Sets the visibility for this progress indicator's inner ring. Note that
// the inner ring will only be painted while `progress_` is incomplete,
// regardless of the value of `visible` provided.
void SetInnerRingVisible(bool visible);
// Sets the visibility of the progress indicator's outer ring track. Note that
// the track will only be painted while `progress_` is incomplete, regardless
// of the value of `visible` provided.
void SetOuterRingTrackVisible(bool visible);
// Sets the width for this progress indicator's outer ring stroke.
void SetOuterRingStrokeWidth(float width);
// Returns the underlying `animation_registry_` in which to look up animations
// for the associated `animation_key_`. NOTE: This may return `nullptr`.
ProgressIndicatorAnimationRegistry* animation_registry() {
return animation_registry_;
}
// Returns the `animation_key_` for which to look up animations in the
// underlying `animation_registry_`. NOTE: This may return `nullptr`.
ProgressIndicatorAnimationRegistry::AnimationKey animation_key() const {
return animation_key_;
}
// Returns the underlying `progress_` for which to paint indication.
// NOTE: If absent, progress is indeterminate.
// NOTE: If present, progress must be >= `0.f` and <= `1.f`.
const std::optional<float>& progress() const { return progress_; }
protected:
// Each progress indicator is associated with an `animation_key_` which is
// used to look up animations in the provided `animation_registry`. When an
// animation exists, it will be painted in lieu of the determinate progress
// indication that would otherwise be painted for the cached `progress_`.
// NOTE: `animation_registry` may be `nullptr` if animations are not needed.
ProgressIndicator(
ProgressIndicatorAnimationRegistry* animation_registry,
ProgressIndicatorAnimationRegistry::AnimationKey animation_key);
// Returns the calculated progress to paint to the owned `layer()`. This is
// invoked during `UpdateVisualState()` just prior to painting.
// NOTE: If absent, progress is indeterminate.
// NOTE: If present, progress must be >= `0.f` and <= `1.f`.
// NOTE: If progress == `1.f`, progress is complete and will not be painted.
virtual std::optional<float> CalculateProgress() const = 0;
private:
// ui::LayerDelegate:
void OnDeviceScaleFactorChanged(float old_scale, float new_scale) override;
void OnPaintLayer(const ui::PaintContext& context) override;
void UpdateVisualState() override;
// Invoked when the icon `animation` associated with this progress indicator's
// `animation_key_` has changed in the `animation_registry_`.
// NOTE: The specified `animation` may be `nullptr`.
void OnProgressIconAnimationChanged(ProgressIconAnimation* animation);
// Invoked when the ring `animation` associated with this progress indicator's
// `animation_key_` has changed in the `animation_registry_`.
// NOTE: The specified `animation` may be `nullptr`.
void OnProgressRingAnimationChanged(ProgressRingAnimation* animation);
// The animation registry in which to look up animations for the associated
// `animation_key_`. When an animation exists, it will be painted in lieu of
// the determinate progress indication that would otherwise be painted for the
// cached `progress_`.
const raw_ptr<ProgressIndicatorAnimationRegistry, DanglingUntriaged>
animation_registry_;
// The key for which to look up animations in the `animation_registry_`.
// When an animation exists, it will be painted in lieu of the determinate
// progress indication that would otherwise be painted for the cached
// `progress_`.
const ProgressIndicatorAnimationRegistry::AnimationKey animation_key_;
// A subscription to receive events when the icon animation associated with
// this progress indicator's `animation_key_` has changed in the
// `animation_registry_`.
base::CallbackListSubscription icon_animation_changed_subscription_;
// A subscription to receive events on updates to the icon animation owned by
// the `animation_registry_` which is associated with this progress
// indicator's `animation_key_`. On icon animation update, the progress
// indicator will `InvalidateLayer()` to trigger paint of the next animation
// frame.
base::CallbackListSubscription icon_animation_updated_subscription_;
// A subscription to receive events when the ring animation associated with
// this progress indicator's `animation_key_` has changed in the
// `animation_registry_`.
base::CallbackListSubscription ring_animation_changed_subscription_;
// A subscription to receive events on updates to the ring animation owned by
// the `animation_registry_` which is associated with this progress
// indicator's `animation_key_`. On ring animation update, the progress
// indicator will `InvalidateLayer()` to trigger paint of the next animation
// frame.
base::CallbackListSubscription ring_animation_updated_subscription_;
// Used to resolve the color to use to paint progress indication. Non-null if
// and only if the `layer()` which is owned by this progress indicator exists.
ColorResolver color_resolver_;
// The color ID to use in lieu of the default when painting progress
// indication. If absent, default colors are used.
std::optional<ui::ColorId> color_id_;
// Cached progress returned from `CalculateProgress()` just prior to painting.
// NOTE: If absent, progress is indeterminate.
// NOTE: If present, progress must be >= `0.f` and <= `1.f`.
std::optional<float> progress_ = kProgressComplete;
// The list of callbacks for which to notify `progress_` changes.
base::RepeatingClosureList progress_changed_callback_list_;
// Whether this progress indicator's inner icon is visible. Note that the
// inner icon will only be painted while `progress_` is incomplete, regardless
// of this value.
bool inner_icon_visible_ = true;
// Whether this progress indicator's inner ring is visible. Note that the
// inner ring will only be painted while `progress_` is incomplete, regardless
// of this value.
bool inner_ring_visible_ = true;
// Whether this progress indicator's outer ring track is visible. Note that
// the track will only be painted while `progress_` is incomplete, regardless
// of this value.
bool outer_ring_track_visible_ = false;
// The width for the outer ring stroke.
std::optional<float> outer_ring_stroke_width_;
};
} // namespace ash
#endif // ASH_SYSTEM_PROGRESS_INDICATOR_PROGRESS_INDICATOR_H_