1 // Copyright 2019 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 #ifndef ASH_STYLE_ASH_COLOR_PROVIDER_H_
6 #define ASH_STYLE_ASH_COLOR_PROVIDER_H_
7 
8 #include "ash/ash_export.h"
9 #include "ash/public/cpp/session/session_observer.h"
10 #include "base/observer_list.h"
11 #include "third_party/skia/include/core/SkColor.h"
12 #include "ui/gfx/color_palette.h"
13 #include "ui/gfx/vector_icon_types.h"
14 
15 class PrefChangeRegistrar;
16 class PrefRegistrySimple;
17 class PrefService;
18 
19 namespace views {
20 class ImageButton;
21 class LabelButton;
22 }  // namespace views
23 
24 namespace ash {
25 class ColorModeObserver;
26 
27 // The color provider for system UI. It provides colors for Shield layer, Base
28 // layer, Controls layer and Content layer. Shield layer is a combination of
29 // color, opacity and blur which may change depending on the context, it is
30 // usually a fullscreen layer. e.g, PowerButtoneMenuScreenView for power button
31 // menu. Base layer is the bottom layer of any UI displayed on top of all other
32 // UIs. e.g, the ShelfView that contains all the shelf items. Controls layer is
33 // where components such as icons and inkdrops lay on, it may also indicate the
34 // state of an interactive element (active/inactive states). Content layer means
35 // the UI elements, e.g., separator, text, icon. The color of an element in
36 // system UI will be the combination of the colors of the four layers.
37 class ASH_EXPORT AshColorProvider : public SessionObserver {
38  public:
39   // Types of Shield layer. Number at the end of each type indicates the alpha
40   // value.
41   enum class ShieldLayerType {
42     kShield20 = 0,
43     kShield40,
44     kShield60,
45     kShield80,
46     kShield90,
47   };
48 
49   // Blur sigma for system UI layers.
50   enum class LayerBlurSigma {
51     kBlurDefault = 30,  // Default blur sigma is 30.
52     kBlurSigma20 = 20,
53     kBlurSigma10 = 10,
54   };
55 
56   // Types of Base layer.
57   enum class BaseLayerType {
58     // Number at the end of each transparent type indicates the alpha value.
59     kTransparent20 = 0,
60     kTransparent40,
61     kTransparent60,
62     kTransparent80,
63     kTransparent90,
64 
65     // Base layer is opaque.
66     kOpaque,
67   };
68 
69   // Types of Controls layer.
70   enum class ControlsLayerType {
71     kHairlineBorderColor,
72     kControlBackgroundColorActive,
73     kControlBackgroundColorInactive,
74     kControlBackgroundColorAlert,
75     kControlBackgroundColorWarning,
76     kControlBackgroundColorPositive,
77     kFocusAuraColor,
78     kFocusRingColor,
79   };
80 
81   enum class ContentLayerType {
82     kSeparatorColor,
83 
84     kTextColorPrimary,
85     kTextColorSecondary,
86     kTextColorAlert,
87     kTextColorWarning,
88     kTextColorPositive,
89 
90     kIconColorPrimary,
91     kIconColorSecondary,
92     kIconColorAlert,
93     kIconColorWarning,
94     kIconColorPositive,
95     // Color for prominent icon, e.g, "Add connection" icon button inside
96     // VPN detailed view.
97     kIconColorProminent,
98 
99     // The default color for button labels.
100     kButtonLabelColor,
101     kButtonLabelColorPrimary,
102 
103     // Color for blue button labels, e.g, 'Retry' button of the system toast.
104     kButtonLabelColorBlue,
105 
106     kButtonIconColor,
107     kButtonIconColorPrimary,
108 
109     // Color for app state indicator.
110     kAppStateIndicatorColor,
111     kAppStateIndicatorColorInactive,
112 
113     // Color for the shelf drag handle in tablet mode.
114     kShelfHandleColor,
115 
116     // Color for slider.
117     kSliderColorActive,
118     kSliderColorInactive,
119 
120     // Color for radio button.
121     kRadioColorActive,
122     kRadioColorInactive,
123 
124     // Color for current active desk's border.
125     kCurrentDeskColor,
126   };
127 
128   // Attributes of ripple, includes the base color, opacity of inkdrop and
129   // highlight.
130   struct RippleAttributes {
RippleAttributesRippleAttributes131     RippleAttributes(SkColor color,
132                      float opacity_of_inkdrop,
133                      float opacity_of_highlight)
134         : base_color(color),
135           inkdrop_opacity(opacity_of_inkdrop),
136           highlight_opacity(opacity_of_highlight) {}
137     const SkColor base_color;
138     const float inkdrop_opacity;
139     const float highlight_opacity;
140   };
141 
142   AshColorProvider();
143   AshColorProvider(const AshColorProvider& other) = delete;
144   AshColorProvider operator=(const AshColorProvider& other) = delete;
145   ~AshColorProvider() override;
146 
147   static AshColorProvider* Get();
148 
149   // Gets the disabled color on |enabled_color|. It can be disabled background,
150   // an disabled icon, etc.
151   static SkColor GetDisabledColor(SkColor enabled_color);
152 
153   // Gets the color of second tone on the given |color_of_first_tone|. e.g,
154   // power status icon inside status area is a dual tone icon.
155   static SkColor GetSecondToneColor(SkColor color_of_first_tone);
156 
157   static void RegisterProfilePrefs(PrefRegistrySimple* registry);
158 
159   // SessionObserver:
160   void OnActiveUserPrefServiceChanged(PrefService* prefs) override;
161   void OnSessionStateChanged(session_manager::SessionState state) override;
162 
163   SkColor GetShieldLayerColor(ShieldLayerType type) const;
164   SkColor GetBaseLayerColor(BaseLayerType type) const;
165   SkColor GetControlsLayerColor(ControlsLayerType type) const;
166   SkColor GetContentLayerColor(ContentLayerType type) const;
167 
168   // Gets the attributes of ripple on |bg_color|. |bg_color| is the background
169   // color of the UI element that wants to show inkdrop. Applies the color from
170   // GetBackgroundColor if |bg_color| is not given. This means the background
171   // color of the UI element is from Shiled or Base layer. See
172   // GetShieldLayerColor and GetBaseLayerColor.
173   RippleAttributes GetRippleAttributes(
174       SkColor bg_color = gfx::kPlaceholderColor) const;
175 
176   // Gets the background color that can be applied on any layer. The returned
177   // color will be different based on color mode and color theme (see
178   // |is_themed_|).
179   SkColor GetBackgroundColor() const;
180 
181   // Helpers to style different types of buttons. Depending on the type may
182   // style text, icon and background colors for both enabled and disabled
183   // states. May overwrite an prior styles on |button|.
184   void DecoratePillButton(views::LabelButton* button,
185                           const gfx::VectorIcon* icon);
186   void DecorateCloseButton(views::ImageButton* button,
187                            int button_size,
188                            const gfx::VectorIcon& icon);
189   void DecorateIconButton(views::ImageButton* button,
190                           const gfx::VectorIcon& icon,
191                           bool toggled,
192                           int icon_size);
193   void DecorateFloatingIconButton(views::ImageButton* button,
194                                   const gfx::VectorIcon& icon);
195 
196   void AddObserver(ColorModeObserver* observer);
197   void RemoveObserver(ColorModeObserver* observer);
198 
199   // True if pref |kDarkModeEnabled| is true, which means the current color mode
200   // is dark.
201   bool IsDarkModeEnabled() const;
202 
203   // Whether the system color mode is themed, by default is true. If true, the
204   // background color will be calculated based on extracted wallpaper color.
205   bool IsThemed() const;
206 
207   // Toggles pref |kDarkModeEnabled|.
208   void ToggleColorMode();
209 
210   // Updates pref |kColorModeThemed| to |is_themed|.
211   void UpdateColorModeThemed(bool is_themed);
212 
213  private:
214   friend class ScopedLightModeAsDefault;
215 
216   // Gets the background default color.
217   SkColor GetBackgroundDefaultColor() const;
218 
219   // Gets the background themed color that's calculated based on the color
220   // extracted from wallpaper. For dark mode, it will be dark muted wallpaper
221   // prominent color + SK_ColorBLACK 50%. For light mode, it will be light
222   // muted wallpaper prominent color + SK_ColorWHITE 75%.
223   SkColor GetBackgroundThemedColor() const;
224 
225   // Notifies all the observers on |kDarkModeEnabled|'s change.
226   void NotifyDarkModeEnabledPrefChange();
227 
228   // Notifies all the observers on |kColorModeThemed|'s change.
229   void NotifyColorModeThemedPrefChange();
230 
231   // Default color mode is dark, which is controlled by pref |kDarkModeEnabled|
232   // currently. But we can also override it to light through
233   // ScopedLightModeAsDefault. This is done to help keeping some of the UI
234   // elements as light by default before launching dark/light mode. Overriding
235   // only if the kDarkLightMode feature is disabled. This variable will be
236   // removed once enabled dark/light mode.
237   bool override_light_mode_as_default_ = false;
238 
239   base::ObserverList<ColorModeObserver> observers_;
240   std::unique_ptr<PrefChangeRegistrar> pref_change_registrar_;
241   PrefService* active_user_pref_service_ = nullptr;  // Not owned.
242 };
243 
244 }  // namespace ash
245 
246 #endif  // ASH_STYLE_ASH_COLOR_PROVIDER_H_
247