views: Support styling of menus (issue #2102)

This commit is contained in:
Marshall Greenblatt
2017-02-25 00:03:31 -05:00
parent b08f0ed713
commit 8fa8af357b
23 changed files with 1124 additions and 65 deletions

View File

@@ -19,6 +19,10 @@
namespace {
const int kSeparatorId = -1;
const int kInvalidGroupId = -1;
const int kInvalidCommandId = -1;
const int kDefaultIndex = -1;
const int kInvalidIndex = -2;
// A simple MenuModel implementation that delegates to CefMenuModelImpl.
class CefSimpleMenuModel : public ui::MenuModel {
@@ -73,6 +77,10 @@ class CefSimpleMenuModel : public ui::MenuModel {
return false;
}
const gfx::FontList* GetLabelFontListAt(int index) const override {
return impl_->GetLabelFontListAt(index);
}
bool GetAcceleratorAt(int index,
ui::Accelerator* accelerator) const override {
int key_code = 0;
@@ -151,6 +159,24 @@ class CefSimpleMenuModel : public ui::MenuModel {
impl_->UnhandledCloseSubmenu(is_rtl);
}
bool GetTextColor(int index,
bool is_hovered,
SkColor* override_color) const override {
return impl_->GetTextColor(index, false, is_hovered, override_color);
}
bool GetMinorTextColor(int index,
bool is_hovered,
SkColor* override_color) const override {
return impl_->GetTextColor(index, true, is_hovered, override_color);
}
bool GetBackgroundColor(int index,
bool is_hovered,
SkColor* override_color) const override {
return impl_->GetBackgroundColor(index, is_hovered, override_color);
}
void MenuWillShow() override {
impl_->MenuWillShow();
}
@@ -175,6 +201,22 @@ class CefSimpleMenuModel : public ui::MenuModel {
DISALLOW_COPY_AND_ASSIGN(CefSimpleMenuModel);
};
cef_menu_color_type_t GetMenuColorType(bool is_text,
bool is_accelerator,
bool is_hovered) {
if (is_text) {
if (is_accelerator) {
return is_hovered ? CEF_MENU_COLOR_TEXT_ACCELERATOR_HOVERED :
CEF_MENU_COLOR_TEXT_ACCELERATOR;
}
return is_hovered ? CEF_MENU_COLOR_TEXT_HOVERED : CEF_MENU_COLOR_TEXT;
}
DCHECK(!is_accelerator);
return is_hovered ? CEF_MENU_COLOR_BACKGROUND_HOVERED :
CEF_MENU_COLOR_BACKGROUND;
}
} // namespace
// static
@@ -198,15 +240,7 @@ struct CefMenuModelImpl::Item {
: type_(type),
command_id_(command_id),
label_(label),
group_id_(group_id),
enabled_(true),
visible_(true),
checked_(false),
has_accelerator_(false),
key_code_(0),
shift_pressed_(false),
ctrl_pressed_(false),
alt_pressed_(false) {
group_id_(group_id) {
}
// Basic information.
@@ -217,16 +251,20 @@ struct CefMenuModelImpl::Item {
CefRefPtr<CefMenuModelImpl> submenu_;
// State information.
bool enabled_;
bool visible_;
bool checked_;
bool enabled_ = true;
bool visible_ = true;
bool checked_ = false;
// Accelerator information.
bool has_accelerator_;
int key_code_;
bool shift_pressed_;
bool ctrl_pressed_;
bool alt_pressed_;
bool has_accelerator_ = false;
int key_code_ = 0;
bool shift_pressed_ = false;
bool ctrl_pressed_ = false;
bool alt_pressed_ = false;
cef_color_t colors_[CEF_MENU_COLOR_COUNT] = {0};
gfx::FontList font_list_;
bool has_font_list_ = false;
};
@@ -270,7 +308,8 @@ bool CefMenuModelImpl::AddSeparator() {
if (!VerifyContext())
return false;
AppendItem(Item(MENUITEMTYPE_SEPARATOR, kSeparatorId, CefString(), -1));
AppendItem(Item(MENUITEMTYPE_SEPARATOR, kSeparatorId, CefString(),
kInvalidGroupId));
return true;
}
@@ -278,7 +317,8 @@ bool CefMenuModelImpl::AddItem(int command_id, const CefString& label) {
if (!VerifyContext())
return false;
AppendItem(Item(MENUITEMTYPE_COMMAND, command_id, label, -1));
AppendItem(Item(MENUITEMTYPE_COMMAND, command_id, label,
kInvalidGroupId));
return true;
}
@@ -286,7 +326,7 @@ bool CefMenuModelImpl::AddCheckItem(int command_id, const CefString& label) {
if (!VerifyContext())
return false;
AppendItem(Item(MENUITEMTYPE_CHECK, command_id, label, -1));
AppendItem(Item(MENUITEMTYPE_CHECK, command_id, label, kInvalidGroupId));
return true;
}
@@ -304,7 +344,7 @@ CefRefPtr<CefMenuModel> CefMenuModelImpl::AddSubMenu(int command_id,
if (!VerifyContext())
return NULL;
Item item(MENUITEMTYPE_SUBMENU, command_id, label, -1);
Item item(MENUITEMTYPE_SUBMENU, command_id, label, kInvalidGroupId);
item.submenu_ = new CefMenuModelImpl(delegate_, menu_model_delegate_, true);
AppendItem(item);
return item.submenu_.get();
@@ -314,8 +354,9 @@ bool CefMenuModelImpl::InsertSeparatorAt(int index) {
if (!VerifyContext())
return false;
InsertItemAt(Item(MENUITEMTYPE_SEPARATOR, kSeparatorId, CefString(), -1),
index);
InsertItemAt(Item(MENUITEMTYPE_SEPARATOR, kSeparatorId, CefString(),
kInvalidGroupId),
index);
return true;
}
@@ -324,7 +365,8 @@ bool CefMenuModelImpl::InsertItemAt(int index, int command_id,
if (!VerifyContext())
return false;
InsertItemAt(Item(MENUITEMTYPE_COMMAND, command_id, label, -1), index);
InsertItemAt(Item(MENUITEMTYPE_COMMAND, command_id, label, kInvalidGroupId),
index);
return true;
}
@@ -333,7 +375,8 @@ bool CefMenuModelImpl::InsertCheckItemAt(int index, int command_id,
if (!VerifyContext())
return false;
InsertItemAt(Item(MENUITEMTYPE_CHECK, command_id, label, -1), index);
InsertItemAt(Item(MENUITEMTYPE_CHECK, command_id, label, kInvalidGroupId),
index);
return true;
}
@@ -342,7 +385,7 @@ bool CefMenuModelImpl::InsertRadioItemAt(int index, int command_id,
if (!VerifyContext())
return false;
InsertItemAt(Item(MENUITEMTYPE_RADIO, command_id, label, -1), index);
InsertItemAt(Item(MENUITEMTYPE_RADIO, command_id, label, group_id), index);
return true;
}
@@ -351,7 +394,7 @@ CefRefPtr<CefMenuModel> CefMenuModelImpl::InsertSubMenuAt(
if (!VerifyContext())
return NULL;
Item item(MENUITEMTYPE_SUBMENU, command_id, label, -1);
Item item(MENUITEMTYPE_SUBMENU, command_id, label, kInvalidGroupId);
item.submenu_ = new CefMenuModelImpl(delegate_, menu_model_delegate_, true);
InsertItemAt(item, index);
return item.submenu_.get();
@@ -374,23 +417,23 @@ bool CefMenuModelImpl::RemoveAt(int index) {
int CefMenuModelImpl::GetIndexOf(int command_id) {
if (!VerifyContext())
return -1;
return kInvalidIndex;
for (ItemVector::iterator i = items_.begin(); i != items_.end(); ++i) {
if ((*i).command_id_ == command_id) {
return static_cast<int>(std::distance(items_.begin(), i));
}
}
return -1;
return kInvalidIndex;
}
int CefMenuModelImpl::GetCommandIdAt(int index) {
if (!VerifyContext())
return -1;
return kInvalidCommandId;
if (index >= 0 && index < static_cast<int>(items_.size()))
return items_[index].command_id_;
return -1;
return kInvalidCommandId;
}
bool CefMenuModelImpl::SetCommandIdAt(int index, int command_id) {
@@ -451,11 +494,11 @@ int CefMenuModelImpl::GetGroupId(int command_id) {
int CefMenuModelImpl::GetGroupIdAt(int index) {
if (!VerifyContext())
return -1;
return kInvalidGroupId;
if (index >= 0 && index < static_cast<int>(items_.size()))
return items_[index].group_id_;
return -1;
return kInvalidGroupId;
}
bool CefMenuModelImpl::SetGroupId(int command_id, int group_id) {
@@ -656,6 +699,95 @@ bool CefMenuModelImpl::GetAcceleratorAt(int index, int& key_code,
return false;
}
bool CefMenuModelImpl::SetColor(int command_id,
cef_menu_color_type_t color_type,
cef_color_t color) {
return SetColorAt(GetIndexOf(command_id), color_type, color);
}
bool CefMenuModelImpl::SetColorAt(int index,
cef_menu_color_type_t color_type,
cef_color_t color) {
if (!VerifyContext())
return false;
if (color_type < 0 || color_type >= CEF_MENU_COLOR_COUNT)
return false;
if (index == kDefaultIndex) {
default_colors_[color_type] = color;
return true;
}
if (index >= 0 && index < static_cast<int>(items_.size())) {
Item& item = items_[index];
item.colors_[color_type] = color;
return true;
}
return false;
}
bool CefMenuModelImpl::GetColor(int command_id,
cef_menu_color_type_t color_type,
cef_color_t& color) {
return GetColorAt(GetIndexOf(command_id), color_type, color);
}
bool CefMenuModelImpl::GetColorAt(int index,
cef_menu_color_type_t color_type,
cef_color_t& color) {
if (!VerifyContext())
return false;
if (color_type < 0 || color_type >= CEF_MENU_COLOR_COUNT)
return false;
if (index == kDefaultIndex) {
color = default_colors_[color_type];
return true;
}
if (index >= 0 && index < static_cast<int>(items_.size())) {
Item& item = items_[index];
color = item.colors_[color_type];
return true;
}
return false;
}
bool CefMenuModelImpl::SetFontList(int command_id, const CefString& font_list) {
return SetFontListAt(GetIndexOf(command_id), font_list);
}
bool CefMenuModelImpl::SetFontListAt(int index, const CefString& font_list) {
if (!VerifyContext())
return false;
if (index == kDefaultIndex) {
if (font_list.empty()) {
has_default_font_list_ = false;
} else {
default_font_list_ = gfx::FontList(font_list);
has_default_font_list_ = true;
}
return true;
}
if (index >= 0 && index < static_cast<int>(items_.size())) {
Item& item = items_[index];
if (font_list.empty()) {
item.has_font_list_ = false;
} else {
item.font_list_ = gfx::FontList(font_list);
item.has_font_list_ = true;
}
return true;
}
return false;
}
void CefMenuModelImpl::ActivatedAt(int index, cef_event_flags_t event_flags) {
if (!VerifyContext())
return;
@@ -700,6 +832,57 @@ void CefMenuModelImpl::UnhandledCloseSubmenu(bool is_rtl) {
base::Bind(&CefMenuModelImpl::OnUnhandledCloseSubmenu, this, is_rtl));
}
bool CefMenuModelImpl::GetTextColor(int index,
bool is_accelerator,
bool is_hovered,
SkColor* override_color) const {
if (index >= 0 && index < static_cast<int>(items_.size())) {
const Item& item = items_[index];
if (!item.enabled_) {
// Use accelerator color for disabled item text.
is_accelerator = true;
}
const cef_menu_color_type_t color_type =
GetMenuColorType(true, is_accelerator, is_hovered);
if (item.colors_[color_type] != 0) {
*override_color = item.colors_[color_type];
return true;
}
}
const cef_menu_color_type_t color_type =
GetMenuColorType(true, is_accelerator, is_hovered);
if (default_colors_[color_type] != 0) {
*override_color = default_colors_[color_type];
return true;
}
return false;
}
bool CefMenuModelImpl::GetBackgroundColor(int index,
bool is_hovered,
SkColor* override_color) const {
const cef_menu_color_type_t color_type =
GetMenuColorType(false, false, is_hovered);
if (index >= 0 && index < static_cast<int>(items_.size())) {
const Item& item = items_[index];
if (item.colors_[color_type] != 0) {
*override_color = item.colors_[color_type];
return true;
}
}
if (default_colors_[color_type] != 0) {
*override_color = default_colors_[color_type];
return true;
}
return false;
}
void CefMenuModelImpl::MenuWillShow() {
if (!VerifyContext())
return;
@@ -737,6 +920,18 @@ base::string16 CefMenuModelImpl::GetFormattedLabelAt(int index) {
return label;
}
const gfx::FontList* CefMenuModelImpl::GetLabelFontListAt(int index) const {
if (index >= 0 && index < static_cast<int>(items_.size())) {
const Item& item = items_[index];
if (item.has_font_list_)
return &item.font_list_;
}
if (has_default_font_list_)
return &default_font_list_;
return nullptr;
}
bool CefMenuModelImpl::VerifyRefCount() {
if (!VerifyContext())
return false;

View File

@@ -14,6 +14,7 @@
#include "base/threading/platform_thread.h"
#include "ui/base/models/menu_model.h"
#include "ui/gfx/font_list.h"
namespace content {
struct MenuItem;
@@ -123,15 +124,37 @@ class CefMenuModelImpl : public CefMenuModel {
bool& shift_pressed, bool& ctrl_pressed, bool& alt_pressed) override;
bool GetAcceleratorAt(int index, int& key_code, bool& shift_pressed,
bool& ctrl_pressed, bool& alt_pressed) override;
bool SetColor(int command_id,
cef_menu_color_type_t color_type,
cef_color_t color) override;
bool SetColorAt(int index,
cef_menu_color_type_t color_type,
cef_color_t color) override;
bool GetColor(int command_id,
cef_menu_color_type_t color_type,
cef_color_t& color) override;
bool GetColorAt(int index,
cef_menu_color_type_t color_type,
cef_color_t& color) override;
bool SetFontList(int command_id, const CefString& font_list) override;
bool SetFontListAt(int index, const CefString& font_list) override;
// Callbacks from the ui::MenuModel implementation.
void ActivatedAt(int index, cef_event_flags_t event_flags);
void MouseOutsideMenu(const gfx::Point& screen_point);
void UnhandledOpenSubmenu(bool is_rtl);
void UnhandledCloseSubmenu(bool is_rtl);
bool GetTextColor(int index,
bool is_accelerator,
bool is_hovered,
SkColor* override_color) const;
bool GetBackgroundColor(int index,
bool is_hovered,
SkColor* override_color) const;
void MenuWillShow();
void MenuWillClose();
base::string16 GetFormattedLabelAt(int index);
const gfx::FontList* GetLabelFontListAt(int index) const;
// Verify that only a single reference exists to all CefMenuModelImpl objects.
bool VerifyRefCount();
@@ -182,6 +205,11 @@ class CefMenuModelImpl : public CefMenuModel {
ItemVector items_;
std::unique_ptr<ui::MenuModel> model_;
// Style information.
cef_color_t default_colors_[CEF_MENU_COLOR_COUNT] = {0};
gfx::FontList default_font_list_;
bool has_default_font_list_ = false;
bool auto_notify_menu_closed_ = true;
IMPLEMENT_REFCOUNTING(CefMenuModelImpl);

View File

@@ -57,6 +57,13 @@ CEF_BUTTON_VIEW_T void CEF_BUTTON_VIEW_D::ButtonPressed(
views::Button* sender, const ui::Event& event) {
if (ParentClass::cef_delegate())
ParentClass::cef_delegate()->OnButtonPressed(GetCefButton());
if (ParentClass::ink_drop_mode() != views::CustomButton::InkDropMode::OFF &&
!ParentClass::IsFocusable()) {
// When ink drop is enabled for non-focusable buttons the ink drop state
// does not get reset properly on click, so we do it here explicitly.
ParentClass::AnimateInkDrop(views::InkDropState::HIDDEN,
ui::LocatedEvent::FromIfValid(&event));
}
}
#endif // CEF_LIBCEF_BROWSER_VIEWS_BUTTON_VIEW_H_

View File

@@ -5,6 +5,7 @@
#include "libcef/browser/views/menu_button_view.h"
#include "ui/gfx/canvas.h"
#include "ui/views/controls/menu/menu_config.h"
CefMenuButtonView::CefMenuButtonView(
CefMenuButtonDelegate* cef_delegate)
@@ -17,6 +18,9 @@ void CefMenuButtonView::Initialize() {
SetDrawStringsFlags(IsFocusable() ? gfx::Canvas::SHOW_PREFIX :
gfx::Canvas::HIDE_PREFIX);
// Use the same default font as MenuItemView.
SetFontList(views::MenuConfig::instance().font_list);
}
CefRefPtr<CefMenuButton> CefMenuButtonView::GetCefMenuButton() const {