OLD | NEW |
---|---|
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 "chrome/browser/ui/views/avatar_menu_bubble_view.h" | 5 #include "chrome/browser/ui/views/avatar_menu_bubble_view.h" |
6 | 6 |
7 #include "base/utf_string_conversions.h" | 7 #include "base/utf_string_conversions.h" |
8 #include "chrome/browser/browser_process.h" | 8 #include "chrome/browser/browser_process.h" |
9 #include "chrome/browser/ui/browser.h" | 9 #include "chrome/browser/ui/browser.h" |
10 #include "chrome/browser/profiles/avatar_menu_model.h" | 10 #include "chrome/browser/profiles/avatar_menu_model.h" |
11 #include "chrome/browser/profiles/profile_info_cache.h" | 11 #include "chrome/browser/profiles/profile_info_cache.h" |
12 #include "chrome/browser/profiles/profile_manager.h" | 12 #include "chrome/browser/profiles/profile_manager.h" |
13 #include "grit/generated_resources.h" | 13 #include "grit/generated_resources.h" |
14 #include "grit/theme_resources.h" | 14 #include "grit/theme_resources.h" |
15 #include "ui/base/l10n/l10n_util.h" | 15 #include "ui/base/l10n/l10n_util.h" |
16 #include "ui/base/resource/resource_bundle.h" | 16 #include "ui/base/resource/resource_bundle.h" |
17 #include "ui/gfx/canvas.h" | 17 #include "ui/gfx/canvas.h" |
18 #include "ui/gfx/canvas_skia.h" | |
18 #include "ui/gfx/font.h" | 19 #include "ui/gfx/font.h" |
19 #include "ui/gfx/image/image.h" | 20 #include "ui/gfx/image/image.h" |
20 #include "views/controls/button/image_button.h" | 21 #include "views/controls/button/image_button.h" |
22 #include "views/controls/image_view.h" | |
23 #include "views/controls/label.h" | |
21 | 24 |
22 namespace { | 25 namespace { |
23 | 26 |
24 const int kBubbleViewMinWidth = 175; | 27 const int kBubbleViewMinWidth = 175; |
Peter Kasting
2011/10/04 20:48:52
Nit: Personally I'd find it more readable if the c
sail
2011/10/04 22:09:20
Fixed. Moved all the constants that were only bein
| |
25 const int kBubbleViewMaxWidth = 800; | 28 const int kBubbleViewMaxWidth = 800; |
26 const int kItemHeight = 32; | 29 const int kItemHeight = 44; |
27 const int kItemMarginY = 8; | 30 const int kItemMarginY = 4; |
28 const int kIconWidth = 38; | 31 const int kIconWidth = 38; |
29 const int kIconMarginX = 6; | 32 const int kIconMarginX = 6; |
30 const int kEditProfileButtonMarginX = 8; | 33 const int kNameFontDelta = 1; |
34 const int kStateFontDelta = -1; | |
35 const int kNameStatePaddingY = 2; | |
36 const float kBadgeOverlapRatioX = 1.0f / 5.0f; | |
37 const float kBadgeOverlapRatioY = 1.0f / 3.0f; | |
38 const int kSeparatorPaddingY = 5; | |
31 | 39 |
32 inline int Round(double x) { | 40 inline int Round(double x) { |
33 return static_cast<int>(x + 0.5); | 41 return static_cast<int>(x + 0.5); |
34 } | 42 } |
35 | 43 |
36 gfx::Rect GetCenteredAndScaledRect(int src_width, int src_height, | 44 gfx::Rect GetCenteredAndScaledRect(int src_width, int src_height, |
37 int dst_x, int dst_y, | 45 int dst_x, int dst_y, |
38 int dst_width, int dst_height) { | 46 int dst_width, int dst_height) { |
39 int scaled_width; | 47 int scaled_width; |
40 int scaled_height; | 48 int scaled_height; |
41 if (src_width > src_height) { | 49 if (src_width > src_height) { |
42 scaled_width = std::min(src_width, dst_width); | 50 scaled_width = std::min(src_width, dst_width); |
43 float scale = static_cast<float>(scaled_width) / | 51 float scale = static_cast<float>(scaled_width) / |
44 static_cast<float>(src_width); | 52 static_cast<float>(src_width); |
45 scaled_height = Round(src_height * scale); | 53 scaled_height = Round(src_height * scale); |
46 } else { | 54 } else { |
47 scaled_height = std::min(src_height, dst_height); | 55 scaled_height = std::min(src_height, dst_height); |
48 float scale = static_cast<float>(scaled_height) / | 56 float scale = static_cast<float>(scaled_height) / |
49 static_cast<float>(src_height); | 57 static_cast<float>(src_height); |
50 scaled_width = Round(src_width * scale); | 58 scaled_width = Round(src_width * scale); |
51 } | 59 } |
52 int x = dst_x + (dst_width - scaled_width) / 2; | 60 int x = dst_x + (dst_width - scaled_width) / 2; |
53 int y = dst_y + (dst_height - scaled_height) / 2; | 61 int y = dst_y + (dst_height - scaled_height) / 2; |
54 return gfx::Rect(x, y, scaled_width, scaled_height); | 62 return gfx::Rect(x, y, scaled_width, scaled_height); |
55 } | 63 } |
56 | 64 |
57 class ProfileItemView : public views::CustomButton { | 65 // Delegate to callback when the highlight state of a control changes. |
66 class HighlightDelegate { | |
67 public: | |
68 virtual void OnHighlightStateChanged() = 0; | |
69 }; | |
70 | |
71 // A custom Link control that forwards highlight state changes. We need to do | |
72 // this to make sure that the ProfileItemView looks highlighted even when | |
73 // the mouse is over this link. | |
74 class EditProfileLink : public views::Link { | |
75 public: | |
76 explicit EditProfileLink(const string16& title, | |
77 HighlightDelegate* delegate) | |
78 : views::Link(UTF16ToWideHack(title)), | |
79 delegate_(delegate), | |
80 state_(views::CustomButton::BS_NORMAL) { | |
81 } | |
82 | |
83 virtual void OnMouseEntered(const views::MouseEvent& event) OVERRIDE { | |
84 views::Link::OnMouseEntered(event); | |
85 state_ = views::CustomButton::BS_HOT; | |
86 delegate_->OnHighlightStateChanged(); | |
87 } | |
88 | |
89 virtual void OnMouseExited(const views::MouseEvent& event) OVERRIDE { | |
90 views::Link::OnMouseExited(event); | |
91 state_ = views::CustomButton::BS_NORMAL; | |
92 delegate_->OnHighlightStateChanged(); | |
93 } | |
94 | |
95 views::CustomButton::ButtonState state() { return state_; } | |
96 | |
97 private: | |
98 HighlightDelegate* delegate_; | |
99 views::CustomButton::ButtonState state_; | |
100 }; | |
101 | |
102 // A custom image view that ignores mouse events so that the parent can receive | |
103 // them them instead. | |
104 class ProfileImageView : public views::ImageView { | |
105 public: | |
106 virtual bool HitTest(const gfx::Point& l) const OVERRIDE { | |
107 return false; | |
108 } | |
109 }; | |
110 | |
111 // Control that shows information about a single profile. | |
112 class ProfileItemView : public views::CustomButton, | |
113 public HighlightDelegate { | |
58 public: | 114 public: |
59 ProfileItemView(const AvatarMenuModel::Item& item, | 115 ProfileItemView(const AvatarMenuModel::Item& item, |
60 views::ButtonListener* listener) | 116 views::ButtonListener* switch_profile_listener, |
61 : views::CustomButton(listener), | 117 views::LinkListener* edit_profile_listener) |
118 : views::CustomButton(switch_profile_listener), | |
62 item_(item) { | 119 item_(item) { |
120 image_view_ = new ProfileImageView(); | |
121 SkBitmap profile_icon = item_.icon; | |
122 if (item_.active) { | |
123 SkBitmap badged_icon = GetBadgedIcon(profile_icon); | |
124 image_view_->SetImage(&badged_icon); | |
125 } else { | |
126 image_view_->SetImage(&profile_icon); | |
127 } | |
128 AddChildView(image_view_); | |
129 | |
130 // Add a label to show the profile name. | |
131 name_label_ = new views::Label(UTF16ToWideHack(item_.name)); | |
132 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); | |
133 gfx::Font base_font = rb.GetFont(ResourceBundle::BaseFont); | |
134 int style = item_.active ? gfx::Font::BOLD : 0; | |
135 name_label_->SetFont(base_font.DeriveFont(kNameFontDelta, style)); | |
136 name_label_->SetHorizontalAlignment(views::Label::ALIGN_LEFT); | |
137 AddChildView(name_label_); | |
138 | |
139 // Add a label to show the sync state. | |
140 sync_state_label_ = new views::Label(UTF16ToWideHack(item_.sync_state)); | |
141 sync_state_label_->SetFont(base_font.DeriveFont(kStateFontDelta)); | |
142 sync_state_label_->SetHorizontalAlignment(views::Label::ALIGN_LEFT); | |
143 sync_state_label_->SetEnabled(false); | |
144 AddChildView(sync_state_label_); | |
145 | |
146 // Add an edit profile link. | |
147 edit_link_ = new EditProfileLink( | |
148 l10n_util::GetStringUTF16(IDS_PROFILES_EDIT_PROFILE_LINK), this); | |
149 edit_link_->set_listener(edit_profile_listener); | |
150 edit_link_->SetHorizontalAlignment(views::Label::ALIGN_LEFT); | |
151 edit_link_->SetNormalColor(SkColorSetRGB(0, 0x79, 0xda)); | |
Peter Kasting
2011/10/04 20:48:52
This is dangerous. The background color could ver
sail
2011/10/04 22:09:20
I'd like to fix this separately as a part of bug 9
Peter Kasting
2011/10/04 22:12:48
That's fine.
| |
152 AddChildView(edit_link_); | |
153 | |
154 OnHighlightStateChanged(); | |
63 } | 155 } |
64 | 156 |
65 virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE { | 157 virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE { |
66 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); | 158 if (IsHighlighted()) { |
67 | 159 canvas->FillRectInt(SkColorSetRGB(227, 237, 246), 0, 0, |
Peter Kasting
2011/10/04 20:48:52
Nit: You used hex above and decimal here.
This is
sail
2011/10/04 22:09:20
Changed to hex. As above, I'm working on fixing th
| |
68 // Draw the profile icon on the left. | 160 width(), height()); |
69 SkBitmap profile_icon = item_.icon; | |
70 gfx::Rect profile_icon_rect = GetCenteredAndScaledRect( | |
71 profile_icon.width(), profile_icon.height(), | |
72 0, 0, kIconWidth, height()); | |
73 canvas->DrawBitmapInt(profile_icon, 0, 0, profile_icon.width(), | |
74 profile_icon.height(), profile_icon_rect.x(), | |
75 profile_icon_rect.y(), profile_icon_rect.width(), | |
76 profile_icon_rect.height(), false); | |
77 | |
78 // If this profile is selected then draw a check mark on the bottom right | |
79 // of the profile icon. | |
80 if (item_.active) { | |
81 SkBitmap check_icon = rb.GetImageNamed(IDR_PROFILE_SELECTED); | |
82 int y = profile_icon_rect.bottom() - check_icon.height(); | |
83 int x = profile_icon_rect.right() - check_icon.width() + 2; | |
84 canvas->DrawBitmapInt(check_icon, 0, 0, check_icon.width(), | |
85 check_icon.height(), x, y, check_icon.width(), | |
86 check_icon.height(), false); | |
87 } | 161 } |
88 | |
89 // Draw the profile name to the right of the profile icon. | |
90 int name_x = profile_icon_rect.right() + kIconMarginX; | |
91 canvas->DrawStringInt(item_.name, rb.GetFont(ResourceBundle::BaseFont), | |
92 GetNameColor(), name_x, 0, width() - name_x, | |
93 height()); | |
94 } | 162 } |
95 | 163 |
96 virtual gfx::Size GetPreferredSize() OVERRIDE { | 164 virtual gfx::Size GetPreferredSize() OVERRIDE { |
97 gfx::Font font = ResourceBundle::GetSharedInstance().GetFont( | 165 int width = std::max(name_label_->GetPreferredSize().width(), |
98 ResourceBundle::BaseFont); | 166 sync_state_label_->GetPreferredSize().width()); |
99 int title_width = font.GetStringWidth(item_.name); | 167 width = std::max(edit_link_->GetPreferredSize().width(), |
100 return gfx::Size(kIconWidth + kIconMarginX + title_width, kItemHeight); | 168 width); |
169 return gfx::Size(kIconWidth + kIconMarginX + width, kItemHeight); | |
101 } | 170 } |
102 | 171 |
103 private: | 172 virtual void Layout() OVERRIDE { |
104 SkColor GetNameColor() { | 173 // Profile icon. |
105 bool normal = state() != views::CustomButton::BS_PUSHED && | 174 const SkBitmap& icon = image_view_->GetImage(); |
106 state() != views::CustomButton::BS_HOT; | 175 gfx::Rect icon_rect = GetCenteredAndScaledRect( |
107 if (item_.active) | 176 icon.width(), icon.height(), 0, 0, kIconWidth, height()); |
108 return normal ? SkColorSetRGB(30, 30, 30) : SkColorSetRGB(0, 0, 0); | 177 image_view_->SetBoundsRect(icon_rect); |
109 return normal ? SkColorSetRGB(128, 128, 128) : SkColorSetRGB(64, 64, 64); | 178 |
179 int label_x = icon_rect.right() + kIconMarginX; | |
180 int max_label_width = width() - label_x; | |
181 gfx::Size name_size = name_label_->GetPreferredSize(); | |
182 name_size.set_width(std::max(name_size.width(), max_label_width)); | |
Peter Kasting
2011/10/04 20:48:52
Do you mean std::min() in these three cases?
sail
2011/10/04 22:09:20
Ouch, good catch. Fixed.
| |
183 gfx::Size state_size = sync_state_label_->GetPreferredSize(); | |
184 state_size.set_width(std::max(state_size.width(), max_label_width)); | |
185 gfx::Size edit_size = edit_link_->GetPreferredSize(); | |
186 edit_size.set_width(std::max(edit_size.width(), max_label_width)); | |
187 | |
188 int labels_height = name_size.height() + edit_size.height() + | |
189 kNameStatePaddingY; | |
190 int y = (height() - labels_height) / 2; | |
191 name_label_->SetBounds(label_x, y, name_size.width(), name_size.height()); | |
192 | |
193 int bottom = y + name_size.height() + kNameStatePaddingY + | |
194 std::max(state_size.height(), edit_size.height()); | |
Peter Kasting
2011/10/04 20:48:52
If you're using max(state, edit) for the height he
sail
2011/10/04 22:09:20
Done. Good idea.
| |
195 sync_state_label_->SetBounds(label_x, bottom - state_size.height(), | |
196 state_size.width(), state_size.height()); | |
197 // The edit link overlaps the sync state label. | |
198 edit_link_->SetBounds(label_x, bottom - edit_size.height(), | |
199 edit_size.width(), edit_size.height()); | |
110 } | 200 } |
111 | 201 |
202 virtual void OnHighlightStateChanged() OVERRIDE { | |
203 bool show_edit = IsHighlighted() && item_.active; | |
204 sync_state_label_->SetVisible(!show_edit); | |
205 edit_link_->SetVisible(show_edit); | |
206 SchedulePaint(); | |
207 } | |
208 | |
209 virtual void OnMouseEntered(const views::MouseEvent& event) OVERRIDE { | |
210 views::CustomButton::OnMouseEntered(event); | |
211 OnHighlightStateChanged(); | |
212 } | |
213 | |
214 virtual void OnMouseExited(const views::MouseEvent& event) OVERRIDE { | |
215 views::CustomButton::OnMouseExited(event); | |
216 OnHighlightStateChanged(); | |
217 } | |
218 | |
219 EditProfileLink* edit_link() { return edit_link_; } | |
220 const AvatarMenuModel::Item& item() { return item_; } | |
221 | |
222 private: | |
223 bool IsHighlighted() { | |
224 return state() == views::CustomButton::BS_PUSHED || | |
225 state() == views::CustomButton::BS_HOT || | |
226 edit_link_->state() == views::CustomButton::BS_PUSHED || | |
227 edit_link_->state() == views::CustomButton::BS_HOT; | |
228 } | |
229 | |
230 SkBitmap GetBadgedIcon(const SkBitmap& icon) { | |
231 gfx::Rect icon_rect = GetCenteredAndScaledRect( | |
232 icon.width(), icon.height(), 0, 0, kIconWidth, kItemHeight); | |
233 | |
234 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); | |
235 SkBitmap badge = rb.GetImageNamed(IDR_PROFILE_SELECTED); | |
236 int width = icon_rect.width() + badge.width() * kBadgeOverlapRatioX; | |
237 int height = icon_rect.height() + badge.height() * kBadgeOverlapRatioY; | |
238 | |
239 gfx::CanvasSkia canvas(width, height, false); | |
240 canvas.DrawBitmapInt(icon, 0, 0, icon.width(), icon.height(), 0, 0, | |
241 icon_rect.width(), icon_rect.height(), true); | |
242 canvas.DrawBitmapInt(badge, width - badge.width(), height - badge.height()); | |
243 return canvas.ExtractBitmap(); | |
244 } | |
245 | |
246 EditProfileLink* edit_link_; | |
247 views::ImageView* image_view_; | |
112 AvatarMenuModel::Item item_; | 248 AvatarMenuModel::Item item_; |
249 views::Label* name_label_; | |
250 views::Label* sync_state_label_; | |
113 }; | 251 }; |
114 | 252 |
115 } // namespace | 253 } // namespace |
116 | 254 |
117 class EditProfileButton : public views::ImageButton { | |
118 public: | |
119 EditProfileButton(size_t profile_index, views::ButtonListener* listener) | |
120 : views::ImageButton(listener), | |
121 profile_index_(profile_index) { | |
122 } | |
123 | |
124 size_t profile_index() { | |
125 return profile_index_; | |
126 } | |
127 | |
128 private: | |
129 size_t profile_index_; | |
130 }; | |
131 | |
132 AvatarMenuBubbleView::AvatarMenuBubbleView(Browser* browser) | 255 AvatarMenuBubbleView::AvatarMenuBubbleView(Browser* browser) |
133 : add_profile_link_(NULL), | 256 : add_profile_link_(NULL), |
134 browser_(browser), | 257 browser_(browser) { |
135 edit_profile_button_(NULL) { | |
136 avatar_menu_model_.reset(new AvatarMenuModel( | 258 avatar_menu_model_.reset(new AvatarMenuModel( |
137 &g_browser_process->profile_manager()->GetProfileInfoCache(), | 259 &g_browser_process->profile_manager()->GetProfileInfoCache(), |
138 this, browser_)); | 260 this, browser_)); |
139 // Build the menu for the first time. | 261 // Build the menu for the first time. |
140 OnAvatarMenuModelChanged(avatar_menu_model_.get()); | 262 OnAvatarMenuModelChanged(avatar_menu_model_.get()); |
141 } | 263 } |
142 | 264 |
143 AvatarMenuBubbleView::~AvatarMenuBubbleView() { | 265 AvatarMenuBubbleView::~AvatarMenuBubbleView() { |
144 } | 266 } |
145 | 267 |
146 gfx::Size AvatarMenuBubbleView::GetPreferredSize() { | 268 gfx::Size AvatarMenuBubbleView::GetPreferredSize() { |
147 int max_width = 0; | 269 int max_width = 0; |
148 int total_height = 0; | 270 int total_height = 0; |
149 for (size_t i = 0; i < item_views_.size(); ++i) { | 271 for (size_t i = 0; i < item_views_.size(); ++i) { |
150 gfx::Size size = item_views_[i]->GetPreferredSize(); | 272 gfx::Size size = item_views_[i]->GetPreferredSize(); |
151 if (i == edit_profile_button_->profile_index()) { | |
152 size.set_width(size.width() + | |
153 edit_profile_button_->GetPreferredSize().width() + | |
154 kEditProfileButtonMarginX); | |
155 } | |
156 | |
157 max_width = std::max(max_width, size.width()); | 273 max_width = std::max(max_width, size.width()); |
158 total_height += size.height() + kItemMarginY; | 274 total_height += size.height() + kItemMarginY; |
159 } | 275 } |
160 | 276 |
277 total_height += kSeparatorPaddingY * 2 + | |
278 separator_->GetPreferredSize().height(); | |
279 | |
161 gfx::Size add_profile_size = add_profile_link_->GetPreferredSize(); | 280 gfx::Size add_profile_size = add_profile_link_->GetPreferredSize(); |
162 max_width = std::max(max_width, | 281 max_width = std::max(max_width, |
163 add_profile_size.width() + kIconWidth + kIconMarginX); | 282 add_profile_size.width() + kIconWidth + kIconMarginX); |
164 total_height += add_profile_link_->GetPreferredSize().height(); | 283 total_height += add_profile_link_->GetPreferredSize().height(); |
165 | 284 |
166 int total_width = std::min(std::max(max_width, kBubbleViewMinWidth), | 285 int total_width = std::min(std::max(max_width, kBubbleViewMinWidth), |
167 kBubbleViewMaxWidth); | 286 kBubbleViewMaxWidth); |
168 return gfx::Size(total_width, total_height); | 287 return gfx::Size(total_width, total_height); |
169 } | 288 } |
170 | 289 |
171 void AvatarMenuBubbleView::Layout() { | 290 void AvatarMenuBubbleView::Layout() { |
172 int y = 0; | 291 int y = 0; |
173 for (size_t i = 0; i < item_views_.size(); ++i) { | 292 for (size_t i = 0; i < item_views_.size(); ++i) { |
174 views::CustomButton* item_view = item_views_[i]; | 293 views::CustomButton* item_view = item_views_[i]; |
175 int item_height = item_view->GetPreferredSize().height(); | 294 int item_height = item_view->GetPreferredSize().height(); |
176 int item_width = width(); | 295 int item_width = width(); |
177 | |
178 if (i == edit_profile_button_->profile_index()) { | |
179 gfx::Size edit_size = edit_profile_button_->GetPreferredSize(); | |
180 edit_profile_button_->SetBounds(width() - edit_size.width(), y, | |
181 edit_size.width(), item_height); | |
182 item_width -= edit_size.width() + kEditProfileButtonMarginX; | |
183 } | |
184 | |
185 item_view->SetBounds(0, y, item_width, item_height); | 296 item_view->SetBounds(0, y, item_width, item_height); |
186 y += item_height + kItemMarginY; | 297 y += item_height + kItemMarginY; |
187 } | 298 } |
188 | 299 |
300 y += kSeparatorPaddingY; | |
301 int separator_height = separator_->GetPreferredSize().height(); | |
302 separator_->SetBounds(0, y, width(), separator_height); | |
303 y += kSeparatorPaddingY + separator_height; | |
304 | |
189 add_profile_link_->SetBounds(kIconWidth + kIconMarginX, y, width(), | 305 add_profile_link_->SetBounds(kIconWidth + kIconMarginX, y, width(), |
190 add_profile_link_->GetPreferredSize().height()); | 306 add_profile_link_->GetPreferredSize().height()); |
191 } | 307 } |
192 | 308 |
193 void AvatarMenuBubbleView::ButtonPressed(views::Button* sender, | 309 void AvatarMenuBubbleView::ButtonPressed(views::Button* sender, |
194 const views::Event& event) { | 310 const views::Event& event) { |
195 if (sender == edit_profile_button_) { | 311 for (size_t i = 0; i < item_views_.size(); ++i) { |
196 avatar_menu_model_->EditProfile(edit_profile_button_->profile_index()); | 312 ProfileItemView* item_view = static_cast<ProfileItemView*>(item_views_[i]); |
197 } else { | 313 if (sender == item_view) { |
198 for (size_t i = 0; i < item_views_.size(); ++i) { | 314 // Clicking on the active profile shouldn't do anything. |
199 if (sender == item_views_[i]) { | 315 if (!item_view->item().active) |
200 avatar_menu_model_->SwitchToProfile(i); | 316 avatar_menu_model_->SwitchToProfile(i); |
201 break; | 317 break; |
202 } | |
203 } | 318 } |
204 } | 319 } |
205 } | 320 } |
206 | 321 |
207 void AvatarMenuBubbleView::LinkClicked(views::Link* source, int event_flags) { | 322 void AvatarMenuBubbleView::LinkClicked(views::Link* source, int event_flags) { |
208 DCHECK_EQ(source, add_profile_link_); | 323 if (source == add_profile_link_) { |
209 avatar_menu_model_->AddNewProfile(); | 324 avatar_menu_model_->AddNewProfile(); |
325 return; | |
326 } | |
327 | |
328 for (size_t i = 0; i < item_views_.size(); ++i) { | |
329 ProfileItemView* item_view = static_cast<ProfileItemView*>(item_views_[i]); | |
330 if (source == item_view->edit_link()) { | |
331 avatar_menu_model_->EditProfile(i); | |
332 return; | |
333 } | |
334 } | |
210 } | 335 } |
211 | 336 |
212 void AvatarMenuBubbleView::BubbleClosing(Bubble* bubble, | 337 void AvatarMenuBubbleView::BubbleClosing(Bubble* bubble, |
213 bool closed_by_escape) { | 338 bool closed_by_escape) { |
214 } | 339 } |
215 | 340 |
216 bool AvatarMenuBubbleView::CloseOnEscape() { | 341 bool AvatarMenuBubbleView::CloseOnEscape() { |
217 return true; | 342 return true; |
218 } | 343 } |
219 | 344 |
220 bool AvatarMenuBubbleView::FadeInOnShow() { | 345 bool AvatarMenuBubbleView::FadeInOnShow() { |
221 return false; | 346 return false; |
222 } | 347 } |
223 | 348 |
224 void AvatarMenuBubbleView::OnAvatarMenuModelChanged( | 349 void AvatarMenuBubbleView::OnAvatarMenuModelChanged( |
225 AvatarMenuModel* avatar_menu_model) { | 350 AvatarMenuModel* avatar_menu_model) { |
226 // Unset all our child view references and call RemoveAllChildViews() which | 351 // Unset all our child view references and call RemoveAllChildViews() which |
227 // will actually delete them. | 352 // will actually delete them. |
228 add_profile_link_ = NULL; | 353 add_profile_link_ = NULL; |
229 edit_profile_button_ = NULL; | |
230 item_views_.clear(); | 354 item_views_.clear(); |
231 RemoveAllChildViews(true); | 355 RemoveAllChildViews(true); |
232 | 356 |
233 for (size_t i = 0; i < avatar_menu_model->GetNumberOfItems(); ++i) { | 357 for (size_t i = 0; i < avatar_menu_model->GetNumberOfItems(); ++i) { |
234 const AvatarMenuModel::Item& item = avatar_menu_model->GetItemAt(i); | 358 const AvatarMenuModel::Item& item = avatar_menu_model->GetItemAt(i); |
235 ProfileItemView* item_view = new ProfileItemView(item, this); | 359 ProfileItemView* item_view = new ProfileItemView(item, this, this); |
236 item_view->SetAccessibleName(l10n_util::GetStringFUTF16( | 360 item_view->SetAccessibleName(l10n_util::GetStringFUTF16( |
237 IDS_PROFILES_SWITCH_TO_PROFILE_ACCESSIBLE_NAME, item.name)); | 361 IDS_PROFILES_SWITCH_TO_PROFILE_ACCESSIBLE_NAME, item.name)); |
238 AddChildView(item_view); | 362 AddChildView(item_view); |
239 item_views_.push_back(item_view); | 363 item_views_.push_back(item_view); |
364 } | |
240 | 365 |
241 if (item.active) { | 366 separator_ = new views::Separator(); |
242 DCHECK(!edit_profile_button_); | 367 AddChildView(separator_); |
243 edit_profile_button_ = new EditProfileButton(i, this); | |
244 edit_profile_button_->SetAccessibleName(l10n_util::GetStringFUTF16( | |
245 IDS_PROFILES_CUSTOMIZE_PROFILE_ACCESSIBLE_NAME, item.name)); | |
246 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); | |
247 edit_profile_button_->SetImage(views::CustomButton::BS_NORMAL, | |
248 rb.GetImageNamed(IDR_PROFILE_EDIT)); | |
249 edit_profile_button_->SetImage(views::CustomButton::BS_HOT, | |
250 rb.GetImageNamed(IDR_PROFILE_EDIT_HOVER)); | |
251 edit_profile_button_->SetImage(views::CustomButton::BS_PUSHED, | |
252 rb.GetImageNamed(IDR_PROFILE_EDIT_PRESSED)); | |
253 edit_profile_button_->SetImageAlignment(views::ImageButton::ALIGN_CENTER, | |
254 views::ImageButton::ALIGN_MIDDLE); | |
255 AddChildView(edit_profile_button_); | |
256 } | |
257 } | |
258 | 368 |
259 add_profile_link_ = new views::Link(UTF16ToWide( | 369 add_profile_link_ = new views::Link(UTF16ToWide( |
260 l10n_util::GetStringUTF16(IDS_PROFILES_CREATE_NEW_PROFILE_LINK))); | 370 l10n_util::GetStringUTF16(IDS_PROFILES_CREATE_NEW_PROFILE_LINK))); |
261 add_profile_link_->set_listener(this); | 371 add_profile_link_->set_listener(this); |
262 add_profile_link_->SetHorizontalAlignment(views::Label::ALIGN_LEFT); | 372 add_profile_link_->SetHorizontalAlignment(views::Label::ALIGN_LEFT); |
263 add_profile_link_->SetNormalColor(SkColorSetRGB(0, 0x79, 0xda)); | 373 add_profile_link_->SetNormalColor(SkColorSetRGB(0, 0x79, 0xda)); |
264 AddChildView(add_profile_link_); | 374 AddChildView(add_profile_link_); |
265 | 375 |
266 PreferredSizeChanged(); | 376 PreferredSizeChanged(); |
267 } | 377 } |
OLD | NEW |