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;