libyui-gtk  2.44.5
 All Classes Functions
YGMenuButton.cc
1 /********************************************************************
2  * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
3  ********************************************************************/
4 
5 #define YUILogComponent "gtk"
6 #include <yui/Libyui_config.h>
7 #include "YGUI.h"
8 #include "YGUtils.h"
9 #include "YGWidget.h"
10 #include "YMenuButton.h"
11 #include "ygtkmenubutton.h"
12 
13 static void selected_item_cb (GtkMenuItem *menuitem, YItem *item)
14 {
15  // HACK: gtk_menu_get_active() doesn't work properly
16  GtkWidget *menu = gtk_widget_get_ancestor (GTK_WIDGET (menuitem), GTK_TYPE_MENU);
17  g_object_set_data (G_OBJECT (menu), "active", menuitem);
18 
19  YGUI::ui()->sendEvent (new YMenuEvent (item));
20 }
21 
22 static void doCreateMenu (GtkWidget *parent, YItemIterator begin, YItemIterator end)
23 {
24  for (YItemIterator it = begin; it != end; it++) {
25  GtkWidget *entry;
26  std::string str = YGUtils::mapKBAccel ((*it)->label());
27 
28  entry = gtk_menu_item_new_with_mnemonic (str.c_str());
29 
30  gtk_menu_shell_append (GTK_MENU_SHELL (parent), entry);
31 
32  if ((*it)->hasChildren()) {
33  GtkWidget *submenu = gtk_menu_new();
34  doCreateMenu (submenu, (*it)->childrenBegin(), (*it)->childrenEnd());
35  gtk_menu_item_set_submenu (GTK_MENU_ITEM (entry), submenu);
36  }
37  else
38  g_signal_connect (G_OBJECT (entry), "activate",
39  G_CALLBACK (selected_item_cb), *it);
40  }
41 }
42 
43 class YGMenuButton : public YMenuButton, public YGWidget
44 {
45 public:
46  YGMenuButton (YWidget *parent, const std::string &label)
47  : YMenuButton (NULL, label),
48  YGWidget (this, parent, YGTK_TYPE_MENU_BUTTON, NULL)
49  { setLabel (label); }
50 
51  // YMenuButton
52  virtual void setLabel (const std::string &label)
53  {
54  std::string str = YGUtils::mapKBAccel (label.c_str());
55  ygtk_menu_button_set_label (YGTK_MENU_BUTTON (getWidget()), str.c_str());
56  YMenuButton::setLabel (label);
57  }
58 
59  virtual void rebuildMenuTree()
60  {
61  GtkWidget *menu = gtk_menu_new();
62  doCreateMenu (menu, itemsBegin(), itemsEnd());
63  gtk_widget_show_all (menu);
64  ygtk_menu_button_set_popup (YGTK_MENU_BUTTON (getWidget()), menu);
65  }
66 
67  YGWIDGET_IMPL_COMMON (YMenuButton)
68 };
69 
70 YMenuButton *YGWidgetFactory::createMenuButton (YWidget *parent, const std::string &label)
71 { return new YGMenuButton (parent, label); }
72 
73 #include <YContextMenu.h>
74 
75 class YGContextMenu : public YContextMenu, public YGWidget
76 {
77  int m_deactivateTimeout;
78 
79 public:
81  : YContextMenu(),
82  YGWidget (this, NULL, GTK_TYPE_MENU, NULL)
83  {
84  // "cancel" signal doesnt seem to work properly
85  m_deactivateTimeout = 0;
86  connect (getWidget(), "deactivate", G_CALLBACK (deactivate_cb), this);
87  }
88 
89  // YContextMenu
90  virtual void rebuildMenuTree()
91  {
92  GtkWidget *menu = getWidget();
93  doCreateMenu (menu, itemsBegin(), itemsEnd());
94  gtk_widget_show_all (menu);
95  gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL, 3, gtk_get_current_event_time());
96  }
97 
98  // callbacks
99  static void deactivate_cb (GtkMenuShell *menu, YGContextMenu *pThis)
100  { // ugly: we need to make sure a selection was made before this callback called
101  // we'll use a timeout because deactivate seems to be called more than once
102  if(pThis->m_deactivateTimeout == 0)
103  pThis->m_deactivateTimeout = g_timeout_add_full (G_PRIORITY_LOW, 50, cancel_cb, pThis, NULL);
104  //g_idle_add_full (G_PRIORITY_LOW, cancel_cb, pThis, NULL);
105  }
106 
107  static gboolean cancel_cb (gpointer data)
108  {
109  YGContextMenu *pThis = (YGContextMenu *) data;
110  if (!g_object_get_data (G_OBJECT (pThis->getWidget()), "active"))
111  YGUI::ui()->sendEvent (new YCancelEvent());
112  delete pThis;
113  return FALSE;
114  }
115 
116  YGWIDGET_IMPL_COMMON (YContextMenu)
117 };
118 
119 bool YGApplication::openContextMenu (const YItemCollection &itemCollection)
120 {
121  YGContextMenu *menu = new YGContextMenu();
122  menu->addItems (itemCollection);
123  return true;
124 }
125