diff options
24 files changed, 342 insertions, 248 deletions
diff --git a/chrome/browser/autocomplete/autocomplete_edit_view_win.cc b/chrome/browser/autocomplete/autocomplete_edit_view_win.cc index 7aac332..0bc4f6c 100644 --- a/chrome/browser/autocomplete/autocomplete_edit_view_win.cc +++ b/chrome/browser/autocomplete/autocomplete_edit_view_win.cc @@ -41,6 +41,7 @@ #include "skia/ext/skia_utils_win.h" #include "views/drag_utils.h" #include "views/focus/focus_util_win.h" +#include "views/widget/widget.h" #pragma comment(lib, "oleacc.lib") // Needed for accessibility support. @@ -468,33 +469,6 @@ AutocompleteEditViewWin::AutocompleteEditViewWin( cf.crTextColor = GetSysColor(COLOR_GRAYTEXT); SetDefaultCharFormat(cf); - // Set up context menu. - context_menu_.reset(views::Menu::Create(this, views::Menu::TOPLEFT, m_hWnd)); - if (popup_window_mode_) { - context_menu_->AppendMenuItemWithLabel(IDS_COPY, - l10n_util::GetString(IDS_COPY)); - } else { - context_menu_->AppendMenuItemWithLabel(IDS_UNDO, - l10n_util::GetString(IDS_UNDO)); - context_menu_->AppendSeparator(); - context_menu_->AppendMenuItemWithLabel(IDS_CUT, - l10n_util::GetString(IDS_CUT)); - context_menu_->AppendMenuItemWithLabel(IDS_COPY, - l10n_util::GetString(IDS_COPY)); - context_menu_->AppendMenuItemWithLabel(IDS_PASTE, - l10n_util::GetString(IDS_PASTE)); - // GetContextualLabel() will override this next label with the - // IDS_PASTE_AND_SEARCH label as needed. - context_menu_->AppendMenuItemWithLabel( - IDS_PASTE_AND_GO, l10n_util::GetString(IDS_PASTE_AND_GO)); - context_menu_->AppendSeparator(); - context_menu_->AppendMenuItemWithLabel( - IDS_SELECT_ALL, l10n_util::GetString(IDS_SELECT_ALL)); - context_menu_->AppendSeparator(); - context_menu_->AppendMenuItemWithLabel( - IDS_EDIT_SEARCH_ENGINES, l10n_util::GetString(IDS_EDIT_SEARCH_ENGINES)); - } - // By default RichEdit has a drop target. Revoke it so that we can install our // own. Revoke takes care of deleting the existing one. RevokeDragDrop(m_hWnd); @@ -954,12 +928,16 @@ void AutocompleteEditViewWin::HandleExternalMsg(UINT msg, SendMessage(msg, flags, MAKELPARAM(client_point.x, client_point.y)); } -bool AutocompleteEditViewWin::IsCommandEnabled(int id) const { - switch (id) { +bool AutocompleteEditViewWin::IsCommandIdChecked(int command_id) const { + return false; +} + +bool AutocompleteEditViewWin::IsCommandIdEnabled(int command_id) const { + switch (command_id) { case IDS_UNDO: return !!CanUndo(); - case IDS_CUT: return !!CanCut(); - case IDS_COPY: return !!CanCopy(); - case IDS_PASTE: return !!CanPaste(); + case IDC_CUT: return !!CanCut(); + case IDC_COPY: return !!CanCopy(); + case IDC_PASTE: return !!CanPaste(); case IDS_PASTE_AND_GO: return CanPasteAndGo(GetClipboardText()); case IDS_SELECT_ALL: return !!CanSelectAll(); case IDS_EDIT_SEARCH_ENGINES: @@ -968,21 +946,28 @@ bool AutocompleteEditViewWin::IsCommandEnabled(int id) const { } } -bool AutocompleteEditViewWin::GetContextualLabel(int id, - std::wstring* out) const { - if ((id != IDS_PASTE_AND_GO) || - // No need to change the default IDS_PASTE_AND_GO label unless this is a - // search. - !model_->is_paste_and_search()) - return false; +bool AutocompleteEditViewWin::GetAcceleratorForCommandId( + int command_id, + views::Accelerator* accelerator) { + return parent_view_->GetWidget()->GetAccelerator(command_id, accelerator); +} - out->assign(l10n_util::GetString(IDS_PASTE_AND_SEARCH)); - return true; +bool AutocompleteEditViewWin::IsLabelForCommandIdDynamic(int command_id) const { + // No need to change the default IDS_PASTE_AND_GO label unless this is a + // search. + return command_id == IDS_PASTE_AND_GO; } -void AutocompleteEditViewWin::ExecuteCommand(int id) { +std::wstring AutocompleteEditViewWin::GetLabelForCommandId( + int command_id) const { + DCHECK(command_id == IDS_PASTE_AND_GO); + return l10n_util::GetString(model_->is_paste_and_search() ? + IDS_PASTE_AND_SEARCH : IDS_PASTE_AND_GO); +} + +void AutocompleteEditViewWin::ExecuteCommand(int command_id) { ScopedFreeze freeze(this, GetTextObjectModel()); - if (id == IDS_PASTE_AND_GO) { + if (command_id == IDS_PASTE_AND_GO) { // This case is separate from the switch() below since we don't want to wrap // it in OnBefore/AfterPossibleChange() calls. model_->PasteAndGo(); @@ -990,20 +975,20 @@ void AutocompleteEditViewWin::ExecuteCommand(int id) { } OnBeforePossibleChange(); - switch (id) { + switch (command_id) { case IDS_UNDO: Undo(); break; - case IDS_CUT: + case IDC_CUT: Cut(); break; - case IDS_COPY: + case IDC_COPY: Copy(); break; - case IDS_PASTE: + case IDC_PASTE: Paste(); break; @@ -1173,13 +1158,14 @@ void AutocompleteEditViewWin::OnChar(TCHAR ch, UINT repeat_count, UINT flags) { } void AutocompleteEditViewWin::OnContextMenu(HWND window, const CPoint& point) { + BuildContextMenu(); if (point.x == -1 || point.y == -1) { POINT p; GetCaretPos(&p); MapWindowPoints(HWND_DESKTOP, &p, 1); - context_menu_->RunMenuAt(p.x, p.y); + context_menu_->RunContextMenuAt(gfx::Point(p)); } else { - context_menu_->RunMenuAt(point.x, point.y); + context_menu_->RunContextMenuAt(gfx::Point(point)); } } @@ -2329,3 +2315,30 @@ void AutocompleteEditViewWin::RepaintDropHighlight(int position) { InvalidateRect(&highlight_bounds, false); } } + +void AutocompleteEditViewWin::BuildContextMenu() { + if (context_menu_contents_.get()) + return; + + context_menu_contents_.reset(new views::SimpleMenuModel(this)); + // Set up context menu. + if (popup_window_mode_) { + context_menu_contents_->AddItemWithStringId(IDS_COPY, IDS_COPY); + } else { + context_menu_contents_->AddItemWithStringId(IDS_UNDO, IDS_UNDO); + context_menu_contents_->AddSeparator(); + context_menu_contents_->AddItemWithStringId(IDC_CUT, IDS_CUT); + context_menu_contents_->AddItemWithStringId(IDC_COPY, IDS_COPY); + context_menu_contents_->AddItemWithStringId(IDC_PASTE, IDS_PASTE); + // GetContextualLabel() will override this next label with the + // IDS_PASTE_AND_SEARCH label as needed. + context_menu_contents_->AddItemWithStringId(IDS_PASTE_AND_GO, + IDS_PASTE_AND_GO); + context_menu_contents_->AddSeparator(); + context_menu_contents_->AddItemWithStringId(IDS_SELECT_ALL, IDS_SELECT_ALL); + context_menu_contents_->AddSeparator(); + context_menu_contents_->AddItemWithStringId(IDS_EDIT_SEARCH_ENGINES, + IDS_EDIT_SEARCH_ENGINES); + } + context_menu_.reset(new views::Menu2(context_menu_contents_.get())); +} diff --git a/chrome/browser/autocomplete/autocomplete_edit_view_win.h b/chrome/browser/autocomplete/autocomplete_edit_view_win.h index 822ebea..0c91820 100644 --- a/chrome/browser/autocomplete/autocomplete_edit_view_win.h +++ b/chrome/browser/autocomplete/autocomplete_edit_view_win.h @@ -19,7 +19,7 @@ #include "chrome/browser/toolbar_model.h" #include "chrome/browser/views/autocomplete/autocomplete_popup_contents_view.h" #include "chrome/common/page_transition_types.h" -#include "views/controls/menu/menu.h" +#include "views/controls/menu/simple_menu_model.h" #include "webkit/glue/window_open_disposition.h" class AutocompletePopupModel; @@ -44,7 +44,7 @@ class AutocompleteEditViewWin CWinTraits<WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL | ES_NOHIDESEL> >, public CRichEditCommands<AutocompleteEditViewWin>, - public views::Menu::Delegate, + public views::SimpleMenuModel::Delegate, public AutocompleteEditView { public: struct State { @@ -179,10 +179,14 @@ class AutocompleteEditViewWin DEFAULT_REFLECTION_HANDLER() // avoids black margin area END_MSG_MAP() - // Menu::Delegate - virtual bool IsCommandEnabled(int id) const; - virtual bool GetContextualLabel(int id, std::wstring* out) const; - virtual void ExecuteCommand(int id); + // SimpleMenuModel::Delegate + virtual bool IsCommandIdChecked(int command_id) const; + virtual bool IsCommandIdEnabled(int command_id) const; + virtual bool GetAcceleratorForCommandId(int command_id, + views::Accelerator* accelerator); + virtual bool IsLabelForCommandIdDynamic(int command_id) const; + virtual std::wstring GetLabelForCommandId(int command_id) const; + virtual void ExecuteCommand(int command_id); private: // This object freezes repainting of the edit until the object is destroyed. @@ -357,6 +361,9 @@ class AutocompleteEditViewWin // text. void RepaintDropHighlight(int position); + // Generates the context menu for the edit field. + void BuildContextMenu(); + scoped_ptr<AutocompleteEditModel> model_; scoped_ptr<AutocompletePopupView> popup_view_; @@ -426,7 +433,8 @@ class AutocompleteEditViewWin CHARRANGE saved_selection_for_focus_change_; // The context menu for the edit. - scoped_ptr<views::Menu> context_menu_; + scoped_ptr<views::SimpleMenuModel> context_menu_contents_; + scoped_ptr<views::Menu2> context_menu_; // Font we're using. We keep a reference to make sure the font supplied to // the constructor doesn't go away before we do. diff --git a/chrome/browser/autocomplete/search_provider.cc b/chrome/browser/autocomplete/search_provider.cc index d3d91ca..8a6d305 100644 --- a/chrome/browser/autocomplete/search_provider.cc +++ b/chrome/browser/autocomplete/search_provider.cc @@ -716,15 +716,15 @@ void SearchProvider::AddMatchToMap(const std::wstring& query_string, // looks odd if both the first and last s are highlighted. if (input_position != 0) { match.contents_class.push_back( - ACMatchClassification(0, ACMatchClassification::MATCH)); + ACMatchClassification(0, ACMatchClassification::NONE)); } match.contents_class.push_back( - ACMatchClassification(input_position, ACMatchClassification::NONE)); + ACMatchClassification(input_position, ACMatchClassification::DIM)); size_t next_fragment_position = input_position + input_text.length(); if (next_fragment_position < query_string.length()) { match.contents_class.push_back( ACMatchClassification(next_fragment_position, - ACMatchClassification::MATCH)); + ACMatchClassification::NONE)); } } } else { diff --git a/chrome/browser/external_tab_container.cc b/chrome/browser/external_tab_container.cc index 2dbf706..6c9b2a8 100644 --- a/chrome/browser/external_tab_container.cc +++ b/chrome/browser/external_tab_container.cc @@ -4,6 +4,7 @@ #include "chrome/browser/external_tab_container.h" +#include "app/l10n_util.h" #include "app/win_util.h" #include "base/logging.h" #include "base/win_util.h" @@ -268,17 +269,17 @@ bool ExternalTabContainer::HandleContextMenu(const ContextMenuParams& params) { external_context_menu_.reset( new RenderViewContextMenuExternalWin(tab_contents(), params, - GetNativeView(), disabled_context_menu_ids_)); external_context_menu_->Init(); POINT screen_pt = { params.x, params.y }; MapWindowPoints(GetNativeView(), HWND_DESKTOP, &screen_pt, 1); + bool rtl = l10n_util::TextDirection() == l10n_util::RIGHT_TO_LEFT; automation_->Send( new AutomationMsg_ForwardContextMenuToExternalHost(0, tab_handle_, external_context_menu_->GetMenuHandle(), screen_pt.x, screen_pt.y, - external_context_menu_->GetTPMAlignFlags())); + rtl ? TPM_RIGHTALIGN : TPM_LEFTALIGN)); return true; } diff --git a/chrome/browser/tab_contents/render_view_context_menu_external_win.cc b/chrome/browser/tab_contents/render_view_context_menu_external_win.cc index 0c19f94..a9667c9 100644 --- a/chrome/browser/tab_contents/render_view_context_menu_external_win.cc +++ b/chrome/browser/tab_contents/render_view_context_menu_external_win.cc @@ -9,9 +9,8 @@ RenderViewContextMenuExternalWin::RenderViewContextMenuExternalWin( TabContents* tab_contents, const ContextMenuParams& params, - HWND owner, const std::vector<int> disabled_ids) - : RenderViewContextMenuWin(tab_contents, params, owner), + : RenderViewContextMenuWin(tab_contents, params), disabled_menu_ids_(disabled_ids) { } diff --git a/chrome/browser/tab_contents/render_view_context_menu_external_win.h b/chrome/browser/tab_contents/render_view_context_menu_external_win.h index 3c31e44..0bd6f24 100644 --- a/chrome/browser/tab_contents/render_view_context_menu_external_win.h +++ b/chrome/browser/tab_contents/render_view_context_menu_external_win.h @@ -15,7 +15,6 @@ class RenderViewContextMenuExternalWin : public RenderViewContextMenuWin { public: RenderViewContextMenuExternalWin(TabContents* tab_contents, const ContextMenuParams& params, - HWND window, const std::vector<int> disabled_menu_ids); ~RenderViewContextMenuExternalWin() {} diff --git a/chrome/browser/tab_contents/render_view_context_menu_win.cc b/chrome/browser/tab_contents/render_view_context_menu_win.cc index 952993f..66a923c 100644 --- a/chrome/browser/tab_contents/render_view_context_menu_win.cc +++ b/chrome/browser/tab_contents/render_view_context_menu_win.cc @@ -9,90 +9,44 @@ #include "chrome/browser/profile.h" #include "grit/generated_resources.h" +//////////////////////////////////////////////////////////////////////////////// +// RenderViewContextMenuWin, public: + RenderViewContextMenuWin::RenderViewContextMenuWin( TabContents* tab_contents, - const ContextMenuParams& params, - HWND owner) + const ContextMenuParams& params) : RenderViewContextMenu(tab_contents, params), - sub_menu_(NULL), - owner_(owner) { - // anchor_position set per http://crbug.com/10827. - views::Menu::AnchorPoint anchor_position = views::Menu::TOPLEFT; - if (l10n_util::GetTextDirection() == l10n_util::RIGHT_TO_LEFT) - anchor_position = views::Menu::TOPRIGHT; - menu_.reset(new views::MenuWin(this, anchor_position, owner_)); + current_radio_group_id_(-1), + sub_menu_contents_(NULL) { + menu_contents_.reset(new views::SimpleMenuModel(this)); + InitMenu(params.node); + menu_.reset(new views::Menu2(menu_contents_.get())); } RenderViewContextMenuWin::~RenderViewContextMenuWin() { } void RenderViewContextMenuWin::RunMenuAt(int x, int y) { - menu_->RunMenuAt(x, y); -} - -void RenderViewContextMenuWin::AppendMenuItem(int id) { - AppendItem(id, l10n_util::GetString(id), views::Menu::NORMAL); -} - -void RenderViewContextMenuWin::AppendMenuItem(int id, - const std::wstring& label) { - AppendItem(id, label, views::Menu::NORMAL); -} - -void RenderViewContextMenuWin::AppendRadioMenuItem(int id, - const std::wstring& label) { - AppendItem(id, label, views::Menu::RADIO); -} - -void RenderViewContextMenuWin::AppendCheckboxMenuItem(int id, - const std::wstring& label) { - AppendItem(id, label, views::Menu::CHECKBOX); -} - -void RenderViewContextMenuWin::AppendSeparator() { - views::Menu* menu = sub_menu_ ? sub_menu_ : menu_.get(); - menu->AppendSeparator(); -} - -void RenderViewContextMenuWin::StartSubMenu(int id, const std::wstring& label) { - if (sub_menu_) { - NOTREACHED(); - return; - } - sub_menu_ = menu_->AppendSubMenu(id, label); -} - -void RenderViewContextMenuWin::FinishSubMenu() { - DCHECK(sub_menu_); - sub_menu_ = NULL; -} - -void RenderViewContextMenuWin::AppendItem( - int id, - const std::wstring& label, - views::Menu::MenuItemType type) { - views::Menu* menu = sub_menu_ ? sub_menu_ : menu_.get(); - menu->AppendMenuItem(id, label, type); + menu_->RunContextMenuAt(gfx::Point(x, y)); } -bool RenderViewContextMenuWin::IsCommandEnabled(int id) const { - return IsItemCommandEnabled(id); -} +//////////////////////////////////////////////////////////////////////////////// +// RenderViewContextMenuWin, views::SimpleMenuModel::Delegate implementation: -bool RenderViewContextMenuWin::IsItemChecked(int id) const { - return ItemIsChecked(id); +bool RenderViewContextMenuWin::IsCommandIdChecked(int command_id) const { + return ItemIsChecked(command_id); } -void RenderViewContextMenuWin::ExecuteCommand(int id) { - ExecuteItemCommand(id); +bool RenderViewContextMenuWin::IsCommandIdEnabled(int command_id) const { + return IsItemCommandEnabled(command_id); } -bool RenderViewContextMenuWin::GetAcceleratorInfo( - int id, +bool RenderViewContextMenuWin::GetAcceleratorForCommandId( + int command_id, views::Accelerator* accel) { // There are no formally defined accelerators we can query so we assume // that Ctrl+C, Ctrl+V, Ctrl+X, Ctrl-A, etc do what they normally do. - switch (id) { + switch (command_id) { case IDS_CONTENT_CONTEXT_UNDO: *accel = views::Accelerator(L'Z', false, true, false); return true; @@ -121,3 +75,64 @@ bool RenderViewContextMenuWin::GetAcceleratorInfo( return false; } } + +void RenderViewContextMenuWin::ExecuteCommand(int command_id) { + ExecuteItemCommand(command_id); +} + +//////////////////////////////////////////////////////////////////////////////// +// RenderViewContextMenuWin, protected: + +void RenderViewContextMenuWin::AppendMenuItem(int id) { + current_radio_group_id_ = -1; + GetTargetModel()->AddItemWithStringId(id, id); +} + +void RenderViewContextMenuWin::AppendMenuItem(int id, + const std::wstring& label) { + current_radio_group_id_ = -1; + GetTargetModel()->AddItem(id, label); +} + +void RenderViewContextMenuWin::AppendRadioMenuItem(int id, + const std::wstring& label) { + if (current_radio_group_id_ < 0) + current_radio_group_id_ = id; + GetTargetModel()->AddRadioItem(id, label, current_radio_group_id_); +} + +void RenderViewContextMenuWin::AppendCheckboxMenuItem( + int id, + const std::wstring& label) { + current_radio_group_id_ = -1; + GetTargetModel()->AddCheckItem(id, label); +} + +void RenderViewContextMenuWin::AppendSeparator() { + current_radio_group_id_ = -1; + GetTargetModel()->AddSeparator(); +} + +void RenderViewContextMenuWin::StartSubMenu(int id, const std::wstring& label) { + if (sub_menu_contents_) { + NOTREACHED() << "nested submenus not supported yet"; + return; + } + current_radio_group_id_ = -1; + sub_menu_contents_ = new views::SimpleMenuModel(this); + menu_contents_->AddSubMenu(label, sub_menu_contents_); + submenu_models_.push_back(sub_menu_contents_); +} + +void RenderViewContextMenuWin::FinishSubMenu() { + DCHECK(sub_menu_contents_); + current_radio_group_id_ = -1; + sub_menu_contents_ = NULL; +} + +//////////////////////////////////////////////////////////////////////////////// +// RenderViewContextMenuWin, private: + +views::SimpleMenuModel* RenderViewContextMenuWin::GetTargetModel() const { + return sub_menu_contents_ ? sub_menu_contents_ : menu_contents_.get(); +} diff --git a/chrome/browser/tab_contents/render_view_context_menu_win.h b/chrome/browser/tab_contents/render_view_context_menu_win.h index 3488d59..e188533 100644 --- a/chrome/browser/tab_contents/render_view_context_menu_win.h +++ b/chrome/browser/tab_contents/render_view_context_menu_win.h @@ -6,34 +6,30 @@ #define CHROME_BROWSER_TAB_CONTENTS_RENDER_VIEW_CONTEXT_MENU_WIN_H_ #include "base/scoped_ptr.h" +#include "base/scoped_vector.h" #include "chrome/browser/tab_contents/render_view_context_menu.h" #include "views/accelerator.h" -#include "views/controls/menu/menu_win.h" +#include "views/controls/menu/simple_menu_model.h" class RenderViewContextMenuWin : public RenderViewContextMenu, - public views::Menu::Delegate { + public views::SimpleMenuModel::Delegate { public: RenderViewContextMenuWin(TabContents* tab_contents, - const ContextMenuParams& params, - HWND window); + const ContextMenuParams& params); ~RenderViewContextMenuWin(); void RunMenuAt(int x, int y); - // Menu::Delegate implementation --------------------------------------------- - virtual bool IsCommandEnabled(int id) const; - virtual bool IsItemChecked(int id) const; - virtual void ExecuteCommand(int id); - // TODO(port): move the logic in this function to RenderViewContextMenu. - virtual bool GetAcceleratorInfo(int id, views::Accelerator* accel); + // Overridden from SimpleMenuModel::Delegate: + virtual bool IsCommandIdChecked(int command_id) const; + virtual bool IsCommandIdEnabled(int command_id) const; + virtual bool GetAcceleratorForCommandId(int command_id, + views::Accelerator* accelerator); + virtual void ExecuteCommand(int command_id); HMENU GetMenuHandle() const { - return (menu_.get() ? menu_->GetMenuHandle() : NULL); - } - - unsigned int GetTPMAlignFlags() const { - return (menu_.get() ? menu_->GetTPMAlignFlags() : 0); + return (menu_.get() ? menu_->GetNativeMenu() : NULL); } protected: @@ -47,13 +43,21 @@ class RenderViewContextMenuWin : public RenderViewContextMenu, virtual void FinishSubMenu(); private: - // Append the item to |sub_menu_| if it exists, or |menu_| otherwise. - void AppendItem(int id, - const std::wstring& label, - views::Menu::MenuItemType type); + // Gets the target model to append items to. This is either the main context + // menu, or a submenu if we've descended into one. + views::SimpleMenuModel* GetTargetModel() const; + + // The current radio group for radio menu items. + int current_radio_group_id_; - scoped_ptr<views::MenuWin> menu_; - views::Menu* sub_menu_; + // The context menu itself and its contents. + scoped_ptr<views::SimpleMenuModel> menu_contents_; + scoped_ptr<views::Menu2> menu_; + // TODO(beng): This way of building submenus is kind of retarded, but it + // hasn't hurt us yet. It's just a bit awkward. + views::SimpleMenuModel* sub_menu_contents_; + // We own submenu models that we create, so we store them here. + ScopedVector<views::SimpleMenuModel> submenu_models_; HWND owner_; }; diff --git a/chrome/browser/tab_contents/tab_contents_view_win.cc b/chrome/browser/tab_contents/tab_contents_view_win.cc index 341eb50..9452737 100644 --- a/chrome/browser/tab_contents/tab_contents_view_win.cc +++ b/chrome/browser/tab_contents/tab_contents_view_win.cc @@ -394,15 +394,10 @@ void TabContentsViewWin::HandleKeyboardEvent( void TabContentsViewWin::ShowContextMenu(const ContextMenuParams& params) { // Allow delegates to handle the context menu operation first. - if (tab_contents()->delegate()->HandleContextMenu(params)) { + if (tab_contents()->delegate()->HandleContextMenu(params)) return; - } - - RenderViewContextMenuWin menu(tab_contents(), - params, - GetNativeView()); - menu.Init(); + context_menu_.reset(new RenderViewContextMenuWin(tab_contents(), params)); POINT screen_pt = { params.x, params.y }; MapWindowPoints(GetNativeView(), HWND_DESKTOP, &screen_pt, 1); @@ -411,7 +406,7 @@ void TabContentsViewWin::ShowContextMenu(const ContextMenuParams& params) { // the context menu is being displayed. bool old_state = MessageLoop::current()->NestableTasksAllowed(); MessageLoop::current()->SetNestableTasksAllowed(true); - menu.RunMenuAt(screen_pt.x, screen_pt.y); + context_menu_->RunMenuAt(screen_pt.x, screen_pt.y); MessageLoop::current()->SetNestableTasksAllowed(old_state); } diff --git a/chrome/browser/tab_contents/tab_contents_view_win.h b/chrome/browser/tab_contents/tab_contents_view_win.h index 07bd545..6af85a1 100644 --- a/chrome/browser/tab_contents/tab_contents_view_win.h +++ b/chrome/browser/tab_contents/tab_contents_view_win.h @@ -10,11 +10,11 @@ #include "chrome/browser/tab_contents/tab_contents_view.h" #include "views/widget/widget_win.h" +class RenderViewContextMenuWin; class SadTabView; struct WebDropData; class WebDropTarget; - // Windows-specific implementation of the TabContentsView. It is a HWND that // contains all of the contents of the tab and associated child views. class TabContentsViewWin : public TabContentsView, @@ -101,6 +101,9 @@ class TabContentsViewWin : public TabContentsView, // The id used in the ViewStorage to store the last focused view. int last_focused_view_storage_id_; + // The context menu. Callbacks are asynchronous so we need to keep it around. + scoped_ptr<RenderViewContextMenuWin> context_menu_; + DISALLOW_COPY_AND_ASSIGN(TabContentsViewWin); }; diff --git a/chrome/browser/views/bookmark_bar_view.h b/chrome/browser/views/bookmark_bar_view.h index 23f98e3..c747610 100644 --- a/chrome/browser/views/bookmark_bar_view.h +++ b/chrome/browser/views/bookmark_bar_view.h @@ -13,7 +13,6 @@ #include "chrome/common/notification_registrar.h" #include "views/controls/button/menu_button.h" #include "views/controls/label.h" -#include "views/controls/menu/menu.h" #include "views/controls/menu/view_menu_delegate.h" #include "views/view.h" #include "third_party/skia/include/core/SkRect.h" @@ -37,7 +36,6 @@ class BookmarkBarView : public views::View, public BookmarkModelObserver, public views::ViewMenuDelegate, public views::ButtonListener, - public views::Menu::Delegate, public NotificationObserver, public views::ContextMenuController, public views::DragController, diff --git a/chrome/browser/views/bookmark_editor_view.cc b/chrome/browser/views/bookmark_editor_view.cc index b845b39..3208099 100644 --- a/chrome/browser/views/bookmark_editor_view.cc +++ b/chrome/browser/views/bookmark_editor_view.cc @@ -187,20 +187,30 @@ void BookmarkEditorView::ButtonPressed(Button* sender) { } } -void BookmarkEditorView::ExecuteCommand(int id) { +bool BookmarkEditorView::IsCommandIdChecked(int command_id) const { + return false; +} + +bool BookmarkEditorView::IsCommandIdEnabled(int command_id) const { + return (command_id != IDS_EDIT || !running_menu_for_root_); +} + +bool BookmarkEditorView::GetAcceleratorForCommandId( + int command_id, + views::Accelerator* accelerator) { + return GetWidget()->GetAccelerator(command_id, accelerator); +} + +void BookmarkEditorView::ExecuteCommand(int command_id) { DCHECK(tree_view_->GetSelectedNode()); - if (id == IDS_EDIT) { + if (command_id == IDS_EDIT) { tree_view_->StartEditing(tree_view_->GetSelectedNode()); } else { - DCHECK(id == IDS_BOOMARK_EDITOR_NEW_FOLDER_MENU_ITEM); + DCHECK(command_id == IDS_BOOMARK_EDITOR_NEW_FOLDER_MENU_ITEM); NewGroup(); } } -bool BookmarkEditorView::IsCommandEnabled(int id) const { - return (id != IDS_EDIT || !running_menu_for_root_); -} - void BookmarkEditorView::Show(HWND parent_hwnd) { views::Window::CreateChromeWindow(parent_hwnd, gfx::Rect(), this); UserInputChanged(); @@ -228,14 +238,15 @@ void BookmarkEditorView::ShowContextMenu(View* source, running_menu_for_root_ = (tree_model_->GetParent(tree_view_->GetSelectedNode()) == tree_model_->GetRoot()); - context_menu_.reset(views::Menu::Create(this, views::Menu::TOPLEFT, - GetWidget()->GetNativeView())); - context_menu_->AppendMenuItemWithLabel(IDS_EDIT, - l10n_util::GetString(IDS_EDIT)); - context_menu_->AppendMenuItemWithLabel( - IDS_BOOMARK_EDITOR_NEW_FOLDER_MENU_ITEM, - l10n_util::GetString(IDS_BOOMARK_EDITOR_NEW_FOLDER_MENU_ITEM)); - context_menu_->RunMenuAt(x, y); + if (!context_menu_contents_.get()) { + context_menu_contents_.reset(new views::SimpleMenuModel(this)); + context_menu_contents_->AddItemWithStringId(IDS_EDIT, IDS_EDIT); + context_menu_contents_->AddItemWithStringId( + IDS_BOOMARK_EDITOR_NEW_FOLDER_MENU_ITEM, + IDS_BOOMARK_EDITOR_NEW_FOLDER_MENU_ITEM); + context_menu_.reset(new views::Menu2(context_menu_contents_.get())); + } + context_menu_->RunContextMenuAt(gfx::Point(x, y)); } void BookmarkEditorView::Init() { diff --git a/chrome/browser/views/bookmark_editor_view.h b/chrome/browser/views/bookmark_editor_view.h index 1758325..51ef925 100644 --- a/chrome/browser/views/bookmark_editor_view.h +++ b/chrome/browser/views/bookmark_editor_view.h @@ -11,7 +11,7 @@ #include "chrome/browser/bookmarks/bookmark_editor.h" #include "chrome/browser/bookmarks/bookmark_model.h" #include "views/controls/button/button.h" -#include "views/controls/menu/menu.h" +#include "views/controls/menu/simple_menu_model.h" #include "views/controls/textfield/textfield.h" #include "views/controls/tree/tree_view.h" #include "views/window/dialog_delegate.h" @@ -40,7 +40,7 @@ class BookmarkEditorView : public BookmarkEditor, public views::DialogDelegate, public views::Textfield::Controller, public views::ContextMenuController, - public views::Menu::Delegate, + public views::SimpleMenuModel::Delegate, public BookmarkModelObserver { FRIEND_TEST(BookmarkEditorViewTest, ChangeParent); FRIEND_TEST(BookmarkEditorViewTest, ChangeParentAndURL); @@ -91,12 +91,12 @@ class BookmarkEditorView : public BookmarkEditor, // NativeButton. virtual void ButtonPressed(views::Button* sender); - // Menu::Delegate method. - virtual void ExecuteCommand(int id); - - // Menu::Delegate method, return false if id is edit and the bookmark node - // was selected, true otherwise. - virtual bool IsCommandEnabled(int id) const; + // SimpleMenuModel::Delegate. + virtual bool IsCommandIdChecked(int command_id) const; + virtual bool IsCommandIdEnabled(int command_id) const; + virtual bool GetAcceleratorForCommandId(int command_id, + views::Accelerator* accelerator); + virtual void ExecuteCommand(int command_id); // Creates a Window and adds the BookmarkEditorView to it. When the window is // closed the BookmarkEditorView is deleted. @@ -244,7 +244,8 @@ class BookmarkEditorView : public BookmarkEditor, BookmarkNode* node_; // The context menu. - scoped_ptr<views::Menu> context_menu_; + scoped_ptr<views::SimpleMenuModel> context_menu_contents_; + scoped_ptr<views::Menu2> context_menu_; // Mode used to create nodes from. BookmarkModel* bb_model_; diff --git a/chrome/browser/views/bookmark_table_view.h b/chrome/browser/views/bookmark_table_view.h index ed83bcb..b80d1fa 100644 --- a/chrome/browser/views/bookmark_table_view.h +++ b/chrome/browser/views/bookmark_table_view.h @@ -7,7 +7,6 @@ #include "chrome/browser/bookmarks/bookmark_drag_data.h" #include "chrome/browser/bookmarks/bookmark_drop_info.h" -#include "views/controls/menu/menu.h" #include "views/controls/table/table_view.h" class BookmarkModel; diff --git a/chrome/browser/views/frame/browser_view.cc b/chrome/browser/views/frame/browser_view.cc index 1b3e42b..db7a04f 100644 --- a/chrome/browser/views/frame/browser_view.cc +++ b/chrome/browser/views/frame/browser_view.cc @@ -55,7 +55,6 @@ #include "grit/generated_resources.h" #include "grit/theme_resources.h" #include "grit/webkit_resources.h" -#include "views/controls/menu/menu.h" #if defined(OS_WIN) #include "views/controls/scrollbar/native_scroll_bar.h" #endif @@ -461,6 +460,20 @@ bool BrowserView::AcceleratorPressed(const views::Accelerator& accelerator) { } bool BrowserView::GetAccelerator(int cmd_id, views::Accelerator* accelerator) { + // The standard Ctrl-X, Ctrl-V and Ctrl-C are not defined as accelerators + // anywhere so we need to check for them explicitly here. + switch (cmd_id) { + case IDC_CUT: + *accelerator = views::Accelerator(L'X', false, true, false); + return true; + case IDC_COPY: + *accelerator = views::Accelerator(L'C', false, true, false); + return true; + case IDC_PASTE: + *accelerator = views::Accelerator(L'V', false, true, false); + return true; + } + // Else, we retrieve the accelerator information from the accelerator table. std::map<views::Accelerator, int>::iterator it = accelerator_table_->begin(); for (; it != accelerator_table_->end(); ++it) { diff --git a/chrome/browser/views/tabs/tab_renderer.h b/chrome/browser/views/tabs/tab_renderer.h index e68308c..d265b53 100644 --- a/chrome/browser/views/tabs/tab_renderer.h +++ b/chrome/browser/views/tabs/tab_renderer.h @@ -10,7 +10,6 @@ #include "app/throb_animation.h" #include "base/gfx/point.h" #include "views/controls/button/image_button.h" -#include "views/controls/menu/menu.h" #include "views/view.h" class TabContents; diff --git a/chrome/browser/views/tabs/tab_strip.h b/chrome/browser/views/tabs/tab_strip.h index 013f9d1..71f0301 100644 --- a/chrome/browser/views/tabs/tab_strip.h +++ b/chrome/browser/views/tabs/tab_strip.h @@ -10,7 +10,6 @@ #include "chrome/browser/tabs/tab_strip_model.h" #include "chrome/browser/views/tabs/tab.h" #include "views/controls/button/image_button.h" -#include "views/controls/menu/menu.h" #include "views/view.h" #if defined(OS_WIN) #include "views/widget/widget_win.h" diff --git a/chrome/browser/views/toolbar_view.cc b/chrome/browser/views/toolbar_view.cc index 3d64b1d..02f31fc 100644 --- a/chrome/browser/views/toolbar_view.cc +++ b/chrome/browser/views/toolbar_view.cc @@ -171,8 +171,9 @@ ToolbarView::ToolbarView(Browser* browser) profile_(NULL), browser_(browser), tab_(NULL), - profiles_menu_(NULL), - profiles_helper_(new GetProfilesHelper(this)) { + profiles_menu_contents_(NULL), + ALLOW_THIS_IN_INITIALIZER_LIST( + profiles_helper_(new GetProfilesHelper(this))) { browser_->command_updater()->AddCommandObserver(IDC_BACK, this); browser_->command_updater()->AddCommandObserver(IDC_FORWARD, this); browser_->command_updater()->AddCommandObserver(IDC_RELOAD, this); @@ -253,21 +254,6 @@ int ToolbarView::GetNextAccessibleViewIndex(int view_index, bool nav_left) { // ToolbarView, Menu::BaseControllerDelegate overrides: bool ToolbarView::GetAcceleratorInfo(int id, views::Accelerator* accel) { - // The standard Ctrl-X, Ctrl-V and Ctrl-C are not defined as accelerators - // anywhere so we need to check for them explicitly here. - // TODO(cpu) Bug 1109102. Query WebKit land for the actual bindings. - switch (id) { - case IDC_CUT: - *accel = views::Accelerator(L'X', false, true, false); - return true; - case IDC_COPY: - *accel = views::Accelerator(L'C', false, true, false); - return true; - case IDC_PASTE: - *accel = views::Accelerator(L'V', false, true, false); - return true; - } - // Else, we retrieve the accelerator information from the frame. return GetWidget()->GetAccelerator(id, accel); } @@ -294,7 +280,7 @@ void ToolbarView::RunMenu(views::View* source, const gfx::Point& pt, void ToolbarView::OnGetProfilesDone( const std::vector<std::wstring>& profiles) { // Nothing to do if the menu has gone away. - if (!profiles_menu_) + if (!profiles_menu_contents_.get()) return; // Store the latest list of profiles in the browser. @@ -305,20 +291,20 @@ void ToolbarView::OnGetProfilesDone( for (int i = IDC_NEW_WINDOW_PROFILE_0; (i <= IDC_NEW_WINDOW_PROFILE_LAST) && (iter != profiles.end()); ++i, ++iter) - profiles_menu_->AppendMenuItemWithLabel(i, *iter); + profiles_menu_contents_->AddItem(i, *iter); // If there are more profiles then show "Other" link. if (iter != profiles.end()) { - profiles_menu_->AppendSeparator(); - profiles_menu_->AppendMenuItemWithLabel( - IDC_SELECT_PROFILE, l10n_util::GetString(IDS_SELECT_PROFILE)); + profiles_menu_contents_->AddSeparator(); + profiles_menu_contents_->AddItemWithStringId(IDC_SELECT_PROFILE, + IDS_SELECT_PROFILE); } // Always show a link to select a new profile. - profiles_menu_->AppendSeparator(); - profiles_menu_->AppendMenuItemWithLabel( + profiles_menu_contents_->AddSeparator(); + profiles_menu_contents_->AddItemWithStringId( IDC_NEW_PROFILE, - l10n_util::GetString(IDS_SELECT_PROFILE_DIALOG_NEW_PROFILE_ENTRY)); + IDS_SELECT_PROFILE_DIALOG_NEW_PROFILE_ENTRY); } //////////////////////////////////////////////////////////////////////////////// @@ -1068,6 +1054,17 @@ void ToolbarView::CreateAppMenu() { app_menu_contents_->AddItemWithStringId(IDC_NEW_WINDOW, IDS_NEW_WINDOW); app_menu_contents_->AddItemWithStringId(IDC_NEW_INCOGNITO_WINDOW, IDS_NEW_INCOGNITO_WINDOW); + // Enumerate profiles asynchronously and then create the parent menu item. + // We will create the child menu items for this once the asynchronous call is + // done. See OnGetProfilesDone(). + const CommandLine& command_line = *CommandLine::ForCurrentProcess(); + if (command_line.HasSwitch(switches::kEnableUserDataDirProfiles)) { + profiles_helper_->GetProfiles(NULL); + profiles_menu_contents_.reset(new views::SimpleMenuModel(this)); + app_menu_contents_->AddSubMenuWithStringId(IDS_PROFILE_MENU, + profiles_menu_contents_.get()); + } + app_menu_contents_->AddSeparator(); app_menu_contents_->AddCheckItemWithStringId(IDC_SHOW_BOOKMARK_BAR, IDS_SHOW_BOOKMARK_BAR); diff --git a/chrome/browser/views/toolbar_view.h b/chrome/browser/views/toolbar_view.h index 169448b..efd9d2c 100644 --- a/chrome/browser/views/toolbar_view.h +++ b/chrome/browser/views/toolbar_view.h @@ -227,8 +227,8 @@ class ToolbarView : public views::View, // Current tab we're showing state for. TabContents* tab_; - // Profiles menu to populate with profile names. - views::Menu* profiles_menu_; + // Contents of the profiles menu to populate with profile names. + scoped_ptr<views::SimpleMenuModel> profiles_menu_contents_; // Helper class to enumerate profiles information on the file thread. scoped_refptr<GetProfilesHelper> profiles_helper_; diff --git a/views/controls/menu/menu_2.cc b/views/controls/menu/menu_2.cc index 8ce63b6..2a0ed56 100644 --- a/views/controls/menu/menu_2.cc +++ b/views/controls/menu/menu_2.cc @@ -50,6 +50,10 @@ void Menu2::RunMenuAt(const gfx::Point& point, Alignment alignment) { wrapper_->RunMenuAt(point, alignment); } +void Menu2::RunContextMenuAt(const gfx::Point& point) { + wrapper_->RunMenuAt(point, ALIGN_TOPLEFT); +} + void Menu2::CancelMenu() { wrapper_->CancelMenu(); } diff --git a/views/controls/menu/menu_2.h b/views/controls/menu/menu_2.h index a131ee5..68c4833 100644 --- a/views/controls/menu/menu_2.h +++ b/views/controls/menu/menu_2.h @@ -114,8 +114,10 @@ class Menu2 { }; // Runs the menu at the specified point. This may or may not block, depending - // on the platform and type of menu in use. + // on the platform and type of menu in use. RunContextMenuAt is the same, but + // the alignment is the default for a context menu. void RunMenuAt(const gfx::Point& point, Alignment alignment); + void RunContextMenuAt(const gfx::Point& point); // Cancels the active menu. void CancelMenu(); diff --git a/views/controls/menu/native_menu_win.cc b/views/controls/menu/native_menu_win.cc index c82844e..c5f8331 100644 --- a/views/controls/menu/native_menu_win.cc +++ b/views/controls/menu/native_menu_win.cc @@ -63,7 +63,7 @@ class NativeMenuWin::MenuHostWindow { NativeMenuWin* GetNativeMenuWinFromHMENU(HMENU hmenu) const { MENUINFO mi = {0}; mi.cbSize = sizeof(mi); - mi.fMask = MIM_MENUDATA; + mi.fMask = MIM_MENUDATA | MIM_STYLE; GetMenuInfo(hmenu, &mi); return reinterpret_cast<NativeMenuWin*>(mi.dwMenuData); } @@ -92,7 +92,9 @@ class NativeMenuWin::MenuHostWindow { // Called when the user selects a specific item. void OnMenuCommand(int position, HMENU menu) { - GetNativeMenuWinFromHMENU(menu)->model_->ActivatedAt(position); + NativeMenuWin* intergoat = GetNativeMenuWinFromHMENU(menu); + Menu2Model* model = intergoat->model_; + model->ActivatedAt(position); } // Called as the user moves their mouse or arrows through the contents of the @@ -165,6 +167,7 @@ NativeMenuWin::NativeMenuWin(Menu2Model* model, HWND system_menu_for) NativeMenuWin::~NativeMenuWin() { STLDeleteContainerPointers(items_.begin(), items_.end()); + DestroyMenu(menu_); } //////////////////////////////////////////////////////////////////////////////// diff --git a/views/controls/textfield/native_textfield_win.cc b/views/controls/textfield/native_textfield_win.cc index d2044a5..65c6b53 100644 --- a/views/controls/textfield/native_textfield_win.cc +++ b/views/controls/textfield/native_textfield_win.cc @@ -97,21 +97,6 @@ NativeTextfieldWin::NativeTextfieldWin(Textfield* textfield) ole_interface.Attach(GetOleInterface()); text_object_model_ = ole_interface; - context_menu_.reset(new MenuWin(this, Menu::TOPLEFT, m_hWnd)); - context_menu_->AppendMenuItemWithLabel(IDS_APP_UNDO, - l10n_util::GetString(IDS_APP_UNDO)); - context_menu_->AppendSeparator(); - context_menu_->AppendMenuItemWithLabel(IDS_APP_CUT, - l10n_util::GetString(IDS_APP_CUT)); - context_menu_->AppendMenuItemWithLabel(IDS_APP_COPY, - l10n_util::GetString(IDS_APP_COPY)); - context_menu_->AppendMenuItemWithLabel(IDS_APP_PASTE, - l10n_util::GetString(IDS_APP_PASTE)); - context_menu_->AppendSeparator(); - context_menu_->AppendMenuItemWithLabel( - IDS_APP_SELECT_ALL, - l10n_util::GetString(IDS_APP_SELECT_ALL)); - container_view_ = new NativeViewHost; textfield_->AddChildView(container_view_); container_view_->set_focus_view(textfield_); @@ -227,13 +212,17 @@ gfx::NativeView NativeTextfieldWin::GetTestingHandle() const { } //////////////////////////////////////////////////////////////////////////////// -// NativeTextfieldWin, Menu::Delegate implementation: +// NativeTextfieldWin, SimpleMenuModel::Delegate implementation: + +bool NativeTextfieldWin::IsCommandIdChecked(int command_id) const { + return false; +} -bool NativeTextfieldWin::IsCommandEnabled(int id) const { - switch (id) { +bool NativeTextfieldWin::IsCommandIdEnabled(int command_id) const { + switch (command_id) { case IDS_APP_UNDO: return !textfield_->read_only() && !!CanUndo(); case IDS_APP_CUT: return !textfield_->read_only() && - !textfield_->IsPassword() && !!CanCut(); + !textfield_->IsPassword() && !!CanCut(); case IDS_APP_COPY: return !!CanCopy() && !textfield_->IsPassword(); case IDS_APP_PASTE: return !textfield_->read_only() && !!CanPaste(); case IDS_APP_SELECT_ALL: return !!CanSelectAll(); @@ -242,10 +231,28 @@ bool NativeTextfieldWin::IsCommandEnabled(int id) const { } } -void NativeTextfieldWin::ExecuteCommand(int id) { +bool NativeTextfieldWin::GetAcceleratorForCommandId(int command_id, + Accelerator* accelerator) { + // The standard Ctrl-X, Ctrl-V and Ctrl-C are not defined as accelerators + // anywhere so we need to check for them explicitly here. + switch (command_id) { + case IDS_APP_CUT: + *accelerator = views::Accelerator(L'X', false, true, false); + return true; + case IDS_APP_COPY: + *accelerator = views::Accelerator(L'C', false, true, false); + return true; + case IDS_APP_PASTE: + *accelerator = views::Accelerator(L'V', false, true, false); + return true; + } + return container_view_->GetWidget()->GetAccelerator(command_id, accelerator); +} + +void NativeTextfieldWin::ExecuteCommand(int command_id) { ScopedFreeze freeze(this, GetTextObjectModel()); OnBeforePossibleChange(); - switch (id) { + switch (command_id) { case IDS_APP_UNDO: Undo(); break; case IDS_APP_CUT: Cut(); break; case IDS_APP_COPY: Copy(); break; @@ -269,7 +276,8 @@ void NativeTextfieldWin::OnContextMenu(HWND window, const CPoint& point) { GetCaretPos(&p); MapWindowPoints(HWND_DESKTOP, &p, 1); } - context_menu_->RunMenuAt(p.x, p.y); + BuildContextMenu(); + context_menu_->RunContextMenuAt(gfx::Point(p)); } void NativeTextfieldWin::OnCopy() { @@ -837,6 +845,21 @@ ITextDocument* NativeTextfieldWin::GetTextObjectModel() const { return text_object_model_; } +void NativeTextfieldWin::BuildContextMenu() { + if (context_menu_contents_.get()) + return; + context_menu_contents_.reset(new SimpleMenuModel(this)); + context_menu_contents_->AddItemWithStringId(IDS_APP_UNDO, IDS_APP_UNDO); + context_menu_contents_->AddSeparator(); + context_menu_contents_->AddItemWithStringId(IDS_APP_CUT, IDS_APP_CUT); + context_menu_contents_->AddItemWithStringId(IDS_APP_COPY, IDS_APP_COPY); + context_menu_contents_->AddItemWithStringId(IDS_APP_PASTE, IDS_APP_PASTE); + context_menu_contents_->AddSeparator(); + context_menu_contents_->AddItemWithStringId(IDS_APP_SELECT_ALL, + IDS_APP_SELECT_ALL); + context_menu_.reset(new Menu2(context_menu_contents_.get())); +} + //////////////////////////////////////////////////////////////////////////////// // NativeTextfieldWrapper, public: diff --git a/views/controls/textfield/native_textfield_win.h b/views/controls/textfield/native_textfield_win.h index 58034c0..514c27f 100644 --- a/views/controls/textfield/native_textfield_win.h +++ b/views/controls/textfield/native_textfield_win.h @@ -13,6 +13,7 @@ #include <tom.h> // For ITextDocument, a COM interface to CRichEditCtrl #include <vsstyle.h> +#include "views/controls/menu/simple_menu_model.h" #include "views/controls/textfield/native_textfield_wrapper.h" namespace views { @@ -28,7 +29,7 @@ class NativeTextfieldWin CWinTraits<kDefaultEditStyle> >, public CRichEditCommands<NativeTextfieldWin>, public NativeTextfieldWrapper, - public Menu::Delegate { + public SimpleMenuModel::Delegate { public: DECLARE_WND_CLASS(L"ViewsTextfieldEdit"); @@ -52,6 +53,13 @@ class NativeTextfieldWin virtual View* GetView(); virtual gfx::NativeView GetTestingHandle() const; + // Overridden from SimpleMenuModel::Delegate: + virtual bool IsCommandIdChecked(int command_id) const; + virtual bool IsCommandIdEnabled(int command_id) const; + virtual bool GetAcceleratorForCommandId(int command_id, + Accelerator* accelerator); + virtual void ExecuteCommand(int command_id); + // CWindowImpl BEGIN_MSG_MAP(Edit) MSG_WM_CHAR(OnChar) @@ -79,10 +87,6 @@ class NativeTextfieldWin MSG_WM_SYSKEYDOWN(OnKeyDown) END_MSG_MAP() - // Menu::Delegate - virtual bool IsCommandEnabled(int id) const; - virtual void ExecuteCommand(int id); - private: // This object freezes repainting of the edit until the object is destroyed. // Some methods of the CRichEditCtrl draw synchronously to the screen. If we @@ -156,6 +160,9 @@ class NativeTextfieldWin // alive. ITextDocument* GetTextObjectModel() const; + // Generates the contents of the context menu. + void BuildContextMenu(); + // The Textfield this object is bound to. Textfield* textfield_; @@ -177,8 +184,9 @@ class NativeTextfieldWin static bool did_load_library_; - // The context menu for the edit. - scoped_ptr<Menu> context_menu_; + // The contents of the context menu for the edit. + scoped_ptr<SimpleMenuModel> context_menu_contents_; + scoped_ptr<Menu2> context_menu_; // Border insets. gfx::Insets content_insets_; |