Chromium Code Reviews| Index: chrome/browser/ui/views/avatar_menu_bubble_view.cc |
| =================================================================== |
| --- chrome/browser/ui/views/avatar_menu_bubble_view.cc (revision 104769) |
| +++ chrome/browser/ui/views/avatar_menu_bubble_view.cc (working copy) |
| @@ -18,7 +18,6 @@ |
| #include "ui/base/resource/resource_bundle.h" |
| #include "ui/gfx/canvas.h" |
| #include "ui/gfx/canvas_skia.h" |
| -#include "ui/gfx/color_utils.h" |
| #include "ui/gfx/font.h" |
| #include "ui/gfx/image/image.h" |
| #include "views/controls/button/image_button.h" |
| @@ -32,8 +31,6 @@ |
| const int kIconWidth = 38; |
| const int kIconMarginX = 6; |
| const int kSeparatorPaddingY = 5; |
| -const SkColor kHighlightBackgroundColor = SkColorSetRGB(0xe3, 0xed, 0xf6); |
| -const SkColor kLinkColor = SkColorSetRGB(0, 0x79, 0xda); |
| inline int Round(double x) { |
| return static_cast<int>(x + 0.5); |
| @@ -60,6 +57,9 @@ |
| return gfx::Rect(x, y, scaled_width, scaled_height); |
| } |
| + |
| +// HighlightDelegate ---------------------------------------------------------- |
| + |
| // Delegate to callback when the highlight state of a control changes. |
| class HighlightDelegate { |
| public: |
| @@ -67,30 +67,20 @@ |
| virtual void OnHighlightStateChanged() = 0; |
| }; |
| + |
| +// EditProfileLink ------------------------------------------------------------ |
| + |
| // A custom Link control that forwards highlight state changes. We need to do |
| // this to make sure that the ProfileItemView looks highlighted even when |
| // the mouse is over this link. |
| class EditProfileLink : public views::Link { |
| public: |
| explicit EditProfileLink(const string16& title, |
| - HighlightDelegate* delegate) |
| - : views::Link(title), |
| - delegate_(delegate), |
| - state_(views::CustomButton::BS_NORMAL) { |
| - } |
| + HighlightDelegate* delegate); |
| - virtual void OnMouseEntered(const views::MouseEvent& event) OVERRIDE { |
| - views::Link::OnMouseEntered(event); |
| - state_ = views::CustomButton::BS_HOT; |
| - delegate_->OnHighlightStateChanged(); |
| - } |
| + virtual void OnMouseEntered(const views::MouseEvent& event) OVERRIDE; |
| + virtual void OnMouseExited(const views::MouseEvent& event) OVERRIDE; |
| - virtual void OnMouseExited(const views::MouseEvent& event) OVERRIDE { |
| - views::Link::OnMouseExited(event); |
| - state_ = views::CustomButton::BS_NORMAL; |
| - delegate_->OnHighlightStateChanged(); |
| - } |
| - |
| views::CustomButton::ButtonState state() { return state_; } |
| private: |
| @@ -98,173 +88,205 @@ |
| views::CustomButton::ButtonState state_; |
| }; |
| +EditProfileLink::EditProfileLink(const string16& title, |
| + HighlightDelegate* delegate) |
| + : views::Link(title), |
| + delegate_(delegate), |
| + state_(views::CustomButton::BS_NORMAL) { |
| +} |
| + |
| +void EditProfileLink::OnMouseEntered(const views::MouseEvent& event) { |
| + views::Link::OnMouseEntered(event); |
| + state_ = views::CustomButton::BS_HOT; |
| + delegate_->OnHighlightStateChanged(); |
| +} |
| + |
| +void EditProfileLink::OnMouseExited(const views::MouseEvent& event) { |
| + views::Link::OnMouseExited(event); |
| + state_ = views::CustomButton::BS_NORMAL; |
| + delegate_->OnHighlightStateChanged(); |
| +} |
| + |
| + |
| +// ProfileImageView ----------------------------------------------------------- |
| + |
| // A custom image view that ignores mouse events so that the parent can receive |
| // them them instead. |
| class ProfileImageView : public views::ImageView { |
| public: |
| - virtual bool HitTest(const gfx::Point& l) const OVERRIDE { |
| - return false; |
| - } |
| + virtual bool HitTest(const gfx::Point& l) const OVERRIDE; |
| }; |
| +bool ProfileImageView::HitTest(const gfx::Point& l) const { |
| + return false; |
| +} |
| + |
| + |
| +// ProfileItemView ------------------------------------------------------------ |
| + |
| // Control that shows information about a single profile. |
| class ProfileItemView : public views::CustomButton, |
| public HighlightDelegate { |
| public: |
| ProfileItemView(const AvatarMenuModel::Item& item, |
| views::ButtonListener* switch_profile_listener, |
| - views::LinkListener* edit_profile_listener) |
| - : views::CustomButton(switch_profile_listener), |
| - item_(item) { |
| - image_view_ = new ProfileImageView(); |
| - SkBitmap profile_icon = item_.icon; |
| - if (item_.active) { |
| - SkBitmap badged_icon = GetBadgedIcon(profile_icon); |
| - image_view_->SetImage(&badged_icon); |
| - } else { |
| - image_view_->SetImage(&profile_icon); |
| - } |
| - AddChildView(image_view_); |
| + views::LinkListener* edit_profile_listener); |
| - // Add a label to show the profile name. |
| - name_label_ = new views::Label(item_.name); |
| - ResourceBundle& rb = ResourceBundle::GetSharedInstance(); |
| - gfx::Font base_font = rb.GetFont(ResourceBundle::BaseFont); |
| - int style = item_.active ? gfx::Font::BOLD : 0; |
| - const int kNameFontDelta = 1; |
| - name_label_->SetFont(base_font.DeriveFont(kNameFontDelta, style)); |
| - name_label_->SetHorizontalAlignment(views::Label::ALIGN_LEFT); |
| - AddChildView(name_label_); |
| + virtual gfx::Size GetPreferredSize() OVERRIDE; |
| + virtual void Layout() OVERRIDE; |
| + virtual void OnMouseEntered(const views::MouseEvent& event) OVERRIDE; |
| + virtual void OnMouseExited(const views::MouseEvent& event) OVERRIDE; |
| - // Add a label to show the sync state. |
| - sync_state_label_ = new views::Label(item_.sync_state); |
| - const int kStateFontDelta = -1; |
| - sync_state_label_->SetFont(base_font.DeriveFont(kStateFontDelta)); |
| - sync_state_label_->SetHorizontalAlignment(views::Label::ALIGN_LEFT); |
| - sync_state_label_->SetEnabled(false); |
| - AddChildView(sync_state_label_); |
| + virtual void OnHighlightStateChanged() OVERRIDE; |
| - // Add an edit profile link. |
| - edit_link_ = new EditProfileLink( |
| - l10n_util::GetStringUTF16(IDS_PROFILES_EDIT_PROFILE_LINK), this); |
| - edit_link_->set_listener(edit_profile_listener); |
| - edit_link_->SetHorizontalAlignment(views::Label::ALIGN_LEFT); |
| - edit_link_->MakeReadableOverBackgroundColor(kHighlightBackgroundColor); |
| - edit_link_->SetNormalColor( |
| - color_utils::GetReadableColor(kLinkColor, kHighlightBackgroundColor)); |
| - edit_link_->SetHasFocusBorder(true); |
| - AddChildView(edit_link_); |
| + EditProfileLink* edit_link() { return edit_link_; } |
| + const AvatarMenuModel::Item& item() { return item_; } |
| - OnHighlightStateChanged(); |
| - } |
| + private: |
| + static SkBitmap GetBadgedIcon(const SkBitmap& icon); |
| - virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE { |
| - if (IsHighlighted()) { |
| - canvas->FillRectInt(kHighlightBackgroundColor, 0, 0, |
| - width(), height()); |
| - } |
| - } |
| + bool IsHighlighted() const; |
| - virtual gfx::Size GetPreferredSize() OVERRIDE { |
| - int width = std::max(name_label_->GetPreferredSize().width(), |
| - sync_state_label_->GetPreferredSize().width()); |
| - width = std::max(edit_link_->GetPreferredSize().width(), |
| - width); |
| - return gfx::Size(kIconWidth + kIconMarginX + width, kItemHeight); |
| - } |
| + EditProfileLink* edit_link_; |
| + views::ImageView* image_view_; |
| + AvatarMenuModel::Item item_; |
| + views::Label* name_label_; |
| + views::Label* sync_state_label_; |
| +}; |
| - virtual void Layout() OVERRIDE { |
| - // Profile icon. |
| - const SkBitmap& icon = image_view_->GetImage(); |
| - gfx::Rect icon_rect = GetCenteredAndScaledRect( |
| - icon.width(), icon.height(), 0, 0, kIconWidth, height()); |
| - image_view_->SetBoundsRect(icon_rect); |
| +ProfileItemView::ProfileItemView(const AvatarMenuModel::Item& item, |
| + views::ButtonListener* switch_profile_listener, |
| + views::LinkListener* edit_profile_listener) |
| + : views::CustomButton(switch_profile_listener), |
| + item_(item) { |
| + image_view_ = new ProfileImageView(); |
| + SkBitmap profile_icon = item_.icon; |
| + image_view_->SetImage(item_.active ? |
| + &GetBadgedIcon(profile_icon) : &profile_icon); |
| + AddChildView(image_view_); |
| - int label_x = icon_rect.right() + kIconMarginX; |
| - int max_label_width = width() - label_x; |
| - gfx::Size name_size = name_label_->GetPreferredSize(); |
| - name_size.set_width(std::min(name_size.width(), max_label_width)); |
| - gfx::Size state_size = sync_state_label_->GetPreferredSize(); |
| - state_size.set_width(std::min(state_size.width(), max_label_width)); |
| - gfx::Size edit_size = edit_link_->GetPreferredSize(); |
| - edit_size.set_width(std::min(edit_size.width(), max_label_width)); |
| + // Add a label to show the profile name. |
| + name_label_ = new views::Label(item_.name); |
| + ResourceBundle& rb = ResourceBundle::GetSharedInstance(); |
| + gfx::Font base_font = rb.GetFont(ResourceBundle::BaseFont); |
| + int style = item_.active ? gfx::Font::BOLD : 0; |
| + const int kNameFontDelta = 1; |
| + name_label_->SetFont(base_font.DeriveFont(kNameFontDelta, style)); |
| + name_label_->SetHorizontalAlignment(views::Label::ALIGN_LEFT); |
| + AddChildView(name_label_); |
| - const int kNameStatePaddingY = 2; |
| - int labels_height = name_size.height() + kNameStatePaddingY + |
| - std::max(state_size.height(), edit_size.height()); |
| - int y = (height() - labels_height) / 2; |
| - name_label_->SetBounds(label_x, y, name_size.width(), name_size.height()); |
| + // Add a label to show the sync state. |
| + sync_state_label_ = new views::Label(item_.sync_state); |
| + const int kStateFontDelta = -1; |
| + sync_state_label_->SetFont(base_font.DeriveFont(kStateFontDelta)); |
| + sync_state_label_->SetHorizontalAlignment(views::Label::ALIGN_LEFT); |
| + sync_state_label_->SetEnabled(false); |
| + AddChildView(sync_state_label_); |
| - int bottom = y + labels_height; |
| - sync_state_label_->SetBounds(label_x, bottom - state_size.height(), |
| - state_size.width(), state_size.height()); |
| - // The edit link overlaps the sync state label. |
| - edit_link_->SetBounds(label_x, bottom - edit_size.height(), |
| - edit_size.width(), edit_size.height()); |
| - } |
| + // Add an edit profile link. |
| + edit_link_ = new EditProfileLink( |
| + l10n_util::GetStringUTF16(IDS_PROFILES_EDIT_PROFILE_LINK), this); |
| + edit_link_->set_listener(edit_profile_listener); |
| + edit_link_->SetHorizontalAlignment(views::Label::ALIGN_LEFT); |
| + 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.
|
| + AddChildView(edit_link_); |
| - virtual void OnHighlightStateChanged() OVERRIDE { |
| - bool is_highlighted = IsHighlighted(); |
| - bool show_edit = is_highlighted && item_.active; |
| - sync_state_label_->SetVisible(!show_edit); |
| - edit_link_->SetVisible(show_edit); |
| + OnHighlightStateChanged(); |
| +} |
| - SkColor background_color = |
| - is_highlighted ? kHighlightBackgroundColor : Bubble::kBackgroundColor; |
| - name_label_->MakeReadableOverBackgroundColor(background_color); |
| - sync_state_label_->MakeReadableOverBackgroundColor(background_color); |
| +gfx::Size ProfileItemView::GetPreferredSize() { |
| + int width = std::max(name_label_->GetPreferredSize().width(), |
| + sync_state_label_->GetPreferredSize().width()); |
| + width = std::max(edit_link_->GetPreferredSize().width(), width); |
| + return gfx::Size(kIconWidth + kIconMarginX + width, kItemHeight); |
| +} |
| - SchedulePaint(); |
| - } |
| +void ProfileItemView::Layout() { |
| + // Profile icon. |
| + const SkBitmap& icon = image_view_->GetImage(); |
| + gfx::Rect icon_rect = GetCenteredAndScaledRect( |
| + icon.width(), icon.height(), 0, 0, kIconWidth, height()); |
| + image_view_->SetBoundsRect(icon_rect); |
| - virtual void OnMouseEntered(const views::MouseEvent& event) OVERRIDE { |
| - views::CustomButton::OnMouseEntered(event); |
| - OnHighlightStateChanged(); |
| - } |
| + int label_x = icon_rect.right() + kIconMarginX; |
| + int max_label_width = width() - label_x; |
| + gfx::Size name_size = name_label_->GetPreferredSize(); |
| + name_size.set_width(std::min(name_size.width(), max_label_width)); |
| + gfx::Size state_size = sync_state_label_->GetPreferredSize(); |
| + state_size.set_width(std::min(state_size.width(), max_label_width)); |
| + gfx::Size edit_size = edit_link_->GetPreferredSize(); |
| + edit_size.set_width(std::min(edit_size.width(), max_label_width)); |
| - virtual void OnMouseExited(const views::MouseEvent& event) OVERRIDE { |
| - views::CustomButton::OnMouseExited(event); |
| - OnHighlightStateChanged(); |
| - } |
| + const int kNameStatePaddingY = 2; |
| + int labels_height = name_size.height() + kNameStatePaddingY + |
| + std::max(state_size.height(), edit_size.height()); |
| + int y = (height() - labels_height) / 2; |
| + name_label_->SetBounds(label_x, y, name_size.width(), name_size.height()); |
| - EditProfileLink* edit_link() { return edit_link_; } |
| - const AvatarMenuModel::Item& item() { return item_; } |
| + int bottom = y + labels_height; |
| + sync_state_label_->SetBounds(label_x, bottom - state_size.height(), |
| + state_size.width(), state_size.height()); |
| + // The edit link overlaps the sync state label. |
| + edit_link_->SetBounds(label_x, bottom - edit_size.height(), |
| + edit_size.width(), edit_size.height()); |
| +} |
| - private: |
| - bool IsHighlighted() { |
| - return state() == views::CustomButton::BS_PUSHED || |
| - state() == views::CustomButton::BS_HOT || |
| - edit_link_->state() == views::CustomButton::BS_PUSHED || |
| - edit_link_->state() == views::CustomButton::BS_HOT; |
| - } |
| +void ProfileItemView::OnMouseEntered(const views::MouseEvent& event) { |
| + views::CustomButton::OnMouseEntered(event); |
| + OnHighlightStateChanged(); |
| +} |
| - SkBitmap GetBadgedIcon(const SkBitmap& icon) { |
| - gfx::Rect icon_rect = GetCenteredAndScaledRect( |
| - icon.width(), icon.height(), 0, 0, kIconWidth, kItemHeight); |
| +void ProfileItemView::OnMouseExited(const views::MouseEvent& event) { |
| + views::CustomButton::OnMouseExited(event); |
| + OnHighlightStateChanged(); |
| +} |
| - ResourceBundle& rb = ResourceBundle::GetSharedInstance(); |
| - SkBitmap badge = rb.GetImageNamed(IDR_PROFILE_SELECTED); |
| - const float kBadgeOverlapRatioX = 1.0f / 5.0f; |
| - int width = icon_rect.width() + badge.width() * kBadgeOverlapRatioX; |
| - const float kBadgeOverlapRatioY = 1.0f / 3.0f; |
| - int height = icon_rect.height() + badge.height() * kBadgeOverlapRatioY; |
| +void ProfileItemView::OnHighlightStateChanged() { |
| + set_background(IsHighlighted() ? views::Background::CreateSolidBackground( |
|
sail
2011/10/10 23:49:34
cool!
|
| + SkColorSetRGB(0xe3, 0xed, 0xf6)) : NULL); |
| + SkColor background_color = background() ? |
| + background()->get_color() : Bubble::kBackgroundColor; |
| + name_label_->SetBackgroundColor(background_color); |
| + sync_state_label_->SetBackgroundColor(background_color); |
| + edit_link_->SetBackgroundColor(background_color); |
| - gfx::CanvasSkia canvas(width, height, false); |
| - canvas.DrawBitmapInt(icon, 0, 0, icon.width(), icon.height(), 0, 0, |
| - icon_rect.width(), icon_rect.height(), true); |
| - canvas.DrawBitmapInt(badge, width - badge.width(), height - badge.height()); |
| - return canvas.ExtractBitmap(); |
| - } |
| + bool show_edit = IsHighlighted() && item_.active; |
| + sync_state_label_->SetVisible(!show_edit); |
| + edit_link_->SetVisible(show_edit); |
| + SchedulePaint(); |
| +} |
| - EditProfileLink* edit_link_; |
| - views::ImageView* image_view_; |
| - AvatarMenuModel::Item item_; |
| - views::Label* name_label_; |
| - views::Label* sync_state_label_; |
| -}; |
| +// static |
| +SkBitmap ProfileItemView::GetBadgedIcon(const SkBitmap& icon) { |
| + gfx::Rect icon_rect = GetCenteredAndScaledRect( |
| + icon.width(), icon.height(), 0, 0, kIconWidth, kItemHeight); |
| + ResourceBundle& rb = ResourceBundle::GetSharedInstance(); |
| + SkBitmap badge = rb.GetImageNamed(IDR_PROFILE_SELECTED); |
| + const float kBadgeOverlapRatioX = 1.0f / 5.0f; |
| + int width = icon_rect.width() + badge.width() * kBadgeOverlapRatioX; |
| + const float kBadgeOverlapRatioY = 1.0f / 3.0f; |
| + int height = icon_rect.height() + badge.height() * kBadgeOverlapRatioY; |
| + |
| + gfx::CanvasSkia canvas(width, height, false); |
| + canvas.DrawBitmapInt(icon, 0, 0, icon.width(), icon.height(), 0, 0, |
| + icon_rect.width(), icon_rect.height(), true); |
| + canvas.DrawBitmapInt(badge, width - badge.width(), height - badge.height()); |
| + return canvas.ExtractBitmap(); |
| +} |
| + |
| +bool ProfileItemView::IsHighlighted() const { |
| + return state() == views::CustomButton::BS_PUSHED || |
| + state() == views::CustomButton::BS_HOT || |
| + edit_link_->state() == views::CustomButton::BS_PUSHED || |
| + edit_link_->state() == views::CustomButton::BS_HOT; |
| +} |
| + |
| } // namespace |
| + |
| +// AvatarMenuBubbleView ------------------------------------------------------- |
| + |
| AvatarMenuBubbleView::AvatarMenuBubbleView(Browser* browser) |
| : add_profile_link_(NULL), |
| browser_(browser) { |
| @@ -385,9 +407,8 @@ |
| l10n_util::GetStringUTF16(IDS_PROFILES_CREATE_NEW_PROFILE_LINK)); |
| add_profile_link_->set_listener(this); |
| add_profile_link_->SetHorizontalAlignment(views::Label::ALIGN_LEFT); |
| - add_profile_link_->MakeReadableOverBackgroundColor(Bubble::kBackgroundColor); |
| - add_profile_link_->SetNormalColor( |
| - color_utils::GetReadableColor(kLinkColor, Bubble::kBackgroundColor)); |
| + add_profile_link_->SetBackgroundColor(Bubble::kBackgroundColor); |
| + add_profile_link_->SetEnabledColor(SkColorSetRGB(0xe3, 0xed, 0xf6)); |
| AddChildView(add_profile_link_); |
| PreferredSizeChanged(); |