Lumiera  0.pre.03
»edit your freedom«
menu-button.cpp
Go to the documentation of this file.
1 /*
2  MenuButton - button widget to invoke a menu
3 
4  Copyright (C) Lumiera.org
5  2008, Joel Holdsworth <joel@airwebreathe.org.uk>
6 
7  This program is free software; you can redistribute it and/or
8  modify it under the terms of the GNU General Public License as
9  published by the Free Software Foundation; either version 2 of
10  the License, or (at your option) any later version.
11 
12  This program is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with this program; if not, write to the Free Software
19  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 
21 * *****************************************************/
22 
23 
30 
31 
32 using namespace Gtk;
33 using namespace Glib;
34 using namespace sigc;
35 
36 
37 #define POPUP_SLUG "TheMenu"
38 #define POPUP_PATH "/" POPUP_SLUG
39 
40 namespace stage {
41 namespace widget {
42 
43  namespace {
44  const int CaptionPadding = 4;
45  const ArrowType arrowType = ARROW_DOWN;
46  const ShadowType shadowType = SHADOW_NONE;
47  }
48 
49 
50 
51  MenuButton::MenuButton()
52  : ToggleButton()
53  , arrow(arrowType, shadowType)
54  , uimanager(UIManager::create())
55  , actions(ActionGroup::create())
56  {
57  setupButton();
58  }
59 
60 
61  MenuButton::MenuButton (StockID const& stock_id)
62  : ToggleButton()
63  , image(stock_id, ICON_SIZE_MENU)
64  , caption()
65  , arrow(arrowType, shadowType)
66  {
67  StockItem stock_item;
68  REQUIRE (StockItem::lookup (stock_id, stock_item));
69  caption.set_text_with_mnemonic (stock_item.get_label());
70  hBox.pack_start (image);
71  setupButton();
72  }
73 
74 
75  MenuButton::MenuButton (cuString& label, bool mnemonic)
76  : ToggleButton()
77  , caption(label, mnemonic)
78  , arrow(arrowType, shadowType)
79  {
80  setupButton();
81  }
82 
83 
84 
85  Gtk::Widget*
86  MenuButton::get (uString slug)
87  {
88  //TODO: if (slug == "Menu") return &get_menu();
89  uString path (POPUP_PATH);
90  path.append("/");
91  return uimanager->get_widget(path.append(slug));
92  }
93 
94 
95  Menu&
97  {
98  uString path ("/");
99  path.append (POPUP_SLUG);
100  Menu* p_menu = dynamic_cast<Menu*>(
101  uimanager->get_widget(path));
102  REQUIRE (p_menu);
103  return *p_menu;
104  }
105 
106 
107  void
108  MenuButton::append (uString &slug, uString &title,
109  sigc::slot<void> &callback, bool toggle)
110  {
111  if (!toggle)
112  actions->add(Action::create(slug, title,""), callback);
113  else
114  actions->add(ToggleAction::create(slug, title,"",false), callback);
115 
116  uimanager->add_ui(uimanager->new_merge_id(),
117  ustring("ui/").append(POPUP_SLUG),
118  slug, slug, Gtk::UI_MANAGER_AUTO,
119  false);
120  uimanager->ensure_update();
121  }
122 
123 
124  void
125  MenuButton::append (const char *slug, const char* title,
126  sigc::slot<void>& callback, bool toggle)
127  {
128  uString uSlug (slug);
129  uString uTitle (_(title));
130  append (uSlug, uTitle, callback, toggle);
131  }
132 
133 
134  void
136  {
137  uimanager->add_ui_separator(
138  uimanager->new_merge_id(),
139  ustring("ui/").append(POPUP_SLUG),
140  "Separator", Gtk::UI_MANAGER_SEPARATOR,
141  false);
142  }
143 
144 
145  void
147  {
148  get_menu().popup(mem_fun(this, &MenuButton::on_menu_position),
149  0, gtk_get_current_event_time());
150  set_active();
151  }
152 
153 
154  void
156  {
157  uimanager = UIManager::create();
158  actions = ActionGroup::create();
159  uimanager->insert_action_group(actions);
160 
161  // Setup the UIManager with a popup menu
162  const guint rootId = uimanager->new_merge_id();
163  uimanager->add_ui(rootId, "ui",
164  POPUP_SLUG, POPUP_SLUG,
165  Gtk::UI_MANAGER_POPUP);
166 
167  get_menu().signal_deactivate().connect(mem_fun(
169 
170  arrow.set(ARROW_DOWN, SHADOW_NONE);
171 
172  hBox.pack_start(caption, PACK_EXPAND_WIDGET, CaptionPadding);
173  hBox.pack_start(arrow);
174 
175  add(hBox);
176  show_all();
177  }
178 
179 
180  void
182  {
183  popup();
184  }
185 
186 
187  void
189  {
190  set_active(false);
191  }
192 
193 
194  void
195  MenuButton::on_menu_position (int& x, int& y, bool& push_in)
196  {
197  Glib::RefPtr<Gdk::Window> window = get_window();
198  REQUIRE(window);
199 
200  window->get_origin(x, y);
201  const Allocation allocation = get_allocation();
202  x += allocation.get_x();
203  y += allocation.get_y() + allocation.get_height();
204 
205  push_in = true;
206  }
207 
208 
209 }}// stage::widget
void appendSeparator()
Append a Gtk::SeparatorMenuItem to the Menu.
Image image
The image that will optionally display an icon.
Label caption
caption text label to show on the button.
void on_menu_position(int &x, int &y, bool &push_in)
callback function used to determine the correct position for the popup menu.
Arrow arrow
The arrow widget that will be displayed to hint the user that this button is a drop-down.
Menu & get_menu()
Gets the menu which will be displayed when the button is clicked on.
Definition: menu-button.cpp:96
Lumiera GTK UI implementation root.
Definition: guifacade.cpp:46
void append(uString &slug, uString &title, sigc::slot< void > &callback, bool toggle=false)
Append a Menu Item to the Menu.
void popup()
Pops up the menu.
Gtk::Widget * get(uString slug)
Get an object from the Menu.
Definition: menu-button.cpp:86
void setupButton()
An internal method which sets up the button at create time.
void on_pressed()
An event handler for when the button is pressed.
MenuButton()
Create an empty button.
Definition: menu-button.cpp:51
HBox hBox
hBox for the layout of an image, caption and arrow.
void on_menu_deactivated()
An event handler for when the menu is closed.