]> Pileus Git - ~andy/gtk/blob - gtk/gtkcellareabox.c
Implemented basic child list handling on GtkCellAreaBox
[~andy/gtk] / gtk / gtkcellareabox.c
1 /* gtkcellarea.c
2  *
3  * Copyright (C) 2010 Openismus GmbH
4  *
5  * Authors:
6  *      Tristan Van Berkom <tristanvb@openismus.com>
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public
19  * License along with this library; if not, write to the
20  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21  * Boston, MA 02111-1307, USA.
22  */
23
24 #include "gtkorientable.h"
25 #include "gtkcelllayout.h"
26 #include "gtkcellareabox.h"
27
28 /* GObjectClass */
29 static void      gtk_cell_area_box_finalize                       (GObject            *object);
30 static void      gtk_cell_area_box_dispose                        (GObject            *object);
31 static void      gtk_cell_area_box_set_property                   (GObject            *object,
32                                                                    guint               prop_id,
33                                                                    const GValue       *value,
34                                                                    GParamSpec         *pspec);
35 static void      gtk_cell_area_box_get_property                   (GObject            *object,
36                                                                    guint               prop_id,
37                                                                    GValue             *value,
38                                                                    GParamSpec         *pspec);
39
40 /* GtkCellAreaClass */
41 static void      gtk_cell_area_box_add                            (GtkCellArea        *area,
42                                                                    GtkCellRenderer    *renderer);
43 static void      gtk_cell_area_box_remove                         (GtkCellArea        *area,
44                                                                    GtkCellRenderer    *renderer);
45 static void      gtk_cell_area_box_forall                         (GtkCellArea        *area,
46                                                                    GtkCellCallback     callback,
47                                                                    gpointer            callback_data);
48 static gint      gtk_cell_area_box_event                          (GtkCellArea        *area,
49                                                                    GtkWidget          *widget,
50                                                                    GdkEvent           *event,
51                                                                    const GdkRectangle *cell_area);
52 static void      gtk_cell_area_box_render                         (GtkCellArea        *area,
53                                                                    cairo_t            *cr,
54                                                                    GtkWidget          *widget,
55                                                                    const GdkRectangle *cell_area);
56
57 static GtkSizeRequestMode gtk_cell_area_box_get_request_mode      (GtkCellArea        *area);
58 static void      gtk_cell_area_box_get_preferred_width            (GtkCellArea        *area,
59                                                                    GtkWidget          *widget,
60                                                                    gint               *minimum_width,
61                                                                    gint               *natural_width);
62 static void      gtk_cell_area_box_get_preferred_height           (GtkCellArea        *area,
63                                                                    GtkWidget          *widget,
64                                                                    gint               *minimum_height,
65                                                                    gint               *natural_height);
66 static void      gtk_cell_area_box_get_preferred_height_for_width (GtkCellArea        *area,
67                                                                    GtkWidget          *widget,
68                                                                    gint                width,
69                                                                    gint               *minimum_height,
70                                                                    gint               *natural_height);
71 static void      gtk_cell_area_box_get_preferred_width_for_height (GtkCellArea        *area,
72                                                                    GtkWidget          *widget,
73                                                                    gint                height,
74                                                                    gint               *minimum_width,
75                                                                    gint               *natural_width);
76
77 /* GtkCellLayoutIface */
78 static void      gtk_cell_area_box_cell_layout_init               (GtkCellLayoutIface *iface);
79 static void      gtk_cell_area_box_layout_pack_start              (GtkCellLayout      *cell_layout,
80                                                                    GtkCellRenderer    *renderer,
81                                                                    gboolean            expand);
82 static void      gtk_cell_area_box_layout_pack_end                (GtkCellLayout      *cell_layout,
83                                                                    GtkCellRenderer    *renderer,
84                                                                    gboolean            expand);
85
86
87 /* CellInfo metadata handling */
88 typedef struct {
89   GtkCellRenderer *renderer;
90
91   guint            expand : 1;
92   guint            pack   : 1;
93 } CellInfo;
94
95 static CellInfo  *cell_info_new  (GtkCellRenderer *renderer, 
96                                   gboolean         expand,
97                                   GtkPackType      pack);
98 static void       cell_info_free (CellInfo        *info);
99 static gint       cell_info_find (CellInfo        *info,
100                                   GtkCellRenderer *renderer);
101
102
103 struct _GtkCellAreaBoxPrivate
104 {
105   GtkOrientation orientation;
106
107   GList *cells;
108 };
109
110 enum {
111   PROP_0,
112   PROP_ORIENTATION
113 };
114
115 G_DEFINE_TYPE_WITH_CODE (GtkCellAreaBox, gtk_cell_area_box, GTK_TYPE_CELL_AREA,
116                          G_IMPLEMENT_INTERFACE (GTK_TYPE_CELL_LAYOUT,
117                                                 gtk_cell_area_box_cell_layout_init)
118                          G_IMPLEMENT_INTERFACE (GTK_TYPE_ORIENTABLE, NULL));
119
120 static void
121 gtk_cell_area_box_init (GtkCellAreaBox *box)
122 {
123   GtkCellAreaBoxPrivate *priv;
124
125   box->priv = G_TYPE_INSTANCE_GET_PRIVATE (box,
126                                            GTK_TYPE_CELL_AREA_BOX,
127                                            GtkCellAreaBoxPrivate);
128   priv = box->priv;
129
130   priv->orientation = GTK_ORIENTATION_HORIZONTAL;
131   priv->cells       = NULL;
132 }
133
134 static void 
135 gtk_cell_area_box_class_init (GtkCellAreaBoxClass *class)
136 {
137   GObjectClass     *object_class = G_OBJECT_CLASS (class);
138   GtkCellAreaClass *area_class   = GTK_CELL_AREA_CLASS (class);
139
140   /* GObjectClass */
141   object_class->finalize     = gtk_cell_area_box_finalize;
142   object_class->dispose      = gtk_cell_area_box_dispose;
143   object_class->set_property = gtk_cell_area_box_set_property;
144   object_class->get_property = gtk_cell_area_box_get_property;
145
146   /* GtkCellAreaClass */
147   area_class->add                            = gtk_cell_area_box_add;
148   area_class->remove                         = gtk_cell_area_box_remove;
149   area_class->forall                         = gtk_cell_area_box_forall;
150   area_class->event                          = gtk_cell_area_box_event;
151   area_class->render                         = gtk_cell_area_box_render;
152   
153   area_class->get_request_mode               = gtk_cell_area_box_get_request_mode;
154   area_class->get_preferred_width            = gtk_cell_area_box_get_preferred_width;
155   area_class->get_preferred_height           = gtk_cell_area_box_get_preferred_height;
156   area_class->get_preferred_height_for_width = gtk_cell_area_box_get_preferred_height_for_width;
157   area_class->get_preferred_width_for_height = gtk_cell_area_box_get_preferred_width_for_height;
158
159   g_object_class_override_property (object_class, PROP_ORIENTATION, "orientation");
160
161
162   g_type_class_add_private (object_class, sizeof (GtkCellAreaBoxPrivate));
163 }
164
165
166 /*************************************************************
167  *                    CellInfo Basics                        *
168  *************************************************************/
169 static CellInfo *
170 cell_info_new  (GtkCellRenderer *renderer, 
171                 gboolean         expand,
172                 GtkPackType      pack)
173 {
174   CellInfo *info = g_slice_new (CellInfo);
175   
176   info->renderer = g_object_ref_sink (renderer);
177   info->expand   = expand;
178   info->pack     = pack;
179
180   return info;
181 }
182
183 static void
184 cell_info_free (CellInfo *info)
185 {
186   g_object_unref (info->renderer);
187
188   g_slice_free (CellInfo, info);
189 }
190
191 static gint
192 cell_info_find (CellInfo        *info,
193                 GtkCellRenderer *renderer)
194 {
195   return (info->renderer == renderer) ? 0 : -1;
196 }
197
198 /*************************************************************
199  *                      GObjectClass                         *
200  *************************************************************/
201 static void
202 gtk_cell_area_box_finalize (GObject *object)
203 {
204   G_OBJECT_CLASS (gtk_cell_area_box_parent_class)->finalize (object);
205 }
206
207 static void
208 gtk_cell_area_box_dispose (GObject *object)
209 {
210   G_OBJECT_CLASS (gtk_cell_area_box_parent_class)->dispose (object);
211 }
212
213 static void
214 gtk_cell_area_box_set_property (GObject       *object,
215                                 guint          prop_id,
216                                 const GValue  *value,
217                                 GParamSpec    *pspec)
218 {
219
220 }
221
222 static void
223 gtk_cell_area_box_get_property (GObject     *object,
224                                 guint        prop_id,
225                                 GValue      *value,
226                                 GParamSpec  *pspec)
227 {
228
229 }
230
231 /*************************************************************
232  *                    GtkCellAreaClass                       *
233  *************************************************************/
234 static void      
235 gtk_cell_area_box_add (GtkCellArea        *area,
236                        GtkCellRenderer    *renderer)
237 {
238   gtk_cell_area_box_pack_start (GTK_CELL_AREA_BOX (area),
239                                 renderer, FALSE);
240 }
241
242 static void
243 gtk_cell_area_box_remove (GtkCellArea        *area,
244                           GtkCellRenderer    *renderer)
245 {
246   GtkCellAreaBox        *box  = GTK_CELL_AREA_BOX (area);
247   GtkCellAreaBoxPrivate *priv = box->priv;
248   GList                 *node;
249
250   node = g_list_find_custom (priv->cells, renderer, 
251                              (GCompareFunc)cell_info_find);
252
253   if (node)
254     {
255       CellInfo *info = node->data;
256
257       cell_info_free (info);
258
259       priv->cells = g_list_delete_link (priv->cells, node);
260     }
261   else
262     g_warning ("Trying to remove a cell renderer that is not present GtkCellAreaBox");
263 }
264
265 static void
266 gtk_cell_area_box_forall (GtkCellArea        *area,
267                           GtkCellCallback     callback,
268                           gpointer            callback_data)
269 {
270   GtkCellAreaBox        *box  = GTK_CELL_AREA_BOX (area);
271   GtkCellAreaBoxPrivate *priv = box->priv;
272   GList                 *list;
273
274   for (list = priv->cells; list; list = list->next)
275     {
276       CellInfo *info = list->data;
277
278       callback (info->renderer, callback_data);
279     }
280 }
281
282 static gint
283 gtk_cell_area_box_event (GtkCellArea        *area,
284                          GtkWidget          *widget,
285                          GdkEvent           *event,
286                          const GdkRectangle *cell_area)
287 {
288
289
290   return 0;
291 }
292
293 static void
294 gtk_cell_area_box_render (GtkCellArea        *area,
295                           cairo_t            *cr,
296                           GtkWidget          *widget,
297                           const GdkRectangle *cell_area)
298 {
299
300 }
301
302 static GtkSizeRequestMode 
303 gtk_cell_area_box_get_request_mode (GtkCellArea *area)
304 {
305   GtkCellAreaBox        *box  = GTK_CELL_AREA_BOX (area);
306   GtkCellAreaBoxPrivate *priv = box->priv;
307
308   return (priv->orientation) == GTK_ORIENTATION_HORIZONTAL ?
309     GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH :
310     GTK_SIZE_REQUEST_WIDTH_FOR_HEIGHT;
311 }
312
313 static void
314 gtk_cell_area_box_get_preferred_width (GtkCellArea        *area,
315                                        GtkWidget          *widget,
316                                        gint               *minimum_width,
317                                        gint               *natural_width)
318 {
319
320 }
321
322 static void
323 gtk_cell_area_box_get_preferred_height (GtkCellArea        *area,
324                                         GtkWidget          *widget,
325                                         gint               *minimum_height,
326                                         gint               *natural_height)
327 {
328
329
330 }
331
332 static void
333 gtk_cell_area_box_get_preferred_height_for_width (GtkCellArea        *area,
334                                                   GtkWidget          *widget,
335                                                   gint                width,
336                                                   gint               *minimum_height,
337                                                   gint               *natural_height)
338 {
339
340 }
341
342 static void
343 gtk_cell_area_box_get_preferred_width_for_height (GtkCellArea        *area,
344                                                   GtkWidget          *widget,
345                                                   gint                height,
346                                                   gint               *minimum_width,
347                                                   gint               *natural_width)
348 {
349
350 }
351
352
353
354 /*************************************************************
355  *                    GtkCellLayoutIface                     *
356  *************************************************************/
357 static void
358 gtk_cell_area_box_cell_layout_init (GtkCellLayoutIface *iface)
359 {
360   iface->pack_start = gtk_cell_area_box_layout_pack_start;
361   iface->pack_end   = gtk_cell_area_box_layout_pack_end;
362 }
363
364 static void
365 gtk_cell_area_box_layout_pack_start (GtkCellLayout      *cell_layout,
366                                      GtkCellRenderer    *renderer,
367                                      gboolean            expand)
368 {
369   gtk_cell_area_box_pack_start (GTK_CELL_AREA_BOX (cell_layout), renderer, expand);
370 }
371
372 static void
373 gtk_cell_area_box_layout_pack_end (GtkCellLayout      *cell_layout,
374                                    GtkCellRenderer    *renderer,
375                                    gboolean            expand)
376 {
377   gtk_cell_area_box_pack_end (GTK_CELL_AREA_BOX (cell_layout), renderer, expand);
378 }
379
380 /*************************************************************
381  *                            API                            *
382  *************************************************************/
383 GtkCellArea *
384 gtk_cell_area_box_new (void)
385 {
386   return (GtkCellArea *)g_object_new (GTK_TYPE_CELL_AREA_BOX, NULL);
387 }
388
389 void
390 gtk_cell_area_box_pack_start  (GtkCellAreaBox  *box,
391                                GtkCellRenderer *renderer,
392                                gboolean         expand)
393 {
394   GtkCellAreaBoxPrivate *priv;
395   CellInfo              *info;
396
397   g_return_if_fail (GTK_IS_CELL_AREA_BOX (box));
398   g_return_if_fail (GTK_IS_CELL_RENDERER (renderer));
399
400   priv = box->priv;
401
402   if (g_list_find_custom (priv->cells, renderer, 
403                           (GCompareFunc)cell_info_find))
404     {
405       g_warning ("Refusing to add the same cell renderer to a GtkCellAreaBox twice");
406       return;
407     }
408
409   info = cell_info_new (renderer, expand, GTK_PACK_START);
410
411   priv->cells = g_list_append (priv->cells, info);
412 }
413
414 void
415 gtk_cell_area_box_pack_end (GtkCellAreaBox  *box,
416                             GtkCellRenderer *renderer,
417                             gboolean         expand)
418 {
419   GtkCellAreaBoxPrivate *priv;
420   CellInfo              *info;
421
422   g_return_if_fail (GTK_IS_CELL_AREA_BOX (box));
423   g_return_if_fail (GTK_IS_CELL_RENDERER (renderer));
424
425   priv = box->priv;
426
427   if (g_list_find_custom (priv->cells, renderer, 
428                           (GCompareFunc)cell_info_find))
429     {
430       g_warning ("Refusing to add the same cell renderer to a GtkCellArea twice");
431       return;
432     }
433
434   info = cell_info_new (renderer, expand, GTK_PACK_END);
435
436   priv->cells = g_list_append (priv->cells, info);
437 }