| Index: chrome/browser/ui/views/avatar_menu_bubble_view.cc
|
| ===================================================================
|
| --- chrome/browser/ui/views/avatar_menu_bubble_view.cc (revision 104959)
|
| +++ 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,210 @@
|
| 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_;
|
| +};
|
| +
|
| +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;
|
| + if (item_.active) {
|
| + SkBitmap badged_icon(GetBadgedIcon(profile_icon));
|
| + image_view_->SetImage(&badged_icon);
|
| + } else {
|
| + image_view_->SetImage(&profile_icon);
|
| }
|
| + AddChildView(image_view_);
|
|
|
| - 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);
|
| + // 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_);
|
|
|
| - 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 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_);
|
|
|
| - 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 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));
|
| + edit_link_->SetHasFocusBorder(true);
|
| + AddChildView(edit_link_);
|
|
|
| - 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());
|
| - }
|
| + OnHighlightStateChanged();
|
| +}
|
|
|
| - 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);
|
| +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);
|
| +}
|
|
|
| - SkColor background_color =
|
| - is_highlighted ? kHighlightBackgroundColor : Bubble::kBackgroundColor;
|
| - name_label_->MakeReadableOverBackgroundColor(background_color);
|
| - sync_state_label_->MakeReadableOverBackgroundColor(background_color);
|
| +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);
|
|
|
| - SchedulePaint();
|
| - }
|
| + 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 OnMouseEntered(const views::MouseEvent& event) OVERRIDE {
|
| - views::CustomButton::OnMouseEntered(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());
|
|
|
| - virtual void OnMouseExited(const views::MouseEvent& event) OVERRIDE {
|
| - views::CustomButton::OnMouseExited(event);
|
| - OnHighlightStateChanged();
|
| - }
|
| + 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());
|
| +}
|
|
|
| - EditProfileLink* edit_link() { return edit_link_; }
|
| - const AvatarMenuModel::Item& item() { return item_; }
|
| +void ProfileItemView::OnMouseEntered(const views::MouseEvent& event) {
|
| + views::CustomButton::OnMouseEntered(event);
|
| + OnHighlightStateChanged();
|
| +}
|
|
|
| - 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::OnMouseExited(const views::MouseEvent& event) {
|
| + views::CustomButton::OnMouseExited(event);
|
| + OnHighlightStateChanged();
|
| +}
|
|
|
| - SkBitmap GetBadgedIcon(const SkBitmap& icon) {
|
| - gfx::Rect icon_rect = GetCenteredAndScaledRect(
|
| - icon.width(), icon.height(), 0, 0, kIconWidth, kItemHeight);
|
| +void ProfileItemView::OnHighlightStateChanged() {
|
| + set_background(IsHighlighted() ? views::Background::CreateSolidBackground(
|
| + 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);
|
|
|
| - 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;
|
| + bool show_edit = IsHighlighted() && item_.active;
|
| + sync_state_label_->SetVisible(!show_edit);
|
| + edit_link_->SetVisible(show_edit);
|
| + SchedulePaint();
|
| +}
|
|
|
| - 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();
|
| - }
|
| +// static
|
| +SkBitmap ProfileItemView::GetBadgedIcon(const SkBitmap& icon) {
|
| + gfx::Rect icon_rect = GetCenteredAndScaledRect(
|
| + icon.width(), icon.height(), 0, 0, kIconWidth, kItemHeight);
|
|
|
| - EditProfileLink* edit_link_;
|
| - views::ImageView* image_view_;
|
| - AvatarMenuModel::Item item_;
|
| - views::Label* name_label_;
|
| - views::Label* sync_state_label_;
|
| -};
|
| + 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 +412,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();
|
|
|