OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ash/system/user/tray_user.h" | 5 #include "ash/system/user/tray_user.h" |
6 | 6 |
7 #include <algorithm> | |
8 #include <climits> | |
9 #include <queue> | |
10 #include <vector> | |
11 | |
7 #include "ash/shell.h" | 12 #include "ash/shell.h" |
8 #include "ash/system/tray/system_tray.h" | 13 #include "ash/system/tray/system_tray.h" |
9 #include "ash/system/tray/system_tray_delegate.h" | 14 #include "ash/system/tray/system_tray_delegate.h" |
10 #include "ash/system/tray/tray_constants.h" | 15 #include "ash/system/tray/tray_constants.h" |
11 #include "ash/system/tray/tray_item_view.h" | 16 #include "ash/system/tray/tray_item_view.h" |
12 #include "ash/system/tray/tray_views.h" | 17 #include "ash/system/tray/tray_views.h" |
18 #include "base/i18n/rtl.h" | |
19 #include "base/logging.h" | |
20 #include "base/memory/scoped_vector.h" | |
21 #include "base/string16.h" | |
22 #include "base/string_util.h" | |
13 #include "base/utf_string_conversions.h" | 23 #include "base/utf_string_conversions.h" |
14 #include "grit/ash_strings.h" | 24 #include "grit/ash_strings.h" |
15 #include "skia/ext/image_operations.h" | 25 #include "skia/ext/image_operations.h" |
16 #include "third_party/skia/include/core/SkCanvas.h" | 26 #include "third_party/skia/include/core/SkCanvas.h" |
27 #include "third_party/skia/include/core/SkColor.h" | |
17 #include "third_party/skia/include/core/SkPaint.h" | 28 #include "third_party/skia/include/core/SkPaint.h" |
18 #include "third_party/skia/include/core/SkPath.h" | 29 #include "third_party/skia/include/core/SkPath.h" |
30 #include "ui/base/l10n/l10n_util.h" | |
19 #include "ui/base/resource/resource_bundle.h" | 31 #include "ui/base/resource/resource_bundle.h" |
32 #include "ui/base/text/text_elider.h" | |
20 #include "ui/gfx/canvas.h" | 33 #include "ui/gfx/canvas.h" |
34 #include "ui/gfx/font.h" | |
21 #include "ui/gfx/image/image.h" | 35 #include "ui/gfx/image/image.h" |
22 #include "ui/gfx/image/image_skia_operations.h" | 36 #include "ui/gfx/image/image_skia_operations.h" |
37 #include "ui/gfx/insets.h" | |
38 #include "ui/gfx/rect.h" | |
39 #include "ui/gfx/render_text.h" | |
23 #include "ui/gfx/size.h" | 40 #include "ui/gfx/size.h" |
24 #include "ui/gfx/skia_util.h" | 41 #include "ui/gfx/skia_util.h" |
42 #include "ui/views/border.h" | |
25 #include "ui/views/controls/button/button.h" | 43 #include "ui/views/controls/button/button.h" |
26 #include "ui/views/controls/button/text_button.h" | |
27 #include "ui/views/controls/image_view.h" | 44 #include "ui/views/controls/image_view.h" |
28 #include "ui/views/controls/label.h" | 45 #include "ui/views/controls/label.h" |
46 #include "ui/views/controls/link.h" | |
47 #include "ui/views/controls/link_listener.h" | |
29 #include "ui/views/layout/box_layout.h" | 48 #include "ui/views/layout/box_layout.h" |
30 #include "ui/views/view.h" | 49 #include "ui/views/view.h" |
31 #include "ui/views/widget/widget.h" | 50 #include "ui/views/widget/widget.h" |
32 | 51 |
33 namespace { | 52 namespace { |
34 | 53 |
35 const int kUserInfoVerticalPadding = 10; | 54 const int kUserDetailsVerticalPadding = 5; |
55 const int kUserCardVerticalPadding = 10; | |
56 const int kProfileRoundedCornerRadius = 2; | |
36 const int kUserIconSize = 27; | 57 const int kUserIconSize = 27; |
37 const int kProfileRoundedCornerRadius = 2; | 58 |
59 // The invisible word joiner character, used as a marker to indicate the start | |
60 // and end of the user's display name in the public account user card's text. | |
61 const char16 kDisplayNameMark[] = { 0x2060 }; | |
38 | 62 |
39 } // namespace | 63 } // namespace |
40 | 64 |
41 namespace ash { | 65 namespace ash { |
42 namespace internal { | 66 namespace internal { |
43 | 67 |
44 namespace tray { | 68 namespace tray { |
45 | 69 |
46 // A custom image view with rounded edges. | 70 // A custom image view with rounded edges. |
47 class RoundedImageView : public views::View { | 71 class RoundedImageView : public views::View { |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
92 | 116 |
93 private: | 117 private: |
94 gfx::ImageSkia image_; | 118 gfx::ImageSkia image_; |
95 gfx::ImageSkia resized_; | 119 gfx::ImageSkia resized_; |
96 gfx::Size image_size_; | 120 gfx::Size image_size_; |
97 int corner_radius_; | 121 int corner_radius_; |
98 | 122 |
99 DISALLOW_COPY_AND_ASSIGN(RoundedImageView); | 123 DISALLOW_COPY_AND_ASSIGN(RoundedImageView); |
100 }; | 124 }; |
101 | 125 |
126 // The user details shown in public account mode. This is essentially a label | |
127 // but with custom painting code as the text is styled with multiple colors and | |
128 // contains a link. | |
129 class PublicAccountUserDetails : public views::View, | |
msw
2012/11/16 22:29:32
nit: separate declaration and definition.
bartfab (slow)
2012/11/19 17:34:06
Done, although I was just following the style used
| |
130 public views::LinkListener { | |
131 public: | |
132 PublicAccountUserDetails(SystemTrayItem* owner, int used_width) | |
133 : learn_more_(NULL), | |
134 font_(ResourceBundle::GetSharedInstance().GetFont( | |
135 ResourceBundle::BaseFont)) { | |
136 set_border(views::Border::CreateEmptyBorder( | |
137 kUserDetailsVerticalPadding, | |
138 kTrayPopupPaddingHorizontal - kTrayPopupPaddingBetweenItems, | |
139 kUserDetailsVerticalPadding, 0)); | |
140 | |
141 ash::SystemTrayDelegate* delegate = | |
142 ash::Shell::GetInstance()->tray_delegate(); | |
143 // Retrieve the user's display name and wrap it with markers. | |
144 string16 display_name = delegate->GetUserDisplayName(); | |
145 ReplaceChars(display_name, kDisplayNameMark, string16(), &display_name); | |
146 display_name.insert(0U, 1U, kDisplayNameMark[0]); | |
147 display_name.push_back(kDisplayNameMark[0]); | |
148 // Retrieve the domain managing the device and wrap it with markers. | |
149 string16 domain = UTF8ToUTF16(delegate->GetEnterpriseDomain()); | |
150 ReplaceChars(domain, kDisplayNameMark, string16(), &domain); | |
151 base::i18n::WrapStringWithLTRFormatting(&domain); | |
152 // Retrieve the label text, inserting the display name and domain. | |
153 text_ = l10n_util::GetStringFUTF16(IDS_ASH_STATUS_TRAY_PUBLIC_LABEL, | |
154 display_name, domain); | |
155 | |
156 learn_more_ = new views::Link( | |
157 l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_PUBLIC_LEARN_MORE)); | |
158 learn_more_->SetUnderline(false); | |
159 learn_more_->set_listener(this); | |
160 AddChildView(learn_more_); | |
161 | |
162 CalculatePreferredSize(owner, used_width); | |
163 } | |
164 | |
165 // Overridden from views::LinkListener. | |
166 virtual void LinkClicked(views::Link* source, int event_flags) OVERRIDE { | |
167 DCHECK_EQ(source, learn_more_); | |
168 ash::Shell::GetInstance()->tray_delegate()->ShowPublicAccountInfo(); | |
169 } | |
170 | |
171 // Overridden from views::View. | |
172 void Layout() OVERRIDE { | |
173 lines_.clear(); | |
174 const gfx::Rect& contents_area = GetContentsBounds(); | |
175 if (contents_area.IsEmpty()) | |
msw
2012/11/16 22:29:32
nit: does this happen?
bartfab (slow)
2012/11/19 17:34:06
Yes, it happens during bubble construction:
Creat
| |
176 return; | |
177 | |
178 // Word-wrap the label text. | |
179 std::vector<string16> lines; | |
180 ui::ElideRectangleText(text_, font_, contents_area.width(), | |
msw
2012/11/16 22:29:32
Does ElideRectangleText do the right thing if the
bartfab (slow)
2012/11/19 17:34:06
Yes, I verified that all conceivable LTR/RTL combi
| |
181 contents_area.height(), ui::TRUNCATE_LONG_WORDS, | |
182 &lines); | |
183 // Loop through the lines, creating a renderer for each. | |
184 gfx::Point position = contents_area.origin(); | |
185 std::queue<size_t> display_name_markers; | |
186 for (std::vector<string16>::const_iterator it = lines.begin(); | |
187 it != lines.end(); ++it) { | |
msw
2012/11/16 22:29:32
nit: indent one more space (just my preference to
bartfab (slow)
2012/11/19 17:34:06
Yes, this is my preference as well. The missing sp
| |
188 gfx::RenderText* line = gfx::RenderText::CreateInstance(); | |
189 line->SetDirectionalityMode(gfx::DIRECTIONALITY_FROM_UI); | |
190 line->SetText(*it); | |
191 const gfx::Size size(contents_area.width(), | |
192 line->GetStringSize().height()); | |
193 line->SetDisplayRect(gfx::Rect(position, size)); | |
194 position.set_y(position.y() + size.height()); | |
195 | |
196 // Set the default text color for the line. | |
197 gfx::StyleRange default_style(line->default_style()); | |
198 default_style.foreground = kPublicAccountUserCardTextColor; | |
199 line->set_default_style(default_style); | |
200 line->ApplyDefaultStyle(); | |
201 | |
202 // Locate any markers indicating the start and end of the user's display | |
msw
2012/11/16 22:29:32
nit: you should be able to safely assume that ther
bartfab (slow)
2012/11/19 17:34:06
Done.
| |
203 // name. | |
204 size_t pos = 0; | |
205 while ((pos = it->find(kDisplayNameMark, pos)) != string16::npos) { | |
206 display_name_markers.push(pos); | |
207 ++pos; | |
208 } | |
209 // If the display name extends past the end of this line, synthesize a | |
210 // marker at the end of the line and another at the start of the next | |
211 // line. | |
212 if (display_name_markers.size() % 2) { | |
213 display_name_markers.push(it->size()); | |
214 display_name_markers.push(0); | |
stevenjb
2012/11/16 21:13:52
This is confusing. It looks like this means that w
bartfab (slow)
2012/11/19 17:34:06
I reworked the code as per Mike's suggestion. I am
| |
215 } | |
216 // Loop through the intervals enclosed by markers and apply a custom text | |
217 // color to the display name. | |
218 if (display_name_markers.size() >= 2) { | |
219 gfx::StyleRange display_name_style(line->default_style()); | |
220 display_name_style.foreground = kPublicAccountUserCardNameColor; | |
221 while (display_name_markers.size() >= 2) { | |
msw
2012/11/16 22:29:32
there should only be one non-default style range p
bartfab (slow)
2012/11/19 17:34:06
Correct. I simplified the code, removing the loop.
| |
222 display_name_style.range.set_start(display_name_markers.front()); | |
223 display_name_markers.pop(); | |
224 display_name_style.range.set_end(display_name_markers.front()); | |
225 display_name_markers.pop(); | |
226 line->ApplyStyleRange(display_name_style); | |
227 } | |
228 } | |
229 lines_.push_back(line); | |
230 } | |
231 | |
232 // Position link after the label text, separated by a space. If it does not | |
msw
2012/11/16 22:29:32
This should be tested for RTL UI; I suspect that i
bartfab (slow)
2012/11/19 17:34:06
I heavily tested this for RTL and did not encounte
| |
233 // fit onto the last line of the text, wrap the link onto its own line. | |
234 const gfx::Size last_line_size = lines_.back()->GetStringSize(); | |
235 const int space_width = font_.GetStringWidth(ASCIIToUTF16(" ")); | |
236 const gfx::Size link_size = learn_more_->GetPreferredSize(); | |
237 if (contents_area.width() - last_line_size.width() >= | |
238 space_width + link_size.width()) { | |
239 position.set_x(position.x() + last_line_size.width() + space_width); | |
240 position.set_y(position.y() - last_line_size.height()); | |
241 } | |
242 position.set_y(position.y() - learn_more_->GetInsets().top()); | |
243 gfx::Rect learn_more_bounds(position, link_size); | |
244 learn_more_bounds.Intersect(contents_area); | |
245 learn_more_->SetBoundsRect(learn_more_bounds); | |
246 } | |
247 | |
248 virtual gfx::Size GetPreferredSize() OVERRIDE { | |
249 return preferred_size_; | |
250 } | |
251 | |
252 private: | |
253 virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE { | |
254 for (ScopedVector<gfx::RenderText>::const_iterator it = lines_.begin(); | |
255 it != lines_.end(); ++it) | |
256 (*it)->Draw(canvas); | |
257 views::View::OnPaint(canvas); | |
258 } | |
259 | |
260 // Calculate a preferred size that ensures the label text and the following | |
261 // link do not wrap over more than three lines in total for esthetic reasons. | |
stevenjb
2012/11/16 21:13:52
nit: align, aesthetic (more common)
msw
2012/11/16 22:29:32
What's done for arbitrarily long doman/user names?
bartfab (slow)
2012/11/19 17:34:06
Done.
bartfab (slow)
2012/11/19 17:34:06
I added a maximum width. The text can now wrap to
| |
262 void CalculatePreferredSize(SystemTrayItem* owner, int used_width) { | |
263 const gfx::Size link_size = learn_more_->GetPreferredSize(); | |
264 const int space_width = font_.GetStringWidth(ASCIIToUTF16(" ")); | |
265 int min_width = std::max(1, link_size.width()); | |
msw
2012/11/16 22:29:32
nit: it should be safe to assume the link width is
bartfab (slow)
2012/11/19 17:34:06
Done.
| |
266 int max_width = font_.GetStringWidth(text_) + | |
267 space_width + link_size.width(); | |
stevenjb
2012/11/16 21:13:52
We should probably limit max width here to a reaso
bartfab (slow)
2012/11/19 17:34:06
Done.
| |
268 // Do a binary search for the minimum width that ensures no more than three | |
269 // lines are needed. The lower bound is the width of the link (as no | |
270 // wrapping is permitted inside the link). The upper bound is the width of | |
271 // the label text and link when put on a single line. | |
272 while (min_width < max_width) { | |
msw
2012/11/16 22:29:32
I fear this will be the performance bottleneck for
bartfab (slow)
2012/11/19 17:34:06
Since this is a binary search, it only takes a han
| |
273 const int width = (min_width + max_width) / 2; | |
274 std::vector<string16> lines; | |
msw
2012/11/16 22:29:32
nit: declare |lines| outside this loop and use it
bartfab (slow)
2012/11/19 17:34:06
Done.
| |
275 const bool truncated = ui::ElideRectangleText( | |
276 text_, font_, width, INT_MAX, ui::TRUNCATE_LONG_WORDS, &lines); | |
277 const int line_count = lines.size() + | |
278 (width - font_.GetStringWidth(lines.back()) <= | |
stevenjb
2012/11/16 21:13:52
Avoid this (expensive) calculation if truncated?
bartfab (slow)
2012/11/19 17:34:06
Done.
| |
279 space_width + link_size.width()); | |
msw
2012/11/16 22:29:32
nit: make this a ternary * ? 0 : 1; to explicitly
bartfab (slow)
2012/11/19 17:34:06
I reordered the code to avoid this implicit bool-t
| |
280 if (truncated || line_count > 3) | |
281 min_width = width + 1; | |
282 else | |
283 max_width = width; | |
284 } | |
285 | |
286 // If the space available for the user details in the system tray bubble | |
287 // is larger than the minimum width calculated above, use that width | |
288 // instead, potentially wrapping onto less than three lines. | |
289 const gfx::Insets insets = GetInsets(); | |
290 views::TrayBubbleView* bubble_view = | |
291 owner->system_tray()->GetSystemBubble()->bubble_view(); | |
292 const int available_width = | |
msw
2012/11/16 22:29:32
The initial min_width value above (line 265) shoul
bartfab (slow)
2012/11/19 17:34:06
Done.
| |
293 bubble_view->GetPreferredSize().width() - (used_width + insets.width()); | |
294 min_width = std::max(min_width, available_width); | |
295 | |
296 // Calculate the corresponding height and set the preferred size. | |
297 std::vector<string16> lines; | |
298 ui::ElideRectangleText( | |
299 text_, font_, min_width, INT_MAX, ui::TRUNCATE_LONG_WORDS, &lines); | |
300 const int line_count = lines.size() + | |
msw
2012/11/16 22:29:32
ditto nit: make this a ternary * ? 0 : 1; to expli
bartfab (slow)
2012/11/19 17:34:06
Done.
| |
301 (min_width - font_.GetStringWidth(lines.back()) <= | |
302 space_width + link_size.width()); | |
303 const int line_height = font_.GetHeight(); | |
304 const int link_extra_height = std::max( | |
305 link_size.height() - learn_more_->GetInsets().top() - line_height, 0); | |
306 preferred_size_ = gfx::Size( | |
307 min_width + insets.width(), | |
308 line_count * line_height + link_extra_height + insets.height()); | |
309 | |
310 // If the system tray bubble currently is too narrow to provide the | |
msw
2012/11/16 22:29:32
nit: "is currently"
bartfab (slow)
2012/11/19 17:34:06
Done.
| |
311 // calculated minimum width, resize the bubble. | |
312 if (min_width > available_width) | |
msw
2012/11/16 22:29:32
nit: can't you just call bubble_view->SizeToConten
bartfab (slow)
2012/11/19 17:34:06
Unfortunately, no:
SizeToContents() takes all chi
| |
313 bubble_view->SetWidth(preferred_size_.width() + used_width); | |
314 } | |
315 | |
316 string16 text_; | |
317 views::Link* learn_more_; | |
318 gfx::Font font_; | |
319 gfx::Size preferred_size_; | |
320 ScopedVector<gfx::RenderText> lines_; | |
321 | |
322 DISALLOW_COPY_AND_ASSIGN(PublicAccountUserDetails); | |
323 }; | |
324 | |
102 class UserView : public views::View, | 325 class UserView : public views::View, |
msw
2012/11/16 22:29:32
nit: separate declaration and definition.
bartfab (slow)
2012/11/19 17:34:06
Done.
| |
103 public views::ButtonListener { | 326 public views::ButtonListener { |
104 public: | 327 public: |
105 explicit UserView(ash::user::LoginStatus login) | 328 explicit UserView(SystemTrayItem* owner, |
106 : login_(login), | 329 ash::user::LoginStatus login) |
107 container_(NULL), | 330 : user_card_(NULL), |
108 user_info_(NULL), | 331 logout_button_(NULL) { |
109 username_(NULL), | 332 CHECK(login != ash::user::LOGGED_IN_NONE); |
110 email_(NULL), | |
111 signout_(NULL) { | |
112 CHECK(login_ != ash::user::LOGGED_IN_NONE); | |
113 | |
114 bool public_account = login_ == ash::user::LOGGED_IN_PUBLIC; | |
115 bool guest = login_ == ash::user::LOGGED_IN_GUEST; | |
116 bool locked = login_ == ash::user::LOGGED_IN_LOCKED; | |
117 | |
118 set_background(views::Background::CreateSolidBackground( | 333 set_background(views::Background::CreateSolidBackground( |
119 public_account ? kPublicAccountBackgroundColor : kBackgroundColor)); | 334 login == ash::user::LOGGED_IN_PUBLIC ? kPublicAccountBackgroundColor : |
120 | 335 kBackgroundColor)); |
121 container_ = new TrayPopupLabelButtonContainer; | 336 SetLayoutManager(new views::BoxLayout(views::BoxLayout::kHorizontal, 0, 0, |
122 container_->layout()->set_spread_blank_space(false); | 337 kTrayPopupPaddingBetweenItems)); |
123 AddChildView(container_); | 338 AddLogoutButton(login); |
124 | 339 AddUserCard(owner, login); |
125 if (!guest) | 340 } |
126 AddUserInfo(); | 341 |
127 | 342 // Overridden from views::View. |
128 // A user should not be able to modify logged in state when screen is | 343 virtual gfx::Size GetPreferredSize() OVERRIDE { |
344 gfx::Size size = views::View::GetPreferredSize(); | |
345 if (!user_card_) { | |
346 // Make sure the default user default view item is at least as tall as the | |
347 // other items. | |
348 size.set_height(std::max(size.height(), | |
349 kTrayPopupItemHeight + GetInsets().height())); | |
350 } | |
351 return size; | |
352 } | |
353 | |
354 virtual void Layout() OVERRIDE { | |
355 gfx::Rect contents_area(GetContentsBounds()); | |
356 if (user_card_ && logout_button_) { | |
357 // Give the logout button the space it requests. | |
358 gfx::Rect logout_area = contents_area; | |
359 logout_area.ClampToCenteredSize(logout_button_->GetPreferredSize()); | |
360 logout_area.set_x(contents_area.right() - logout_area.width()); | |
361 logout_button_->SetBoundsRect(logout_area); | |
362 | |
363 // Give the remaining space to the user card. | |
364 gfx::Rect user_card_area = contents_area; | |
365 user_card_area.set_width(contents_area.width() - | |
366 (logout_area.width() + kTrayPopupPaddingBetweenItems)); | |
367 user_card_->SetBoundsRect(user_card_area); | |
368 } else if (user_card_) { | |
369 user_card_->SetBoundsRect(contents_area); | |
370 } else if (logout_button_) { | |
371 logout_button_->SetBoundsRect(contents_area); | |
372 } | |
373 } | |
374 | |
375 private: | |
376 void AddLogoutButton(ash::user::LoginStatus login) { | |
377 // The logout button must be added before the user card. | |
378 DCHECK(!user_card_); | |
379 | |
380 // A user should not be able to modify logged-in state when screen is | |
129 // locked. | 381 // locked. |
130 if (!locked) | 382 if (login == ash::user::LOGGED_IN_LOCKED) |
131 AddButtonContainer(); | 383 return; |
132 } | 384 |
133 | 385 TrayPopupLabelButton* logout_button = new TrayPopupLabelButton( |
134 virtual ~UserView() {} | 386 this, ash::user::GetLocalizedSignOutStringForStatus(login, true)); |
135 | 387 // In public account mode, the logout button has custom padding. |
136 // Create container for buttons. | 388 if (login == ash::user::LOGGED_IN_PUBLIC) { |
137 void AddButtonContainer() { | 389 gfx::Insets extra_padding = logout_button->GetExtraPadding(); |
138 TrayPopupLabelButton* button = new TrayPopupLabelButton(this, | 390 extra_padding.Set(kTrayPopupPublicAccountLogoutButtonExtraPaddingVertical, |
139 ash::user::GetLocalizedSignOutStringForStatus(login_, true)); | 391 extra_padding.left(), |
140 container_->AddLabelButton(button); | 392 kTrayPopupPublicAccountLogoutButtonExtraPaddingVertical, |
141 signout_ = button; | 393 extra_padding.right()); |
142 } | 394 logout_button->SetExtraPadding(extra_padding); |
143 | 395 } |
144 private: | 396 logout_button_ = logout_button; |
145 void AddUserInfo() { | 397 AddChildView(logout_button); |
146 user_info_ = new views::View; | 398 } |
147 user_info_->SetLayoutManager(new views::BoxLayout( | 399 |
148 views::BoxLayout::kHorizontal, kTrayPopupPaddingHorizontal, | 400 void AddUserCard(SystemTrayItem* owner, ash::user::LoginStatus login) { |
149 kUserInfoVerticalPadding, kTrayPopupPaddingBetweenItems)); | 401 if (login == ash::user::LOGGED_IN_GUEST) |
150 container_->AddChildView(user_info_); | 402 return; |
151 | 403 |
152 if (login_ == ash::user::LOGGED_IN_KIOSK) { | 404 set_border(views::Border::CreateEmptyBorder( |
153 views::Label* label = new views::Label; | 405 0, kTrayPopupPaddingHorizontal, 0, kTrayPopupPaddingHorizontal)); |
406 | |
407 // Add a vertical separator between the logout button and the user card. | |
408 if (logout_button_) { | |
409 int border_width = 1; | |
410 SkColor border_color = kButtonStrokeColor; | |
411 // In public account mode, the vertical separator has a custom style. | |
412 if (login == ash::user::LOGGED_IN_PUBLIC) { | |
413 border_width = 2; | |
414 border_color = kPublicAccountLogoutButtonStrokeColor; | |
415 } | |
416 const bool rtl = base::i18n::IsRTL(); | |
417 logout_button_->set_border(views::Border::CreateSolidSidedBorder( | |
418 0, rtl ? 0 : border_width, 0, rtl ? border_width : 0, border_color)); | |
419 } | |
420 | |
421 user_card_ = new views::View(); | |
422 user_card_->SetLayoutManager(new views::BoxLayout( | |
423 views::BoxLayout::kHorizontal, 0, kUserCardVerticalPadding, | |
424 kTrayPopupPaddingBetweenItems)); | |
425 AddChildViewAt(user_card_, 0); | |
426 | |
427 if (login == ash::user::LOGGED_IN_KIOSK) { | |
428 views::Label* details = new views::Label; | |
154 ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance(); | 429 ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance(); |
155 label->SetText( | 430 details->SetText( |
156 bundle.GetLocalizedString(IDS_ASH_STATUS_TRAY_KIOSK_LABEL)); | 431 bundle.GetLocalizedString(IDS_ASH_STATUS_TRAY_KIOSK_LABEL)); |
157 label->set_border(views::Border::CreateEmptyBorder( | 432 details->set_border(views::Border::CreateEmptyBorder(0, 4, 0, 1)); |
158 0, 4, 0, 1)); | 433 details->SetHorizontalAlignment(gfx::ALIGN_LEFT); |
159 label->SetHorizontalAlignment(gfx::ALIGN_LEFT); | 434 user_card_->AddChildView(details); |
160 user_info_->AddChildView(label); | 435 return; |
161 return; | 436 } |
162 } | 437 |
163 | 438 RoundedImageView* avatar = |
164 RoundedImageView* image = new RoundedImageView(kProfileRoundedCornerRadius); | 439 new RoundedImageView(kProfileRoundedCornerRadius); |
165 image->SetImage(ash::Shell::GetInstance()->tray_delegate()->GetUserImage(), | 440 avatar->SetImage(ash::Shell::GetInstance()->tray_delegate()->GetUserImage(), |
166 gfx::Size(kUserIconSize, kUserIconSize)); | 441 gfx::Size(kUserIconSize, kUserIconSize)); |
167 user_info_->AddChildView(image); | 442 user_card_->AddChildView(avatar); |
168 | 443 |
169 views::View* user = new views::View; | 444 if (login == ash::user::LOGGED_IN_PUBLIC) { |
170 user->SetLayoutManager(new views::BoxLayout( | 445 user_card_->AddChildView(new PublicAccountUserDetails( |
171 views::BoxLayout::kVertical, 0, 5, 0)); | 446 owner, GetPreferredSize().width() + kTrayPopupPaddingBetweenItems)); |
172 ash::SystemTrayDelegate* tray = | 447 return; |
448 } | |
449 | |
450 ash::SystemTrayDelegate* delegate = | |
173 ash::Shell::GetInstance()->tray_delegate(); | 451 ash::Shell::GetInstance()->tray_delegate(); |
174 username_ = new views::Label(tray->GetUserDisplayName()); | 452 views::View* details = new views::View; |
175 username_->SetHorizontalAlignment(gfx::ALIGN_LEFT); | 453 details->SetLayoutManager(new views::BoxLayout( |
176 user->AddChildView(username_); | 454 views::BoxLayout::kVertical, 0, kUserDetailsVerticalPadding, 0)); |
177 | 455 views::Label* username = new views::Label(delegate->GetUserDisplayName()); |
178 email_ = new views::Label(UTF8ToUTF16(tray->GetUserEmail())); | 456 username->SetHorizontalAlignment(gfx::ALIGN_LEFT); |
179 email_->SetFont(username_->font().DeriveFont(-1)); | 457 details->AddChildView(username); |
180 email_->SetHorizontalAlignment(gfx::ALIGN_LEFT); | 458 |
181 email_->SetEnabled(false); | 459 views::Label* email = |
msw
2012/11/16 22:29:32
nit: you might want to SetElideBehavior for this l
bartfab (slow)
2012/11/19 17:34:06
Done.
| |
182 user->AddChildView(email_); | 460 new views::Label(UTF8ToUTF16(delegate->GetUserEmail())); |
183 | 461 email->SetFont(username->font().DeriveFont(-1)); |
184 user_info_->AddChildView(user); | 462 email->SetHorizontalAlignment(gfx::ALIGN_LEFT); |
463 email->SetEnabled(false); | |
464 details->AddChildView(email); | |
465 user_card_->AddChildView(details); | |
185 } | 466 } |
186 | 467 |
187 // Overridden from views::ButtonListener. | 468 // Overridden from views::ButtonListener. |
188 virtual void ButtonPressed(views::Button* sender, | 469 virtual void ButtonPressed(views::Button* sender, |
189 const ui::Event& event) OVERRIDE { | 470 const ui::Event& event) OVERRIDE { |
190 CHECK(sender == signout_); | 471 CHECK(sender == logout_button_); |
191 ash::SystemTrayDelegate* tray = ash::Shell::GetInstance()->tray_delegate(); | 472 ash::Shell::GetInstance()->tray_delegate()->SignOut(); |
192 tray->SignOut(); | 473 } |
193 } | 474 |
194 | 475 views::View* user_card_; |
195 // Overridden from views::View. | 476 views::View* logout_button_; |
196 virtual gfx::Size GetPreferredSize() OVERRIDE { | |
197 gfx::Size size; | |
198 if (user_info_) | |
199 size = user_info_->GetPreferredSize(); | |
200 if (signout_) { | |
201 gfx::Size signout_size = signout_->GetPreferredSize(); | |
202 // Make sure the user default view item at least as tall as the other | |
203 // tray popup items. | |
204 if (size.height() == 0) | |
205 size.set_height(kTrayPopupItemHeight); | |
206 size.set_height(std::max(size.height(), signout_size.height())); | |
207 size.set_width(size.width() + signout_size.width() + | |
208 kTrayPopupPaddingHorizontal * 2 + kTrayPopupPaddingBetweenItems); | |
209 } | |
210 return size; | |
211 } | |
212 | |
213 virtual void Layout() OVERRIDE { | |
214 views::View::Layout(); | |
215 if (bounds().IsEmpty()) | |
216 return; | |
217 | |
218 container_->SetBoundsRect(gfx::Rect(size())); | |
219 if (signout_ && user_info_) { | |
220 gfx::Rect signout_bounds(bounds()); | |
221 signout_bounds.ClampToCenteredSize(signout_->GetPreferredSize()); | |
222 signout_bounds.set_x(width() - signout_bounds.width() - | |
223 kTrayPopupPaddingHorizontal); | |
224 signout_->SetBoundsRect(signout_bounds); | |
225 | |
226 gfx::Rect usercard_bounds(user_info_->GetPreferredSize()); | |
227 usercard_bounds.set_width(signout_bounds.x()); | |
228 user_info_->SetBoundsRect(usercard_bounds); | |
229 } else if (signout_) { | |
230 signout_->SetBoundsRect(gfx::Rect(size())); | |
231 } else if (user_info_) { | |
232 user_info_->SetBoundsRect(gfx::Rect(size())); | |
233 } | |
234 } | |
235 | |
236 user::LoginStatus login_; | |
237 | |
238 TrayPopupLabelButtonContainer* container_; | |
239 views::View* user_info_; | |
240 views::Label* username_; | |
241 views::Label* email_; | |
242 | |
243 views::Button* signout_; | |
244 | 477 |
245 DISALLOW_COPY_AND_ASSIGN(UserView); | 478 DISALLOW_COPY_AND_ASSIGN(UserView); |
246 }; | 479 }; |
247 | 480 |
248 } // namespace tray | 481 } // namespace tray |
249 | 482 |
250 TrayUser::TrayUser(SystemTray* system_tray) | 483 TrayUser::TrayUser(SystemTray* system_tray) |
251 : SystemTrayItem(system_tray), | 484 : SystemTrayItem(system_tray), |
252 user_(NULL), | 485 user_(NULL), |
253 avatar_(NULL), | 486 avatar_(NULL), |
(...skipping 17 matching lines...) Expand all Loading... | |
271 UpdateAfterLoginStatusChange(status); | 504 UpdateAfterLoginStatusChange(status); |
272 return avatar_ ? static_cast<views::View*>(avatar_) | 505 return avatar_ ? static_cast<views::View*>(avatar_) |
273 : static_cast<views::View*>(label_); | 506 : static_cast<views::View*>(label_); |
274 } | 507 } |
275 | 508 |
276 views::View* TrayUser::CreateDefaultView(user::LoginStatus status) { | 509 views::View* TrayUser::CreateDefaultView(user::LoginStatus status) { |
277 if (status == user::LOGGED_IN_NONE) | 510 if (status == user::LOGGED_IN_NONE) |
278 return NULL; | 511 return NULL; |
279 | 512 |
280 CHECK(user_ == NULL); | 513 CHECK(user_ == NULL); |
281 user_ = new tray::UserView(status); | 514 user_ = new tray::UserView(this, status); |
282 return user_; | 515 return user_; |
283 } | 516 } |
284 | 517 |
285 views::View* TrayUser::CreateDetailedView(user::LoginStatus status) { | 518 views::View* TrayUser::CreateDetailedView(user::LoginStatus status) { |
286 return NULL; | 519 return NULL; |
287 } | 520 } |
288 | 521 |
289 void TrayUser::DestroyTrayView() { | 522 void TrayUser::DestroyTrayView() { |
290 avatar_ = NULL; | 523 avatar_ = NULL; |
291 label_ = NULL; | 524 label_ = NULL; |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
349 // Check for null to avoid crbug.com/150944. | 582 // Check for null to avoid crbug.com/150944. |
350 if (avatar_) { | 583 if (avatar_) { |
351 avatar_->SetImage( | 584 avatar_->SetImage( |
352 ash::Shell::GetInstance()->tray_delegate()->GetUserImage(), | 585 ash::Shell::GetInstance()->tray_delegate()->GetUserImage(), |
353 gfx::Size(kUserIconSize, kUserIconSize)); | 586 gfx::Size(kUserIconSize, kUserIconSize)); |
354 } | 587 } |
355 } | 588 } |
356 | 589 |
357 } // namespace internal | 590 } // namespace internal |
358 } // namespace ash | 591 } // namespace ash |
OLD | NEW |