Home | History | Annotate | Download | only in menu
      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