diff options
author | sail@chromium.org <sail@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-06-10 17:48:39 +0000 |
---|---|---|
committer | sail@chromium.org <sail@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-06-10 17:48:39 +0000 |
commit | 440c3efe7e46d48ee62ccfdabbede831fd6b4662 (patch) | |
tree | 5eb05df99b33136cbe3d263f5e9018815c5cc5b2 | |
parent | 5af135a2b8d8b0d1a434f09dd866721dc9a47c5e (diff) | |
download | chromium_src-440c3efe7e46d48ee62ccfdabbede831fd6b4662.zip chromium_src-440c3efe7e46d48ee62ccfdabbede831fd6b4662.tar.gz chromium_src-440c3efe7e46d48ee62ccfdabbede831fd6b4662.tar.bz2 |
Change profile menu button to avatar button
This change doesn't add any new functionality. It simply changes the profile menu button so that it now draws an avatar icon.
Once this is checked in next steps will be to:
- associate avatar icons to profiles
- expand the profile menu
BUG=None
TEST=Ran on Windows and verified that things look ok.
Review URL: http://codereview.chromium.org/7003080
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@88683 0039d316-1c4b-4281-b951-d872f2087c98
28 files changed, 271 insertions, 642 deletions
diff --git a/chrome/app/theme/profile_tag_center_aero.png b/chrome/app/theme/profile_tag_center_aero.png Binary files differdeleted file mode 100644 index 407f9ff..0000000 --- a/chrome/app/theme/profile_tag_center_aero.png +++ /dev/null diff --git a/chrome/app/theme/profile_tag_center_mask.png b/chrome/app/theme/profile_tag_center_mask.png Binary files differdeleted file mode 100644 index 9f8368b..0000000 --- a/chrome/app/theme/profile_tag_center_mask.png +++ /dev/null diff --git a/chrome/app/theme/profile_tag_center_opaque.png b/chrome/app/theme/profile_tag_center_opaque.png Binary files differdeleted file mode 100644 index f4c3149..0000000 --- a/chrome/app/theme/profile_tag_center_opaque.png +++ /dev/null diff --git a/chrome/app/theme/profile_tag_inactive_center_aero.png b/chrome/app/theme/profile_tag_inactive_center_aero.png Binary files differdeleted file mode 100644 index 09dd158..0000000 --- a/chrome/app/theme/profile_tag_inactive_center_aero.png +++ /dev/null diff --git a/chrome/app/theme/profile_tag_inactive_left_aero.png b/chrome/app/theme/profile_tag_inactive_left_aero.png Binary files differdeleted file mode 100644 index cec460a..0000000 --- a/chrome/app/theme/profile_tag_inactive_left_aero.png +++ /dev/null diff --git a/chrome/app/theme/profile_tag_inactive_right_aero.png b/chrome/app/theme/profile_tag_inactive_right_aero.png Binary files differdeleted file mode 100644 index 208def6a..0000000 --- a/chrome/app/theme/profile_tag_inactive_right_aero.png +++ /dev/null diff --git a/chrome/app/theme/profile_tag_left_aero.png b/chrome/app/theme/profile_tag_left_aero.png Binary files differdeleted file mode 100644 index 206d081..0000000 --- a/chrome/app/theme/profile_tag_left_aero.png +++ /dev/null diff --git a/chrome/app/theme/profile_tag_left_mask.png b/chrome/app/theme/profile_tag_left_mask.png Binary files differdeleted file mode 100644 index fa6a33e..0000000 --- a/chrome/app/theme/profile_tag_left_mask.png +++ /dev/null diff --git a/chrome/app/theme/profile_tag_left_opaque.png b/chrome/app/theme/profile_tag_left_opaque.png Binary files differdeleted file mode 100644 index ba6db11..0000000 --- a/chrome/app/theme/profile_tag_left_opaque.png +++ /dev/null diff --git a/chrome/app/theme/profile_tag_right_aero.png b/chrome/app/theme/profile_tag_right_aero.png Binary files differdeleted file mode 100644 index 3f26f11..0000000 --- a/chrome/app/theme/profile_tag_right_aero.png +++ /dev/null diff --git a/chrome/app/theme/profile_tag_right_mask.png b/chrome/app/theme/profile_tag_right_mask.png Binary files differdeleted file mode 100644 index c94dc28..0000000 --- a/chrome/app/theme/profile_tag_right_mask.png +++ /dev/null diff --git a/chrome/app/theme/profile_tag_right_opaque.png b/chrome/app/theme/profile_tag_right_opaque.png Binary files differdeleted file mode 100644 index c8ac3c0..0000000 --- a/chrome/app/theme/profile_tag_right_opaque.png +++ /dev/null diff --git a/chrome/app/theme/theme_resources.grd b/chrome/app/theme/theme_resources.grd index 8bdc77c..db56cb4 100644 --- a/chrome/app/theme/theme_resources.grd +++ b/chrome/app/theme/theme_resources.grd @@ -215,18 +215,7 @@ <!-- NOTE: product_logo_*.* files beyond what's listed above are referenced by installer code; don't remove them unless you know what you're doing! --> - <include name="IDR_PROFILE_TAG_CENTER_AERO" file="profile_tag_center_aero.png" type="BINDATA" /> - <include name="IDR_PROFILE_TAG_LEFT_AERO" file="profile_tag_left_aero.png" type="BINDATA" /> - <include name="IDR_PROFILE_TAG_RIGHT_AERO" file="profile_tag_right_aero.png" type="BINDATA" /> - <include name="IDR_PROFILE_TAG_INACTIVE_CENTER_AERO" file="profile_tag_inactive_center_aero.png" type="BINDATA" /> - <include name="IDR_PROFILE_TAG_INACTIVE_LEFT_AERO" file="profile_tag_inactive_left_aero.png" type="BINDATA" /> - <include name="IDR_PROFILE_TAG_INACTIVE_RIGHT_AERO" file="profile_tag_inactive_right_aero.png" type="BINDATA" /> - <include name="IDR_PROFILE_TAG_CENTER_THEMED" file="profile_tag_center_opaque.png" type="BINDATA" /> - <include name="IDR_PROFILE_TAG_LEFT_THEMED" file="profile_tag_left_opaque.png" type="BINDATA" /> - <include name="IDR_PROFILE_TAG_RIGHT_THEMED" file="profile_tag_right_opaque.png" type="BINDATA" /> - <include name="IDR_PROFILE_TAG_CENTER_MASK" file="profile_tag_center_mask.png" type="BINDATA" /> - <include name="IDR_PROFILE_TAG_LEFT_MASK" file="profile_tag_left_mask.png" type="BINDATA" /> - <include name="IDR_PROFILE_TAG_RIGHT_MASK" file="profile_tag_right_mask.png" type="BINDATA" /> + <include name="IDR_PROFILE_AVATAR_1" file="avatar_cupcake.png" type="BINDATA" /> <include name="IDR_RESTORE_BUTTON_MASK" file="restore_button_mask.png" type="BINDATA" /> <include name="IDR_SAD_FAVICON" file="sadfavicon.png" type="BINDATA" /> <include name="IDR_SAD_TAB" file="sadtab.png" type="BINDATA" /> diff --git a/chrome/browser/ui/views/avatar_menu_button.cc b/chrome/browser/ui/views/avatar_menu_button.cc new file mode 100644 index 0000000..e2585ca --- /dev/null +++ b/chrome/browser/ui/views/avatar_menu_button.cc @@ -0,0 +1,71 @@ +// 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_button.h" + +#include "ui/gfx/canvas_skia.h" +#include "views/controls/menu/menu_model_adapter.h" +#include "views/window/window.h" + +// Menu should display below the image on the frame. This +// offset size depends on whether the frame is in glass or opaque mode. +const int kMenuDisplayOffset = 5; + +static inline int Round(double x) { + return static_cast<int>(floor(x + 0.5)); +} + +AvatarMenuButton::AvatarMenuButton(const std::wstring& text, + ui::MenuModel* menu_model) + : MenuButton(NULL, text, this, false), + menu_model_(menu_model) { + // In RTL mode, the avatar icon should be looking the opposite direction. + EnableCanvasFlippingForRTLUI(true); +} + +AvatarMenuButton::~AvatarMenuButton() {} + +void AvatarMenuButton::OnPaint(gfx::Canvas* canvas) { + const SkBitmap& icon = GetImageToPaint(); + if (!icon.isNull()) { + // Scale the image to fit the width of the button. + int src_width = icon.width(); + int src_x = 0; + int dst_width = std::min(src_width, width()); + int dst_x = Round((width() - dst_width) / 2.0); + + // Scale the height and maintain aspect ratio. This means that the + // icon may not fit in the view. That's ok, we just center it vertically. + float scale = + static_cast<float>(dst_width) / static_cast<float>(icon.width()); + int scaled_height = Round(height() / scale); + int src_height = std::min(scaled_height, icon.height()); + int src_y = Round((icon.height() - src_height) / 2.0); + int dst_height = src_height * scale; + int dst_y = Round((height() - dst_height) / 2.0); + + canvas->DrawBitmapInt(icon, src_x, src_y, src_width, src_height, + dst_x, dst_y, dst_width, dst_height, false); + } +} + +gfx::Size AvatarMenuButton::GetPreferredAvatarSize() { + return gfx::Size(38, 31); +} + +// views::ViewMenuDelegate implementation +void AvatarMenuButton::RunMenu(views::View* source, const gfx::Point& pt) { + if (!menu_model_.get()) + return; + + views::MenuModelAdapter menu_model_adapter(menu_model_.get()); + views::MenuItemView menu(&menu_model_adapter); + menu_model_adapter.BuildMenu(&menu); + + gfx::Point menu_point(pt.x(), pt.y() + kMenuDisplayOffset); + menu.RunMenuAt(source->GetWindow()->GetNativeWindow(), NULL, + gfx::Rect(pt, gfx::Size(0, 0)), + views::MenuItemView::TOPRIGHT, + true); +} diff --git a/chrome/browser/ui/views/avatar_menu_button.h b/chrome/browser/ui/views/avatar_menu_button.h new file mode 100644 index 0000000..1675e59 --- /dev/null +++ b/chrome/browser/ui/views/avatar_menu_button.h @@ -0,0 +1,47 @@ +// 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. + +#ifndef CHROME_BROWSER_UI_VIEWS_AVATAR_MENU_BUTTON_H_ +#define CHROME_BROWSER_UI_VIEWS_AVATAR_MENU_BUTTON_H_ +#pragma once + +#include <string> + +#include "base/compiler_specific.h" +#include "ui/base/models/simple_menu_model.h" +#include "views/controls/button/menu_button.h" +#include "views/controls/menu/view_menu_delegate.h" + +namespace gfx { +class Canvas; +} + +// AvatarMenuButton +// +// A button used to show either the incognito avatar or the profile avatar. +// The button can optionally have a menu attached to it. + +class AvatarMenuButton : public views::MenuButton, + public views::ViewMenuDelegate { + public: + // Creates a new button. The object will take ownership of the menu model. + AvatarMenuButton(const std::wstring& text, ui::MenuModel* menu_model); + + virtual ~AvatarMenuButton(); + + // views::MenuButton + virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE; + + static gfx::Size GetPreferredAvatarSize(); + + private: + // views::ViewMenuDelegate + virtual void RunMenu(views::View* source, const gfx::Point& pt) OVERRIDE; + + scoped_ptr<ui::MenuModel> menu_model_; + + DISALLOW_COPY_AND_ASSIGN(AvatarMenuButton); +}; + +#endif // CHROME_BROWSER_UI_VIEWS_AVATAR_MENU_BUTTON_H_ diff --git a/chrome/browser/ui/views/frame/browser_view.cc b/chrome/browser/ui/views/frame/browser_view.cc index a0c2f30..3c4b856 100644 --- a/chrome/browser/ui/views/frame/browser_view.cc +++ b/chrome/browser/ui/views/frame/browser_view.cc @@ -464,8 +464,10 @@ bool BrowserView::IsOffTheRecord() const { return browser_->profile()->IsOffTheRecord(); } -bool BrowserView::ShouldShowOffTheRecordAvatar() const { - return IsOffTheRecord() && IsBrowserTypeNormal(); +bool BrowserView::ShouldShowAvatar() const { + return IsBrowserTypeNormal() && + (IsOffTheRecord() || + CommandLine::ForCurrentProcess()->HasSwitch(switches::kMultiProfiles)); } bool BrowserView::AcceleratorPressed(const views::Accelerator& accelerator) { diff --git a/chrome/browser/ui/views/frame/browser_view.h b/chrome/browser/ui/views/frame/browser_view.h index f45afeb..d61522a 100644 --- a/chrome/browser/ui/views/frame/browser_view.h +++ b/chrome/browser/ui/views/frame/browser_view.h @@ -165,9 +165,8 @@ class BrowserView : public BrowserBubbleHost, // incognito. bool IsOffTheRecord() const; - // Returns true if the non-client view should render the Incognito - // avatar icon if the window is incognito. - virtual bool ShouldShowOffTheRecordAvatar() const; + // Returns true if the non-client view should render an avatar icon. + virtual bool ShouldShowAvatar() const; // Handle the specified |accelerator| being pressed. virtual bool AcceleratorPressed(const views::Accelerator& accelerator); diff --git a/chrome/browser/ui/views/frame/glass_browser_frame_view.cc b/chrome/browser/ui/views/frame/glass_browser_frame_view.cc index fb16075..f2e26c9 100644 --- a/chrome/browser/ui/views/frame/glass_browser_frame_view.cc +++ b/chrome/browser/ui/views/frame/glass_browser_frame_view.cc @@ -11,9 +11,9 @@ #include "chrome/browser/prefs/pref_service.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/themes/theme_service.h" +#include "chrome/browser/ui/profile_menu_model.h" +#include "chrome/browser/ui/views/avatar_menu_button.h" #include "chrome/browser/ui/views/frame/browser_view.h" -#include "chrome/browser/ui/views/profile_menu_button.h" -#include "chrome/browser/ui/views/profile_tag_view.h" #include "chrome/browser/ui/views/tabs/side_tab_strip.h" #include "chrome/browser/ui/views/tabs/tab.h" #include "chrome/browser/ui/views/tabs/tab_strip.h" @@ -46,13 +46,13 @@ const int kNonClientRestoredExtraThickness = 11; // In the window corners, the resize areas don't actually expand bigger, but the // 16 px at the end of the top and bottom edges triggers diagonal resizing. const int kResizeAreaCornerSize = 16; -// The OTR avatar ends 2 px above the bottom of the tabstrip (which, given the +// The avatar ends 2 px above the bottom of the tabstrip (which, given the // way the tabstrip draws its bottom edge, will appear like a 1 px gap to the // user). -const int kOTRBottomSpacing = 2; -// There are 2 px on each side of the OTR avatar (between the frame border and +const int kAvatarBottomSpacing = 2; +// There are 2 px on each side of the avatar (between the frame border and // it on the left, and between it and the tabstrip on the right). -const int kOTRSideSpacing = 2; +const int kAvatarSideSpacing = 2; // The content left/right images have a shadow built into them. const int kContentEdgeShadowThickness = 2; // The top 1 px of the tabstrip is shadow; in maximized mode we push this off @@ -66,12 +66,6 @@ const int kNewTabCaptionRestoredSpacing = 5; // similar vertical coordinates, we need to reserve a larger, 16 px gap to avoid // looking too cluttered. const int kNewTabCaptionMaximizedSpacing = 16; -// Y position for profile button inside the frame. -const int kProfileButtonYPosition = 2; -// Y position for profile tag inside the frame. -const int kProfileTagYPosition = 1; -// Offset y position of profile button and tag by this amount when maximized. -const int kProfileElementMaximizedYOffset = 6; } /////////////////////////////////////////////////////////////////////////////// @@ -86,18 +80,29 @@ GlassBrowserFrameView::GlassBrowserFrameView(BrowserFrame* frame, throbber_frame_(0) { if (browser_view_->ShouldShowWindowIcon()) InitThrobberIcons(); - // If multi-profile is enabled set up profile button and login notifications. + + if (browser_view_->ShouldShowAvatar()) { + ui::MenuModel* menu_model = browser_view_->IsOffTheRecord() ? + NULL : new ProfileMenuModel; + // AvatarMenuButton takes ownership of |menu_model|. + avatar_button_.reset(new AvatarMenuButton(std::wstring(), menu_model)); + AddChildView(avatar_button_.get()); + + if (browser_view_->IsOffTheRecord()) { + avatar_button_->SetIcon(browser_view_->GetOTRAvatarIcon()); + } else { + // TODO(sail) Get the avatar icon assigned to this profile. + ResourceBundle& rb = ResourceBundle::GetSharedInstance(); + avatar_button_->SetIcon(*rb.GetBitmapNamed(IDR_PROFILE_AVATAR_1)); + // TODO(sail) Also need to call SetHoverIcon() and SetPushedIcon(). + } + } + + // If multi-profile is enabled set up login notifications. const CommandLine& browser_command_line = *CommandLine::ForCurrentProcess(); if (browser_command_line.HasSwitch(switches::kMultiProfiles) && - !browser_view->ShouldShowOffTheRecordAvatar()) { + !browser_view->IsOffTheRecord()) { RegisterLoginNotifications(); - profile_button_.reset(new ProfileMenuButton(std::wstring(), - browser_view_->browser()->profile())); - profile_button_->SetVisible(false); - profile_tag_.reset(new ProfileTagView(frame_, profile_button_.get())); - profile_tag_->SetVisible(false); - AddChildView(profile_tag_.get()); - AddChildView(profile_button_.get()); } } @@ -117,8 +122,8 @@ gfx::Rect GlassBrowserFrameView::GetBoundsForTabStrip( } int minimize_button_offset = std::min(frame_->GetMinimizeButtonOffset(), width()); - int tabstrip_x = browser_view_->ShouldShowOffTheRecordAvatar() ? - (otr_avatar_bounds_.right() + kOTRSideSpacing) : + int tabstrip_x = browser_view_->ShouldShowAvatar() ? + (avatar_bounds_.right() + kAvatarSideSpacing) : NonClientBorderThickness(); // In RTL languages, we have moved an avatar icon left by the size of window // controls to prevent it from being rendered over them. So, we use its x @@ -126,15 +131,11 @@ gfx::Rect GlassBrowserFrameView::GetBoundsForTabStrip( // a tab strip until the left end of this window without considering the size // of window controls in RTL languages. if (base::i18n::IsRTL()) { - if (!browser_view_->ShouldShowOffTheRecordAvatar() && frame_->IsMaximized()) - tabstrip_x += otr_avatar_bounds_.x(); + if (!browser_view_->ShouldShowAvatar() && frame_->IsMaximized()) + tabstrip_x += avatar_bounds_.x(); minimize_button_offset = width(); } - int maximized_spacing = - kNewTabCaptionMaximizedSpacing + - (show_profile_button() && profile_button_->IsVisible() ? - profile_button_->GetPreferredSize().width() + - ProfileMenuButton::kProfileTagHorizontalSpacing : 0); + int maximized_spacing = kNewTabCaptionMaximizedSpacing; int tabstrip_width = minimize_button_offset - tabstrip_x - (frame_->IsMaximized() ? maximized_spacing : kNewTabCaptionRestoredSpacing); @@ -197,6 +198,11 @@ int GlassBrowserFrameView::NonClientHitTest(const gfx::Point& point) { if (!browser_view_->IsBrowserTypeNormal() || !bounds().Contains(point)) return HTNOWHERE; + // See if the point is within the avatar menu button. + if (avatar_button_.get() && + avatar_button_->GetMirroredBounds().Contains(point)) + return HTCLIENT; + int frame_component = frame_->client_view()->NonClientHitTest(point); // See if we're in the sysmenu region. We still have to check the tabstrip @@ -210,11 +216,6 @@ int GlassBrowserFrameView::NonClientHitTest(const gfx::Point& point) { if (frame_component != HTNOWHERE) return frame_component; - // See if the point is within the profile menu button. - if (show_profile_button() && profile_button_->IsVisible() && - profile_button_->GetMirroredBounds().Contains(point)) - return HTCLIENT; - int frame_border_thickness = FrameBorderThickness(); int window_component = GetHTComponentForFrame(point, frame_border_thickness, nonclient_border_thickness, frame_border_thickness, @@ -232,24 +233,18 @@ void GlassBrowserFrameView::OnPaint(gfx::Canvas* canvas) { return; // Nothing is visible, so don't bother to paint. PaintToolbarBackground(canvas); - if (browser_view_->ShouldShowOffTheRecordAvatar()) - PaintOTRAvatar(canvas); if (!frame_->IsMaximized()) PaintRestoredClientEdge(canvas); } void GlassBrowserFrameView::Layout() { - LayoutOTRAvatar(); + LayoutAvatar(); LayoutClientView(); - LayoutProfileTag(); } bool GlassBrowserFrameView::HitTest(const gfx::Point& l) const { - // The ProfileMenuButton intrudes into the client area when the window is - // maximized. - return (frame_->IsMaximized() && show_profile_button() && - profile_button_->IsVisible() && - profile_button_->GetMirroredBounds().Contains(l)) || + return (avatar_button_.get() && + avatar_button_->GetMirroredBounds().Contains(l)) || !frame_->client_view()->bounds().Contains(l); } @@ -382,27 +377,6 @@ void GlassBrowserFrameView::PaintToolbarBackground(gfx::Canvas* canvas) { w - (2 * kClientEdgeThickness), kClientEdgeThickness); } -void GlassBrowserFrameView::PaintOTRAvatar(gfx::Canvas* canvas) { - // In RTL mode, the avatar icon should be looking the opposite direction. - canvas->Save(); - if (base::i18n::IsRTL()) { - canvas->TranslateInt(width(), 0); - canvas->ScaleInt(-1, 1); - } - - SkBitmap otr_avatar_icon = browser_view_->GetOTRAvatarIcon(); - int w = otr_avatar_bounds_.width(); - int h = otr_avatar_bounds_.height(); - canvas->DrawBitmapInt(otr_avatar_icon, 0, - // Bias the rounding to select a region that's lower rather than higher, - // as the shadows at the image top mean the apparent center is below the - // real center. - ((otr_avatar_icon.height() - otr_avatar_bounds_.height()) + 1) / 2, w, h, - otr_avatar_bounds_.x(), otr_avatar_bounds_.y(), w, h, false); - - canvas->Restore(); -} - void GlassBrowserFrameView::PaintRestoredClientEdge(gfx::Canvas* canvas) { ui::ThemeProvider* tp = GetThemeProvider(); gfx::Rect client_area_bounds = CalculateClientAreaBounds(width(), height()); @@ -453,81 +427,41 @@ void GlassBrowserFrameView::PaintRestoredClientEdge(gfx::Canvas* canvas) { client_area_bottom + kClientEdgeThickness - client_area_top); } -void GlassBrowserFrameView::LayoutOTRAvatar() { - int otr_x = NonClientBorderThickness() + kOTRSideSpacing; +void GlassBrowserFrameView::LayoutAvatar() { + int avatar_x = NonClientBorderThickness() + kAvatarSideSpacing; // Move this avatar icon by the size of window controls to prevent it from // being rendered over them in RTL languages. This code also needs to adjust // the width of a tab strip to avoid decreasing this size twice. (See the // comment in GetBoundsForTabStrip().) if (base::i18n::IsRTL()) - otr_x += width() - frame_->GetMinimizeButtonOffset(); + avatar_x += width() - frame_->GetMinimizeButtonOffset(); + + gfx::Size preferred_size = AvatarMenuButton::GetPreferredAvatarSize(); - SkBitmap otr_avatar_icon = browser_view_->GetOTRAvatarIcon(); - int otr_bottom, otr_restored_y; + int avatar_bottom, avatar_restored_y; if (browser_view_->UseVerticalTabs()) { - otr_bottom = NonClientTopBorderHeight(false, false) - kOTRBottomSpacing; - otr_restored_y = kFrameShadowThickness; + avatar_bottom = NonClientTopBorderHeight(false, false) - + kAvatarBottomSpacing; + avatar_restored_y = kFrameShadowThickness; } else { - otr_bottom = GetHorizontalTabStripVerticalOffset(false) + - browser_view_->GetTabStripHeight() - kOTRBottomSpacing; - otr_restored_y = otr_bottom - otr_avatar_icon.height(); + avatar_bottom = GetHorizontalTabStripVerticalOffset(false) + + browser_view_->GetTabStripHeight() - kAvatarBottomSpacing; + avatar_restored_y = avatar_bottom - preferred_size.height(); } - int otr_y = frame_->IsMaximized() ? + int avatar_y = frame_->IsMaximized() ? (NonClientTopBorderHeight(false, true) + kTabstripTopShadowThickness) : - otr_restored_y; - otr_avatar_bounds_.SetRect(otr_x, otr_y, otr_avatar_icon.width(), - browser_view_->ShouldShowOffTheRecordAvatar() ? (otr_bottom - otr_y) : 0); + avatar_restored_y; + avatar_bounds_.SetRect(avatar_x, avatar_y, preferred_size.width(), + browser_view_->ShouldShowAvatar() ? (avatar_bottom - avatar_y) : 0); + + if (avatar_button_.get()) + avatar_button_->SetBoundsRect(avatar_bounds_); } void GlassBrowserFrameView::LayoutClientView() { client_view_bounds_ = CalculateClientAreaBounds(width(), height()); } -void GlassBrowserFrameView::LayoutProfileTag() { - if (!show_profile_button()) - return; - - string16 profile_name = UTF8ToUTF16(browser_view_->browser()->profile()-> - GetPrefs()->GetString(prefs::kGoogleServicesUsername)); - if (!profile_name.empty()) { - profile_button_->SetText(profile_name); - profile_button_->SetTextShadowColors( - ProfileMenuButton::kDefaultActiveTextShadow, - ProfileMenuButton::kDefaultInactiveTextShadow); - } else { - profile_button_->SetText(l10n_util::GetStringUTF16( - IDS_PROFILES_NOT_SIGNED_IN_MENU)); - profile_button_->SetTextShadowColors( - ProfileMenuButton::kDarkTextShadow, - ProfileMenuButton::kDefaultInactiveTextShadow); - } - - profile_button_->ClearMaxTextSize(); - profile_button_->SetVisible(true); - int x_tag = - // The x position of minimize button in the frame - frame_->GetMinimizeButtonOffset() - - // - the space between the minimize button and the profile button - ProfileMenuButton::kProfileTagHorizontalSpacing - - // - the width of the profile button - profile_button_->GetPreferredSize().width(); - int y_maximized_offset = frame_->IsMaximized() ? - kProfileElementMaximizedYOffset : 0; - profile_button_->SetBounds( - x_tag, - kProfileButtonYPosition + y_maximized_offset, - profile_button_->GetPreferredSize().width(), - profile_button_->GetPreferredSize().height()); - - profile_tag_->SetVisible(true); - profile_tag_->set_is_signed_in(!profile_name.empty()); - profile_tag_->SetBounds( - x_tag, - kProfileTagYPosition + y_maximized_offset, - profile_button_->GetPreferredSize().width(), - ProfileTagView::kProfileTagHeight); -} - gfx::Rect GlassBrowserFrameView::CalculateClientAreaBounds(int width, int height) const { if (!browser_view_->IsTabStripVisible()) @@ -592,7 +526,7 @@ void GlassBrowserFrameView::Observe(NotificationType type, DCHECK_EQ(NotificationType::PREF_CHANGED, type.value); std::string* name = Details<std::string>(details).ptr(); if (prefs::kGoogleServicesUsername == *name) - LayoutProfileTag(); + LayoutAvatar(); } void GlassBrowserFrameView::RegisterLoginNotifications() { diff --git a/chrome/browser/ui/views/frame/glass_browser_frame_view.h b/chrome/browser/ui/views/frame/glass_browser_frame_view.h index 26077f0..14ac8a4 100644 --- a/chrome/browser/ui/views/frame/glass_browser_frame_view.h +++ b/chrome/browser/ui/views/frame/glass_browser_frame_view.h @@ -14,9 +14,7 @@ #include "views/window/non_client_view.h" class BrowserView; -class ProfileMenuButton; -class ProfileMenuModel; -class ProfileTagView; +class AvatarMenuButton; class SkBitmap; class GlassBrowserFrameView : public BrowserNonClientFrameView, @@ -66,13 +64,11 @@ class GlassBrowserFrameView : public BrowserNonClientFrameView, // Paint various sub-components of this view. void PaintToolbarBackground(gfx::Canvas* canvas); - void PaintOTRAvatar(gfx::Canvas* canvas); void PaintRestoredClientEdge(gfx::Canvas* canvas); // Layout various sub-components of this view. - void LayoutOTRAvatar(); + void LayoutAvatar(); void LayoutClientView(); - void LayoutProfileTag(); // Returns the bounds of the client area for the specified view size. gfx::Rect CalculateClientAreaBounds(int width, int height) const; @@ -92,11 +88,8 @@ class GlassBrowserFrameView : public BrowserNonClientFrameView, // Receive notifications when the user's Google services user name changes. void RegisterLoginNotifications(); - // Returns true if the ProfileButton has been created. - bool show_profile_button() const { return profile_button_.get() != NULL; } - - // The layout rect of the OTR avatar icon, if visible. - gfx::Rect otr_avatar_bounds_; + // The layout rect of the avatar icon, if visible. + gfx::Rect avatar_bounds_; // The frame that hosts this view. BrowserFrame* frame_; @@ -107,11 +100,9 @@ class GlassBrowserFrameView : public BrowserNonClientFrameView, // The bounds of the ClientView. gfx::Rect client_view_bounds_; - // Menu button that displays user's name and multi-profile menu. - scoped_ptr<ProfileMenuButton> profile_button_; - - // Image tag displayed on frame beneath profile_button_. - scoped_ptr<ProfileTagView> profile_tag_; + // Menu button that displays that either the incognito icon or the profile + // icon. + scoped_ptr<AvatarMenuButton> avatar_button_; // Whether or not the window throbber is currently animating. bool throbber_running_; diff --git a/chrome/browser/ui/views/frame/opaque_browser_frame_view.cc b/chrome/browser/ui/views/frame/opaque_browser_frame_view.cc index 356775e..c3bc04b 100644 --- a/chrome/browser/ui/views/frame/opaque_browser_frame_view.cc +++ b/chrome/browser/ui/views/frame/opaque_browser_frame_view.cc @@ -10,10 +10,10 @@ #include "chrome/browser/prefs/pref_service.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/themes/theme_service.h" +#include "chrome/browser/ui/profile_menu_model.h" +#include "chrome/browser/ui/views/avatar_menu_button.h" #include "chrome/browser/ui/views/frame/browser_frame.h" #include "chrome/browser/ui/views/frame/browser_view.h" -#include "chrome/browser/ui/views/profile_menu_button.h" -#include "chrome/browser/ui/views/profile_tag_view.h" #include "chrome/browser/ui/views/tabs/tab_strip.h" #include "chrome/browser/ui/views/toolbar_view.h" #include "chrome/common/chrome_switches.h" @@ -74,13 +74,13 @@ const int kIconMinimumSize = 16; const int kIconTitleSpacing = 4; // There is a 5 px gap between the title text and the caption buttons. const int kTitleLogoSpacing = 5; -// The OTR avatar ends 2 px above the bottom of the tabstrip (which, given the +// The avatar ends 2 px above the bottom of the tabstrip (which, given the // way the tabstrip draws its bottom edge, will appear like a 1 px gap to the // user). -const int kOTRBottomSpacing = 2; -// There are 2 px on each side of the OTR avatar (between the frame border and +const int kAvatarBottomSpacing = 2; +// There are 2 px on each side of the avatar (between the frame border and // it on the left, and between it and the tabstrip on the right). -const int kOTRSideSpacing = 2; +const int kAvatarSideSpacing = 2; // The top 1 px of the tabstrip is shadow; in maximized mode we push this off // the top of the screen so the tabs appear flush against the screen edge. const int kTabstripTopShadowThickness = 1; @@ -93,13 +93,11 @@ const int kNewTabCaptionRestoredSpacing = 5; // looking too cluttered. const int kNewTabCaptionMaximizedSpacing = 16; // How far to indent the tabstrip from the left side of the screen when there -// is no OTR icon. +// is no avatar icon. const int kTabStripIndent = 1; // Inset from the top of the toolbar/tabstrip to the shadow. Used only for // vertical tabs. const int kVerticalTabBorderInset = 3; -// Y position for profile tag inside the frame. -const int kProfileTagYPosition = 1; // Converts |bounds| from |src|'s coordinate system to |dst|, and checks if // |pt| is contained within. @@ -200,18 +198,28 @@ OpaqueBrowserFrameView::OpaqueBrowserFrameView(BrowserFrame* frame, window_icon_->Update(); } - // If multi-profile is enabled set up profile button and login notifications. + if (browser_view_->ShouldShowAvatar()) { + ui::MenuModel* menu_model = browser_view_->IsOffTheRecord() ? + NULL : new ProfileMenuModel; + // AvatarMenuButton takes ownership of |menu_model|. + avatar_button_.reset(new AvatarMenuButton(std::wstring(), menu_model)); + AddChildView(avatar_button_.get()); + + if (browser_view_->IsOffTheRecord()) { + avatar_button_->SetIcon(browser_view_->GetOTRAvatarIcon()); + } else { + // TODO(sail) Get the avatar icon assigned to this profile. + ResourceBundle& rb = ResourceBundle::GetSharedInstance(); + avatar_button_->SetIcon(*rb.GetBitmapNamed(IDR_PROFILE_AVATAR_1)); + // TODO(sail) Also need to call SetHoverIcon() and SetPushedIcon(). + } + } + + // If multi-profile is enabled set up login notifications. const CommandLine& browser_command_line = *CommandLine::ForCurrentProcess(); if (browser_command_line.HasSwitch(switches::kMultiProfiles) && - !browser_view_->ShouldShowOffTheRecordAvatar()) { + !browser_view->IsOffTheRecord()) { RegisterLoginNotifications(); - profile_button_.reset(new ProfileMenuButton(std::wstring(), - browser_view_->browser()->profile())); - profile_button_->SetVisible(false); - profile_tag_.reset(new ProfileTagView(frame_, profile_button_.get())); - profile_tag_->SetVisible(false); - AddChildView(profile_tag_.get()); - AddChildView(profile_button_.get()); } } @@ -269,15 +277,11 @@ gfx::Rect OpaqueBrowserFrameView::GetBoundsForTabStrip( browser_view_->height()); } - int tabstrip_x = browser_view_->ShouldShowOffTheRecordAvatar() ? - (otr_avatar_bounds_.right() + kOTRSideSpacing) : + int tabstrip_x = browser_view_->ShouldShowAvatar() ? + (avatar_bounds_.right() + kAvatarSideSpacing) : NonClientBorderThickness() + kTabStripIndent; - int maximized_spacing = - kNewTabCaptionMaximizedSpacing + - (show_profile_button() && profile_button_->IsVisible() ? - profile_button_->GetPreferredSize().width() + - ProfileMenuButton::kProfileTagHorizontalSpacing : 0); + int maximized_spacing = kNewTabCaptionMaximizedSpacing; int tabstrip_width = minimize_button_->x() - tabstrip_x - (frame_->IsMaximized() ? maximized_spacing : kNewTabCaptionRestoredSpacing); @@ -340,8 +344,12 @@ int OpaqueBrowserFrameView::NonClientHitTest(const gfx::Point& point) { if (!bounds().Contains(point)) return HTNOWHERE; - int frame_component = - frame_->client_view()->NonClientHitTest(point); + // See if the point is within the avatar menu button. + if (avatar_button_.get() && + avatar_button_->GetMirroredBounds().Contains(point)) + return HTCLIENT; + + int frame_component = frame_->client_view()->NonClientHitTest(point); // See if we're in the sysmenu region. We still have to check the tabstrip // first so that clicks in a tab don't get treated as sysmenu clicks. @@ -371,11 +379,6 @@ int OpaqueBrowserFrameView::NonClientHitTest(const gfx::Point& point) { minimize_button_->GetMirroredBounds().Contains(point)) return HTMINBUTTON; - // See if the point is within the profile menu button. - if (show_profile_button() && profile_button_->IsVisible() && - profile_button_->GetMirroredBounds().Contains(point)) - return HTCLIENT; - views::WindowDelegate* delegate = frame_->window_delegate(); if (!delegate) { LOG(WARNING) << "delegate is NULL, returning safe default."; @@ -428,8 +431,6 @@ void OpaqueBrowserFrameView::OnPaint(gfx::Canvas* canvas) { if (browser_view_->IsToolbarVisible() || browser_view_->UseCompactNavigationBar()) PaintToolbarBackground(canvas); - if (browser_view_->ShouldShowOffTheRecordAvatar()) - PaintOTRAvatar(canvas); if (!frame_->IsMaximized()) PaintRestoredClientEdge(canvas); } @@ -437,8 +438,7 @@ void OpaqueBrowserFrameView::OnPaint(gfx::Canvas* canvas) { void OpaqueBrowserFrameView::Layout() { LayoutWindowControls(); LayoutTitleBar(); - LayoutOTRAvatar(); - LayoutProfileTag(); + LayoutAvatar(); client_view_bounds_ = CalculateClientAreaBounds(width(), height()); } @@ -524,7 +524,7 @@ void OpaqueBrowserFrameView::Observe(NotificationType type, DCHECK_EQ(NotificationType::PREF_CHANGED, type.value); std::string* name = Details<std::string>(details).ptr(); if (prefs::kGoogleServicesUsername == *name) - LayoutProfileTag(); + LayoutAvatar(); } /////////////////////////////////////////////////////////////////////////////// @@ -925,27 +925,6 @@ void OpaqueBrowserFrameView::PaintToolbarBackground(gfx::Canvas* canvas) { w - (2 * kClientEdgeThickness), kClientEdgeThickness); } -void OpaqueBrowserFrameView::PaintOTRAvatar(gfx::Canvas* canvas) { - // In RTL mode, the avatar icon should be looking the opposite direction. - canvas->Save(); - if (base::i18n::IsRTL()) { - canvas->TranslateInt(width(), 0); - canvas->ScaleInt(-1, 1); - } - - SkBitmap otr_avatar_icon = browser_view_->GetOTRAvatarIcon(); - int w = otr_avatar_bounds_.width(); - int h = otr_avatar_bounds_.height(); - canvas->DrawBitmapInt(otr_avatar_icon, 0, - // Bias the rounding to select a region that's lower rather than higher, - // as the shadows at the image top mean the apparent center is below the - // real center. - ((otr_avatar_icon.height() - otr_avatar_bounds_.height()) + 1) / 2, w, h, - otr_avatar_bounds_.x(), otr_avatar_bounds_.y(), w, h, false); - - canvas->Restore(); -} - void OpaqueBrowserFrameView::PaintRestoredClientEdge(gfx::Canvas* canvas) { ui::ThemeProvider* tp = GetThemeProvider(); int client_area_top = frame_->client_view()->y(); @@ -1134,67 +1113,30 @@ void OpaqueBrowserFrameView::LayoutTitleBar() { } } -void OpaqueBrowserFrameView::LayoutOTRAvatar() { - SkBitmap otr_avatar_icon = browser_view_->GetOTRAvatarIcon(); - int otr_bottom, otr_restored_y; +void OpaqueBrowserFrameView::LayoutAvatar() { + // Even though the avatar is used for both incognito and profiles we always + // use the incognito icon to layout the avatar button. + SkBitmap incognito_icon = browser_view_->GetOTRAvatarIcon(); + + int avatar_bottom, avatar_restored_y; if (browser_view_->UseVerticalTabs()) { - otr_bottom = NonClientTopBorderHeight(false, false) - kOTRBottomSpacing; - otr_restored_y = kFrameShadowThickness; + avatar_bottom = NonClientTopBorderHeight(false, false) - + kAvatarBottomSpacing; + avatar_restored_y = kFrameShadowThickness; } else { - otr_bottom = GetHorizontalTabStripVerticalOffset(false) + - browser_view_->GetTabStripHeight() - kOTRBottomSpacing; - otr_restored_y = otr_bottom - otr_avatar_icon.height(); + avatar_bottom = GetHorizontalTabStripVerticalOffset(false) + + browser_view_->GetTabStripHeight() - kAvatarBottomSpacing; + avatar_restored_y = avatar_bottom - incognito_icon.height(); } - int otr_y = frame_->IsMaximized() ? + int avatar_y = frame_->IsMaximized() ? (NonClientTopBorderHeight(false, true) + kTabstripTopShadowThickness) : - otr_restored_y; - otr_avatar_bounds_.SetRect(NonClientBorderThickness() + kOTRSideSpacing, - otr_y, otr_avatar_icon.width(), - browser_view_->ShouldShowOffTheRecordAvatar() ? (otr_bottom - otr_y) : 0); -} + avatar_restored_y; + avatar_bounds_.SetRect(NonClientBorderThickness() + kAvatarSideSpacing, + avatar_y, incognito_icon.width(), + browser_view_->ShouldShowAvatar() ? (avatar_bottom - avatar_y) : 0); -void OpaqueBrowserFrameView::LayoutProfileTag() { - if (!show_profile_button()) - return; - - string16 profile_name = UTF8ToUTF16(browser_view_->browser()->profile()-> - GetPrefs()->GetString(prefs::kGoogleServicesUsername)); - if (!profile_name.empty()) { - profile_button_->SetText(UTF16ToWideHack(profile_name)); - } else { - profile_button_->SetText(UTF16ToWideHack(l10n_util::GetStringUTF16( - IDS_PROFILES_NOT_SIGNED_IN_MENU))); - } - profile_button_->SetTextShadowColors(ProfileMenuButton::kDarkTextShadow, - ProfileMenuButton::kDarkTextShadow); - profile_button_->ClearMaxTextSize(); - profile_button_->SetVisible(true); - int x_tag = - // The x position of minimize button in the frame - minimize_button_->x() - - // - the space between the minimize button and the profile button - ProfileMenuButton::kProfileTagHorizontalSpacing - - // - the width of the profile button - profile_button_->GetPreferredSize().width(); - // Adjust for different default font sizes on different Windows platforms. - int y_tag = profile_button_->font().GetHeight() < 14 ? 2 : 0; - int maximized = frame_->IsMaximized(); - profile_button_->SetBounds( - x_tag, - maximized ? 0 : y_tag, - profile_button_->GetPreferredSize().width(), - profile_button_->GetPreferredSize().height()); - - if (!profile_name.empty()) { - profile_tag_->SetVisible(true); - profile_tag_->SetBounds( - x_tag, - maximized ? 0 : kProfileTagYPosition, - profile_button_->GetPreferredSize().width(), - ProfileTagView::kProfileTagHeight); - } else { - profile_tag_->SetVisible(false); - } + if (avatar_button_.get()) + avatar_button_->SetBoundsRect(avatar_bounds_); } gfx::Rect OpaqueBrowserFrameView::CalculateClientAreaBounds(int width, diff --git a/chrome/browser/ui/views/frame/opaque_browser_frame_view.h b/chrome/browser/ui/views/frame/opaque_browser_frame_view.h index 6e36207b..be06c3d 100644 --- a/chrome/browser/ui/views/frame/opaque_browser_frame_view.h +++ b/chrome/browser/ui/views/frame/opaque_browser_frame_view.h @@ -18,9 +18,7 @@ class BrowserView; namespace gfx { class Font; } -class ProfileMenuButton; -class ProfileMenuModel; -class ProfileTagView; +class AvatarMenuButton; class TabContents; namespace views { class ImageButton; @@ -144,14 +142,12 @@ class OpaqueBrowserFrameView : public BrowserNonClientFrameView, void PaintMaximizedFrameBorder(gfx::Canvas* canvas); void PaintTitleBar(gfx::Canvas* canvas); void PaintToolbarBackground(gfx::Canvas* canvas); - void PaintOTRAvatar(gfx::Canvas* canvas); void PaintRestoredClientEdge(gfx::Canvas* canvas); // Layout various sub-components of this view. void LayoutWindowControls(); void LayoutTitleBar(); - void LayoutOTRAvatar(); - void LayoutProfileTag(); + void LayoutAvatar(); // Returns the bounds of the client area for the specified view size. gfx::Rect CalculateClientAreaBounds(int width, int height) const; @@ -159,14 +155,11 @@ class OpaqueBrowserFrameView : public BrowserNonClientFrameView, // Receive notifications when the user's Google services user name changes. void RegisterLoginNotifications(); - // Returns true if the ProfileButton has been created. - bool show_profile_button() const { return profile_button_.get() != NULL; } - // The layout rect of the title, if visible. gfx::Rect title_bounds_; - // The layout rect of the OTR avatar icon, if visible. - gfx::Rect otr_avatar_bounds_; + // The layout rect of the avatar icon, if visible. + gfx::Rect avatar_bounds_; // Window controls. views::ImageButton* minimize_button_; @@ -186,11 +179,9 @@ class OpaqueBrowserFrameView : public BrowserNonClientFrameView, // The bounds of the ClientView. gfx::Rect client_view_bounds_; - // Menu button that displays user's name and multi-profile menu. - scoped_ptr<ProfileMenuButton> profile_button_; - - // Image tag displayed on frame beneath profile_button_. - scoped_ptr<ProfileTagView> profile_tag_; + // Menu button that displays that either the incognito icon or the profile + // icon. + scoped_ptr<AvatarMenuButton> avatar_button_; // The Google services user name associated with this BrowserView's profile. StringPrefMember username_pref_; diff --git a/chrome/browser/ui/views/profile_menu_button.cc b/chrome/browser/ui/views/profile_menu_button.cc deleted file mode 100644 index 684226f..0000000 --- a/chrome/browser/ui/views/profile_menu_button.cc +++ /dev/null @@ -1,62 +0,0 @@ -// 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/profile_menu_button.h" - -#include "chrome/browser/ui/profile_menu_model.h" -#include "ui/base/text/text_elider.h" -#include "ui/gfx/color_utils.h" -#include "views/controls/button/button.h" -#include "views/controls/menu/menu_item_view.h" -#include "views/controls/menu/menu_model_adapter.h" -#include "views/window/window.h" - -// Menu should display below the profile button tag image on the frame. This -// offset size depends on whether the frame is in glass or opaque mode. -const int kMenuDisplayOffset = 7; - -// TextHover is slightly darker than enabled color, for a subtle hover shift. -const SkColor kTextHover = 0xFFDDDDDD; -const SkColor kTextEnabled = SK_ColorWHITE; -const SkColor kTextHighlighted = SK_ColorWHITE; - -// Horizontal padding beside profile menu button, to center it in the -// underlying tag image. -const int kProfileButtonBorderSpacing = 10; - -// Maximum width for name string in pixels. -const int kMaxTextWidth = 200; - -ProfileMenuButton::ProfileMenuButton(const std::wstring& text, Profile* profile) - : MenuButton(NULL, text, this, true) { - // Turn off hover highlighting and position button in the center of the - // underlying profile tag image. - set_border(views::Border::CreateEmptyBorder( - 0, kProfileButtonBorderSpacing, 0, kProfileButtonBorderSpacing)); - SetHoverColor(kTextHover); - SetEnabledColor(kTextEnabled); - SetHighlightColor(kTextHighlighted); - - profile_menu_model_.reset(new ProfileMenuModel); -} - -ProfileMenuButton::~ProfileMenuButton() {} - -void ProfileMenuButton::SetText(const std::wstring& text) { - MenuButton::SetText(UTF16ToWideHack(ui::ElideText(WideToUTF16Hack(text), - font(), kMaxTextWidth, false))); -} - -// views::ViewMenuDelegate implementation -void ProfileMenuButton::RunMenu(views::View* source, const gfx::Point &pt) { - views::MenuModelAdapter menu_model_adapter(profile_menu_model_.get()); - views::MenuItemView menu(&menu_model_adapter); - menu_model_adapter.BuildMenu(&menu); - - gfx::Point menu_point(pt.x(), pt.y() + kMenuDisplayOffset); - menu.RunMenuAt(source->GetWidget()->GetNativeWindow(), NULL, - gfx::Rect(pt, gfx::Size(0, 0)), - views::MenuItemView::TOPRIGHT, - true); -} diff --git a/chrome/browser/ui/views/profile_menu_button.h b/chrome/browser/ui/views/profile_menu_button.h deleted file mode 100644 index c1389b9..0000000 --- a/chrome/browser/ui/views/profile_menu_button.h +++ /dev/null @@ -1,61 +0,0 @@ -// 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. - -#ifndef CHROME_BROWSER_UI_VIEWS_PROFILE_MENU_BUTTON_H_ -#define CHROME_BROWSER_UI_VIEWS_PROFILE_MENU_BUTTON_H_ -#pragma once - -#include <string> - -#include "base/compiler_specific.h" -#include "ui/base/models/simple_menu_model.h" -#include "views/controls/button/menu_button.h" -#include "views/controls/menu/view_menu_delegate.h" - -class Profile; -class ProfileMenuModel; - -namespace gfx { -class Canvas; -} - -namespace ui { -class Accelerator; -} - -// ProfileMenuButton -// -// Shows the button for the multiprofile menu with an image layered -// underneath that displays the profile tag. - -class ProfileMenuButton : public views::MenuButton, - public views::ViewMenuDelegate { - public: - // DefaultActiveTextShadow is a darkened blue color that works with Windows - // default theme background coloring. - static const SkColor kDefaultActiveTextShadow = 0xFF708DB3; - // InactiveTextShadow is a light gray for inactive default themed buttons. - static const SkColor kDefaultInactiveTextShadow = SK_ColorLTGRAY; - // DarkTextShadow is used to shadow names on themed browser frames. - static const SkColor kDarkTextShadow = SK_ColorGRAY; - // Space between window controls and end of profile tag. - static const int kProfileTagHorizontalSpacing = 5; - - ProfileMenuButton(const std::wstring& text, Profile* profile); - - virtual ~ProfileMenuButton(); - - // Override MenuButton to clamp text at kMaxTextWidth. - virtual void SetText(const std::wstring& text) OVERRIDE; - - private: - // Overridden from views::ViewMenuDelegate: - virtual void RunMenu(views::View* source, const gfx::Point& pt) OVERRIDE; - - scoped_ptr<ProfileMenuModel> profile_menu_model_; - - DISALLOW_COPY_AND_ASSIGN(ProfileMenuButton); -}; - -#endif // CHROME_BROWSER_UI_VIEWS_PROFILE_MENU_BUTTON_H_ diff --git a/chrome/browser/ui/views/profile_tag_view.cc b/chrome/browser/ui/views/profile_tag_view.cc deleted file mode 100644 index ed96923..0000000 --- a/chrome/browser/ui/views/profile_tag_view.cc +++ /dev/null @@ -1,144 +0,0 @@ -// 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/profile_tag_view.h" - -#include "chrome/browser/themes/theme_service.h" -#include "chrome/browser/ui/views/frame/browser_frame.h" -#include "chrome/browser/ui/views/profile_menu_button.h" -#include "grit/theme_resources.h" -#include "ui/base/theme_provider.h" -#include "ui/gfx/canvas_skia.h" -#include "ui/gfx/color_utils.h" -#include "ui/gfx/skbitmap_operations.h" -#include "views/widget/widget.h" - -namespace { -// Colors for primary profile. TODO(mirandac): add colors for multi-profile. -color_utils::HSL hsl_active_shift = { 0.594, 0.5, 0.5 }; -} - -ProfileTagView::ProfileTagView(BrowserFrame* frame, - ProfileMenuButton* profile_menu_button) - : profile_tag_bitmaps_created_(false), - frame_(frame), - profile_menu_button_(profile_menu_button) { -} - -ProfileTagView::~ProfileTagView() { -} - -void ProfileTagView::OnPaint(gfx::Canvas* canvas) { - CreateProfileTagBitmaps(); - - // The tag image consists of a right and left edge, and a center section that - // scales to fit the length of the user's name. We can't just scale the whole - // image, or the left and right edges would be distorted. - int tag_width = profile_menu_button_->GetPreferredSize().width(); - int center_tag_width = tag_width - active_profile_tag_left_.width() - - active_profile_tag_right_.width(); - - bool use_active = GetWidget()->IsActive() && is_signed_in_; - SkBitmap* profile_tag_left = use_active ? &active_profile_tag_left_ : - &inactive_profile_tag_left_; - SkBitmap* profile_tag_center = use_active ? &active_profile_tag_center_ : - &inactive_profile_tag_center_; - SkBitmap* profile_tag_right = use_active ? &active_profile_tag_right_ : - &inactive_profile_tag_right_; - - if (!active_profile_tag_left_background_.empty()) { - canvas->DrawBitmapInt(active_profile_tag_left_background_, 0, 0); - canvas->DrawBitmapInt(active_profile_tag_center_background_, 0, 0, - profile_tag_center->width(), - profile_tag_center->height(), - profile_tag_left->width(), 0, - center_tag_width, - profile_tag_center->height(), true); - canvas->DrawBitmapInt(active_profile_tag_right_background_, - profile_tag_left->width() + center_tag_width, 0); - } - - canvas->DrawBitmapInt(*profile_tag_left, 0, 0); - canvas->DrawBitmapInt(*profile_tag_center, 0, 0, - profile_tag_center->width(), - profile_tag_center->height(), - profile_tag_left->width(), 0, - center_tag_width, - profile_tag_center->height(), true); - canvas->DrawBitmapInt(*profile_tag_right, - profile_tag_left->width() + center_tag_width, 0); -} - -void ProfileTagView::CreateProfileTagBitmaps() { - // Lazily create profile tag bitmaps on first display. - // TODO(mirandac): Cache these per profile, instead of creating every time. - if (profile_tag_bitmaps_created_) - return; - profile_tag_bitmaps_created_ = true; - - ui::ThemeProvider* theme_provider = frame_->GetThemeProvider(); - bool aero = theme_provider->ShouldUseNativeFrame(); - SkBitmap* profile_tag_center = aero ? - theme_provider->GetBitmapNamed(IDR_PROFILE_TAG_CENTER_AERO) : - theme_provider->GetBitmapNamed(IDR_PROFILE_TAG_CENTER_THEMED); - SkBitmap* profile_tag_left = aero ? - theme_provider->GetBitmapNamed(IDR_PROFILE_TAG_LEFT_AERO) : - theme_provider->GetBitmapNamed(IDR_PROFILE_TAG_LEFT_THEMED); - SkBitmap* profile_tag_right = aero ? - theme_provider->GetBitmapNamed(IDR_PROFILE_TAG_RIGHT_AERO) : - theme_provider->GetBitmapNamed(IDR_PROFILE_TAG_RIGHT_THEMED); - inactive_profile_tag_center_ = aero ? - *theme_provider->GetBitmapNamed(IDR_PROFILE_TAG_INACTIVE_CENTER_AERO) : - *theme_provider->GetBitmapNamed(IDR_PROFILE_TAG_CENTER_THEMED); - inactive_profile_tag_left_ = aero ? - *theme_provider->GetBitmapNamed(IDR_PROFILE_TAG_INACTIVE_LEFT_AERO) : - *theme_provider->GetBitmapNamed(IDR_PROFILE_TAG_LEFT_THEMED); - inactive_profile_tag_right_ = aero ? - *theme_provider->GetBitmapNamed(IDR_PROFILE_TAG_INACTIVE_RIGHT_AERO) : - *theme_provider->GetBitmapNamed(IDR_PROFILE_TAG_RIGHT_THEMED); - - // Color if we're using the Aero theme; otherwise the tag will be given by - // the window controls background from the theme. - if (theme_provider->ShouldUseNativeFrame()) { - active_profile_tag_center_ = SkBitmapOperations::CreateHSLShiftedBitmap( - *profile_tag_center, hsl_active_shift); - active_profile_tag_left_ = SkBitmapOperations::CreateHSLShiftedBitmap( - *profile_tag_left, hsl_active_shift); - active_profile_tag_right_ = SkBitmapOperations::CreateHSLShiftedBitmap( - *profile_tag_right, hsl_active_shift); - - // No backgrounds used in Aero theme. - active_profile_tag_center_background_.reset(); - active_profile_tag_left_background_.reset(); - active_profile_tag_center_background_.reset(); - } else { - active_profile_tag_center_ = *profile_tag_center; - active_profile_tag_left_ = *profile_tag_left; - active_profile_tag_right_ = *profile_tag_right; - - SkBitmap* background = theme_provider->GetBitmapNamed( - IDR_THEME_WINDOW_CONTROL_BACKGROUND); - if (!background) { - active_profile_tag_center_background_.reset(); - active_profile_tag_left_background_.reset(); - active_profile_tag_center_background_.reset(); - } else { - active_profile_tag_center_background_ = - SkBitmapOperations::CreateButtonBackground( - theme_provider->GetColor(ThemeService::COLOR_BUTTON_BACKGROUND), - *background, - *(theme_provider->GetBitmapNamed(IDR_PROFILE_TAG_CENTER_MASK))); - active_profile_tag_left_background_ = - SkBitmapOperations::CreateButtonBackground( - theme_provider->GetColor(ThemeService::COLOR_BUTTON_BACKGROUND), - *background, - *(theme_provider->GetBitmapNamed(IDR_PROFILE_TAG_LEFT_MASK))); - active_profile_tag_right_background_ = - SkBitmapOperations::CreateButtonBackground( - theme_provider->GetColor(ThemeService::COLOR_BUTTON_BACKGROUND), - *background, - *(theme_provider->GetBitmapNamed(IDR_PROFILE_TAG_RIGHT_MASK))); - } - } -} diff --git a/chrome/browser/ui/views/profile_tag_view.h b/chrome/browser/ui/views/profile_tag_view.h deleted file mode 100644 index 017c775..0000000 --- a/chrome/browser/ui/views/profile_tag_view.h +++ /dev/null @@ -1,68 +0,0 @@ -// 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. - -#ifndef CHROME_BROWSER_UI_VIEWS_PROFILE_TAG_VIEW_H_ -#define CHROME_BROWSER_UI_VIEWS_PROFILE_TAG_VIEW_H_ -#pragma once - -#include "third_party/skia/include/core/SkBitmap.h" -#include "views/view.h" - -class BrowserFrame; -class ProfileMenuButton; - -namespace gfx { -class Canvas; -} - -// ProfileTag -// -// Displays the tinted button image underneath the ProfileMenuButton. - -class ProfileTagView : public views::View { - public: - // Height of profile tag. - static const int kProfileTagHeight = 20; - - ProfileTagView(BrowserFrame* frame, - ProfileMenuButton* profile_menu_button); - virtual ~ProfileTagView(); - - // Paint the profile tag background image on the given canvas. - virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE; - - void set_is_signed_in(bool is_signed_in) { is_signed_in_ = is_signed_in; } - - private: - // Create the bitmaps to be displayed on the frame behind the profile button. - void CreateProfileTagBitmaps(); - - // True if the bitmaps to display the profile tag have been created. - bool profile_tag_bitmaps_created_; - - // Bitmaps for the profile tag in active and inactive states. - SkBitmap active_profile_tag_center_; - SkBitmap active_profile_tag_left_; - SkBitmap active_profile_tag_right_; - SkBitmap inactive_profile_tag_center_; - SkBitmap inactive_profile_tag_left_; - SkBitmap inactive_profile_tag_right_; - // Bitmaps used for a themed profile background. - SkBitmap active_profile_tag_center_background_; - SkBitmap active_profile_tag_left_background_; - SkBitmap active_profile_tag_right_background_; - - // True if the user is signed in to a personalized Chrome profile. - bool is_signed_in_; - - // The frame that hosts this view. - BrowserFrame* frame_; - - // The button to be displayed above this view. - ProfileMenuButton* profile_menu_button_; - - DISALLOW_COPY_AND_ASSIGN(ProfileTagView); -}; - -#endif // CHROME_BROWSER_UI_VIEWS_PROFILE_TAG_VIEW_H_ diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index 965ba81..c906790 100644 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -2945,6 +2945,8 @@ 'browser/ui/views/autocomplete/autocomplete_result_view_model.h', 'browser/ui/views/autocomplete/touch_autocomplete_popup_contents_view.cc', 'browser/ui/views/autocomplete/touch_autocomplete_popup_contents_view.h', + 'browser/ui/views/avatar_menu_button.cc', + 'browser/ui/views/avatar_menu_button.h', 'browser/ui/views/bookmarks/bookmark_bar_instructions_view.cc', 'browser/ui/views/bookmarks/bookmark_bar_instructions_view.h', 'browser/ui/views/bookmarks/bookmark_bar_view.cc', @@ -3175,10 +3177,6 @@ 'browser/ui/views/page_info_bubble_view.h', 'browser/ui/views/pinned_contents_info_bubble.cc', 'browser/ui/views/pinned_contents_info_bubble.h', - 'browser/ui/views/profile_menu_button.cc', - 'browser/ui/views/profile_menu_button.h', - 'browser/ui/views/profile_tag_view.cc', - 'browser/ui/views/profile_tag_view.h', 'browser/ui/views/reload_button.cc', 'browser/ui/views/reload_button.h', 'browser/ui/views/repost_form_warning_view.cc', diff --git a/views/controls/button/text_button.cc b/views/controls/button/text_button.cc index c88af99..9d4cf72 100644 --- a/views/controls/button/text_button.cc +++ b/views/controls/button/text_button.cc @@ -653,13 +653,7 @@ gfx::Size TextButton::GetPreferredSize() { void TextButton::PaintButton(gfx::Canvas* canvas, PaintButtonMode mode) { TextButtonBase::PaintButton(canvas, mode); - SkBitmap icon = icon_; - if (show_multiple_icon_states_) { - if (has_hover_icon_ && (state() == BS_HOT)) - icon = icon_hover_; - else if (has_pushed_icon_ && (state() == BS_PUSHED)) - icon = icon_pushed_; - } + const SkBitmap& icon = GetImageToPaint(); if (icon.width() > 0) { gfx::Rect text_bounds = GetTextBounds(); @@ -702,14 +696,7 @@ void TextButton::GetExtraParams(gfx::NativeTheme::ExtraParams* params) const { gfx::Rect TextButton::GetTextBounds() const { int extra_width = 0; - SkBitmap icon = icon_; - if (show_multiple_icon_states_) { - if (has_hover_icon_ && (state() == BS_HOT)) - icon = icon_hover_; - else if (has_pushed_icon_ && (state() == BS_PUSHED)) - icon = icon_pushed_; - } - + const SkBitmap& icon = GetImageToPaint(); if (icon.width() > 0) extra_width = icon.width() + (text_.empty() ? 0 : icon_text_spacing_); @@ -727,4 +714,14 @@ gfx::Rect TextButton::GetTextBounds() const { return bounds; } +const SkBitmap& TextButton::GetImageToPaint() const { + if (show_multiple_icon_states_) { + if (has_hover_icon_ && (state() == BS_HOT)) + return icon_hover_; + if (has_pushed_icon_ && (state() == BS_PUSHED)) + return icon_pushed_; + } + return icon_; +} + } // namespace views diff --git a/views/controls/button/text_button.h b/views/controls/button/text_button.h index cebf988..d816120 100644 --- a/views/controls/button/text_button.h +++ b/views/controls/button/text_button.h @@ -353,6 +353,9 @@ class TextButton : public TextButtonBase { protected: SkBitmap icon() const { return icon_; } + // Returns the image to paint. This is invoked from paint. + virtual const SkBitmap& GetImageToPaint() const; + // Overridden from NativeThemeDelegate: virtual gfx::NativeTheme::Part GetThemePart() const OVERRIDE; |