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 <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/utf_string_conversions.h" | 9 #include "base/utf_string_conversions.h" |
10 #include "chrome/browser/browser_process.h" | 10 #include "chrome/browser/browser_process.h" |
11 #include "chrome/browser/ui/browser.h" | 11 #include "chrome/browser/ui/browser.h" |
12 #include "chrome/browser/profiles/avatar_menu_model.h" | 12 #include "chrome/browser/profiles/avatar_menu_model.h" |
13 #include "chrome/browser/profiles/profile_info_cache.h" | 13 #include "chrome/browser/profiles/profile_info_cache.h" |
14 #include "chrome/browser/profiles/profile_manager.h" | 14 #include "chrome/browser/profiles/profile_manager.h" |
15 #include "grit/generated_resources.h" | 15 #include "grit/generated_resources.h" |
16 #include "grit/theme_resources.h" | 16 #include "grit/theme_resources.h" |
17 #include "ui/base/l10n/l10n_util.h" | 17 #include "ui/base/l10n/l10n_util.h" |
18 #include "ui/base/resource/resource_bundle.h" | 18 #include "ui/base/resource/resource_bundle.h" |
19 #include "ui/gfx/canvas.h" | 19 #include "ui/gfx/canvas.h" |
20 #include "ui/gfx/canvas_skia.h" | 20 #include "ui/gfx/canvas_skia.h" |
21 #include "ui/gfx/color_utils.h" | |
22 #include "ui/gfx/font.h" | 21 #include "ui/gfx/font.h" |
23 #include "ui/gfx/image/image.h" | 22 #include "ui/gfx/image/image.h" |
24 #include "views/controls/button/image_button.h" | 23 #include "views/controls/button/image_button.h" |
25 #include "views/controls/image_view.h" | 24 #include "views/controls/image_view.h" |
26 #include "views/controls/label.h" | 25 #include "views/controls/label.h" |
27 | 26 |
28 namespace { | 27 namespace { |
29 | 28 |
30 const int kItemHeight = 44; | 29 const int kItemHeight = 44; |
31 const int kItemMarginY = 4; | 30 const int kItemMarginY = 4; |
32 const int kIconWidth = 38; | 31 const int kIconWidth = 38; |
33 const int kIconMarginX = 6; | 32 const int kIconMarginX = 6; |
34 const int kSeparatorPaddingY = 5; | 33 const int kSeparatorPaddingY = 5; |
35 const SkColor kHighlightBackgroundColor = SkColorSetRGB(0xe3, 0xed, 0xf6); | |
36 const SkColor kLinkColor = SkColorSetRGB(0, 0x79, 0xda); | |
37 | 34 |
38 inline int Round(double x) { | 35 inline int Round(double x) { |
39 return static_cast<int>(x + 0.5); | 36 return static_cast<int>(x + 0.5); |
40 } | 37 } |
41 | 38 |
42 gfx::Rect GetCenteredAndScaledRect(int src_width, int src_height, | 39 gfx::Rect GetCenteredAndScaledRect(int src_width, int src_height, |
43 int dst_x, int dst_y, | 40 int dst_x, int dst_y, |
44 int dst_width, int dst_height) { | 41 int dst_width, int dst_height) { |
45 int scaled_width; | 42 int scaled_width; |
46 int scaled_height; | 43 int scaled_height; |
47 if (src_width > src_height) { | 44 if (src_width > src_height) { |
48 scaled_width = std::min(src_width, dst_width); | 45 scaled_width = std::min(src_width, dst_width); |
49 float scale = static_cast<float>(scaled_width) / | 46 float scale = static_cast<float>(scaled_width) / |
50 static_cast<float>(src_width); | 47 static_cast<float>(src_width); |
51 scaled_height = Round(src_height * scale); | 48 scaled_height = Round(src_height * scale); |
52 } else { | 49 } else { |
53 scaled_height = std::min(src_height, dst_height); | 50 scaled_height = std::min(src_height, dst_height); |
54 float scale = static_cast<float>(scaled_height) / | 51 float scale = static_cast<float>(scaled_height) / |
55 static_cast<float>(src_height); | 52 static_cast<float>(src_height); |
56 scaled_width = Round(src_width * scale); | 53 scaled_width = Round(src_width * scale); |
57 } | 54 } |
58 int x = dst_x + (dst_width - scaled_width) / 2; | 55 int x = dst_x + (dst_width - scaled_width) / 2; |
59 int y = dst_y + (dst_height - scaled_height) / 2; | 56 int y = dst_y + (dst_height - scaled_height) / 2; |
60 return gfx::Rect(x, y, scaled_width, scaled_height); | 57 return gfx::Rect(x, y, scaled_width, scaled_height); |
61 } | 58 } |
62 | 59 |
| 60 |
| 61 // HighlightDelegate ---------------------------------------------------------- |
| 62 |
63 // Delegate to callback when the highlight state of a control changes. | 63 // Delegate to callback when the highlight state of a control changes. |
64 class HighlightDelegate { | 64 class HighlightDelegate { |
65 public: | 65 public: |
66 virtual ~HighlightDelegate() {} | 66 virtual ~HighlightDelegate() {} |
67 virtual void OnHighlightStateChanged() = 0; | 67 virtual void OnHighlightStateChanged() = 0; |
68 }; | 68 }; |
69 | 69 |
| 70 |
| 71 // EditProfileLink ------------------------------------------------------------ |
| 72 |
70 // A custom Link control that forwards highlight state changes. We need to do | 73 // A custom Link control that forwards highlight state changes. We need to do |
71 // this to make sure that the ProfileItemView looks highlighted even when | 74 // this to make sure that the ProfileItemView looks highlighted even when |
72 // the mouse is over this link. | 75 // the mouse is over this link. |
73 class EditProfileLink : public views::Link { | 76 class EditProfileLink : public views::Link { |
74 public: | 77 public: |
75 explicit EditProfileLink(const string16& title, | 78 explicit EditProfileLink(const string16& title, |
76 HighlightDelegate* delegate) | 79 HighlightDelegate* delegate); |
77 : views::Link(title), | |
78 delegate_(delegate), | |
79 state_(views::CustomButton::BS_NORMAL) { | |
80 } | |
81 | 80 |
82 virtual void OnMouseEntered(const views::MouseEvent& event) OVERRIDE { | 81 virtual void OnMouseEntered(const views::MouseEvent& event) OVERRIDE; |
83 views::Link::OnMouseEntered(event); | 82 virtual void OnMouseExited(const views::MouseEvent& event) OVERRIDE; |
84 state_ = views::CustomButton::BS_HOT; | |
85 delegate_->OnHighlightStateChanged(); | |
86 } | |
87 | |
88 virtual void OnMouseExited(const views::MouseEvent& event) OVERRIDE { | |
89 views::Link::OnMouseExited(event); | |
90 state_ = views::CustomButton::BS_NORMAL; | |
91 delegate_->OnHighlightStateChanged(); | |
92 } | |
93 | 83 |
94 views::CustomButton::ButtonState state() { return state_; } | 84 views::CustomButton::ButtonState state() { return state_; } |
95 | 85 |
96 private: | 86 private: |
97 HighlightDelegate* delegate_; | 87 HighlightDelegate* delegate_; |
98 views::CustomButton::ButtonState state_; | 88 views::CustomButton::ButtonState state_; |
99 }; | 89 }; |
100 | 90 |
| 91 EditProfileLink::EditProfileLink(const string16& title, |
| 92 HighlightDelegate* delegate) |
| 93 : views::Link(title), |
| 94 delegate_(delegate), |
| 95 state_(views::CustomButton::BS_NORMAL) { |
| 96 } |
| 97 |
| 98 void EditProfileLink::OnMouseEntered(const views::MouseEvent& event) { |
| 99 views::Link::OnMouseEntered(event); |
| 100 state_ = views::CustomButton::BS_HOT; |
| 101 delegate_->OnHighlightStateChanged(); |
| 102 } |
| 103 |
| 104 void EditProfileLink::OnMouseExited(const views::MouseEvent& event) { |
| 105 views::Link::OnMouseExited(event); |
| 106 state_ = views::CustomButton::BS_NORMAL; |
| 107 delegate_->OnHighlightStateChanged(); |
| 108 } |
| 109 |
| 110 |
| 111 // ProfileImageView ----------------------------------------------------------- |
| 112 |
101 // A custom image view that ignores mouse events so that the parent can receive | 113 // A custom image view that ignores mouse events so that the parent can receive |
102 // them them instead. | 114 // them them instead. |
103 class ProfileImageView : public views::ImageView { | 115 class ProfileImageView : public views::ImageView { |
104 public: | 116 public: |
105 virtual bool HitTest(const gfx::Point& l) const OVERRIDE { | 117 virtual bool HitTest(const gfx::Point& l) const OVERRIDE; |
106 return false; | |
107 } | |
108 }; | 118 }; |
109 | 119 |
| 120 bool ProfileImageView::HitTest(const gfx::Point& l) const { |
| 121 return false; |
| 122 } |
| 123 |
| 124 |
| 125 // ProfileItemView ------------------------------------------------------------ |
| 126 |
110 // Control that shows information about a single profile. | 127 // Control that shows information about a single profile. |
111 class ProfileItemView : public views::CustomButton, | 128 class ProfileItemView : public views::CustomButton, |
112 public HighlightDelegate { | 129 public HighlightDelegate { |
113 public: | 130 public: |
114 ProfileItemView(const AvatarMenuModel::Item& item, | 131 ProfileItemView(const AvatarMenuModel::Item& item, |
115 views::ButtonListener* switch_profile_listener, | 132 views::ButtonListener* switch_profile_listener, |
116 views::LinkListener* edit_profile_listener) | 133 views::LinkListener* edit_profile_listener); |
117 : views::CustomButton(switch_profile_listener), | 134 |
118 item_(item) { | 135 virtual gfx::Size GetPreferredSize() OVERRIDE; |
119 image_view_ = new ProfileImageView(); | 136 virtual void Layout() OVERRIDE; |
120 SkBitmap profile_icon = item_.icon; | 137 virtual void OnMouseEntered(const views::MouseEvent& event) OVERRIDE; |
121 if (item_.active) { | 138 virtual void OnMouseExited(const views::MouseEvent& event) OVERRIDE; |
122 SkBitmap badged_icon = GetBadgedIcon(profile_icon); | 139 |
123 image_view_->SetImage(&badged_icon); | 140 virtual void OnHighlightStateChanged() OVERRIDE; |
124 } else { | |
125 image_view_->SetImage(&profile_icon); | |
126 } | |
127 AddChildView(image_view_); | |
128 | |
129 // Add a label to show the profile name. | |
130 name_label_ = new views::Label(item_.name); | |
131 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); | |
132 gfx::Font base_font = rb.GetFont(ResourceBundle::BaseFont); | |
133 int style = item_.active ? gfx::Font::BOLD : 0; | |
134 const int kNameFontDelta = 1; | |
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(item_.sync_state); | |
141 const int kStateFontDelta = -1; | |
142 sync_state_label_->SetFont(base_font.DeriveFont(kStateFontDelta)); | |
143 sync_state_label_->SetHorizontalAlignment(views::Label::ALIGN_LEFT); | |
144 sync_state_label_->SetEnabled(false); | |
145 AddChildView(sync_state_label_); | |
146 | |
147 // Add an edit profile link. | |
148 edit_link_ = new EditProfileLink( | |
149 l10n_util::GetStringUTF16(IDS_PROFILES_EDIT_PROFILE_LINK), this); | |
150 edit_link_->set_listener(edit_profile_listener); | |
151 edit_link_->SetHorizontalAlignment(views::Label::ALIGN_LEFT); | |
152 edit_link_->MakeReadableOverBackgroundColor(kHighlightBackgroundColor); | |
153 edit_link_->SetNormalColor( | |
154 color_utils::GetReadableColor(kLinkColor, kHighlightBackgroundColor)); | |
155 edit_link_->SetHasFocusBorder(true); | |
156 AddChildView(edit_link_); | |
157 | |
158 OnHighlightStateChanged(); | |
159 } | |
160 | |
161 virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE { | |
162 if (IsHighlighted()) { | |
163 canvas->FillRectInt(kHighlightBackgroundColor, 0, 0, | |
164 width(), height()); | |
165 } | |
166 } | |
167 | |
168 virtual gfx::Size GetPreferredSize() OVERRIDE { | |
169 int width = std::max(name_label_->GetPreferredSize().width(), | |
170 sync_state_label_->GetPreferredSize().width()); | |
171 width = std::max(edit_link_->GetPreferredSize().width(), | |
172 width); | |
173 return gfx::Size(kIconWidth + kIconMarginX + width, kItemHeight); | |
174 } | |
175 | |
176 virtual void Layout() OVERRIDE { | |
177 // Profile icon. | |
178 const SkBitmap& icon = image_view_->GetImage(); | |
179 gfx::Rect icon_rect = GetCenteredAndScaledRect( | |
180 icon.width(), icon.height(), 0, 0, kIconWidth, height()); | |
181 image_view_->SetBoundsRect(icon_rect); | |
182 | |
183 int label_x = icon_rect.right() + kIconMarginX; | |
184 int max_label_width = width() - label_x; | |
185 gfx::Size name_size = name_label_->GetPreferredSize(); | |
186 name_size.set_width(std::min(name_size.width(), max_label_width)); | |
187 gfx::Size state_size = sync_state_label_->GetPreferredSize(); | |
188 state_size.set_width(std::min(state_size.width(), max_label_width)); | |
189 gfx::Size edit_size = edit_link_->GetPreferredSize(); | |
190 edit_size.set_width(std::min(edit_size.width(), max_label_width)); | |
191 | |
192 const int kNameStatePaddingY = 2; | |
193 int labels_height = name_size.height() + kNameStatePaddingY + | |
194 std::max(state_size.height(), edit_size.height()); | |
195 int y = (height() - labels_height) / 2; | |
196 name_label_->SetBounds(label_x, y, name_size.width(), name_size.height()); | |
197 | |
198 int bottom = y + labels_height; | |
199 sync_state_label_->SetBounds(label_x, bottom - state_size.height(), | |
200 state_size.width(), state_size.height()); | |
201 // The edit link overlaps the sync state label. | |
202 edit_link_->SetBounds(label_x, bottom - edit_size.height(), | |
203 edit_size.width(), edit_size.height()); | |
204 } | |
205 | |
206 virtual void OnHighlightStateChanged() OVERRIDE { | |
207 bool is_highlighted = IsHighlighted(); | |
208 bool show_edit = is_highlighted && item_.active; | |
209 sync_state_label_->SetVisible(!show_edit); | |
210 edit_link_->SetVisible(show_edit); | |
211 | |
212 SkColor background_color = | |
213 is_highlighted ? kHighlightBackgroundColor : Bubble::kBackgroundColor; | |
214 name_label_->MakeReadableOverBackgroundColor(background_color); | |
215 sync_state_label_->MakeReadableOverBackgroundColor(background_color); | |
216 | |
217 SchedulePaint(); | |
218 } | |
219 | |
220 virtual void OnMouseEntered(const views::MouseEvent& event) OVERRIDE { | |
221 views::CustomButton::OnMouseEntered(event); | |
222 OnHighlightStateChanged(); | |
223 } | |
224 | |
225 virtual void OnMouseExited(const views::MouseEvent& event) OVERRIDE { | |
226 views::CustomButton::OnMouseExited(event); | |
227 OnHighlightStateChanged(); | |
228 } | |
229 | 141 |
230 EditProfileLink* edit_link() { return edit_link_; } | 142 EditProfileLink* edit_link() { return edit_link_; } |
231 const AvatarMenuModel::Item& item() { return item_; } | 143 const AvatarMenuModel::Item& item() { return item_; } |
232 | 144 |
233 private: | 145 private: |
234 bool IsHighlighted() { | 146 static SkBitmap GetBadgedIcon(const SkBitmap& icon); |
235 return state() == views::CustomButton::BS_PUSHED || | 147 |
236 state() == views::CustomButton::BS_HOT || | 148 bool IsHighlighted() const; |
237 edit_link_->state() == views::CustomButton::BS_PUSHED || | |
238 edit_link_->state() == views::CustomButton::BS_HOT; | |
239 } | |
240 | |
241 SkBitmap GetBadgedIcon(const SkBitmap& icon) { | |
242 gfx::Rect icon_rect = GetCenteredAndScaledRect( | |
243 icon.width(), icon.height(), 0, 0, kIconWidth, kItemHeight); | |
244 | |
245 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); | |
246 SkBitmap badge = rb.GetImageNamed(IDR_PROFILE_SELECTED); | |
247 const float kBadgeOverlapRatioX = 1.0f / 5.0f; | |
248 int width = icon_rect.width() + badge.width() * kBadgeOverlapRatioX; | |
249 const float kBadgeOverlapRatioY = 1.0f / 3.0f; | |
250 int height = icon_rect.height() + badge.height() * kBadgeOverlapRatioY; | |
251 | |
252 gfx::CanvasSkia canvas(width, height, false); | |
253 canvas.DrawBitmapInt(icon, 0, 0, icon.width(), icon.height(), 0, 0, | |
254 icon_rect.width(), icon_rect.height(), true); | |
255 canvas.DrawBitmapInt(badge, width - badge.width(), height - badge.height()); | |
256 return canvas.ExtractBitmap(); | |
257 } | |
258 | 149 |
259 EditProfileLink* edit_link_; | 150 EditProfileLink* edit_link_; |
260 views::ImageView* image_view_; | 151 views::ImageView* image_view_; |
261 AvatarMenuModel::Item item_; | 152 AvatarMenuModel::Item item_; |
262 views::Label* name_label_; | 153 views::Label* name_label_; |
263 views::Label* sync_state_label_; | 154 views::Label* sync_state_label_; |
264 }; | 155 }; |
265 | 156 |
| 157 ProfileItemView::ProfileItemView(const AvatarMenuModel::Item& item, |
| 158 views::ButtonListener* switch_profile_listener, |
| 159 views::LinkListener* edit_profile_listener) |
| 160 : views::CustomButton(switch_profile_listener), |
| 161 item_(item) { |
| 162 image_view_ = new ProfileImageView(); |
| 163 SkBitmap profile_icon = item_.icon; |
| 164 if (item_.active) { |
| 165 SkBitmap badged_icon(GetBadgedIcon(profile_icon)); |
| 166 image_view_->SetImage(&badged_icon); |
| 167 } else { |
| 168 image_view_->SetImage(&profile_icon); |
| 169 } |
| 170 AddChildView(image_view_); |
| 171 |
| 172 // Add a label to show the profile name. |
| 173 name_label_ = new views::Label(item_.name); |
| 174 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); |
| 175 gfx::Font base_font = rb.GetFont(ResourceBundle::BaseFont); |
| 176 int style = item_.active ? gfx::Font::BOLD : 0; |
| 177 const int kNameFontDelta = 1; |
| 178 name_label_->SetFont(base_font.DeriveFont(kNameFontDelta, style)); |
| 179 name_label_->SetHorizontalAlignment(views::Label::ALIGN_LEFT); |
| 180 AddChildView(name_label_); |
| 181 |
| 182 // Add a label to show the sync state. |
| 183 sync_state_label_ = new views::Label(item_.sync_state); |
| 184 const int kStateFontDelta = -1; |
| 185 sync_state_label_->SetFont(base_font.DeriveFont(kStateFontDelta)); |
| 186 sync_state_label_->SetHorizontalAlignment(views::Label::ALIGN_LEFT); |
| 187 sync_state_label_->SetEnabled(false); |
| 188 AddChildView(sync_state_label_); |
| 189 |
| 190 // Add an edit profile link. |
| 191 edit_link_ = new EditProfileLink( |
| 192 l10n_util::GetStringUTF16(IDS_PROFILES_EDIT_PROFILE_LINK), this); |
| 193 edit_link_->set_listener(edit_profile_listener); |
| 194 edit_link_->SetHorizontalAlignment(views::Label::ALIGN_LEFT); |
| 195 edit_link_->SetEnabledColor(SkColorSetRGB(0xe3, 0xed, 0xf6)); |
| 196 edit_link_->SetHasFocusBorder(true); |
| 197 AddChildView(edit_link_); |
| 198 |
| 199 OnHighlightStateChanged(); |
| 200 } |
| 201 |
| 202 gfx::Size ProfileItemView::GetPreferredSize() { |
| 203 int width = std::max(name_label_->GetPreferredSize().width(), |
| 204 sync_state_label_->GetPreferredSize().width()); |
| 205 width = std::max(edit_link_->GetPreferredSize().width(), width); |
| 206 return gfx::Size(kIconWidth + kIconMarginX + width, kItemHeight); |
| 207 } |
| 208 |
| 209 void ProfileItemView::Layout() { |
| 210 // Profile icon. |
| 211 const SkBitmap& icon = image_view_->GetImage(); |
| 212 gfx::Rect icon_rect = GetCenteredAndScaledRect( |
| 213 icon.width(), icon.height(), 0, 0, kIconWidth, height()); |
| 214 image_view_->SetBoundsRect(icon_rect); |
| 215 |
| 216 int label_x = icon_rect.right() + kIconMarginX; |
| 217 int max_label_width = width() - label_x; |
| 218 gfx::Size name_size = name_label_->GetPreferredSize(); |
| 219 name_size.set_width(std::min(name_size.width(), max_label_width)); |
| 220 gfx::Size state_size = sync_state_label_->GetPreferredSize(); |
| 221 state_size.set_width(std::min(state_size.width(), max_label_width)); |
| 222 gfx::Size edit_size = edit_link_->GetPreferredSize(); |
| 223 edit_size.set_width(std::min(edit_size.width(), max_label_width)); |
| 224 |
| 225 const int kNameStatePaddingY = 2; |
| 226 int labels_height = name_size.height() + kNameStatePaddingY + |
| 227 std::max(state_size.height(), edit_size.height()); |
| 228 int y = (height() - labels_height) / 2; |
| 229 name_label_->SetBounds(label_x, y, name_size.width(), name_size.height()); |
| 230 |
| 231 int bottom = y + labels_height; |
| 232 sync_state_label_->SetBounds(label_x, bottom - state_size.height(), |
| 233 state_size.width(), state_size.height()); |
| 234 // The edit link overlaps the sync state label. |
| 235 edit_link_->SetBounds(label_x, bottom - edit_size.height(), |
| 236 edit_size.width(), edit_size.height()); |
| 237 } |
| 238 |
| 239 void ProfileItemView::OnMouseEntered(const views::MouseEvent& event) { |
| 240 views::CustomButton::OnMouseEntered(event); |
| 241 OnHighlightStateChanged(); |
| 242 } |
| 243 |
| 244 void ProfileItemView::OnMouseExited(const views::MouseEvent& event) { |
| 245 views::CustomButton::OnMouseExited(event); |
| 246 OnHighlightStateChanged(); |
| 247 } |
| 248 |
| 249 void ProfileItemView::OnHighlightStateChanged() { |
| 250 set_background(IsHighlighted() ? views::Background::CreateSolidBackground( |
| 251 SkColorSetRGB(0xe3, 0xed, 0xf6)) : NULL); |
| 252 SkColor background_color = background() ? |
| 253 background()->get_color() : Bubble::kBackgroundColor; |
| 254 name_label_->SetBackgroundColor(background_color); |
| 255 sync_state_label_->SetBackgroundColor(background_color); |
| 256 edit_link_->SetBackgroundColor(background_color); |
| 257 |
| 258 bool show_edit = IsHighlighted() && item_.active; |
| 259 sync_state_label_->SetVisible(!show_edit); |
| 260 edit_link_->SetVisible(show_edit); |
| 261 SchedulePaint(); |
| 262 } |
| 263 |
| 264 // static |
| 265 SkBitmap ProfileItemView::GetBadgedIcon(const SkBitmap& icon) { |
| 266 gfx::Rect icon_rect = GetCenteredAndScaledRect( |
| 267 icon.width(), icon.height(), 0, 0, kIconWidth, kItemHeight); |
| 268 |
| 269 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); |
| 270 SkBitmap badge = rb.GetImageNamed(IDR_PROFILE_SELECTED); |
| 271 const float kBadgeOverlapRatioX = 1.0f / 5.0f; |
| 272 int width = icon_rect.width() + badge.width() * kBadgeOverlapRatioX; |
| 273 const float kBadgeOverlapRatioY = 1.0f / 3.0f; |
| 274 int height = icon_rect.height() + badge.height() * kBadgeOverlapRatioY; |
| 275 |
| 276 gfx::CanvasSkia canvas(width, height, false); |
| 277 canvas.DrawBitmapInt(icon, 0, 0, icon.width(), icon.height(), 0, 0, |
| 278 icon_rect.width(), icon_rect.height(), true); |
| 279 canvas.DrawBitmapInt(badge, width - badge.width(), height - badge.height()); |
| 280 return canvas.ExtractBitmap(); |
| 281 } |
| 282 |
| 283 bool ProfileItemView::IsHighlighted() const { |
| 284 return state() == views::CustomButton::BS_PUSHED || |
| 285 state() == views::CustomButton::BS_HOT || |
| 286 edit_link_->state() == views::CustomButton::BS_PUSHED || |
| 287 edit_link_->state() == views::CustomButton::BS_HOT; |
| 288 } |
| 289 |
266 } // namespace | 290 } // namespace |
267 | 291 |
| 292 |
| 293 // AvatarMenuBubbleView ------------------------------------------------------- |
| 294 |
268 AvatarMenuBubbleView::AvatarMenuBubbleView(Browser* browser) | 295 AvatarMenuBubbleView::AvatarMenuBubbleView(Browser* browser) |
269 : add_profile_link_(NULL), | 296 : add_profile_link_(NULL), |
270 browser_(browser) { | 297 browser_(browser) { |
271 avatar_menu_model_.reset(new AvatarMenuModel( | 298 avatar_menu_model_.reset(new AvatarMenuModel( |
272 &g_browser_process->profile_manager()->GetProfileInfoCache(), | 299 &g_browser_process->profile_manager()->GetProfileInfoCache(), |
273 this, browser_)); | 300 this, browser_)); |
274 // Build the menu for the first time. | 301 // Build the menu for the first time. |
275 OnAvatarMenuModelChanged(avatar_menu_model_.get()); | 302 OnAvatarMenuModelChanged(avatar_menu_model_.get()); |
276 } | 303 } |
277 | 304 |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
378 item_views_.push_back(item_view); | 405 item_views_.push_back(item_view); |
379 } | 406 } |
380 | 407 |
381 separator_ = new views::Separator(); | 408 separator_ = new views::Separator(); |
382 AddChildView(separator_); | 409 AddChildView(separator_); |
383 | 410 |
384 add_profile_link_ = new views::Link( | 411 add_profile_link_ = new views::Link( |
385 l10n_util::GetStringUTF16(IDS_PROFILES_CREATE_NEW_PROFILE_LINK)); | 412 l10n_util::GetStringUTF16(IDS_PROFILES_CREATE_NEW_PROFILE_LINK)); |
386 add_profile_link_->set_listener(this); | 413 add_profile_link_->set_listener(this); |
387 add_profile_link_->SetHorizontalAlignment(views::Label::ALIGN_LEFT); | 414 add_profile_link_->SetHorizontalAlignment(views::Label::ALIGN_LEFT); |
388 add_profile_link_->MakeReadableOverBackgroundColor(Bubble::kBackgroundColor); | 415 add_profile_link_->SetBackgroundColor(Bubble::kBackgroundColor); |
389 add_profile_link_->SetNormalColor( | 416 add_profile_link_->SetEnabledColor(SkColorSetRGB(0xe3, 0xed, 0xf6)); |
390 color_utils::GetReadableColor(kLinkColor, Bubble::kBackgroundColor)); | |
391 AddChildView(add_profile_link_); | 417 AddChildView(add_profile_link_); |
392 | 418 |
393 PreferredSizeChanged(); | 419 PreferredSizeChanged(); |
394 } | 420 } |
OLD | NEW |