OLD | NEW |
(Empty) | |
| 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 |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "chrome/browser/ui/views/avatar_menu_bubble_view.h" |
| 6 |
| 7 #include "base/utf_string_conversions.h" |
| 8 #include "chrome/browser/browser_process.h" |
| 9 #include "chrome/browser/ui/browser.h" |
| 10 #include "chrome/browser/profiles/avatar_menu_model.h" |
| 11 #include "chrome/browser/profiles/profile_info_cache.h" |
| 12 #include "chrome/browser/profiles/profile_manager.h" |
| 13 #include "grit/generated_resources.h" |
| 14 #include "grit/theme_resources.h" |
| 15 #include "ui/base/l10n/l10n_util.h" |
| 16 #include "ui/base/resource/resource_bundle.h" |
| 17 #include "ui/gfx/canvas.h" |
| 18 #include "ui/gfx/font.h" |
| 19 #include "ui/gfx/image/image.h" |
| 20 #include "views/controls/button/image_button.h" |
| 21 |
| 22 namespace { |
| 23 |
| 24 const int kBubbleViewMinWidth = 175; |
| 25 const int kBubbleViewMaxWidth = 800; |
| 26 const int kItemHeight = 32; |
| 27 const int kItemMarginY = 8; |
| 28 const int kIconWidth = 38; |
| 29 const int kIconMarginX = 6; |
| 30 const int kEditProfileButtonMarginX = 8; |
| 31 |
| 32 inline int Round(double x) { |
| 33 return static_cast<int>(x + 0.5); |
| 34 } |
| 35 |
| 36 gfx::Rect GetCenteredAndScaledRect(int src_width, int src_height, |
| 37 int dst_x, int dst_y, |
| 38 int dst_width, int dst_height) { |
| 39 int scaled_width; |
| 40 int scaled_height; |
| 41 if (src_width > src_height) { |
| 42 scaled_width = std::min(src_width, dst_width); |
| 43 float scale = static_cast<float>(scaled_width) / |
| 44 static_cast<float>(src_width); |
| 45 scaled_height = Round(src_height * scale); |
| 46 } else { |
| 47 scaled_height = std::min(src_height, dst_height); |
| 48 float scale = static_cast<float>(scaled_height) / |
| 49 static_cast<float>(src_height); |
| 50 scaled_width = Round(src_width * scale); |
| 51 } |
| 52 int x = dst_x + (dst_width - scaled_width) / 2; |
| 53 int y = dst_y + (dst_height - scaled_height) / 2; |
| 54 return gfx::Rect(x, y, scaled_width, scaled_height); |
| 55 } |
| 56 |
| 57 class ProfileItemView : public views::CustomButton { |
| 58 public: |
| 59 ProfileItemView(const AvatarMenuModel::Item& item, |
| 60 views::ButtonListener* listener) |
| 61 : views::CustomButton(listener), |
| 62 item_(item) { |
| 63 } |
| 64 |
| 65 virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE { |
| 66 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); |
| 67 |
| 68 // Draw the profile icon on the left. |
| 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 } |
| 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 } |
| 95 |
| 96 virtual gfx::Size GetPreferredSize() OVERRIDE { |
| 97 gfx::Font font = ResourceBundle::GetSharedInstance().GetFont( |
| 98 ResourceBundle::BaseFont); |
| 99 int title_width = font.GetStringWidth(item_.name); |
| 100 return gfx::Size(kIconWidth + kIconMarginX + title_width, kItemHeight); |
| 101 } |
| 102 |
| 103 private: |
| 104 SkColor GetNameColor() { |
| 105 bool normal = state() != views::CustomButton::BS_PUSHED && |
| 106 state() != views::CustomButton::BS_HOT; |
| 107 if (item_.active) |
| 108 return normal ? SkColorSetRGB(30, 30, 30) : SkColorSetRGB(0, 0, 0); |
| 109 return normal ? SkColorSetRGB(128, 128, 128) : SkColorSetRGB(64, 64, 64); |
| 110 } |
| 111 |
| 112 AvatarMenuModel::Item item_; |
| 113 }; |
| 114 |
| 115 } // namespace |
| 116 |
| 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) |
| 133 : add_profile_link_(NULL), |
| 134 browser_(browser), |
| 135 edit_profile_button_(NULL) { |
| 136 avatar_menu_model_.reset(new AvatarMenuModel( |
| 137 &g_browser_process->profile_manager()->GetProfileInfoCache(), |
| 138 this, browser_)); |
| 139 } |
| 140 |
| 141 AvatarMenuBubbleView::~AvatarMenuBubbleView() { |
| 142 } |
| 143 |
| 144 gfx::Size AvatarMenuBubbleView::GetPreferredSize() { |
| 145 int max_width = 0; |
| 146 int total_height = 0; |
| 147 for (size_t i = 0; i < item_views_.size(); ++i) { |
| 148 gfx::Size size = item_views_[i]->GetPreferredSize(); |
| 149 if (i == edit_profile_button_->profile_index()) { |
| 150 size.set_width(size.width() + |
| 151 edit_profile_button_->GetPreferredSize().width() + |
| 152 kEditProfileButtonMarginX); |
| 153 } |
| 154 |
| 155 max_width = std::max(max_width, size.width()); |
| 156 total_height += size.height() + kItemMarginY; |
| 157 } |
| 158 |
| 159 gfx::Size add_profile_size = add_profile_link_->GetPreferredSize(); |
| 160 max_width = std::max(max_width, |
| 161 add_profile_size.width() + kIconWidth + kIconMarginX); |
| 162 total_height += add_profile_link_->GetPreferredSize().height(); |
| 163 |
| 164 int total_width = std::min(std::max(max_width, kBubbleViewMinWidth), |
| 165 kBubbleViewMaxWidth); |
| 166 return gfx::Size(total_width, total_height); |
| 167 } |
| 168 |
| 169 void AvatarMenuBubbleView::Layout() { |
| 170 int y = 0; |
| 171 for (size_t i = 0; i < item_views_.size(); ++i) { |
| 172 views::CustomButton* item_view = item_views_[i]; |
| 173 int item_height = item_view->GetPreferredSize().height(); |
| 174 int item_width = width(); |
| 175 |
| 176 if (i == edit_profile_button_->profile_index()) { |
| 177 gfx::Size edit_size = edit_profile_button_->GetPreferredSize(); |
| 178 edit_profile_button_->SetBounds(width() - edit_size.width(), y, |
| 179 edit_size.width(), item_height); |
| 180 item_width -= edit_size.width() + kEditProfileButtonMarginX; |
| 181 } |
| 182 |
| 183 item_view->SetBounds(0, y, item_width, item_height); |
| 184 y += item_height + kItemMarginY; |
| 185 } |
| 186 |
| 187 add_profile_link_->SetBounds(kIconWidth + kIconMarginX, y, width(), |
| 188 add_profile_link_->GetPreferredSize().height()); |
| 189 } |
| 190 |
| 191 void AvatarMenuBubbleView::ButtonPressed(views::Button* sender, |
| 192 const views::Event& event) { |
| 193 if (sender == edit_profile_button_) { |
| 194 avatar_menu_model_->EditProfile(edit_profile_button_->profile_index()); |
| 195 } else { |
| 196 for (size_t i = 0; i < item_views_.size(); ++i) { |
| 197 if (sender == item_views_[i]) { |
| 198 avatar_menu_model_->SwitchToProfile(i); |
| 199 break; |
| 200 } |
| 201 } |
| 202 } |
| 203 } |
| 204 |
| 205 void AvatarMenuBubbleView::LinkClicked(views::Link* source, int event_flags) { |
| 206 DCHECK_EQ(source, add_profile_link_); |
| 207 avatar_menu_model_->AddNewProfile(); |
| 208 } |
| 209 |
| 210 void AvatarMenuBubbleView::BubbleClosing(Bubble* bubble, |
| 211 bool closed_by_escape) { |
| 212 } |
| 213 |
| 214 bool AvatarMenuBubbleView::CloseOnEscape() { |
| 215 return true; |
| 216 } |
| 217 |
| 218 bool AvatarMenuBubbleView::FadeInOnShow() { |
| 219 return false; |
| 220 } |
| 221 |
| 222 void AvatarMenuBubbleView::OnAvatarMenuModelChanged( |
| 223 AvatarMenuModel* avatar_menu_model) { |
| 224 // Unset all our child view references and call RemoveAllChildViews() which |
| 225 // will actually delete them. |
| 226 add_profile_link_ = NULL; |
| 227 edit_profile_button_ = NULL; |
| 228 item_views_.clear(); |
| 229 RemoveAllChildViews(true); |
| 230 |
| 231 for (size_t i = 0; i < avatar_menu_model->GetNumberOfItems(); ++i) { |
| 232 const AvatarMenuModel::Item& item = avatar_menu_model->GetItemAt(i); |
| 233 ProfileItemView* item_view = new ProfileItemView(item, this); |
| 234 item_view->SetAccessibleName(l10n_util::GetStringFUTF16( |
| 235 IDS_PROFILES_SWITCH_TO_PROFILE_ACCESSIBLE_NAME, item.name)); |
| 236 AddChildView(item_view); |
| 237 item_views_.push_back(item_view); |
| 238 |
| 239 if (item.active) { |
| 240 DCHECK(!edit_profile_button_); |
| 241 edit_profile_button_ = new EditProfileButton(i, this); |
| 242 edit_profile_button_->SetAccessibleName(l10n_util::GetStringFUTF16( |
| 243 IDS_PROFILES_CUSTOMIZE_PROFILE_ACCESSIBLE_NAME, item.name)); |
| 244 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); |
| 245 edit_profile_button_->SetImage(views::CustomButton::BS_NORMAL, |
| 246 rb.GetImageNamed(IDR_PROFILE_EDIT)); |
| 247 edit_profile_button_->SetImage(views::CustomButton::BS_HOT, |
| 248 rb.GetImageNamed(IDR_PROFILE_EDIT_HOVER)); |
| 249 edit_profile_button_->SetImage(views::CustomButton::BS_PUSHED, |
| 250 rb.GetImageNamed(IDR_PROFILE_EDIT_PRESSED)); |
| 251 edit_profile_button_->SetImageAlignment(views::ImageButton::ALIGN_CENTER, |
| 252 views::ImageButton::ALIGN_MIDDLE); |
| 253 AddChildView(edit_profile_button_); |
| 254 } |
| 255 } |
| 256 |
| 257 add_profile_link_ = new views::Link(UTF16ToWide( |
| 258 l10n_util::GetStringUTF16(IDS_PROFILES_CREATE_NEW_PROFILE_LINK))); |
| 259 add_profile_link_->SetHorizontalAlignment(views::Label::ALIGN_LEFT); |
| 260 add_profile_link_->SetNormalColor(SkColorSetRGB(0, 0x79, 0xda)); |
| 261 AddChildView(add_profile_link_); |
| 262 |
| 263 PreferredSizeChanged(); |
| 264 } |
OLD | NEW |