Commit 47436cee authored by noms's avatar noms Committed by Commit bot

[Win] Redesign the new avatar button.

Screenshots: https://drive.google.com/open?id=0B1B1Up4p2NRMc28yXzJuRFRZbWs&authuser=1

TL; DR:
- never show a drop down arrow in the button. This means we can do s/MenuButton/LabelButton
- if there is one local, non-signed in profile, show a tiny button with a generic avatar
- in all other cases, show the avatar button with the profile name
- updated the button insets so that the icons are centered correctly in the button
- the new tab button should completely slide under the avatar button
- because of this, I made public the new tab button width (and height, to be consistent)

BUG=410946

Review URL: https://codereview.chromium.org/598163002

Cr-Commit-Position: refs/heads/master@{#296959}
parent e86ad221
......@@ -678,7 +678,7 @@
<!-- New style avatar button -->
<if expr="toolkit_views">
<!-- Windows, themed -->
<structure type="chrome_scaled_image" name="IDR_AVATAR_THEMED_BUTTON_DROPARROW" file="win/avatar_button/themed/sign_in_button_arrow.png" />
<structure type="chrome_scaled_image" name="IDR_AVATAR_THEMED_BUTTON_AVATAR" file="win/avatar_button/themed/sign_in_button_avatar.png" />
<structure type="chrome_scaled_image" name="IDR_AVATAR_THEMED_BUTTON_NORMAL_BOTTOM" file="win/avatar_button/themed/sign_in_button_bottom.png" />
<structure type="chrome_scaled_image" name="IDR_AVATAR_THEMED_BUTTON_NORMAL_BOTTOM_LEFT" file="win/avatar_button/themed/sign_in_button_bottom_left.png" />
<structure type="chrome_scaled_image" name="IDR_AVATAR_THEMED_BUTTON_NORMAL_BOTTOM_RIGHT" file="win/avatar_button/themed/sign_in_button_bottom_right.png" />
......@@ -708,7 +708,7 @@
<structure type="chrome_scaled_image" name="IDR_AVATAR_THEMED_BUTTON_PRESSED_TOP_RIGHT" file="win/avatar_button/themed/sign_in_button_pressed_top_right.png" />
<!-- Windows, Aero -->
<structure type="chrome_scaled_image" name="IDR_AVATAR_GLASS_BUTTON_DROPARROW" file="win/avatar_button/win7/sign_in_button_arrow.png" />
<structure type="chrome_scaled_image" name="IDR_AVATAR_GLASS_BUTTON_AVATAR" file="win/avatar_button/win7/sign_in_button_avatar.png" />
<structure type="chrome_scaled_image" name="IDR_AVATAR_GLASS_BUTTON_NORMAL_BOTTOM" file="win/avatar_button/win7/sign_in_button_bottom.png" />
<structure type="chrome_scaled_image" name="IDR_AVATAR_GLASS_BUTTON_NORMAL_BOTTOM_LEFT" file="win/avatar_button/win7/sign_in_button_bottom_left.png" />
<structure type="chrome_scaled_image" name="IDR_AVATAR_GLASS_BUTTON_NORMAL_BOTTOM_RIGHT" file="win/avatar_button/win7/sign_in_button_bottom_right.png" />
......@@ -738,7 +738,7 @@
<structure type="chrome_scaled_image" name="IDR_AVATAR_GLASS_BUTTON_PRESSED_TOP_RIGHT" file="win/avatar_button/win7/sign_in_button_pressed_top_right.png" />
<!-- Windows, metro -->
<structure type="chrome_scaled_image" name="IDR_AVATAR_METRO_BUTTON_DROPARROW" file="win/avatar_button/win8/sign_in_button_arrow.png" />
<structure type="chrome_scaled_image" name="IDR_AVATAR_METRO_BUTTON_AVATAR" file="win/avatar_button/win8/sign_in_button_avatar.png" />
<structure type="chrome_scaled_image" name="IDR_AVATAR_METRO_BUTTON_NORMAL_BOTTOM" file="win/avatar_button/win8/sign_in_button_bottom.png" />
<structure type="chrome_scaled_image" name="IDR_AVATAR_METRO_BUTTON_NORMAL_BOTTOM_LEFT" file="win/avatar_button/win8/sign_in_button_bottom_left.png" />
<structure type="chrome_scaled_image" name="IDR_AVATAR_METRO_BUTTON_NORMAL_BOTTOM_RIGHT" file="win/avatar_button/win8/sign_in_button_bottom_right.png" />
......
......@@ -146,10 +146,8 @@ void BrowserNonClientFrameView::UpdateNewStyleAvatarInfo(
if (browser_view_->ShouldShowAvatar()) {
if (!new_avatar_button_) {
base::string16 profile_name = profiles::GetAvatarNameForProfile(
browser_view_->browser()->profile()->GetPath());
new_avatar_button_ = new NewAvatarButton(
listener, profile_name, style, browser_view_->browser());
new_avatar_button_ =
new NewAvatarButton(listener, style, browser_view_->browser());
new_avatar_button_->set_id(VIEW_ID_NEW_AVATAR_BUTTON);
AddChildView(new_avatar_button_);
frame_->GetRootView()->Layout();
......
......@@ -112,7 +112,15 @@ gfx::Rect GlassBrowserFrameView::GetBoundsForTabStrip(
// minimize button.
if (new_avatar_button()) {
DCHECK(switches::IsNewAvatarMenu());
minimize_button_offset -= new_avatar_button()->width();
minimize_button_offset -=
new_avatar_button()->width() + kNewAvatarButtonOffset;
// In non-maximized mode, allow the new tab button to completely slide under
// the avatar button.
if (!frame()->IsMaximized() && !base::i18n::IsRTL()) {
minimize_button_offset +=
TabStrip::kNewTabButtonAssetWidth + kNewTabCaptionRestoredSpacing;
}
}
int tabstrip_x = browser_view()->ShouldShowAvatar() ?
......
......@@ -8,6 +8,7 @@
#include "chrome/browser/profiles/profiles_state.h"
#include "chrome/browser/ui/views/profiles/avatar_label.h"
#include "chrome/browser/ui/views/profiles/avatar_menu_button.h"
#include "chrome/browser/ui/views/tabs/tab_strip.h"
#include "chrome/common/chrome_switches.h"
#include "components/signin/core/common/profile_management_switches.h"
#include "ui/gfx/font.h"
......@@ -382,21 +383,26 @@ void OpaqueBrowserFrameViewLayout::LayoutNewStyleAvatar(views::View* host) {
if (!new_avatar_button_)
return;
gfx::Size label_size = new_avatar_button_->GetPreferredSize();
int button_size_with_offset = kNewAvatarButtonOffset + label_size.width();
int button_width = new_avatar_button_->GetPreferredSize().width();
int button_width_with_offset = button_width + kNewAvatarButtonOffset;
int button_x = host->width() - trailing_button_start_ -
button_size_with_offset;
int button_x =
host->width() - trailing_button_start_ - button_width_with_offset;
int button_y = CaptionButtonY(!IsTitleBarCondensed());
trailing_button_start_ += button_size_with_offset;
minimum_size_for_buttons_ += button_size_with_offset;
minimum_size_for_buttons_ += button_width_with_offset;
trailing_button_start_ += button_width_with_offset;
// In non-maximized mode, allow the new tab button to completely slide under
// the avatar button.
if (!IsTitleBarCondensed()) {
trailing_button_start_ -=
TabStrip::kNewTabButtonAssetWidth + kNewTabCaptionNormalSpacing;
}
// Do not include the 1px padding that is added for the caption buttons.
new_avatar_button_->SetBounds(button_x,
button_y,
label_size.width(),
kCaptionButtonHeightWithPadding - 1);
new_avatar_button_->SetBounds(
button_x, button_y, button_width, kCaptionButtonHeightWithPadding - 1);
}
void OpaqueBrowserFrameViewLayout::LayoutAvatar(views::View* host) {
......
......@@ -528,10 +528,9 @@ TEST_F(OpaqueBrowserFrameViewLayoutTest, WindowWithNewAvatar) {
// Check the location of the avatar button.
EXPECT_EQ("385,1 12x18", new_avatar_button_->bounds().ToString());
// The basic window bounds are (-1, 13 398x29). There should not be an icon
// avatar in the left, and the new avatar button has an offset of 5 to its
// next control.
EXPECT_EQ("-1,13 381x29",
// The new tab button is 39px wide and slides completely under the new
// avatar button, thus increasing the tabstrip by that amount.
EXPECT_EQ("-1,13 420x29",
layout_manager_->GetBoundsForTabStrip(
delegate_->GetTabstripPreferredSize(), kWidth).ToString());
EXPECT_EQ("261x73", layout_manager_->GetMinimumSize(kWidth).ToString());
......
......@@ -31,8 +31,8 @@ scoped_ptr<views::Border> CreateBorder(const int normal_image_set[],
border->SetPainter(false, views::Button::STATE_PRESSED,
views::Painter::CreateImageGridPainter(pushed_image_set));
const int kLeftRightInset = 10;
const int kTopInset = 0;
const int kLeftRightInset = 8;
const int kTopInset = 2;
const int kBottomInset = 4;
border->set_insets(gfx::Insets(kTopInset, kLeftRightInset,
kBottomInset, kLeftRightInset));
......@@ -42,16 +42,12 @@ scoped_ptr<views::Border> CreateBorder(const int normal_image_set[],
} // namespace
NewAvatarButton::NewAvatarButton(
views::ButtonListener* listener,
const base::string16& profile_name,
AvatarButtonStyle button_style,
Browser* browser)
: MenuButton(listener,
profiles::GetAvatarButtonTextForProfile(browser->profile()),
NULL,
true),
NewAvatarButton::NewAvatarButton(views::ButtonListener* listener,
AvatarButtonStyle button_style,
Browser* browser)
: LabelButton(listener, base::string16()),
browser_(browser),
has_auth_error_(false),
suppress_mouse_released_action_(false) {
set_animate_on_state_change(false);
SetTextColor(views::Button::STATE_NORMAL, SK_ColorWHITE);
......@@ -60,6 +56,7 @@ NewAvatarButton::NewAvatarButton(
SetTextShadows(gfx::ShadowValues(10,
gfx::ShadowValue(gfx::Point(), 1.0f, SK_ColorDKGRAY)));
SetTextSubpixelRenderingEnabled(false);
SetHorizontalAlignment(gfx::ALIGN_CENTER);
// The largest text height that fits in the button. If the font list height
// is larger than this, it will be shrunk to match it.
......@@ -74,8 +71,8 @@ NewAvatarButton::NewAvatarButton(
const int kPushedImageSet[] = IMAGE_GRID(IDR_AVATAR_THEMED_BUTTON_PRESSED);
SetBorder(CreateBorder(kNormalImageSet, kHotImageSet, kPushedImageSet));
set_menu_marker(
rb->GetImageNamed(IDR_AVATAR_THEMED_BUTTON_DROPARROW).ToImageSkia());
generic_avatar_ =
*rb->GetImageNamed(IDR_AVATAR_THEMED_BUTTON_AVATAR).ToImageSkia();
#if defined(OS_WIN)
} else if (base::win::GetVersion() >= base::win::VERSION_WIN8) {
const int kNormalImageSet[] = IMAGE_GRID(IDR_AVATAR_METRO_BUTTON_NORMAL);
......@@ -83,8 +80,8 @@ NewAvatarButton::NewAvatarButton(
const int kPushedImageSet[] = IMAGE_GRID(IDR_AVATAR_METRO_BUTTON_PRESSED);
SetBorder(CreateBorder(kNormalImageSet, kHotImageSet, kPushedImageSet));
set_menu_marker(
rb->GetImageNamed(IDR_AVATAR_METRO_BUTTON_DROPARROW).ToImageSkia());
generic_avatar_ =
*rb->GetImageNamed(IDR_AVATAR_METRO_BUTTON_AVATAR).ToImageSkia();
#endif
} else {
const int kNormalImageSet[] = IMAGE_GRID(IDR_AVATAR_GLASS_BUTTON_NORMAL);
......@@ -92,8 +89,8 @@ NewAvatarButton::NewAvatarButton(
const int kPushedImageSet[] = IMAGE_GRID(IDR_AVATAR_GLASS_BUTTON_PRESSED);
SetBorder(CreateBorder(kNormalImageSet, kHotImageSet, kPushedImageSet));
set_menu_marker(
rb->GetImageNamed(IDR_AVATAR_GLASS_BUTTON_DROPARROW).ToImageSkia());
generic_avatar_ =
*rb->GetImageNamed(IDR_AVATAR_GLASS_BUTTON_AVATAR).ToImageSkia();
}
g_browser_process->profile_manager()->GetProfileInfoCache().AddObserver(this);
......@@ -104,9 +101,11 @@ NewAvatarButton::NewAvatarButton(
profiles::GetSigninErrorController(browser_->profile());
if (error) {
error->AddObserver(this);
// This calls UpdateAvatarButtonAndRelayoutParent().
OnErrorChanged();
} else {
UpdateAvatarButtonAndRelayoutParent();
}
SchedulePaint();
}
......@@ -122,14 +121,14 @@ NewAvatarButton::~NewAvatarButton() {
bool NewAvatarButton::OnMousePressed(const ui::MouseEvent& event) {
// Prevent the bubble from being re-shown if it's already showing.
suppress_mouse_released_action_ = ProfileChooserView::IsShowing();
return MenuButton::OnMousePressed(event);
return LabelButton::OnMousePressed(event);
}
void NewAvatarButton::OnMouseReleased(const ui::MouseEvent& event) {
if (suppress_mouse_released_action_)
suppress_mouse_released_action_ = false;
else
MenuButton::OnMouseReleased(event);
LabelButton::OnMouseReleased(event);
}
void NewAvatarButton::OnProfileAdded(const base::FilePath& profile_path) {
......@@ -159,24 +158,45 @@ void NewAvatarButton::OnProfileSupervisedUserIdChanged(
}
void NewAvatarButton::OnErrorChanged() {
gfx::ImageSkia icon;
// If there is an error, show an warning icon.
const SigninErrorController* error =
profiles::GetSigninErrorController(browser_->profile());
if (error && error->HasError()) {
icon = *ui::ResourceBundle::GetSharedInstance().GetImageNamed(
IDR_ICON_PROFILES_AVATAR_BUTTON_ERROR).ToImageSkia();
}
has_auth_error_ = error && error->HasError();
SetImage(views::Button::STATE_NORMAL, icon);
UpdateAvatarButtonAndRelayoutParent();
}
void NewAvatarButton::UpdateAvatarButtonAndRelayoutParent() {
const ProfileInfoCache& cache =
g_browser_process->profile_manager()->GetProfileInfoCache();
// If we have a single local profile, then use the generic avatar
// button instead of the profile name. Never use the generic button if
// the active profile is Guest.
bool use_generic_button = (!browser_->profile()->IsGuestSession() &&
cache.GetNumberOfProfiles() == 1 &&
cache.GetUserNameOfProfileAtIndex(0).empty());
SetText(use_generic_button ? base::string16() :
profiles::GetAvatarButtonTextForProfile(browser_->profile()));
// We want the button to resize if the new text is shorter.
SetText(profiles::GetAvatarButtonTextForProfile(browser_->profile()));
SetMinSize(gfx::Size());
if (use_generic_button) {
SetImage(views::Button::STATE_NORMAL, generic_avatar_);
} else if (has_auth_error_) {
SetImage(views::Button::STATE_NORMAL,
*ui::ResourceBundle::GetSharedInstance().GetImageNamed(
IDR_ICON_PROFILES_AVATAR_BUTTON_ERROR).ToImageSkia());
} else {
SetImage(views::Button::STATE_NORMAL, gfx::ImageSkia());
}
// If we are not using the generic button, then reset the spacing between
// the text and the possible authentication error icon.
const int kDefaultImageTextSpacing = 5;
SetImageLabelSpacing(use_generic_button ? 0 : kDefaultImageTextSpacing);
InvalidateLayout();
// Because the width of the button might have changed, the parent browser
......
......@@ -7,12 +7,12 @@
#include "chrome/browser/profiles/profile_info_cache_observer.h"
#include "components/signin/core/browser/signin_error_controller.h"
#include "ui/views/controls/button/menu_button.h"
#include "ui/views/controls/button/label_button.h"
class Browser;
// Avatar button that displays the active profile's name in the caption area.
class NewAvatarButton : public views::MenuButton,
class NewAvatarButton : public views::LabelButton,
public ProfileInfoCacheObserver,
public SigninErrorController::Observer {
public:
......@@ -23,12 +23,11 @@ class NewAvatarButton : public views::MenuButton,
};
NewAvatarButton(views::ButtonListener* listener,
const base::string16& profile_name,
AvatarButtonStyle button_style,
Browser* browser);
virtual ~NewAvatarButton();
// Views::MenuButton
// Views::LabelButton
virtual bool OnMousePressed(const ui::MouseEvent& event) OVERRIDE;
virtual void OnMouseReleased(const ui::MouseEvent& event) OVERRIDE;
......@@ -55,11 +54,19 @@ class NewAvatarButton : public views::MenuButton,
virtual void OnErrorChanged() OVERRIDE;
// Called when the profile info cache has changed, which means we might
// have to re-display the profile name.
// have to update the icon/text of the button.
void UpdateAvatarButtonAndRelayoutParent();
Browser* browser_;
// Whether the signed in profile has an authentication error. Used to display
// an error icon next to the button text.
bool has_auth_error_;
// The icon displayed instead of the profile name in the local profile case.
// Different assets are used depending on the OS version.
gfx::ImageSkia generic_avatar_;
// This is used to check if the bubble was showing during the mouse pressed
// event. If this is true then the mouse released event is ignored to prevent
// the bubble from reshowing.
......
......@@ -66,6 +66,13 @@ class TabStrip : public views::View,
// restored windows.
static const int kNewTabButtonVerticalOffset;
// The size of the new tab button must be hardcoded because we need to be
// able to lay it out before we are able to get its image from the
// ui::ThemeProvider. It also makes sense to do this, because the size of the
// new tab button should not need to be calculated dynamically.
static const int kNewTabButtonAssetWidth;
static const int kNewTabButtonAssetHeight;
explicit TabStrip(TabStripController* controller);
virtual ~TabStrip();
......@@ -311,13 +318,6 @@ class TabStrip : public views::View,
// Horizontal gap between mini and non-mini-tabs.
static const int kMiniToNonMiniGap;
// The size of the new tab button must be hardcoded because we need to be
// able to lay it out before we are able to get its image from the
// ui::ThemeProvider. It also makes sense to do this, because the size of the
// new tab button should not need to be calculated dynamically.
static const int kNewTabButtonAssetWidth;
static const int kNewTabButtonAssetHeight;
void Init();
// Creates and returns a new tab. The caller owners the returned tab.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment