OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | |
Peter Kasting
2017/05/06 02:23:09
Any way to get this to appear as a moved file w/di
emx
2017/05/09 16:26:52
I don't believe so. Git decides automatically whet
Peter Kasting
2017/05/09 17:40:28
In that case I'd suggest doing the file rename as
emx
2017/05/10 17:38:48
OK, I've made it a separate CL.
| |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "chrome/browser/ui/views/profiles/avatar_button.h" | |
6 | |
7 #include <utility> | |
8 | |
9 #include "chrome/app/vector_icons/vector_icons.h" | |
10 #include "chrome/browser/browser_process.h" | |
11 #include "chrome/browser/profiles/profile_manager.h" | |
12 #include "chrome/browser/profiles/profiles_state.h" | |
13 #include "chrome/browser/signin/signin_manager_factory.h" | |
14 #include "chrome/browser/themes/theme_service.h" | |
15 #include "chrome/browser/themes/theme_service_factory.h" | |
16 #include "chrome/grit/theme_resources.h" | |
17 #include "components/signin/core/browser/signin_manager.h" | |
18 #include "ui/base/resource/resource_bundle.h" | |
19 #include "ui/gfx/color_palette.h" | |
20 #include "ui/gfx/paint_vector_icon.h" | |
21 #include "ui/views/animation/flood_fill_ink_drop_ripple.h" | |
22 #include "ui/views/animation/ink_drop_impl.h" | |
23 #include "ui/views/controls/button/label_button_border.h" | |
24 | |
25 #if defined(OS_WIN) | |
26 #include "base/win/windows_version.h" | |
27 #endif | |
28 | |
29 namespace { | |
30 | |
31 const int kThemedButtonHeight = 20; | |
Peter Kasting
2017/05/06 02:23:08
Nit: Prefer constexpr to const for compile-time co
emx
2017/05/09 16:26:52
Done.
| |
32 | |
33 const int kMdButtonMinWidth = 48; | |
Peter Kasting
2017/05/06 02:23:08
Should these values be computed based on average c
emx
2017/05/09 16:26:52
The minimum width should be the caption button wid
Peter Kasting
2017/05/09 17:40:29
Implementation-wise, the spec is a design suggesti
emx
2017/05/10 17:38:49
OK, let's wait for Alan to reply to the email.
Peter Kasting
2017/05/11 01:03:42
If he doesn't get back with something quickly, I w
| |
34 const int kMdButtonMaxWidth = 96; | |
35 // Height of the "cozy" MD button that slides over the tabstrip | |
Peter Kasting
2017/05/06 02:23:09
Nit: Can avoid the term "Cozy" and just talk about
emx
2017/05/09 16:26:52
Done.
| |
36 // ("tall" MD button height is computed) | |
37 const int kMdButtonCozyHeight = 20; | |
38 const int kMdButtonIconHeight = 16; | |
Peter Kasting
2017/05/06 02:23:09
This height differs slightly from the 20 DIP heigh
emx
2017/05/09 16:26:52
The spec clearly says 16 and it looks fine to me.
Peter Kasting
2017/05/09 17:40:29
See comment earlier about specs being suggestions
emx
2017/05/10 17:38:48
So if the spec is a suggestion, then who actually
Peter Kasting
2017/05/11 01:03:43
It's collaborative, ultimately -- UI Review has fi
emx
2017/05/11 12:56:10
Thanks for the detailed explanation. I agree with
| |
39 const SkColor kMdButtonIconColor = SkColorSetA(SK_ColorBLACK, 0.54 * 0xFF); | |
Peter Kasting
2017/05/06 02:23:09
These kinds of one-off constants (for opacity here
emx
2017/05/09 16:26:52
The highlight opacity of 0.08 is in the spec. Whet
Peter Kasting
2017/05/09 17:40:28
The way I would start is to come back to Alan and
| |
40 // Opacity of the ink drop on hover | |
41 const float kInkDropHighlightOpacity = 0.08f; | |
42 // Opacity of the ink drop on click, which is added to kInkDropHighlightOpacity | |
43 const float kInkDropRippleOpacity = 0.04f; | |
44 | |
45 std::unique_ptr<views::Border> CreateThemedBorder( | |
46 const int normal_image_set[], | |
47 const int hot_image_set[], | |
48 const int pushed_image_set[]) { | |
49 std::unique_ptr<views::LabelButtonAssetBorder> border( | |
50 new views::LabelButtonAssetBorder(views::Button::STYLE_TEXTBUTTON)); | |
51 | |
52 border->SetPainter(false, views::Button::STATE_NORMAL, | |
53 views::Painter::CreateImageGridPainter(normal_image_set)); | |
54 border->SetPainter(false, views::Button::STATE_HOVERED, | |
55 views::Painter::CreateImageGridPainter(hot_image_set)); | |
56 border->SetPainter(false, views::Button::STATE_PRESSED, | |
57 views::Painter::CreateImageGridPainter(pushed_image_set)); | |
58 | |
59 const int kLeftRightInset = 8; | |
60 const int kTopInset = 2; | |
61 const int kBottomInset = 4; | |
Peter Kasting
2017/05/06 02:23:09
Where did these insets come from? They, and the W
emx
2017/05/09 16:26:52
I don't know - this is existing code and I haven't
Peter Kasting
2017/05/09 17:40:28
OK. We really shouldn't do this sort of thing, bu
| |
62 border->set_insets( | |
63 gfx::Insets(kTopInset, kLeftRightInset, kBottomInset, kLeftRightInset)); | |
64 | |
65 return std::move(border); | |
66 } | |
67 | |
68 std::unique_ptr<views::Border> CreateWin10NativeBorder() { | |
Peter Kasting
2017/05/06 02:23:09
Is this really Win10-specific? Or is this basical
emx
2017/05/09 16:26:52
I arrived at these insets by experimentation on Wi
Peter Kasting
2017/05/09 17:40:28
Can you say more about "look OK"? For example, wh
emx
2017/05/10 17:38:48
Having tested the insets again, it actually looks
Peter Kasting
2017/05/11 01:03:43
Sounds good, but it doesn't look like those change
emx
2017/05/11 12:56:10
Yes, sorry, I replied to the comments, but didn't
| |
69 // These insets look OK at 100%, 125%, 150%, 175% and 200% scaling. | |
70 const int kLeftRightInset = 8; | |
71 const int kTopInset = 1; | |
72 const int kBottomInset = 3; | |
73 return views::CreateEmptyBorder(kTopInset, kLeftRightInset, kBottomInset, | |
74 kLeftRightInset); | |
75 } | |
76 | |
77 } // namespace | |
78 | |
79 AvatarButton::AvatarButton(views::ButtonListener* listener, | |
80 AvatarButtonStyle button_style, | |
81 Profile* profile) | |
82 : LabelButton(listener, base::string16()), | |
83 error_controller_(this, profile), | |
84 profile_(profile), | |
85 use_win10_native_button_(false) { | |
86 set_notify_action(CustomButton::NOTIFY_ON_PRESS); | |
87 set_triggerable_event_flags(ui::EF_LEFT_MOUSE_BUTTON | | |
88 ui::EF_RIGHT_MOUSE_BUTTON); | |
89 set_animate_on_state_change(false); | |
90 SetEnabledTextColors(SK_ColorWHITE); | |
91 SetTextSubpixelRenderingEnabled(false); | |
92 SetHorizontalAlignment(gfx::ALIGN_CENTER); | |
93 | |
94 g_browser_process->profile_manager() | |
95 ->GetProfileAttributesStorage() | |
96 .AddObserver(this); | |
97 | |
98 // The largest text height that fits in the button. If the font list height | |
99 // is larger than this, it will be shrunk to match it. | |
100 // TODO(noms): Calculate this constant algorithmically from the button's size. | |
101 const int kDisplayFontHeight = 16; | |
102 SetFontList( | |
103 label()->font_list().DeriveWithHeightUpperBound(kDisplayFontHeight)); | |
104 | |
105 #if defined(OS_WIN) | |
106 // TODO: use MD button in other cases, too [http://crbug.com/591586] | |
Peter Kasting
2017/05/06 02:23:09
Nit: Which other cases? All of them? Only Window
emx
2017/05/09 16:26:52
I don't know which other cases. I added this TODO
Peter Kasting
2017/05/09 17:40:28
It seems like Evan is the likely person to do this
emx
2017/05/11 12:56:10
Makes sense, thanks for explaining. I didn't reali
| |
107 if ((base::win::GetVersion() >= base::win::VERSION_WIN10) && | |
108 ThemeServiceFactory::GetForProfile(profile)->UsingSystemTheme()) { | |
109 DCHECK_EQ(AvatarButtonStyle::NATIVE, button_style); | |
110 use_win10_native_button_ = true; | |
Peter Kasting
2017/05/06 02:23:08
Nit: Again, is "win10 native button" really the ri
emx
2017/05/09 16:26:52
"Win10NativeAvatarButton" was the class name sugge
Peter Kasting
2017/05/09 17:40:28
In the interest of not blocking you, go ahead and
| |
111 } | |
112 #endif // defined(OS_WIN) | |
113 | |
114 if (use_win10_native_button_) { | |
115 generic_avatar_ = gfx::CreateVectorIcon( | |
116 kAccountCircleIcon, kMdButtonIconHeight, kMdButtonIconColor); | |
117 SetBorder(CreateWin10NativeBorder()); | |
118 | |
119 SetInkDropMode(InkDropMode::ON); | |
120 set_has_ink_drop_action_on_click(true); | |
121 SetFocusPainter(nullptr); | |
122 set_ink_drop_base_color(SK_ColorBLACK); | |
123 set_ink_drop_visible_opacity(kInkDropRippleOpacity); | |
124 } else { | |
125 if (button_style == AvatarButtonStyle::THEMED) { | |
126 const int kNormalImageSet[] = IMAGE_GRID(IDR_AVATAR_THEMED_BUTTON_NORMAL); | |
127 const int kHoverImageSet[] = IMAGE_GRID(IDR_AVATAR_THEMED_BUTTON_HOVER); | |
128 const int kPressedImageSet[] = | |
129 IMAGE_GRID(IDR_AVATAR_THEMED_BUTTON_PRESSED); | |
130 SetButtonAvatar(IDR_AVATAR_THEMED_BUTTON_AVATAR); | |
131 SetBorder(CreateThemedBorder(kNormalImageSet, kHoverImageSet, | |
132 kPressedImageSet)); | |
133 #if defined(OS_WIN) | |
134 } else if (base::win::GetVersion() < base::win::VERSION_WIN8) { | |
135 const int kNormalImageSet[] = IMAGE_GRID(IDR_AVATAR_GLASS_BUTTON_NORMAL); | |
136 const int kHoverImageSet[] = IMAGE_GRID(IDR_AVATAR_GLASS_BUTTON_HOVER); | |
137 const int kPressedImageSet[] = | |
138 IMAGE_GRID(IDR_AVATAR_GLASS_BUTTON_PRESSED); | |
139 SetButtonAvatar(IDR_AVATAR_GLASS_BUTTON_AVATAR); | |
140 SetBorder(CreateThemedBorder(kNormalImageSet, kHoverImageSet, | |
141 kPressedImageSet)); | |
142 #endif | |
143 } else { | |
144 const int kNormalImageSet[] = IMAGE_GRID(IDR_AVATAR_NATIVE_BUTTON_NORMAL); | |
145 const int kHoverImageSet[] = IMAGE_GRID(IDR_AVATAR_NATIVE_BUTTON_HOVER); | |
146 const int kPressedImageSet[] = | |
147 IMAGE_GRID(IDR_AVATAR_NATIVE_BUTTON_PRESSED); | |
148 SetButtonAvatar(IDR_AVATAR_NATIVE_BUTTON_AVATAR); | |
149 SetBorder(CreateThemedBorder(kNormalImageSet, kHoverImageSet, | |
150 kPressedImageSet)); | |
151 } | |
152 } | |
153 | |
154 Update(); | |
155 SchedulePaint(); | |
156 } | |
157 | |
158 AvatarButton::~AvatarButton() { | |
159 g_browser_process->profile_manager() | |
160 ->GetProfileAttributesStorage() | |
161 .RemoveObserver(this); | |
Peter Kasting
2017/05/06 02:23:08
Nit: Can we use ScopedObserver to avoid this expli
emx
2017/05/09 16:26:52
Done.
| |
162 } | |
163 | |
164 void AvatarButton::OnGestureEvent(ui::GestureEvent* event) { | |
165 // TODO(wjmaclean): The check for ET_GESTURE_LONG_PRESS is done here since | |
166 // no other UI button based on CustomButton appears to handle mouse | |
167 // right-click. If other cases are identified, it may make sense to move this | |
168 // check to CustomButton. | |
169 if (event->type() == ui::ET_GESTURE_LONG_PRESS) | |
170 NotifyClick(*event); | |
171 else | |
172 LabelButton::OnGestureEvent(event); | |
173 } | |
174 | |
175 gfx::Size AvatarButton::GetMinimumSize() const { | |
176 if (use_win10_native_button_) { | |
177 // Returns the "cozy" size of the button. Called by | |
178 // GlassBrowserFrameView::LayoutProfileSwitcher() when it calculates that | |
179 // the button needs to slide over the tabstrip. | |
180 return gfx::Size(kMdButtonMinWidth, kMdButtonCozyHeight); | |
181 } | |
182 | |
183 return LabelButton::GetMinimumSize(); | |
184 } | |
185 | |
186 gfx::Size AvatarButton::GetPreferredSize() const { | |
187 gfx::Size size = LabelButton::GetPreferredSize(); | |
188 | |
189 if (use_win10_native_button_) { | |
190 // Returns the "tall" (normal) size of the button. Its height should match | |
191 // the caption button height. | |
192 size.set_width( | |
193 std::min(std::max(size.width(), kMdButtonMinWidth), kMdButtonMaxWidth)); | |
Peter Kasting
2017/05/06 02:23:09
Nit: MathUtil::ClampToRange()?
emx
2017/05/09 16:26:52
I tried that, but "git cl upload" failed:
** Pres
Peter Kasting
2017/05/11 01:03:43
Sadness. I'm dealing with this separately, don't
| |
194 // TODO(emx): get the proper height here - see http://crrev/2833363002 | |
Peter Kasting
2017/05/06 02:23:08
You can mark this patchset as dependent on that on
emx
2017/05/09 16:26:52
That one has been committed now.
| |
195 size.set_height(30); | |
196 } else { | |
197 size.set_height(kThemedButtonHeight); | |
198 } | |
199 | |
200 return size; | |
201 } | |
202 | |
203 bool AvatarButton::ShouldUseFloodFillInkDrop() const { | |
204 return true; | |
205 } | |
206 | |
207 std::unique_ptr<views::InkDropHighlight> AvatarButton::CreateInkDropHighlight() | |
208 const { | |
209 auto center = gfx::RectF(GetLocalBounds()).CenterPoint(); | |
210 auto ink_drop_highlight = base::MakeUnique<views::InkDropHighlight>( | |
211 size(), 0, center, GetInkDropBaseColor()); | |
212 ink_drop_highlight->set_visible_opacity(kInkDropHighlightOpacity); | |
213 return ink_drop_highlight; | |
214 } | |
215 | |
216 void AvatarButton::OnAvatarErrorChanged() { | |
217 Update(); | |
218 } | |
219 | |
220 void AvatarButton::OnProfileAdded(const base::FilePath& profile_path) { | |
221 Update(); | |
222 } | |
223 | |
224 void AvatarButton::OnProfileWasRemoved(const base::FilePath& profile_path, | |
225 const base::string16& profile_name) { | |
226 // If deleting the active profile, don't bother updating the avatar | |
227 // button, as the browser window is being closed anyway. | |
228 if (profile_->GetPath() != profile_path) | |
229 Update(); | |
230 } | |
231 | |
232 void AvatarButton::OnProfileNameChanged( | |
233 const base::FilePath& profile_path, | |
234 const base::string16& old_profile_name) { | |
235 if (profile_->GetPath() == profile_path) | |
236 Update(); | |
237 } | |
238 | |
239 void AvatarButton::OnProfileSupervisedUserIdChanged( | |
240 const base::FilePath& profile_path) { | |
241 if (profile_->GetPath() == profile_path) | |
242 Update(); | |
243 } | |
244 | |
245 void AvatarButton::Update() { | |
246 ProfileAttributesStorage& storage = | |
247 g_browser_process->profile_manager()->GetProfileAttributesStorage(); | |
248 | |
249 // If we have a single local profile, then use the generic avatar | |
250 // button instead of the profile name. Never use the generic button if | |
251 // the active profile is Guest. | |
252 const bool use_generic_button = | |
253 !profile_->IsGuestSession() && storage.GetNumberOfProfiles() == 1 && | |
254 !SigninManagerFactory::GetForProfile(profile_)->IsAuthenticated(); | |
255 | |
Peter Kasting
2017/05/06 02:23:09
Nit: Blank line not necessary. Or, leave the func
emx
2017/05/09 16:26:52
Inlined.
| |
256 UpdateButton(use_generic_button); | |
257 | |
258 PreferredSizeChanged(); | |
259 } | |
260 | |
261 void AvatarButton::UpdateButton(bool use_generic_button) { | |
262 SetText(use_generic_button | |
263 ? base::string16() | |
264 : profiles::GetAvatarButtonTextForProfile(profile_)); | |
265 | |
266 // If the button has no text, clear the text shadows to make sure the | |
267 // image is centered correctly. | |
268 SetTextShadows( | |
269 use_generic_button | |
270 ? gfx::ShadowValues() | |
271 : gfx::ShadowValues( | |
272 10, gfx::ShadowValue(gfx::Vector2d(), 2.0f, SK_ColorDKGRAY))); | |
273 | |
274 // We want the button to resize if the new text is shorter. | |
275 SetMinSize(gfx::Size()); | |
276 | |
277 if (use_generic_button) { | |
278 SetImage(views::Button::STATE_NORMAL, generic_avatar_); | |
279 } else if (error_controller_.HasAvatarError()) { | |
280 SetImage(views::Button::STATE_NORMAL, | |
281 gfx::CreateVectorIcon(kSyncProblemIcon, 16, gfx::kGoogleRed700)); | |
282 } else { | |
283 SetImage(views::Button::STATE_NORMAL, gfx::ImageSkia()); | |
284 } | |
285 | |
286 // If we are not using the generic button, then reset the spacing between | |
287 // the text and the possible authentication error icon. | |
288 const int kDefaultImageTextSpacing = 5; | |
289 SetImageLabelSpacing(use_generic_button ? 0 : kDefaultImageTextSpacing); | |
290 } | |
291 | |
292 void AvatarButton::SetButtonAvatar(int avatar_idr) { | |
293 ui::ResourceBundle* rb = &ui::ResourceBundle::GetSharedInstance(); | |
294 generic_avatar_ = *rb->GetImageNamed(avatar_idr).ToImageSkia(); | |
295 } | |
OLD | NEW |