libyui-gtk  2.43.3
 All Classes
YGPushButton.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 <YPushButton.h>
9 #include "YGUtils.h"
10 #include "YGWidget.h"
11 #include <string.h>
12 
13 #include <YLayoutBox.h>
14 #include "ygtkratiobox.h"
15 
16 class YGPushButton : public YPushButton, public YGWidget
17 {
18 bool m_customIcon, m_labelIcon;
19 
20 public:
21  YGPushButton (YWidget *parent, const std::string &label)
22  : YPushButton (NULL, label),
23  YGWidget (this, parent, GTK_TYPE_BUTTON, "can-default", TRUE, NULL)
24  {
25  m_customIcon = m_labelIcon = false;
26  gtk_button_set_use_underline (GTK_BUTTON (getWidget()), TRUE);
27  setLabel (label);
28  connect (getWidget(), "clicked", G_CALLBACK (clicked_cb), this);
29  g_signal_connect (getWidget(), "realize", G_CALLBACK (realize_cb), this);
30  }
31 
32  void setStockIcon (const std::string &label)
33  {
34  if (!m_customIcon) {
35  const char *stock = NULL;
36  switch (functionKey()) {
37  case 1: stock = GTK_STOCK_HELP; break;
38  case 2: stock = GTK_STOCK_INFO; break; // Info
39  case 3: stock = GTK_STOCK_ADD; break;
40  case 4: stock = GTK_STOCK_EDIT; break;
41  case 5: stock = GTK_STOCK_DELETE; break;
42  case 6: stock = GTK_STOCK_EXECUTE; break; // Test
43  case 7: stock = GTK_STOCK_EDIT; break; // Expert
44  // old expert icon: GTK_STOCK_PREFERENCES
45  //case 8: stock = GTK_STOCK_GO_BACK; break;
46  case 9: stock = GTK_STOCK_CANCEL; break;
47  case 10: stock = GTK_STOCK_OK; break; // Next/Finish/OK
48  default: break;
49  }
50  switch (role()) {
51  case YOKButton: stock = GTK_STOCK_OK; break;
52  case YApplyButton: stock = GTK_STOCK_APPLY; break;
53  case YCancelButton: stock = GTK_STOCK_CANCEL; break;
54  case YHelpButton: stock = GTK_STOCK_HELP; break;
55  case YCustomButton: case YMaxButtonRole: break;
56  }
57  m_labelIcon = YGUtils::setStockIcon (getWidget(), label, stock);
58  }
59  }
60 
61  // YPushButton
62  virtual void setLabel (const std::string &label)
63  {
64  YPushButton::setLabel (label);
65  std::string str = YGUtils::mapKBAccel (label);
66  gtk_button_set_label (GTK_BUTTON (getWidget()), str.c_str());
67  setStockIcon (str);
68  }
69 
70  virtual void setRole (YButtonRole role)
71  {
72  YPushButton::setRole (role);
73  if (!m_labelIcon && role != YCustomButton) // to avoid duplications
74  setStockIcon (label());
75  }
76 
77  virtual void setFunctionKey (int key)
78  {
79  YPushButton::setFunctionKey (key);
80  if (!m_labelIcon && hasFunctionKey())
81  setStockIcon (label());
82  }
83 
84  virtual void setHelpButton (bool helpButton)
85  {
86  YPushButton::setHelpButton (helpButton);
87  if (!m_labelIcon && helpButton)
88  setStockIcon (label());
89  }
90 
91  virtual void setIcon (const std::string &icon)
92  {
93  GtkButton *button = GTK_BUTTON (getWidget());
94  if (icon.empty()) {
95  m_customIcon = false;
96  // no need to worry about freeing the image, let it live with button
97  GtkWidget *image = gtk_button_get_image (button);
98  if (image)
99  gtk_widget_hide (image);
100  }
101  else {
102  m_customIcon = true;
103  std::string path (icon);
104  if (path[0] != '/')
105  path = std::string (THEMEDIR) + "/" + path;
106 
107  GError *error = 0;
108  GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file (path.c_str(), &error);
109  if (pixbuf) {
110  GtkWidget *image = gtk_image_new_from_pixbuf (pixbuf);
111  gtk_button_set_image (button, image);
112  // disregard gtk-button-images setting for explicitly set icons
113  gtk_widget_show (image);
114  g_object_unref (G_OBJECT (pixbuf));
115  }
116  else
117  yuiWarning() << "YGPushButton: Couldn't load icon image: " << path << std::endl
118  << "Reason: " << error->message << std::endl;
119  }
120  }
121 
122  virtual void setDefaultButton (bool isDefault)
123  {
124  struct inner {
125  static void realize_cb (GtkWidget *widget)
126  {
127  gtk_widget_grab_default (widget);
128  gtk_widget_grab_focus (widget);
129  }
130  };
131 
132  YPushButton::setDefaultButton (isDefault);
133  if (isDefault) {
134  GtkWidget *button = getWidget();
135  gtk_widget_set_can_default(button, TRUE);
136  if (gtk_widget_get_realized (button))
137  inner::realize_cb (button);
138  g_signal_connect (G_OBJECT (button), "realize",
139  G_CALLBACK (inner::realize_cb), this);
140  }
141  }
142 
143  static bool hasIcon (YWidget *ywidget)
144  {
145  if (dynamic_cast <YPushButton *> (ywidget)) {
146  GtkWidget *button = YGWidget::get (ywidget)->getWidget();
147  GtkWidget *icon = gtk_button_get_image (GTK_BUTTON (button));
148  return icon && gtk_widget_get_visible (icon);
149  }
150  return true;
151  }
152 
153 #if 0
154  static gboolean treat_icon_cb (GtkWidget *widget, GdkEventExpose *event,
155  YGPushButton *pThis)
156  {
157  YLayoutBox *ybox = dynamic_cast <YLayoutBox *> (pThis->parent());
158  if (ybox && !pThis->m_customIcon) {
159  if (ybox->primary() == YD_HORIZ) {
160  // only set stock icons if all to the left have them
161  YWidget *ylast = 0;
162  for (YWidgetListConstIterator it = ybox->childrenBegin();
163  it != ybox->childrenEnd(); it++) {
164  if ((YWidget *) pThis == *it) {
165  if (ylast && !hasIcon (ylast))
166  pThis->setIcon ("");
167  break;
168  }
169  ylast = *it;
170  if (!dynamic_cast <YPushButton *> (ylast))
171  ylast = NULL;
172  }
173  }
174  else { // YD_VERT
175  // different strategy: set icons for all or none
176  bool disableIcons = false;
177  for (YWidgetListConstIterator it = ybox->childrenBegin();
178  it != ybox->childrenEnd(); it++)
179  if (!hasIcon (*it))
180  disableIcons = true;
181  if (disableIcons)
182  for (YWidgetListConstIterator it = ybox->childrenBegin();
183  it != ybox->childrenEnd(); it++)
184  if (dynamic_cast <YPushButton *> (*it)) {
185  YGPushButton *button = (YGPushButton *)
186  YGWidget::get (*it);
187  if (!button->m_customIcon)
188  button->setIcon ("");
189  }
190  }
191  }
192  g_signal_handlers_disconnect_by_func (widget, (gpointer) treat_icon_cb, pThis);
193  return FALSE;
194  }
195 #endif
196 
197  // callbacks
198  static void clicked_cb (GtkButton *button, YGPushButton *pThis)
199  { pThis->emitEvent (YEvent::Activated, IGNORE_NOTIFY_EVENT); }
200 
201 // default values from gtkbbox.c; can vary from style to style, but no way to query those
202 #define DEFAULT_CHILD_MIN_WIDTH 85
203 #define DEFAULT_CHILD_MIN_HEIGHT 27
204 
205  static void realize_cb (GtkWidget *widget, YGPushButton *pThis)
206  { // enlarge button if parent is ButtonBox
207  YWidget *yparent = pThis->m_ywidget->parent();
208  if (yparent && !strcmp (yparent->widgetClass(), "YButtonBox"))
209  ygtk_adj_size_set_min (YGTK_ADJ_SIZE(pThis->getLayout()),
210  DEFAULT_CHILD_MIN_WIDTH, DEFAULT_CHILD_MIN_HEIGHT);
211  }
212 
213  YGWIDGET_IMPL_COMMON (YPushButton)
214 };
215 
216 YPushButton *YGWidgetFactory::createPushButton (YWidget *parent, const std::string &label)
217 { return new YGPushButton (parent, label); }
218