Index: chrome/browser/ui/views/avatar_menu_bubble_view.cc |
diff --git a/chrome/browser/ui/views/avatar_menu_bubble_view.cc b/chrome/browser/ui/views/avatar_menu_bubble_view.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..d482e8973d9ce668cf9491e433124aca83c875d6 |
--- /dev/null |
+++ b/chrome/browser/ui/views/avatar_menu_bubble_view.cc |
@@ -0,0 +1,243 @@ |
+// Copyright (c) 2011 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "chrome/browser/ui/views/avatar_menu_bubble_view.h" |
+ |
+#include "chrome/browser/browser_process.h" |
+#include "chrome/browser/ui/browser.h" |
+#include "chrome/browser/profiles/avatar_menu_model.h" |
+#include "chrome/browser/profiles/profile_info_cache.h" |
+#include "chrome/browser/profiles/profile_manager.h" |
+#include "grit/generated_resources.h" |
+#include "grit/theme_resources.h" |
+#include "ui/base/l10n/l10n_util.h" |
+#include "ui/base/resource/resource_bundle.h" |
+#include "ui/gfx/canvas.h" |
+#include "ui/gfx/font.h" |
+#include "ui/gfx/image/image.h" |
+ |
+namespace { |
+ |
+const int kItemWidth = 210; |
+const int kItemHeight = 32; |
+const int kItemMarginY = 8; |
+const int kIconWidth = 38; |
+const int kIconMarginX = 6; |
+const int kAddUserButtonHeight = 20; |
+const int kEditUserButtonWidth = 19; |
+const int kEditUserButtonMarginX = 3; |
+ |
+inline int Round(double x) { |
+ return static_cast<int>(x + 0.5); |
+} |
+ |
+gfx::Rect GetCenteredAndScaledRect(int src_width, int src_height, |
+ int dst_x, int dst_y, |
+ int dst_width, int dst_height) { |
+ int scaled_width; |
+ int scaled_height; |
+ if (src_width > src_height) { |
+ scaled_width = std::min(src_width, dst_width); |
+ float scale = static_cast<float>(scaled_width) / |
+ static_cast<float>(src_width); |
+ scaled_height = Round(src_height * scale); |
+ } else { |
+ scaled_height = std::min(src_height, dst_height); |
+ float scale = static_cast<float>(scaled_height) / |
+ static_cast<float>(src_height); |
+ scaled_width = Round(src_width * scale); |
+ } |
+ int x = dst_x + (dst_width - scaled_width) / 2; |
+ int y = dst_y + (dst_height - scaled_height) / 2; |
+ return gfx::Rect(x, y, scaled_width, scaled_height); |
+} |
+ |
+class AddUserButton : public views::ImageButton { |
Peter Kasting
2011/08/05 18:08:33
You should use a Link object for this, it will do
sail
2011/08/09 00:47:47
Done.
|
+ public: |
+ explicit AddUserButton(views::ButtonListener* listener) |
+ : views::ImageButton(listener) { |
+ } |
+ |
+ virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE { |
+ ResourceBundle& rb = ResourceBundle::GetSharedInstance(); |
+ int x = kIconWidth + kIconMarginX; |
+ int w = width() - x; |
+ |
+ gfx::Font font(rb.GetFont(ResourceBundle::BaseFont)); |
+ font = font.DeriveFont(0, gfx::Font::UNDERLINED); |
+ |
+ canvas->DrawStringInt( |
+ l10n_util::GetStringUTF16(IDS_PROFILES_CREATE_NEW_PROFILE_LINK), font, |
+ SkColorSetRGB(0, 0x79, 0xda), x, 0, w, height()); |
+ } |
+}; |
+ |
+class ProfileItemView : public views::ImageButton { |
+ public: |
+ ProfileItemView(const AvatarMenuModel::Item& item, |
+ views::ButtonListener* listener) |
+ : views::ImageButton(listener), |
+ item_(item) { |
+ } |
+ |
+ void OnPaint(gfx::Canvas* canvas) { |
+ ResourceBundle& rb = ResourceBundle::GetSharedInstance(); |
+ |
+ // Draw the profile icon on the left. |
+ SkBitmap profile_icon = item_.icon; |
+ gfx::Rect profile_icon_rect = GetCenteredAndScaledRect( |
+ profile_icon.width(), profile_icon.height(), |
+ 0, 0, kIconWidth, height()); |
+ canvas->DrawBitmapInt(profile_icon, 0, 0, profile_icon.width(), |
+ profile_icon.height(), profile_icon_rect.x(), |
+ profile_icon_rect.y(), profile_icon_rect.width(), |
+ profile_icon_rect.height(), false); |
+ |
+ // If this profile is selected then draw a check mark on the bottom right |
+ // of the profile icon. |
+ if (item_.active) { |
+ SkBitmap check_icon = rb.GetImageNamed(IDR_PROFILE_SELECTED); |
+ int y = profile_icon_rect.bottom() - check_icon.height(); |
+ int x = profile_icon_rect.right() - check_icon.width() + 2; |
+ canvas->DrawBitmapInt(check_icon, 0, 0, check_icon.width(), |
+ check_icon.height(), x, y, check_icon.width(), |
+ check_icon.height(), false); |
+ } |
+ |
+ // Draw the profile name to the right of the profile icon. |
+ int name_x = profile_icon_rect.right() + kIconMarginX; |
+ canvas->DrawStringInt(item_.name, rb.GetFont(ResourceBundle::BaseFont), |
+ GetNameColor(), name_x, 0, width() - name_x, |
+ height()); |
+ } |
+ |
+ private: |
+ SkColor GetNameColor() { |
+ bool normal = state() != views::CustomButton::BS_PUSHED && |
+ state() != views::CustomButton::BS_HOT; |
+ if (item_.active) |
+ return normal ? SkColorSetRGB(30, 30, 30) : SkColorSetRGB(0, 0, 0); |
+ else |
Peter Kasting
2011/08/05 18:08:33
Nit: No else after return
sail
2011/08/09 00:47:47
Done.
|
+ return normal ? SkColorSetRGB(128, 128, 128) : SkColorSetRGB(64, 64, 64); |
+ } |
+ |
+ AvatarMenuModel::Item item_; |
+}; |
+ |
+} // namespace |
+ |
+class EditUserButton : public views::ImageButton { |
+ public: |
+ EditUserButton(size_t profile_index, views::ButtonListener* listener) |
+ : views::ImageButton(listener), |
+ profile_index_(profile_index) { |
+ } |
+ |
+ size_t profile_index() { |
+ return profile_index_; |
+ } |
+ |
+ private: |
+ size_t profile_index_; |
+}; |
+ |
+AvatarMenuBubbleView::AvatarMenuBubbleView(Browser* browser) |
+ : add_user_button_(NULL), |
+ browser_(browser), |
+ edit_user_button_(NULL) { |
+ avatar_menu_model_.reset(new AvatarMenuModel( |
+ &g_browser_process->profile_manager()->GetProfileInfoCache(), |
+ this, browser_)); |
+} |
+ |
+AvatarMenuBubbleView::~AvatarMenuBubbleView() { |
+} |
+ |
+gfx::Size AvatarMenuBubbleView::GetPreferredSize() { |
+ return gfx::Size(kItemWidth, (kItemHeight + kItemMarginY) * |
Peter Kasting
2011/08/05 18:08:33
How come we hardcode the size and never check the
sail
2011/08/09 00:47:47
Done.
|
+ item_views_.size() + kAddUserButtonHeight); |
+} |
+ |
+void AvatarMenuBubbleView::Layout() { |
Peter Kasting
2011/08/05 18:08:33
I think you can get rid of most of this code if yo
sail
2011/08/09 00:47:47
I spent half a day on this and I couldn't get a co
|
+ int kItemWidth = width() - kEditUserButtonWidth - kEditUserButtonMarginX; |
+ |
+ for (size_t i = 0; i < item_views_.size(); ++i) { |
+ views::ImageButton* item_view = item_views_[i]; |
+ int y = (kItemHeight + kItemMarginY) * i; |
+ item_view->SetBounds(0, y, kItemWidth, kItemHeight); |
+ } |
+ |
+ int y = (kItemHeight + kItemMarginY) * item_views_.size(); |
+ add_user_button_->SetBounds(0, y, width(), kAddUserButtonHeight); |
+ |
+ y = (kItemHeight + kItemMarginY) * edit_user_button_->profile_index(); |
+ edit_user_button_->SetBounds(width() - kEditUserButtonWidth, y, |
+ kEditUserButtonWidth, kItemHeight); |
+} |
+ |
+void AvatarMenuBubbleView::ButtonPressed(views::Button* sender, |
+ const views::Event& event) { |
+ if (sender == add_user_button_) { |
+ avatar_menu_model_->AddNewProfile(); |
+ } else if (sender == edit_user_button_) { |
+ avatar_menu_model_->EditProfile(edit_user_button_->profile_index()); |
+ } else { |
+ for (size_t i = 0; i < item_views_.size(); ++i) { |
+ if (sender == item_views_[i]) { |
+ avatar_menu_model_->SwitchToProfile(i); |
+ break; |
+ } |
+ } |
+ } |
+} |
+ |
+void AvatarMenuBubbleView::BubbleClosing(Bubble* bubble, |
+ bool closed_by_escape) { |
+} |
+ |
+bool AvatarMenuBubbleView::CloseOnEscape() { |
+ return true; |
+} |
+ |
+bool AvatarMenuBubbleView::FadeInOnShow() { |
+ return false; |
+} |
+ |
+void AvatarMenuBubbleView::OnAvatarMenuModelChanged( |
+ AvatarMenuModel* avatar_menu_model) { |
+ // Unset all our child view references and call RemoveAllChildViews() which |
+ // will actually delete them. |
+ add_user_button_ = NULL; |
+ edit_user_button_ = NULL; |
+ item_views_.clear(); |
+ RemoveAllChildViews(true); |
+ |
+ size_t active_profile_index = 0; |
+ for (size_t i = 0; i < avatar_menu_model->GetNumberOfItems(); ++i) { |
+ const AvatarMenuModel::Item& item = avatar_menu_model->GetItemAt(i); |
+ ProfileItemView* item_view = new ProfileItemView(item, this); |
+ AddChildView(item_view); |
+ item_views_.push_back(item_view); |
+ |
+ if (item.active) |
+ active_profile_index = i; |
+ } |
+ |
+ add_user_button_ = new AddUserButton(this); |
+ AddChildView(add_user_button_); |
+ |
+ edit_user_button_ = new EditUserButton(active_profile_index, this); |
+ ResourceBundle& rb = ResourceBundle::GetSharedInstance(); |
+ edit_user_button_->SetImage(views::CustomButton::BS_NORMAL, |
+ rb.GetImageNamed(IDR_PROFILE_EDIT)); |
+ edit_user_button_->SetImage(views::CustomButton::BS_HOT, |
+ rb.GetImageNamed(IDR_PROFILE_EDIT_HOVER)); |
+ edit_user_button_->SetImage(views::CustomButton::BS_PUSHED, |
+ rb.GetImageNamed(IDR_PROFILE_EDIT_PRESSED)); |
+ edit_user_button_->SetImageAlignment(views::ImageButton::ALIGN_CENTER, |
+ views::ImageButton::ALIGN_MIDDLE); |
+ AddChildView(edit_user_button_); |
+ |
+ PreferredSizeChanged(); |
+} |