1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef UI_VIEWS_CONTROLS_MENU_NATIVE_MENU_WIN_H_ 6 #define UI_VIEWS_CONTROLS_MENU_NATIVE_MENU_WIN_H_ 7 8 #include <vector> 9 10 #include "base/basictypes.h" 11 #include "base/compiler_specific.h" 12 #include "base/memory/scoped_ptr.h" 13 #include "base/memory/weak_ptr.h" 14 #include "base/observer_list.h" 15 #include "base/strings/string16.h" 16 #include "ui/views/controls/menu/menu_wrapper.h" 17 #include "ui/views/views_export.h" 18 19 namespace ui { 20 class MenuModel; 21 } 22 23 namespace views { 24 25 // A Windows implementation of MenuWrapper. 26 // TODO(beng): rename to MenuWin once the old class is dead. 27 class VIEWS_EXPORT NativeMenuWin : public MenuWrapper { 28 public: 29 // Construct a NativeMenuWin, with a model and delegate. If |system_menu_for| 30 // is non-NULL, the NativeMenuWin wraps the system menu for that window. 31 // The caller owns the model and the delegate. 32 NativeMenuWin(ui::MenuModel* model, HWND system_menu_for); 33 virtual ~NativeMenuWin(); 34 35 // Overridden from MenuWrapper: 36 virtual void RunMenuAt(const gfx::Point& point, int alignment) OVERRIDE; 37 virtual void CancelMenu() OVERRIDE; 38 virtual void Rebuild(MenuInsertionDelegateWin* delegate) OVERRIDE; 39 virtual void UpdateStates() OVERRIDE; 40 virtual HMENU GetNativeMenu() const OVERRIDE; 41 virtual MenuAction GetMenuAction() const OVERRIDE; 42 virtual void AddMenuListener(MenuListener* listener) OVERRIDE; 43 virtual void RemoveMenuListener(MenuListener* listener) OVERRIDE; 44 virtual void SetMinimumWidth(int width) OVERRIDE; 45 46 private: 47 // IMPORTANT: Note about indices. 48 // Functions in this class deal in two index spaces: 49 // 1. menu_index - the index of an item within the actual Windows 50 // native menu. 51 // 2. model_index - the index of the item within our model. 52 // These two are most often but not always the same value! The 53 // notable exception is when this object is used to wrap the 54 // Windows System Menu. In this instance, the model indices start 55 // at 0, but the insertion index into the existing menu is not. 56 // It is important to take this into consideration when editing the 57 // code in the functions in this class. 58 59 struct HighlightedMenuItemInfo; 60 61 // Returns true if the item at the specified index is a separator. 62 bool IsSeparatorItemAt(int menu_index) const; 63 64 // Add items. See note above about indices. 65 void AddMenuItemAt(int menu_index, int model_index); 66 void AddSeparatorItemAt(int menu_index, int model_index); 67 68 // Sets the state of the item at the specified index. 69 void SetMenuItemState(int menu_index, 70 bool enabled, 71 bool checked, 72 bool is_default); 73 74 // Sets the label of the item at the specified index. 75 void SetMenuItemLabel(int menu_index, 76 int model_index, 77 const base::string16& label); 78 79 // Updates the local data structure with the correctly formatted version of 80 // |label| at the specified model_index, and adds string data to |mii| if 81 // the menu is not owner-draw. That's a mouthful. This function exists because 82 // of the peculiarities of the Windows menu API. 83 void UpdateMenuItemInfoForString(MENUITEMINFO* mii, 84 int model_index, 85 const base::string16& label); 86 87 // Returns the alignment flags to be passed to TrackPopupMenuEx, based on the 88 // supplied alignment and the UI text direction. 89 UINT GetAlignmentFlags(int alignment) const; 90 91 // Resets the native menu stored in |menu_| by destroying any old menu then 92 // creating a new empty one. 93 void ResetNativeMenu(); 94 95 // Creates the host window that receives notifications from the menu. 96 void CreateHostWindow(); 97 98 // Callback from task to notify menu it was selected. 99 void DelayedSelect(); 100 101 // Given a menu that's currently popped-up, find the currently highlighted 102 // item. Returns true if a highlighted item was found. 103 static bool GetHighlightedMenuItemInfo(HMENU menu, 104 HighlightedMenuItemInfo* info); 105 106 // Hook to receive keyboard events while the menu is open. 107 static LRESULT CALLBACK MenuMessageHook( 108 int n_code, WPARAM w_param, LPARAM l_param); 109 110 // Our attached model and delegate. 111 ui::MenuModel* model_; 112 113 HMENU menu_; 114 115 // True if the contents of menu items in this menu are drawn by the menu host 116 // window, rather than Windows. 117 bool owner_draw_; 118 119 // An object that collects all of the data associated with an individual menu 120 // item. 121 struct ItemData; 122 std::vector<ItemData*> items_; 123 124 // The window that receives notifications from the menu. 125 class MenuHostWindow; 126 friend MenuHostWindow; 127 scoped_ptr<MenuHostWindow> host_window_; 128 129 // The HWND this menu is the system menu for, or NULL if the menu is not a 130 // system menu. 131 HWND system_menu_for_; 132 133 // The index of the first item in the model in the menu. 134 int first_item_index_; 135 136 // The action that took place during the call to RunMenuAt. 137 MenuAction menu_action_; 138 139 // A list of listeners to call when the menu opens. 140 ObserverList<MenuListener> listeners_; 141 142 // Keep track of whether the listeners have already been called at least 143 // once. 144 bool listeners_called_; 145 146 // See comment in MenuMessageHook for details on these. 147 NativeMenuWin* menu_to_select_; 148 int position_to_select_; 149 base::WeakPtrFactory<NativeMenuWin> menu_to_select_factory_; 150 151 // If we're a submenu, this is our parent. 152 NativeMenuWin* parent_; 153 154 // If non-null the destructor sets this to true. This is set to non-null while 155 // the menu is showing. It is used to detect if the menu was deleted while 156 // running. 157 bool* destroyed_flag_; 158 159 // Ugly: a static pointer to the instance of this class that currently 160 // has a menu open, because our hook function that receives keyboard 161 // events doesn't have a mechanism to get a user data pointer. 162 static NativeMenuWin* open_native_menu_win_; 163 164 DISALLOW_COPY_AND_ASSIGN(NativeMenuWin); 165 }; 166 167 } // namespace views 168 169 #endif // UI_VIEWS_CONTROLS_MENU_NATIVE_MENU_WIN_H_ 170