Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(84)

Side by Side Diff: ash/system/user/tray_user.cc

Issue 11377133: Customize user details in ash system bubble for public account mode (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Massively overhauled and redone implementation. Created 8 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698