blob: 5a9a59d711b78e7c95bed2f586fdc0a0ad5bdf6d [file] [log] [blame]
// Copyright 2019 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_PROFILES_PROFILE_MENU_VIEW_BASE_H_
#define CHROME_BROWSER_UI_VIEWS_PROFILES_PROFILE_MENU_VIEW_BASE_H_
#include <stddef.h>
#include <map>
#include <memory>
#include <vector>
#include "base/macros.h"
#include "chrome/browser/profiles/profile_metrics.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/ui/views/close_bubble_on_tab_activation_helper.h"
#include "content/public/browser/web_contents_delegate.h"
#include "ui/gfx/paint_vector_icon.h"
#include "ui/views/bubble/bubble_dialog_delegate_view.h"
#include "ui/views/controls/button/button.h"
#include "ui/views/controls/link_listener.h"
#include "ui/views/controls/styled_label_listener.h"
#include "ui/views/layout/box_layout.h"
#include "ui/views/style/typography.h"
class Browser;
namespace views {
class Button;
class Label;
} // namespace views
struct AccountInfo;
class DiceSigninButtonView;
// This class provides the UI for different menus that are created by user
// clicking the avatar button.
class ProfileMenuViewBase : public content::WebContentsDelegate,
public views::BubbleDialogDelegateView,
public views::ButtonListener,
public views::StyledLabelListener,
public views::LinkListener {
public:
// MenuItems struct keeps the menu items and meta data for a group of items in
// a menu. It takes the ownership of views and passes it to the menu when menu
// is constructed.
struct MenuItems {
MenuItems();
MenuItems(MenuItems&&);
~MenuItems();
enum ItemType {
kNone,
kTitleCard,
kLabel,
kButton,
kStyledButton,
kGeneral
};
std::vector<std::unique_ptr<views::View>> items;
ItemType first_item_type;
ItemType last_item_type;
bool different_item_types;
DISALLOW_COPY_AND_ASSIGN(MenuItems);
};
enum GroupMarginSize { kNone, kTiny, kSmall, kLarge };
// Shows the bubble if one is not already showing. This allows us to easily
// make a button toggle the bubble on and off when clicked: we unconditionally
// call this function when the button is clicked and if the bubble isn't
// showing it will appear while if it is showing, nothing will happen here and
// the existing bubble will auto-close due to focus loss.
static void ShowBubble(
profiles::BubbleViewMode view_mode,
signin_metrics::AccessPoint access_point,
views::Button* anchor_button,
Browser* browser,
bool is_source_keyboard);
static bool IsShowing();
static void Hide();
static ProfileMenuViewBase* GetBubbleForTesting();
ProfileMenuViewBase(views::Button* anchor_button,
Browser* browser);
~ProfileMenuViewBase() override;
// This method is called once to add all menu items.
virtual void BuildMenu() = 0;
// API to build the profile menu.
void SetIdentityInfo(const gfx::ImageSkia& image,
const gfx::ImageSkia& badge,
const base::string16& title,
const base::string16& subtitle = base::string16());
void SetSyncInfo(const gfx::ImageSkia& icon,
const base::string16& description,
const base::string16& clickable_text,
base::RepeatingClosure action);
void AddShortcutFeatureButton(const gfx::ImageSkia& icon,
const base::string16& text,
base::RepeatingClosure action);
void AddAccountFeatureButton(const gfx::ImageSkia& icon,
const base::string16& text,
base::RepeatingClosure action);
void SetProfileHeading(const base::string16& heading);
void AddSelectableProfile(const gfx::ImageSkia& image,
const base::string16& name,
base::RepeatingClosure action);
void AddProfileShortcutFeatureButton(const gfx::ImageSkia& icon,
const base::string16& text,
base::RepeatingClosure action);
void AddProfileFeatureButton(const gfx::ImageSkia& icon,
const base::string16& text,
base::RepeatingClosure action);
// 0 < |icon_to_image_ratio| <= 1 is the size ratio of |icon| in the returned
// image. E.g. a value of 0.8 means that |icon| only takes up 80% of the
// returned image, with the rest being padding around it.
gfx::ImageSkia ImageForMenu(const gfx::VectorIcon& icon,
float icon_to_image_ratio = 1.0f);
gfx::ImageSkia ColoredImageForMenu(const gfx::VectorIcon& icon,
SkColor color);
// Initializes a new group of menu items. A separator is added before them if
// |add_separator| is true.
void AddMenuGroup(bool add_separator = true);
// The following functions add different menu items to the latest menu group.
// They pass the ownership of the generated item to |menu_item_groups_| and
// return a raw pointer to the object. The ownership is transferred to the
// menu when view is repopulated from menu items.
// Please use |AddViewItem| only if none of the previous ones match.
views::Button* CreateAndAddButton(const gfx::ImageSkia& icon,
const base::string16& title,
base::RepeatingClosure action);
views::Button* CreateAndAddBlueButton(const base::string16& text,
bool md_style,
base::RepeatingClosure action);
// If |action| is null the card will be disabled.
views::Button* CreateAndAddTitleCard(std::unique_ptr<views::View> icon_view,
const base::string16& title,
const base::string16& subtitle,
base::RepeatingClosure action);
#if !defined(OS_CHROMEOS)
DiceSigninButtonView* CreateAndAddDiceSigninButton(
AccountInfo* account_info,
gfx::Image* account_icon,
base::RepeatingClosure action);
#endif
views::Label* CreateAndAddLabel(
const base::string16& text,
int text_context = views::style::CONTEXT_LABEL);
views::StyledLabel* CreateAndAddLabelWithLink(const base::string16& text,
gfx::Range link_range,
base::RepeatingClosure action);
void AddViewItem(std::unique_ptr<views::View> view);
Browser* browser() const { return browser_; }
// Return maximal height for the view after which it becomes scrollable.
// TODO(crbug.com/870303): remove when a general solution is available.
int GetMaxHeight() const;
views::Button* anchor_button() const { return anchor_button_; }
gfx::ImageSkia CreateVectorIcon(const gfx::VectorIcon& icon);
int GetDefaultIconSize();
private:
friend class ProfileMenuViewExtensionsTest;
void Reset();
void RepopulateViewFromMenuItems();
// Requests focus for a button when opened by keyboard.
virtual void FocusButtonOnKeyboardOpen() {}
// views::BubbleDialogDelegateView:
void Init() final;
void WindowClosing() override;
void OnThemeChanged() override;
int GetDialogButtons() const override;
ax::mojom::Role GetAccessibleWindowRole() override;
// content::WebContentsDelegate:
bool HandleContextMenu(content::RenderFrameHost* render_frame_host,
const content::ContextMenuParams& params) override;
// views::ButtonListener:
void ButtonPressed(views::Button* button, const ui::Event& event) final;
// views::LinkListener:
void LinkClicked(views::Link* link, int event_flags) final;
// views::StyledLabelListener:
void StyledLabelLinkClicked(views::StyledLabel* link,
const gfx::Range& range,
int event_flags) final;
// Handles all click events.
void OnClick(views::View* clickable_view);
void RegisterClickAction(views::View* clickable_view,
base::RepeatingClosure action);
// Returns the size of different margin types.
int GetMarginSize(GroupMarginSize margin_size) const;
void AddMenuItemInternal(std::unique_ptr<views::View> view,
MenuItems::ItemType item_type);
Browser* const browser_;
// ProfileMenuViewBase takes ownership of all menu_items and passes it to the
// underlying view when it is created.
std::vector<MenuItems> menu_item_groups_;
views::Button* const anchor_button_;
std::map<views::View*, base::RepeatingClosure> click_actions_;
// Component containers.
views::View* identity_info_container_ = nullptr;
views::View* sync_info_container_ = nullptr;
views::View* shortcut_features_container_ = nullptr;
views::View* account_features_container_ = nullptr;
views::View* profile_heading_container_ = nullptr;
views::View* selectable_profiles_container_ = nullptr;
views::View* profile_shortcut_features_container_ = nullptr;
views::View* profile_features_container_ = nullptr;
CloseBubbleOnTabActivationHelper close_bubble_helper_;
DISALLOW_COPY_AND_ASSIGN(ProfileMenuViewBase);
};
#endif // CHROME_BROWSER_UI_VIEWS_PROFILES_PROFILE_MENU_VIEW_BASE_H_