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.
5 #ifndef CHROME_BROWSER_UI_GTK_MENU_GTK_H_
6 #define CHROME_BROWSER_UI_GTK_MENU_GTK_H_
13 #include "base/memory/weak_ptr.h"
14 #include "ui/base/gtk/gtk_signal.h"
15 #include "ui/base/gtk/gtk_signal_registrar.h"
16 #include "ui/gfx/point.h"
23 class ButtonMenuItemModel
;
29 // Delegate class that lets another class control the status of the menu.
32 virtual ~Delegate() {}
34 // Called before a command is executed. This exists for the case where a
35 // model is handling the actual execution of commands, but the delegate
36 // still needs to know that some command got executed. This is called before
37 // and not after the command is executed because its execution may delete
38 // the menu and/or the delegate.
39 virtual void CommandWillBeExecuted() {}
41 // Called when the menu stops showing. This will be called before
42 // ExecuteCommand if the user clicks an item, but will also be called when
43 // the user clicks away from the menu.
44 virtual void StoppedShowing() {}
46 // Return true if we should override the "gtk-menu-images" system setting
47 // when showing image menu items for this menu.
48 virtual bool AlwaysShowIconForCmd(int command_id
) const;
50 // Returns a tinted image used in button in a menu.
51 virtual GtkIconSet
* GetIconSetForId(int idr
);
53 // Returns an icon for the menu item, if available.
54 virtual GtkWidget
* GetImageForCommandId(int command_id
) const;
56 static GtkWidget
* GetDefaultImageForCommandId(int command_id
);
59 MenuGtk(MenuGtk::Delegate
* delegate
, ui::MenuModel
* model
);
62 // Initialize GTK signal handlers.
63 void ConnectSignalHandlers();
65 // These methods are used to build the menu dynamically. The return value
66 // is the new menu item.
67 GtkWidget
* AppendMenuItemWithLabel(int command_id
, const std::string
& label
);
68 GtkWidget
* AppendMenuItemWithIcon(int command_id
, const std::string
& label
,
69 const gfx::Image
& icon
);
70 GtkWidget
* AppendCheckMenuItemWithLabel(int command_id
,
71 const std::string
& label
);
72 GtkWidget
* AppendSeparator();
73 GtkWidget
* InsertSeparator(int position
);
74 GtkWidget
* AppendMenuItem(int command_id
, GtkWidget
* menu_item
);
75 GtkWidget
* InsertMenuItem(int command_id
, GtkWidget
* menu_item
, int position
);
76 GtkWidget
* AppendMenuItemToMenu(int index
,
80 bool connect_to_activate
);
81 GtkWidget
* InsertMenuItemToMenu(int index
,
86 bool connect_to_activate
);
88 // Displays the menu near a widget, as if the widget were a menu bar.
89 // Example: the wrench menu button.
90 // |button| is the mouse button that brought up the menu.
91 // |event_time| is the time from the GdkEvent.
92 void PopupForWidget(GtkWidget
* widget
, int button
, guint32 event_time
);
94 // Displays the menu as a context menu, i.e. at the cursor location.
95 // It is implicit that it was brought up using the right mouse button.
96 // |point| is the point where to put the menu.
97 // |event_time| is the time of the event that triggered the menu's display.
98 void PopupAsContext(const gfx::Point
& point
, guint32 event_time
);
100 // Displays the menu as a context menu for the passed status icon.
101 void PopupAsContextForStatusIcon(guint32 event_time
, guint32 button
,
102 GtkStatusIcon
* icon
);
104 // Displays the menu following a keyboard event (such as selecting |widget|
105 // and pressing "enter").
106 void PopupAsFromKeyEvent(GtkWidget
* widget
);
111 // Repositions the menu to be right under the button. Alignment is set as
112 // object data on |void_widget| with the tag "left_align". If "left_align"
113 // is true, it aligns the left side of the menu with the left side of the
114 // button. Otherwise it aligns the right side of the menu with the right side
115 // of the button. Public since some menus have odd requirements that don't
116 // belong in a public class.
117 static void WidgetMenuPositionFunc(GtkMenu
* menu
,
123 // Positions the menu to appear at the gfx::Point represented by |userdata|.
124 static void PointMenuPositionFunc(GtkMenu
* menu
,
130 GtkWidget
* widget() const { return menu_
; }
132 // Updates all the enabled/checked states and the dynamic labels.
136 // Builds a GtkImageMenuItem.
137 GtkWidget
* BuildMenuItemWithImage(const std::string
& label
,
138 const gfx::Image
& icon
);
140 GtkWidget
* BuildMenuItemWithImage(const std::string
& label
,
143 GtkWidget
* BuildMenuItemWithLabel(const std::string
& label
,
146 // A function that creates a GtkMenu from |model_|.
147 void BuildMenuFromModel();
148 // Implementation of the above; called recursively.
149 void BuildSubmenuFromModel(ui::MenuModel
* model
, GtkWidget
* menu
);
150 // Builds a menu item with buttons in it from the data in the model.
151 GtkWidget
* BuildButtonMenuItem(ui::ButtonMenuItemModel
* model
,
154 void ExecuteCommand(ui::MenuModel
* model
, int id
);
156 // Callback for when a menu item is clicked.
157 CHROMEGTK_CALLBACK_0(MenuGtk
, void, OnMenuItemActivated
);
159 // Called when one of the buttons is pressed.
160 CHROMEGTK_CALLBACK_1(MenuGtk
, void, OnMenuButtonPressed
, int);
162 // Called to maybe activate a button if that button isn't supposed to dismiss
164 CHROMEGTK_CALLBACK_1(MenuGtk
, gboolean
, OnMenuTryButtonPressed
, int);
166 // Updates all the menu items' state.
167 CHROMEGTK_CALLBACK_0(MenuGtk
, void, OnMenuShow
);
169 // Sets the activating widget back to a normal appearance.
170 CHROMEGTK_CALLBACK_0(MenuGtk
, void, OnMenuHidden
);
172 // Focus out event handler for the menu.
173 CHROMEGTK_CALLBACK_1(MenuGtk
, gboolean
, OnMenuFocusOut
, GdkEventFocus
*);
175 // Handles building dynamic submenus on demand when they are shown.
176 CHROMEGTK_CALLBACK_0(MenuGtk
, void, OnSubMenuShow
);
178 // Handles trearing down dynamic submenus when they have been closed.
179 CHROMEGTK_CALLBACK_0(MenuGtk
, void, OnSubMenuHidden
);
181 // Scheduled by OnSubMenuHidden() to avoid deleting submenus when hidden
182 // before pending activations within them are delivered.
183 static void OnSubMenuHiddenCallback(GtkWidget
* submenu
);
185 // Sets the enable/disabled state and dynamic labels on our menu items.
186 static void SetButtonItemInfo(GtkWidget
* button
, gpointer userdata
);
188 // Sets the check mark, enabled/disabled state and dynamic labels on our menu
190 static void SetMenuItemInfo(GtkWidget
* widget
, void* raw_menu
);
192 // Queries this object about the menu state.
193 MenuGtk::Delegate
* delegate_
;
195 // If non-NULL, the MenuModel that we use to populate and control the GTK
196 // menu (overriding the delegate as a controller).
197 ui::MenuModel
* model_
;
199 // For some menu items, we want to show the accelerator, but not actually
200 // explicitly handle it. To this end we connect those menu items' accelerators
201 // to this group, but don't attach this group to any top level window.
202 GtkAccelGroup
* dummy_accel_group_
;
204 // gtk_menu_popup() does not appear to take ownership of popup menus, so
205 // MenuGtk explicitly manages the lifetime of the menu.
208 // True when we should ignore "activate" signals. Used to prevent
209 // menu items from getting activated when we are setting up the
211 static bool block_activation_
;
213 ui::GtkSignalRegistrar signal_
;
215 base::WeakPtrFactory
<MenuGtk
> weak_factory_
;
218 #endif // CHROME_BROWSER_UI_GTK_MENU_GTK_H_