Chromium Code Reviews| 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 image_view_->SetImage(item_.active ? | |
| 165 &GetBadgedIcon(profile_icon) : &profile_icon); | |
| 166 AddChildView(image_view_); | |
| 167 | |
| 168 // Add a label to show the profile name. | |
| 169 name_label_ = new views::Label(item_.name); | |
| 170 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); | |
| 171 gfx::Font base_font = rb.GetFont(ResourceBundle::BaseFont); | |
| 172 int style = item_.active ? gfx::Font::BOLD : 0; | |
| 173 const int kNameFontDelta = 1; | |
| 174 name_label_->SetFont(base_font.DeriveFont(kNameFontDelta, style)); | |
| 175 name_label_->SetHorizontalAlignment(views::Label::ALIGN_LEFT); | |
| 176 AddChildView(name_label_); | |
| 177 | |
| 178 // Add a label to show the sync state. | |
| 179 sync_state_label_ = new views::Label(item_.sync_state); | |
| 180 const int kStateFontDelta = -1; | |
| 181 sync_state_label_->SetFont(base_font.DeriveFont(kStateFontDelta)); | |
| 182 sync_state_label_->SetHorizontalAlignment(views::Label::ALIGN_LEFT); | |
| 183 sync_state_label_->SetEnabled(false); | |
| 184 AddChildView(sync_state_label_); | |
| 185 | |
| 186 // Add an edit profile link. | |
| 187 edit_link_ = new EditProfileLink( | |
| 188 l10n_util::GetStringUTF16(IDS_PROFILES_EDIT_PROFILE_LINK), this); | |
| 189 edit_link_->set_listener(edit_profile_listener); | |
| 190 edit_link_->SetHorizontalAlignment(views::Label::ALIGN_LEFT); | |
| 191 edit_link_->SetEnabledColor(SkColorSetRGB(0xe3, 0xed, 0xf6)); | |
|
sail
2011/10/10 23:49:34
Merge error:
edit_link_->SetHasFocusBorder(true);
Peter Kasting
2011/10/11 00:02:37
Thanks! I totally missed that.
| |
| 192 AddChildView(edit_link_); | |
| 193 | |
| 194 OnHighlightStateChanged(); | |
| 195 } | |
| 196 | |
| 197 gfx::Size ProfileItemView::GetPreferredSize() { | |
| 198 int width = std::max(name_label_->GetPreferredSize().width(), | |
| 199 sync_state_label_->GetPreferredSize().width()); | |
| 200 width = std::max(edit_link_->GetPreferredSize().width(), width); | |
| 201 return gfx::Size(kIconWidth + kIconMarginX + width, kItemHeight); | |
| 202 } | |
| 203 | |
| 204 void ProfileItemView::Layout() { | |
| 205 // Profile icon. | |
| 206 const SkBitmap& icon = image_view_->GetImage(); | |
| 207 gfx::Rect icon_rect = GetCenteredAndScaledRect( | |
| 208 icon.width(), icon.height(), 0, 0, kIconWidth, height()); | |
| 209 image_view_->SetBoundsRect(icon_rect); | |
| 210 | |
| 211 int label_x = icon_rect.right() + kIconMarginX; | |
| 212 int max_label_width = width() - label_x; | |
| 213 gfx::Size name_size = name_label_->GetPreferredSize(); | |
| 214 name_size.set_width(std::min(name_size.width(), max_label_width)); | |
| 215 gfx::Size state_size = sync_state_label_->GetPreferredSize(); | |
| 216 state_size.set_width(std::min(state_size.width(), max_label_width)); | |
| 217 gfx::Size edit_size = edit_link_->GetPreferredSize(); | |
| 218 edit_size.set_width(std::min(edit_size.width(), max_label_width)); | |
| 219 | |
| 220 const int kNameStatePaddingY = 2; | |
| 221 int labels_height = name_size.height() + kNameStatePaddingY + | |
| 222 std::max(state_size.height(), edit_size.height()); | |
| 223 int y = (height() - labels_height) / 2; | |
| 224 name_label_->SetBounds(label_x, y, name_size.width(), name_size.height()); | |
| 225 | |
| 226 int bottom = y + labels_height; | |
| 227 sync_state_label_->SetBounds(label_x, bottom - state_size.height(), | |
| 228 state_size.width(), state_size.height()); | |
| 229 // The edit link overlaps the sync state label. | |
| 230 edit_link_->SetBounds(label_x, bottom - edit_size.height(), | |
| 231 edit_size.width(), edit_size.height()); | |
| 232 } | |
| 233 | |
| 234 void ProfileItemView::OnMouseEntered(const views::MouseEvent& event) { | |
| 235 views::CustomButton::OnMouseEntered(event); | |
| 236 OnHighlightStateChanged(); | |
| 237 } | |
| 238 | |
| 239 void ProfileItemView::OnMouseExited(const views::MouseEvent& event) { | |
| 240 views::CustomButton::OnMouseExited(event); | |
| 241 OnHighlightStateChanged(); | |
| 242 } | |
| 243 | |
| 244 void ProfileItemView::OnHighlightStateChanged() { | |
| 245 set_background(IsHighlighted() ? views::Background::CreateSolidBackground( | |
|
sail
2011/10/10 23:49:34
cool!
| |
| 246 SkColorSetRGB(0xe3, 0xed, 0xf6)) : NULL); | |
| 247 SkColor background_color = background() ? | |
| 248 background()->get_color() : Bubble::kBackgroundColor; | |
| 249 name_label_->SetBackgroundColor(background_color); | |
| 250 sync_state_label_->SetBackgroundColor(background_color); | |
| 251 edit_link_->SetBackgroundColor(background_color); | |
| 252 | |
| 253 bool show_edit = IsHighlighted() && item_.active; | |
| 254 sync_state_label_->SetVisible(!show_edit); | |
| 255 edit_link_->SetVisible(show_edit); | |
| 256 SchedulePaint(); | |
| 257 } | |
| 258 | |
| 259 // static | |
| 260 SkBitmap ProfileItemView::GetBadgedIcon(const SkBitmap& icon) { | |
| 261 gfx::Rect icon_rect = GetCenteredAndScaledRect( | |
| 262 icon.width(), icon.height(), 0, 0, kIconWidth, kItemHeight); | |
| 263 | |
| 264 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); | |
| 265 SkBitmap badge = rb.GetImageNamed(IDR_PROFILE_SELECTED); | |
| 266 const float kBadgeOverlapRatioX = 1.0f / 5.0f; | |
| 267 int width = icon_rect.width() + badge.width() * kBadgeOverlapRatioX; | |
| 268 const float kBadgeOverlapRatioY = 1.0f / 3.0f; | |
| 269 int height = icon_rect.height() + badge.height() * kBadgeOverlapRatioY; | |
| 270 | |
| 271 gfx::CanvasSkia canvas(width, height, false); | |
| 272 canvas.DrawBitmapInt(icon, 0, 0, icon.width(), icon.height(), 0, 0, | |
| 273 icon_rect.width(), icon_rect.height(), true); | |
| 274 canvas.DrawBitmapInt(badge, width - badge.width(), height - badge.height()); | |
| 275 return canvas.ExtractBitmap(); | |
| 276 } | |
| 277 | |
| 278 bool ProfileItemView::IsHighlighted() const { | |
| 279 return state() == views::CustomButton::BS_PUSHED || | |
| 280 state() == views::CustomButton::BS_HOT || | |
| 281 edit_link_->state() == views::CustomButton::BS_PUSHED || | |
| 282 edit_link_->state() == views::CustomButton::BS_HOT; | |
| 283 } | |
| 284 | |
| 266 } // namespace | 285 } // namespace |
| 267 | 286 |
| 287 | |
| 288 // AvatarMenuBubbleView ------------------------------------------------------- | |
| 289 | |
| 268 AvatarMenuBubbleView::AvatarMenuBubbleView(Browser* browser) | 290 AvatarMenuBubbleView::AvatarMenuBubbleView(Browser* browser) |
| 269 : add_profile_link_(NULL), | 291 : add_profile_link_(NULL), |
| 270 browser_(browser) { | 292 browser_(browser) { |
| 271 avatar_menu_model_.reset(new AvatarMenuModel( | 293 avatar_menu_model_.reset(new AvatarMenuModel( |
| 272 &g_browser_process->profile_manager()->GetProfileInfoCache(), | 294 &g_browser_process->profile_manager()->GetProfileInfoCache(), |
| 273 this, browser_)); | 295 this, browser_)); |
| 274 // Build the menu for the first time. | 296 // Build the menu for the first time. |
| 275 OnAvatarMenuModelChanged(avatar_menu_model_.get()); | 297 OnAvatarMenuModelChanged(avatar_menu_model_.get()); |
| 276 } | 298 } |
| 277 | 299 |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 378 item_views_.push_back(item_view); | 400 item_views_.push_back(item_view); |
| 379 } | 401 } |
| 380 | 402 |
| 381 separator_ = new views::Separator(); | 403 separator_ = new views::Separator(); |
| 382 AddChildView(separator_); | 404 AddChildView(separator_); |
| 383 | 405 |
| 384 add_profile_link_ = new views::Link( | 406 add_profile_link_ = new views::Link( |
| 385 l10n_util::GetStringUTF16(IDS_PROFILES_CREATE_NEW_PROFILE_LINK)); | 407 l10n_util::GetStringUTF16(IDS_PROFILES_CREATE_NEW_PROFILE_LINK)); |
| 386 add_profile_link_->set_listener(this); | 408 add_profile_link_->set_listener(this); |
| 387 add_profile_link_->SetHorizontalAlignment(views::Label::ALIGN_LEFT); | 409 add_profile_link_->SetHorizontalAlignment(views::Label::ALIGN_LEFT); |
| 388 add_profile_link_->MakeReadableOverBackgroundColor(Bubble::kBackgroundColor); | 410 add_profile_link_->SetBackgroundColor(Bubble::kBackgroundColor); |
| 389 add_profile_link_->SetNormalColor( | 411 add_profile_link_->SetEnabledColor(SkColorSetRGB(0xe3, 0xed, 0xf6)); |
| 390 color_utils::GetReadableColor(kLinkColor, Bubble::kBackgroundColor)); | |
| 391 AddChildView(add_profile_link_); | 412 AddChildView(add_profile_link_); |
| 392 | 413 |
| 393 PreferredSizeChanged(); | 414 PreferredSizeChanged(); |
| 394 } | 415 } |
| OLD | NEW |