| Index: chrome/browser/ui/views/frame/glass_browser_frame_view.cc
|
| ===================================================================
|
| --- chrome/browser/ui/views/frame/glass_browser_frame_view.cc (revision 88685)
|
| +++ chrome/browser/ui/views/frame/glass_browser_frame_view.cc (working copy)
|
| @@ -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 @@
|
| // 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 avatar ends 2 px above the bottom of the tabstrip (which, given the
|
| +// The OTR 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 kAvatarBottomSpacing = 2;
|
| -// There are 2 px on each side of the avatar (between the frame border and
|
| +const int kOTRBottomSpacing = 2;
|
| +// There are 2 px on each side of the OTR avatar (between the frame border and
|
| // it on the left, and between it and the tabstrip on the right).
|
| -const int kAvatarSideSpacing = 2;
|
| +const int kOTRSideSpacing = 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,6 +66,12 @@
|
| // 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;
|
| }
|
|
|
| ///////////////////////////////////////////////////////////////////////////////
|
| @@ -80,29 +86,18 @@
|
| throbber_frame_(0) {
|
| if (browser_view_->ShouldShowWindowIcon())
|
| InitThrobberIcons();
|
| -
|
| - 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.
|
| + // If multi-profile is enabled set up profile button and login notifications.
|
| const CommandLine& browser_command_line = *CommandLine::ForCurrentProcess();
|
| if (browser_command_line.HasSwitch(switches::kMultiProfiles) &&
|
| - !browser_view->IsOffTheRecord()) {
|
| + !browser_view->ShouldShowOffTheRecordAvatar()) {
|
| 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());
|
| }
|
| }
|
|
|
| @@ -122,8 +117,8 @@
|
| }
|
| int minimize_button_offset =
|
| std::min(frame_->GetMinimizeButtonOffset(), width());
|
| - int tabstrip_x = browser_view_->ShouldShowAvatar() ?
|
| - (avatar_bounds_.right() + kAvatarSideSpacing) :
|
| + int tabstrip_x = browser_view_->ShouldShowOffTheRecordAvatar() ?
|
| + (otr_avatar_bounds_.right() + kOTRSideSpacing) :
|
| 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
|
| @@ -131,11 +126,15 @@
|
| // 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_->ShouldShowAvatar() && frame_->IsMaximized())
|
| - tabstrip_x += avatar_bounds_.x();
|
| + if (!browser_view_->ShouldShowOffTheRecordAvatar() && frame_->IsMaximized())
|
| + tabstrip_x += otr_avatar_bounds_.x();
|
| minimize_button_offset = width();
|
| }
|
| - int maximized_spacing = kNewTabCaptionMaximizedSpacing;
|
| + int maximized_spacing =
|
| + kNewTabCaptionMaximizedSpacing +
|
| + (show_profile_button() && profile_button_->IsVisible() ?
|
| + profile_button_->GetPreferredSize().width() +
|
| + ProfileMenuButton::kProfileTagHorizontalSpacing : 0);
|
| int tabstrip_width = minimize_button_offset - tabstrip_x -
|
| (frame_->IsMaximized() ?
|
| maximized_spacing : kNewTabCaptionRestoredSpacing);
|
| @@ -198,11 +197,6 @@
|
| 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
|
| @@ -216,6 +210,11 @@
|
| 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,
|
| @@ -233,18 +232,24 @@
|
| 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() {
|
| - LayoutAvatar();
|
| + LayoutOTRAvatar();
|
| LayoutClientView();
|
| + LayoutProfileTag();
|
| }
|
|
|
| bool GlassBrowserFrameView::HitTest(const gfx::Point& l) const {
|
| - return (avatar_button_.get() &&
|
| - avatar_button_->GetMirroredBounds().Contains(l)) ||
|
| + // 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)) ||
|
| !frame_->client_view()->bounds().Contains(l);
|
| }
|
|
|
| @@ -377,6 +382,27 @@
|
| 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());
|
| @@ -427,41 +453,81 @@
|
| client_area_bottom + kClientEdgeThickness - client_area_top);
|
| }
|
|
|
| -void GlassBrowserFrameView::LayoutAvatar() {
|
| - int avatar_x = NonClientBorderThickness() + kAvatarSideSpacing;
|
| +void GlassBrowserFrameView::LayoutOTRAvatar() {
|
| + int otr_x = NonClientBorderThickness() + kOTRSideSpacing;
|
| // 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())
|
| - avatar_x += width() - frame_->GetMinimizeButtonOffset();
|
| + otr_x += width() - frame_->GetMinimizeButtonOffset();
|
|
|
| - gfx::Size preferred_size = AvatarMenuButton::GetPreferredAvatarSize();
|
| -
|
| - int avatar_bottom, avatar_restored_y;
|
| + SkBitmap otr_avatar_icon = browser_view_->GetOTRAvatarIcon();
|
| + int otr_bottom, otr_restored_y;
|
| if (browser_view_->UseVerticalTabs()) {
|
| - avatar_bottom = NonClientTopBorderHeight(false, false) -
|
| - kAvatarBottomSpacing;
|
| - avatar_restored_y = kFrameShadowThickness;
|
| + otr_bottom = NonClientTopBorderHeight(false, false) - kOTRBottomSpacing;
|
| + otr_restored_y = kFrameShadowThickness;
|
| } else {
|
| - avatar_bottom = GetHorizontalTabStripVerticalOffset(false) +
|
| - browser_view_->GetTabStripHeight() - kAvatarBottomSpacing;
|
| - avatar_restored_y = avatar_bottom - preferred_size.height();
|
| + otr_bottom = GetHorizontalTabStripVerticalOffset(false) +
|
| + browser_view_->GetTabStripHeight() - kOTRBottomSpacing;
|
| + otr_restored_y = otr_bottom - otr_avatar_icon.height();
|
| }
|
| - int avatar_y = frame_->IsMaximized() ?
|
| + int otr_y = frame_->IsMaximized() ?
|
| (NonClientTopBorderHeight(false, true) + kTabstripTopShadowThickness) :
|
| - 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_);
|
| + otr_restored_y;
|
| + otr_avatar_bounds_.SetRect(otr_x, otr_y, otr_avatar_icon.width(),
|
| + browser_view_->ShouldShowOffTheRecordAvatar() ? (otr_bottom - otr_y) : 0);
|
| }
|
|
|
| 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())
|
| @@ -526,7 +592,7 @@
|
| DCHECK_EQ(NotificationType::PREF_CHANGED, type.value);
|
| std::string* name = Details<std::string>(details).ptr();
|
| if (prefs::kGoogleServicesUsername == *name)
|
| - LayoutAvatar();
|
| + LayoutProfileTag();
|
| }
|
|
|
| void GlassBrowserFrameView::RegisterLoginNotifications() {
|
|
|