#include "chrome/browser/ui/views/profile_chooser_view.h"
-#include "base/command_line.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/profiles/profile_info_util.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/profiles/profile_window.h"
+#include "chrome/browser/profiles/profiles_state.h"
+#include "chrome/browser/signin/mutable_profile_oauth2_token_service.h"
#include "chrome/browser/signin/profile_oauth2_token_service.h"
#include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
+#include "chrome/browser/signin/signin_manager.h"
+#include "chrome/browser/signin/signin_manager_factory.h"
#include "chrome/browser/signin/signin_promo.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_dialogs.h"
#include "chrome/browser/ui/singleton_tabs.h"
#include "chrome/browser/ui/views/user_manager_view.h"
-#include "chrome/common/chrome_switches.h"
#include "chrome/common/url_constants.h"
#include "grit/chromium_strings.h"
#include "grit/generated_resources.h"
#include "third_party/skia/include/core/SkColor.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/canvas.h"
#include "ui/gfx/image/image.h"
#include "ui/gfx/image/image_skia.h"
+#include "ui/gfx/text_elider.h"
+#include "ui/native_theme/native_theme.h"
#include "ui/views/controls/button/blue_button.h"
+#include "ui/views/controls/button/label_button.h"
#include "ui/views/controls/button/menu_button.h"
-#include "ui/views/controls/image_view.h"
#include "ui/views/controls/label.h"
#include "ui/views/controls/link.h"
#include "ui/views/controls/separator.h"
+#include "ui/views/controls/textfield/textfield.h"
#include "ui/views/controls/webview/webview.h"
-#include "ui/views/layout/box_layout.h"
#include "ui/views/layout/grid_layout.h"
#include "ui/views/layout/layout_constants.h"
#include "ui/views/widget/widget.h"
-#if defined(USE_AURA)
-#include "ui/native_theme/native_theme_aura.h"
-#endif
-
namespace {
// Helpers --------------------------------------------------------------------
-const int kLargeImageSide = 64;
-const int kSmallImageSide = 32;
-const int kMinMenuWidth = 250;
+const int kFixedMenuWidth = 250;
const int kButtonHeight = 29;
-const int kArrowHeight = 10;
-
-// Current profile avatar image.
-views::View* CreateProfileImageView(const gfx::Image& icon) {
- views::ImageView* view = new views::ImageView();
-
- gfx::Image image = profiles::GetSizedAvatarIconWithBorder(
- icon, true,
- kLargeImageSide + profiles::kAvatarIconPadding,
- kLargeImageSide + profiles::kAvatarIconPadding);
- view->SetImage(image.ToImageSkia());
-
- return view;
-}
// Creates a GridLayout with a single column. This ensures that all the child
// views added get auto-expanded to fill the full width of the bubble.
-views::GridLayout* CreateSingleColumnLayout(views::View* view) {
+views::GridLayout* CreateSingleColumnLayout(views::View* view, int width) {
views::GridLayout* layout = new views::GridLayout(view);
view->SetLayoutManager(layout);
views::ColumnSet* columns = layout->AddColumnSet(0);
- columns->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, 1,
- views::GridLayout::USE_PREF, 0, 0);
+ columns->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, 0,
+ views::GridLayout::FIXED, width, width);
return layout;
}
columns->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, 0,
views::GridLayout::USE_PREF, 0, 0);
columns->AddPaddingColumn(0, views::kUnrelatedControlLargeHorizontalSpacing);
- columns->AddColumn(views::GridLayout::LEADING, views::GridLayout::TRAILING, 1,
+ columns->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, 1,
views::GridLayout::USE_PREF, 0, 0);
return layout;
}
-views::Link* CreateLink(const string16& link_text,
+views::Link* CreateLink(const base::string16& link_text,
views::LinkListener* listener) {
views::Link* link_button = new views::Link(link_text);
link_button->SetHorizontalAlignment(gfx::ALIGN_LEFT);
}
-// HorizontalPaddingButtonBorder ----------------------------------------------
+// BackgroundColorHoverButton -------------------------------------------------
-// A button border that adds padding before the icon and after the text. This
-// is needed so that the button looks like it is spanning the entire parent
-// view (especially when hovered over), but has the icon indented and aligned
-// with the other items in the parent view.
-class HorizontalPaddingButtonBorder : public views::TextButtonBorder {
+// A custom button that allows for setting a background color when hovered over.
+class BackgroundColorHoverButton : public views::LabelButton {
public:
- HorizontalPaddingButtonBorder() : views::TextButtonBorder() {
- SetInsets(gfx::Insets(0, views::kButtonHEdgeMarginNew,
- 0, views::kButtonHEdgeMarginNew));
- };
-
- virtual ~HorizontalPaddingButtonBorder() {
- };
+ BackgroundColorHoverButton(views::ButtonListener* listener,
+ const base::string16& text,
+ const gfx::ImageSkia& normal_icon,
+ const gfx::ImageSkia& hover_icon);
+ virtual ~BackgroundColorHoverButton();
private:
- // This function is pure virtual in the parent, so we must provide an
- // implementation.
- virtual void Paint(const views::View& view, gfx::Canvas* canvas) OVERRIDE {
- };
+ // views::LabelButton:
+ virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE;
- DISALLOW_COPY_AND_ASSIGN(HorizontalPaddingButtonBorder);
+ DISALLOW_COPY_AND_ASSIGN(BackgroundColorHoverButton);
};
+BackgroundColorHoverButton::BackgroundColorHoverButton(
+ views::ButtonListener* listener,
+ const base::string16& text,
+ const gfx::ImageSkia& normal_icon,
+ const gfx::ImageSkia& hover_icon)
+ : views::LabelButton(listener, text) {
+ SetBorder(views::Border::CreateEmptyBorder(0, views::kButtonHEdgeMarginNew,
+ 0, views::kButtonHEdgeMarginNew));
+ set_min_size(gfx::Size(0, kButtonHeight));
+ SetImage(STATE_NORMAL, normal_icon);
+ SetImage(STATE_HOVERED, hover_icon);
+ SetImage(STATE_PRESSED, hover_icon);
+ SetTextColor(STATE_HOVERED, GetNativeTheme()->GetSystemColor(
+ ui::NativeTheme::kColorId_SelectedMenuItemForegroundColor));
+}
-// BackgroundColorHoverButton -------------------------------------------------
+BackgroundColorHoverButton::~BackgroundColorHoverButton() {}
-// A custom button that allows for setting a background color when hovered over.
-class BackgroundColorHoverButton : public views::TextButton {
+void BackgroundColorHoverButton::OnPaint(gfx::Canvas* canvas) {
+ if ((state() == STATE_PRESSED) || (state() == STATE_HOVERED) || HasFocus()) {
+ canvas->DrawColor(GetNativeTheme()->GetSystemColor(
+ ui::NativeTheme::kColorId_FocusedMenuItemBackgroundColor));
+ }
+ LabelButton::OnPaint(canvas);
+}
+
+} // namespace
+
+
+// EditableProfilePhoto -------------------------------------------------
+
+// A custom Image control that shows a "change" button when moused over.
+class EditableProfilePhoto : public views::ImageView {
public:
- BackgroundColorHoverButton(views::ButtonListener* listener,
- const string16& text,
- const gfx::ImageSkia& normal_icon,
- const gfx::ImageSkia& hover_icon)
- : views::TextButton(listener, text) {
- set_border(new HorizontalPaddingButtonBorder);
- set_min_height(kButtonHeight);
- set_icon_text_spacing(views::kItemLabelSpacing);
- SetIcon(normal_icon);
- SetHoverIcon(hover_icon);
- SetPushedIcon(hover_icon);
- SetHoverColor(GetNativeTheme()->GetSystemColor(
- ui::NativeTheme::kColorId_SelectedMenuItemForegroundColor));
- OnHighlightStateChanged();
- };
-
- virtual ~BackgroundColorHoverButton(){
- };
+ EditableProfilePhoto(views::ButtonListener* listener,
+ const gfx::Image& icon,
+ bool is_editing_allowed)
+ : views::ImageView(),
+ change_photo_button_(NULL) {
+ const int kLargeImageSide = 64;
+ gfx::Image image = profiles::GetSizedAvatarIconWithBorder(
+ icon, true,
+ kLargeImageSide + profiles::kAvatarIconPadding,
+ kLargeImageSide + profiles::kAvatarIconPadding);
+ SetImage(image.ToImageSkia());
+
+ if (!is_editing_allowed)
+ return;
+
+ set_notify_enter_exit_on_child(true);
+
+ // Button overlay that appears when hovering over the image.
+ change_photo_button_ = new views::LabelButton(listener,
+ l10n_util::GetStringUTF16(IDS_PROFILES_PROFILE_CHANGE_PHOTO_BUTTON));
+ change_photo_button_->SetHorizontalAlignment(gfx::ALIGN_CENTER);
+ change_photo_button_->SetBorder(views::Border::NullBorder());
+ const SkColor color = SK_ColorWHITE;
+ change_photo_button_->SetTextColor(views::Button::STATE_NORMAL, color);
+ change_photo_button_->SetTextColor(views::Button::STATE_HOVERED, color);
+
+ const SkColor kBackgroundColor = SkColorSetARGB(125, 0, 0, 0);
+ change_photo_button_->set_background(
+ views::Background::CreateSolidBackground(kBackgroundColor));
+ // Need to take into account the border padding on the avatar.
+ const int kOverlayHeight = 20;
+ change_photo_button_->SetBounds(
+ profiles::kAvatarIconPadding,
+ kLargeImageSide - kOverlayHeight,
+ kLargeImageSide - profiles::kAvatarIconPadding,
+ kOverlayHeight);
+ change_photo_button_->SetVisible(false);
+ AddChildView(change_photo_button_);
+ }
+
+ views::LabelButton* change_photo_button() { return change_photo_button_; }
private:
+ // views::View:
virtual void OnMouseEntered(const ui::MouseEvent& event) OVERRIDE {
- views::TextButton::OnMouseEntered(event);
- OnHighlightStateChanged();
- };
+ if (change_photo_button_)
+ change_photo_button_->SetVisible(true);
+ }
virtual void OnMouseExited(const ui::MouseEvent& event) OVERRIDE {
- views::TextButton::OnMouseExited(event);
- OnHighlightStateChanged();
- };
-
- void OnHighlightStateChanged() {
- bool is_highlighted = (state() == views::TextButton::STATE_PRESSED) ||
- (state() == views::TextButton::STATE_HOVERED) || HasFocus();
- ui::NativeTheme::ColorId color_id = is_highlighted ?
- ui::NativeTheme::kColorId_FocusedMenuItemBackgroundColor :
- ui::NativeTheme::kColorId_MenuBackgroundColor;
- set_background(views::Background::CreateSolidBackground(
- GetNativeTheme()->GetSystemColor(color_id)));
- SchedulePaint();
- };
+ if (change_photo_button_)
+ change_photo_button_->SetVisible(false);
+ }
- DISALLOW_COPY_AND_ASSIGN(BackgroundColorHoverButton);
+ // Button that is shown when hovering over the image view. Can be NULL if
+ // the photo isn't allowed to be edited (e.g. for guest profiles).
+ views::LabelButton* change_photo_button_;
+
+ DISALLOW_COPY_AND_ASSIGN(EditableProfilePhoto);
};
-} // namespace
+
+// EditableProfileName -------------------------------------------------
+
+// A custom text control that turns into a textfield for editing when clicked.
+class EditableProfileName : public views::LabelButton,
+ public views::ButtonListener {
+ public:
+ EditableProfileName(views::TextfieldController* controller,
+ const base::string16& text,
+ bool is_editing_allowed)
+ : views::LabelButton(this, text),
+ profile_name_textfield_(NULL) {
+ ui::ResourceBundle* rb = &ui::ResourceBundle::GetSharedInstance();
+ const gfx::FontList& medium_font_list =
+ rb->GetFontList(ui::ResourceBundle::MediumFont);
+ SetFontList(medium_font_list);
+ SetBorder(views::Border::NullBorder());
+
+ if (!is_editing_allowed)
+ return;
+
+ SetImage(STATE_HOVERED,
+ *rb->GetImageSkiaNamed(IDR_ICON_PROFILES_EDIT_HOVER));
+ SetImage(STATE_PRESSED,
+ *rb->GetImageSkiaNamed(IDR_ICON_PROFILES_EDIT_PRESSED));
+
+ // Textfield that overlaps the button.
+ profile_name_textfield_ = new views::Textfield();
+ profile_name_textfield_->set_controller(controller);
+ profile_name_textfield_->SetFontList(medium_font_list);
+ profile_name_textfield_->SetVisible(false);
+ AddChildView(profile_name_textfield_);
+ }
+
+ views::Textfield* profile_name_textfield() {
+ return profile_name_textfield_;
+ }
+
+ // Hide the editable textfield to show the profile name button instead.
+ void ShowReadOnlyView() {
+ if (profile_name_textfield_)
+ profile_name_textfield_->SetVisible(false);
+ }
+
+ private:
+ // views::ButtonListener:
+ virtual void ButtonPressed(views::Button* sender,
+ const ui::Event& event) OVERRIDE {
+ if (profile_name_textfield_) {
+ profile_name_textfield_->SetVisible(true);
+ profile_name_textfield_->SetText(GetText());
+ profile_name_textfield_->SelectAll(false);
+ profile_name_textfield_->RequestFocus();
+ }
+ }
+
+ // views::LabelButton:
+ virtual bool OnKeyReleased(const ui::KeyEvent& event) OVERRIDE {
+ // Override CustomButton's implementation, which presses the button when
+ // you press space and clicks it when you release space, as the space can be
+ // part of the new profile name typed in the textfield.
+ return false;
+ }
+
+ virtual void Layout() OVERRIDE {
+ if (profile_name_textfield_)
+ profile_name_textfield_->SetBounds(0, 0, width(), height());
+ // This layout trick keeps the text left-aligned and the icon right-aligned.
+ SetHorizontalAlignment(gfx::ALIGN_RIGHT);
+ views::LabelButton::Layout();
+ label()->SetHorizontalAlignment(gfx::ALIGN_LEFT);
+ }
+
+ // Button that is shown when hovering over the image view. Can be NULL if
+ // the profile name isn't allowed to be edited (e.g. for guest profiles).
+ views::Textfield* profile_name_textfield_;
+
+ DISALLOW_COPY_AND_ASSIGN(EditableProfileName);
+};
// ProfileChooserView ---------------------------------------------------------
// static
ProfileChooserView* ProfileChooserView::profile_bubble_ = NULL;
-bool ProfileChooserView::close_on_deactivate_ = true;
+bool ProfileChooserView::close_on_deactivate_for_testing_ = true;
// static
void ProfileChooserView::ShowBubble(
profile_bubble_ = new ProfileChooserView(
anchor_view, arrow, anchor_rect, browser);
views::BubbleDelegateView::CreateBubble(profile_bubble_);
- profile_bubble_->set_close_on_deactivate(close_on_deactivate_);
+ profile_bubble_->set_close_on_deactivate(close_on_deactivate_for_testing_);
profile_bubble_->SetAlignment(border_alignment);
profile_bubble_->GetWidget()->Show();
profile_bubble_->SetArrowPaintType(views::BubbleBorder::PAINT_NONE);
const gfx::Rect& anchor_rect,
Browser* browser)
: BubbleDelegateView(anchor_view, arrow),
- browser_(browser) {
+ browser_(browser),
+ view_mode_(PROFILE_CHOOSER_VIEW) {
// Reset the default margins inherited from the BubbleDelegateView.
set_margins(gfx::Insets());
- // Compensate for built-in vertical padding in the anchor view's image.
- set_anchor_view_insets(gfx::Insets(kArrowHeight, 0, kArrowHeight, 0));
- ResetLinksAndButtons();
+ ResetView();
avatar_menu_.reset(new AvatarMenu(
&g_browser_process->profile_manager()->GetProfileInfoCache(),
this,
browser_));
avatar_menu_->RebuildMenu();
+
+ ProfileOAuth2TokenService* oauth2_token_service =
+ ProfileOAuth2TokenServiceFactory::GetForProfile(browser_->profile());
+ if (oauth2_token_service)
+ oauth2_token_service->AddObserver(this);
}
ProfileChooserView::~ProfileChooserView() {
+ ProfileOAuth2TokenService* oauth2_token_service =
+ ProfileOAuth2TokenServiceFactory::GetForProfile(browser_->profile());
+ if (oauth2_token_service)
+ oauth2_token_service->RemoveObserver(this);
}
-void ProfileChooserView::ResetLinksAndButtons() {
+void ProfileChooserView::ResetView() {
manage_accounts_link_ = NULL;
signout_current_profile_link_ = NULL;
signin_current_profile_link_ = NULL;
- change_photo_link_ = NULL;
guest_button_ = NULL;
end_guest_button_ = NULL;
users_button_ = NULL;
add_user_button_ = NULL;
add_account_button_ = NULL;
+ current_profile_photo_ = NULL;
+ current_profile_name_ = NULL;
open_other_profile_indexes_map_.clear();
+ current_profile_accounts_map_.clear();
}
void ProfileChooserView::Init() {
ShowView(PROFILE_CHOOSER_VIEW, avatar_menu);
}
+void ProfileChooserView::OnRefreshTokenAvailable(
+ const std::string& account_id) {
+ // Refresh the account management view when a new account is added to the
+ // profile.
+ if (view_mode_ == ACCOUNT_MANAGEMENT_VIEW ||
+ view_mode_ == GAIA_SIGNIN_VIEW ||
+ view_mode_ == GAIA_ADD_ACCOUNT_VIEW) {
+ ShowView(ACCOUNT_MANAGEMENT_VIEW, avatar_menu_.get());
+ }
+}
+
+void ProfileChooserView::OnRefreshTokenRevoked(const std::string& account_id) {
+ // Refresh the account management view when an account is removed from the
+ // profile.
+ if (view_mode_ == ACCOUNT_MANAGEMENT_VIEW)
+ ShowView(ACCOUNT_MANAGEMENT_VIEW, avatar_menu_.get());
+}
+
void ProfileChooserView::ShowView(BubbleViewMode view_to_display,
AvatarMenu* avatar_menu) {
// The account management view should only be displayed if the active profile
DCHECK(active_item.signed_in);
}
- ResetLinksAndButtons();
+ ResetView();
RemoveAllChildViews(true);
-
- views::GridLayout* layout = CreateSingleColumnLayout(this);
- layout->set_minimum_size(gfx::Size(kMinMenuWidth, 0));
+ view_mode_ = view_to_display;
if (view_to_display == GAIA_SIGNIN_VIEW ||
view_to_display == GAIA_ADD_ACCOUNT_VIEW) {
// Minimum size for embedded sign in pages as defined in Gaia.
const int kMinGaiaViewWidth = 320;
- const int kMinGaiaViewHeight = 500;
+ const int kMinGaiaViewHeight = 440;
Profile* profile = browser_->profile();
views::WebView* web_view = new views::WebView(profile);
signin::Source source = (view_to_display == GAIA_SIGNIN_VIEW) ?
signin::SOURCE_AVATAR_BUBBLE_SIGN_IN :
signin::SOURCE_AVATAR_BUBBLE_ADD_ACCOUNT;
- web_view->LoadInitialURL(GURL(signin::GetPromoURL(source, false)));
+ GURL url(signin::GetPromoURL(
+ source, false /* auto_close */, true /* is_constrained */));
+ web_view->LoadInitialURL(url);
+ views::GridLayout* layout =
+ CreateSingleColumnLayout(this, kMinGaiaViewWidth);
layout->StartRow(1, 0);
layout->AddView(web_view);
layout->set_minimum_size(
return;
}
+ views::GridLayout* layout = CreateSingleColumnLayout(this, kFixedMenuWidth);
// Separate items into active and alternatives.
Indexes other_profiles;
bool is_guest_view = true;
} else if (sender == add_user_button_) {
profiles::CreateAndSwitchToNewProfile(
browser_->host_desktop_type(),
- profiles::ProfileSwitchingDoneCallback());
+ profiles::ProfileSwitchingDoneCallback(),
+ ProfileMetrics::ADD_NEW_USER_ICON);
} else if (sender == add_account_button_) {
ShowView(GAIA_ADD_ACCOUNT_VIEW, avatar_menu_.get());
+ } else if (sender == current_profile_photo_->change_photo_button()) {
+ avatar_menu_->EditProfile(avatar_menu_->GetActiveProfileIndex());
} else {
// One of the "other profiles" buttons was pressed.
ButtonIndexes::const_iterator match =
DCHECK(match != open_other_profile_indexes_map_.end());
avatar_menu_->SwitchToProfile(
match->second,
- ui::DispositionFromEventFlags(event.flags()) == NEW_WINDOW);
+ ui::DispositionFromEventFlags(event.flags()) == NEW_WINDOW,
+ ProfileMetrics::SWITCH_PROFILE_ICON);
}
}
+void ProfileChooserView::OnMenuButtonClicked(views::View* source,
+ const gfx::Point& point) {
+ AccountButtonIndexes::const_iterator match =
+ current_profile_accounts_map_.find(source);
+ DCHECK(match != current_profile_accounts_map_.end());
+
+ MutableProfileOAuth2TokenService* oauth2_token_service =
+ ProfileOAuth2TokenServiceFactory::GetPlatformSpecificForProfile(
+ browser_->profile());
+ if (oauth2_token_service)
+ oauth2_token_service->RevokeCredentials(match->second);
+}
+
void ProfileChooserView::LinkClicked(views::Link* sender, int event_flags) {
if (sender == manage_accounts_link_) {
// ShowView() will DCHECK if this view is displayed for non signed-in users.
ShowView(ACCOUNT_MANAGEMENT_VIEW, avatar_menu_.get());
} else if (sender == signout_current_profile_link_) {
- avatar_menu_->BeginSignOut();
- } else if (sender == signin_current_profile_link_) {
- if (CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kEnableInlineSignin)) {
- ShowView(GAIA_SIGNIN_VIEW, avatar_menu_.get());
- } else {
- GURL page = signin::GetPromoURL(signin::SOURCE_MENU, false);
- chrome::ShowSingletonTab(browser_, page);
- }
+ profiles::LockProfile(browser_->profile());
} else {
- DCHECK(sender == change_photo_link_);
- avatar_menu_->EditProfile(
+ DCHECK(sender == signin_current_profile_link_);
+ ShowView(GAIA_SIGNIN_VIEW, avatar_menu_.get());
+ }
+}
+
+bool ProfileChooserView::HandleKeyEvent(views::Textfield* sender,
+ const ui::KeyEvent& key_event) {
+ views::Textfield* name_textfield =
+ current_profile_name_->profile_name_textfield();
+ DCHECK(sender == name_textfield);
+
+ if (key_event.key_code() == ui::VKEY_RETURN ||
+ key_event.key_code() == ui::VKEY_TAB) {
+ // Pressing Tab/Enter commits the new profile name, unless it's empty.
+ base::string16 new_profile_name = name_textfield->text();
+ if (new_profile_name.empty())
+ return true;
+
+ const AvatarMenu::Item& active_item = avatar_menu_->GetItemAt(
avatar_menu_->GetActiveProfileIndex());
+ Profile* profile = g_browser_process->profile_manager()->GetProfile(
+ active_item.profile_path);
+ DCHECK(profile);
+
+ if (profile->IsManaged())
+ return true;
+
+ profiles::UpdateProfileName(profile, new_profile_name);
+ current_profile_name_->ShowReadOnlyView();
+ return true;
}
+ return false;
}
views::View* ProfileChooserView::CreateCurrentProfileView(
views::kButtonVEdgeMarginNew,
views::kButtonHEdgeMarginNew);
- views::View* photo_image = CreateProfileImageView(avatar_item.icon);
- view->SetBoundsRect(photo_image->bounds());
-
- views::Label* name_label =
- new views::Label(avatar_item.name,
- ui::ResourceBundle::GetSharedInstance().GetFont(
- ui::ResourceBundle::MediumFont));
- name_label->SetElideBehavior(views::Label::ELIDE_AT_END);
- name_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
+ current_profile_photo_ =
+ new EditableProfilePhoto(this, avatar_item.icon, !is_guest);
+ view->SetBoundsRect(current_profile_photo_->bounds());
+ current_profile_name_ =
+ new EditableProfileName(this, avatar_item.name, !is_guest);
layout->StartRow(1, 0);
- layout->AddView(photo_image, 1, 3);
- layout->AddView(name_label);
+ layout->AddView(current_profile_photo_, 1, 3);
+ layout->AddView(current_profile_name_);
if (is_guest) {
layout->StartRow(1, 0);
views::kButtonVEdgeMarginNew,
views::kButtonHEdgeMarginNew);
- views::View* photo_image = CreateProfileImageView(avatar_item.icon);
- view->SetBoundsRect(photo_image->bounds());
-
- // TODO(noms): The name should actually be a textbox and not a label when
- // we have the functionality to save changes.
- views::Label* name_label =
- new views::Label(avatar_item.name,
- ui::ResourceBundle::GetSharedInstance().GetFont(
- ui::ResourceBundle::MediumFont));
- name_label->SetElideBehavior(views::Label::ELIDE_AT_END);
- name_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
- change_photo_link_ = CreateLink(
- l10n_util::GetStringUTF16(IDS_PROFILES_PROFILE_CHANGE_PHOTO_BUTTON),
- this);
+ current_profile_photo_ =
+ new EditableProfilePhoto(this, avatar_item.icon, true);
+ view->SetBoundsRect(current_profile_photo_->bounds());
+ current_profile_name_ =
+ new EditableProfileName(this, avatar_item.name, true);
layout->StartRow(1, 0);
- layout->AddView(photo_image, 1, 3);
- layout->AddView(name_label);
+ layout->AddView(current_profile_photo_, 1, 3);
+ layout->AddView(current_profile_name_);
layout->StartRow(1, 0);
layout->SkipColumns(1);
- layout->AddView(change_photo_link_);
layout->StartRow(1, 0);
layout->SkipColumns(1);
views::View* ProfileChooserView::CreateGuestProfileView() {
gfx::Image guest_icon =
- ui::ResourceBundle::GetSharedInstance().GetImageNamed(IDR_GUEST_ICON);
+ ui::ResourceBundle::GetSharedInstance().GetImageNamed(IDR_LOGIN_GUEST);
AvatarMenu::Item guest_avatar_item(0, 0, guest_icon);
guest_avatar_item.active = true;
guest_avatar_item.name = l10n_util::GetStringUTF16(
views::View* ProfileChooserView::CreateOtherProfilesView(
const Indexes& avatars_to_show) {
views::View* view = new views::View();
- views::GridLayout* layout = CreateSingleColumnLayout(view);
+ views::GridLayout* layout = CreateSingleColumnLayout(
+ view, kFixedMenuWidth - 2 * views::kButtonHEdgeMarginNew);
layout->SetInsets(0, views::kButtonHEdgeMarginNew,
views::kButtonVEdgeMarginNew, views::kButtonHEdgeMarginNew);
int num_avatars_to_show = avatars_to_show.size();
for (int i = 0; i < num_avatars_to_show; ++i) {
const size_t index = avatars_to_show[i];
const AvatarMenu::Item& item = avatar_menu_->GetItemAt(index);
+ const int kSmallImageSide = 32;
gfx::Image image = profiles::GetSizedAvatarIconWithBorder(
item.icon, true,
kSmallImageSide + profiles::kAvatarIconPadding,
kSmallImageSide + profiles::kAvatarIconPadding);
- views::TextButton* button = new views::TextButton(this, item.name);
+ views::LabelButton* button = new views::LabelButton(this, item.name);
open_other_profile_indexes_map_[button] = index;
- button->SetIcon(*image.ToImageSkia());
- button->set_icon_text_spacing(views::kItemLabelSpacing);
- button->SetFont(ui::ResourceBundle::GetSharedInstance().GetFont(
+ button->SetImage(views::Button::STATE_NORMAL, *image.ToImageSkia());
+ button->SetFontList(ui::ResourceBundle::GetSharedInstance().GetFontList(
ui::ResourceBundle::MediumFont));
- button->set_border(NULL);
+ button->SetBorder(views::Border::NullBorder());
layout->StartRow(1, 0);
layout->AddView(button);
views::View* ProfileChooserView::CreateOptionsView(bool is_guest_view) {
views::View* view = new views::View();
- views::GridLayout* layout = CreateSingleColumnLayout(view);
+ views::GridLayout* layout = CreateSingleColumnLayout(view, kFixedMenuWidth);
// The horizontal padding will be set by each button individually, so that
// in the hovered state the button spans the entire parent view.
layout->SetInsets(views::kRelatedControlVerticalSpacing, 0,
const AvatarMenu::Item& avatar_item) {
DCHECK(avatar_item.signed_in);
views::View* view = new views::View();
- views::GridLayout* layout = CreateSingleColumnLayout(view);
+ int column_width = kFixedMenuWidth - 2 * views::kButtonHEdgeMarginNew;
+ views::GridLayout* layout = CreateSingleColumnLayout(view, column_width);
layout->SetInsets(views::kButtonVEdgeMarginNew,
views::kButtonHEdgeMarginNew,
views::kButtonVEdgeMarginNew,
views::kButtonHEdgeMarginNew);
Profile* profile = browser_->profile();
- std::vector<std::string> accounts(
- ProfileOAuth2TokenServiceFactory::GetForProfile(profile)->GetAccounts());
- for (size_t i = 0; i < accounts.size(); ++i) {
- if (i != 0)
- layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
-
- views::Label* email_label = new views::Label(UTF8ToUTF16(accounts[i]));
- email_label->SetElideBehavior(views::Label::ELIDE_AS_EMAIL);
- email_label->SetFont(ui::ResourceBundle::GetSharedInstance().GetFont(
- ui::ResourceBundle::SmallFont));
- email_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
-
- layout->StartRow(1, 0);
- layout->AddView(email_label);
- }
-
+ std::string primary_account =
+ SigninManagerFactory::GetForProfile(profile)->GetAuthenticatedUsername();
+ DCHECK(!primary_account.empty());
+ std::vector<std::string>accounts =
+ profiles::GetSecondaryAccountsForProfile(profile, primary_account);
+
+ // The primary account should always be listed first.
+ // TODO(rogerta): we still need to further differentiate the primary account
+ // from the others in the UI, so more work is likely required here:
+ // crbug.com/311124.
+ CreateAccountButton(layout, primary_account, true, column_width);
+ for (size_t i = 0; i < accounts.size(); ++i)
+ CreateAccountButton(layout, accounts[i], false, column_width);
layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
add_account_button_ = new views::BlueButton(
layout->AddView(add_account_button_);
return view;
}
+
+void ProfileChooserView::CreateAccountButton(views::GridLayout* layout,
+ const std::string& account,
+ bool is_primary_account,
+ int width) {
+ ui::ResourceBundle* rb = &ui::ResourceBundle::GetSharedInstance();
+ const gfx::ImageSkia* menu_marker =
+ rb->GetImageNamed(IDR_CLOSE_1).ToImageSkia();
+ // Use a MenuButtonListener and not a regular ButtonListener to be
+ // able to distinguish between the unnamed "other profile" buttons and the
+ // unnamed "multiple accounts" buttons.
+ views::MenuButton* email_button = new views::MenuButton(
+ NULL,
+ gfx::ElideEmail(base::UTF8ToUTF16(account),
+ rb->GetFontList(ui::ResourceBundle::BaseFont),
+ width - menu_marker->width()),
+ is_primary_account ? NULL : this, // Cannot delete the primary account.
+ !is_primary_account);
+ email_button->SetBorder(views::Border::CreateEmptyBorder(0, 0, 0, 0));
+ if (!is_primary_account) {
+ email_button->set_menu_marker(menu_marker);
+ layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
+ }
+ layout->StartRow(1, 0);
+ layout->AddView(email_button);
+
+ // Save the original email address, as the button text could be elided.
+ current_profile_accounts_map_[email_button] = account;
+}