libyui-gtk  2.44.8
YGLayout.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 "YGWidget.h"
8 #include "YGUtils.h"
9 
10 /* Our layout stuff is a hybrid between GTK and libyui. We use libyui
11  for YLayoutBox and a couple of other widgets, but we do things GTK
12  friendly, so for single-child containers like GtkNotebook we don't
13  have to do any work. */
14 
15 #include "ygtkfixed.h"
16 #include "YGi18n.h"
17 
18 static void doMoveChild (GtkWidget *fixed, YWidget *ychild, int x, int y)
19 {
20  GtkWidget *child = YGWidget::get (ychild)->getLayout();
21  ygtk_fixed_set_child_pos (YGTK_FIXED (fixed), child, x, y);
22 }
23 
24 #define YGLAYOUT_INIT \
25  ygtk_fixed_setup (YGTK_FIXED (getWidget()), preferred_width_cb, preferred_height_cb, set_size_cb, this);
26 #define YGLAYOUT_PREFERRED_SIZE_IMPL(ParentClass) \
27  static gint preferred_width_cb (YGtkFixed *fixed, gpointer pThis) { \
28  return ((ParentClass *) pThis)->ParentClass::preferredWidth(); \
29  } \
30  static gint preferred_height_cb (YGtkFixed *fixed, gpointer pThis) { \
31  return ((ParentClass *) pThis)->ParentClass::preferredHeight(); \
32  }
33 #define YGLAYOUT_SET_SIZE_IMPL(ParentClass) \
34  static void set_size_cb (YGtkFixed *fixed, gint width, gint height, \
35  gpointer pThis) { \
36  ((ParentClass *) pThis)->ParentClass::setSize (width, height); \
37  } \
38  virtual void moveChild (YWidget *ychild, int x, int y) \
39  { doMoveChild (getWidget(), ychild, x, y); } \
40 
41 #include <YPushButton.h>
42 
44 {
45 GtkSizeGroup *group;
46 
47 public:
48  ButtonHeightGroup() { group = NULL; }
49 
50  void addWidget (YWidget *ywidget)
51  {
52  if (dynamic_cast <YPushButton *> (ywidget)) {
53  bool create_group = !group;
54  if (create_group)
55  group = gtk_size_group_new (GTK_SIZE_GROUP_VERTICAL);
56  gtk_size_group_add_widget (group, YGWidget::get (ywidget)->getLayout());
57  if (create_group)
58  g_object_unref (G_OBJECT (group));
59  }
60  }
61 };
62 
63 #include <YLayoutBox.h>
64 
65 class YGLayoutBox : public YLayoutBox, public YGWidget
66 {
67 // set all buttons in a HBox the same height (some may have icons)
68 ButtonHeightGroup group;
69 
70 public:
71  YGLayoutBox (YWidget *parent, YUIDimension dim)
72  : YLayoutBox (NULL, dim),
73  YGWidget (this, parent, YGTK_TYPE_FIXED, NULL)
74  {
75  setBorder (0);
76  YGLAYOUT_INIT
77  }
78 
79  virtual void doAddChild (YWidget *ychild, GtkWidget *container)
80  {
81  YGWidget::doAddChild (ychild, container);
82  if (primary() == YD_HORIZ)
83  group.addWidget (ychild);
84  }
85 
86  YGWIDGET_IMPL_CONTAINER (YLayoutBox)
87  YGLAYOUT_PREFERRED_SIZE_IMPL (YLayoutBox)
88  YGLAYOUT_SET_SIZE_IMPL (YLayoutBox)
89 };
90 
91 YLayoutBox *YGWidgetFactory::createLayoutBox (YWidget *parent, YUIDimension dimension)
92 { return new YGLayoutBox (parent, dimension); }
93 
94 #include <YButtonBox.h>
95 
96 class YGButtonBox : public YButtonBox, public YGWidget
97 {
98 ButtonHeightGroup group;
99 
100 public:
101  YGButtonBox (YWidget *parent)
102  : YButtonBox (NULL),
103  YGWidget (this, parent, YGTK_TYPE_FIXED, NULL)
104  {
105  setBorder (0);
106  // YUI system variable test for layout policy doesn't work flawlessly
107  setLayoutPolicy (gnomeLayoutPolicy());
108  YGLAYOUT_INIT
109  }
110 
111  virtual void doAddChild (YWidget *ychild, GtkWidget *container)
112  {
113  YGWidget::doAddChild (ychild, container);
114  group.addWidget (ychild);
115  }
116 
117  YGWIDGET_IMPL_CONTAINER (YButtonBox)
118  YGLAYOUT_PREFERRED_SIZE_IMPL (YButtonBox)
119  YGLAYOUT_SET_SIZE_IMPL (YButtonBox)
120 };
121 
122 YButtonBox *YGWidgetFactory::createButtonBox (YWidget *parent)
123 { return new YGButtonBox (parent); }
124 
125 #include <YAlignment.h>
126 
127 class YGAlignment : public YAlignment, public YGWidget
128 {
129  GdkPixbuf *m_background_pixbuf;
130 
131 public:
132  YGAlignment (YWidget *parent, YAlignmentType halign, YAlignmentType valign)
133  : YAlignment (NULL, halign, valign),
134  YGWidget (this, parent, YGTK_TYPE_FIXED, NULL)
135  {
136  setBorder (0);
137  m_background_pixbuf = 0;
138  YGLAYOUT_INIT
139  }
140 
141  virtual ~YGAlignment()
142  {
143  if (m_background_pixbuf)
144  g_object_unref (G_OBJECT (m_background_pixbuf));
145  }
146 
147  YGWIDGET_IMPL_CONTAINER (YAlignment)
148  YGLAYOUT_PREFERRED_SIZE_IMPL (YAlignment)
149  YGLAYOUT_SET_SIZE_IMPL (YAlignment)
150 
151  virtual void setBackgroundPixmap (const std::string &_filename)
152  {
153  YAlignment::setBackgroundPixmap (_filename);
154  // YAlignment will prepend a path to the image
155  std::string filename (YAlignment::backgroundPixmap());
156  if (m_background_pixbuf)
157  g_object_unref (G_OBJECT (m_background_pixbuf));
158 
159  if (filename.empty()) {
160  m_background_pixbuf = 0;
161  g_signal_handlers_disconnect_by_func (G_OBJECT (getWidget()),
162  (void*) draw_event_cb, this);
163  }
164  else {
165  GError *error = 0;
166  m_background_pixbuf = gdk_pixbuf_new_from_file (filename.c_str(), &error);
167  if (!m_background_pixbuf)
168  g_warning ("Setting YAlignment background - couldn't load image '%s' - %s",
169  filename.c_str(), error->message);
170  else
171  g_signal_connect (G_OBJECT (getWidget()), "draw",
172  G_CALLBACK (YGAlignment::draw_event_cb), this);
173  }
174  }
175 
176  static gboolean draw_event_cb (GtkWidget *widget, cairo_t *cr, YGAlignment *pThis, int width, int height)
177  {
178  gdk_cairo_set_source_pixbuf (cr, pThis->m_background_pixbuf, 0, 0);
179  cairo_pattern_set_extend (cairo_get_source (cr), CAIRO_EXTEND_REPEAT);
180 
181  cairo_rectangle (cr, 0, 0, width, height);
182  cairo_fill (cr);
183 
184  gtk_container_propagate_draw (GTK_CONTAINER (widget),
185  gtk_bin_get_child(GTK_BIN (widget)), cr);
186 
187  return TRUE;
188  }
189 };
190 
191 YAlignment *YGWidgetFactory::createAlignment (YWidget *parent, YAlignmentType halign,
192  YAlignmentType valign)
193 { return new YGAlignment (parent, halign, valign); }
194 
195 #include <YEmpty.h>
196 
197 // Just an empty space.
198 class YGEmpty : public YEmpty, public YGWidget
199 {
200 public:
201  YGEmpty (YWidget *parent)
202  : YEmpty (NULL),
203  YGWidget (this, parent, GTK_TYPE_EVENT_BOX, NULL)
204  {
205  setBorder (0);
206  }
207 
208  YGWIDGET_IMPL_COMMON (YEmpty)
209 };
210 
211 YEmpty *YGWidgetFactory::createEmpty (YWidget *parent)
212 { return new YGEmpty (parent); }
213 
214 #include <YSpacing.h>
215 
216 // Empty space, with a fixed size.
217 class YGSpacing : public YSpacing, public YGWidget
218 {
219 public:
220  YGSpacing (YWidget *parent, YUIDimension dim, bool stretchable, YLayoutSize_t size)
221  : YSpacing (NULL, dim, stretchable, size),
222  YGWidget (this, parent, YGTK_TYPE_FIXED, NULL)
223  {
224  setBorder (0);
225  YGLAYOUT_INIT
226  }
227 
228  YGWIDGET_IMPL_COMMON (YSpacing)
229  YGLAYOUT_PREFERRED_SIZE_IMPL (YSpacing)
230  static void set_size_cb (YGtkFixed *fixed, gint width, gint height,
231  gpointer pThis) {}
232 };
233 
234 YSpacing *YGWidgetFactory::createSpacing (YWidget *parent, YUIDimension dim,
235  bool stretchable, YLayoutSize_t size)
236 {
237  return new YGSpacing (parent, dim, stretchable, size);
238 }
239 
240 #include <YReplacePoint.h>
241 
242 // an empty space that will get replaced
243 class YGReplacePoint : public YReplacePoint, public YGWidget
244 {
245 public:
246  YGReplacePoint (YWidget *parent)
247  : YReplacePoint (NULL),
248  YGWidget (this, parent, GTK_TYPE_EVENT_BOX, NULL)
249  {
250  setBorder (0);
251  }
252 
253  YGWIDGET_IMPL_CONTAINER (YReplacePoint)
254 };
255 
256 YReplacePoint *YGWidgetFactory::createReplacePoint (YWidget *parent)
257 { return new YGReplacePoint (parent); }
258 
259 #include <YSquash.h>
260 
261 // A-like YAlignment, YSquash messes around child settings.
262 // In this case, it can remove the stretchable attribute.
263 class YGSquash : public YSquash, public YGWidget
264 {
265 public:
266  YGSquash (YWidget *parent, bool hsquash, bool vsquash)
267  : YSquash (NULL, hsquash, vsquash),
268  YGWidget (this, parent, GTK_TYPE_EVENT_BOX, NULL)
269  {
270  setBorder (0);
271  }
272 
273  YGWIDGET_IMPL_CONTAINER (YSquash)
274 };
275 
276 YSquash *YGWidgetFactory::createSquash (YWidget *parent, bool hsquash, bool vsquash)
277 { return new YGSquash (parent, hsquash, vsquash); }
278