]> Pileus Git - ~andy/gtk/blob - gtk/gtkcellareabox.c
Added GtkCellAreaIter class
[~andy/gtk] / gtk / gtkcellareabox.c
1 /* gtkcellareabox.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 GtkCellAreaIter    *gtk_cell_area_box_create_iter          (GtkCellArea        *area);
58 static GtkSizeRequestMode  gtk_cell_area_box_get_request_mode     (GtkCellArea        *area);
59 static void      gtk_cell_area_box_get_preferred_width            (GtkCellArea        *area,
60                                                                    GtkCellAreaIter    *iter,
61                                                                    GtkWidget          *widget,
62                                                                    gint               *minimum_width,
63                                                                    gint               *natural_width);
64 static void      gtk_cell_area_box_get_preferred_height           (GtkCellArea        *area,
65                                                                    GtkCellAreaIter    *iter,
66                                                                    GtkWidget          *widget,
67                                                                    gint               *minimum_height,
68                                                                    gint               *natural_height);
69 static void      gtk_cell_area_box_get_preferred_height_for_width (GtkCellArea        *area,
70                                                                    GtkCellAreaIter    *iter,
71                                                                    GtkWidget          *widget,
72                                                                    gint                width,
73                                                                    gint               *minimum_height,
74                                                                    gint               *natural_height);
75 static void      gtk_cell_area_box_get_preferred_width_for_height (GtkCellArea        *area,
76                                                                    GtkCellAreaIter    *iter,
77                                                                    GtkWidget          *widget,
78                                                                    gint                height,
79                                                                    gint               *minimum_width,
80                                                                    gint               *natural_width);
81
82 /* GtkCellLayoutIface */
83 static void      gtk_cell_area_box_cell_layout_init               (GtkCellLayoutIface *iface);
84 static void      gtk_cell_area_box_layout_pack_start              (GtkCellLayout      *cell_layout,
85                                                                    GtkCellRenderer    *renderer,
86                                                                    gboolean            expand);
87 static void      gtk_cell_area_box_layout_pack_end                (GtkCellLayout      *cell_layout,
88                                                                    GtkCellRenderer    *renderer,
89                                                                    gboolean            expand);
90 static void      gtk_cell_area_box_layout_reorder                 (GtkCellLayout      *cell_layout,
91                                                                    GtkCellRenderer    *renderer,
92                                                                    gint                position);
93
94
95 /* CellInfo metadata handling */
96 typedef struct {
97   GtkCellRenderer *renderer;
98
99   guint            expand : 1;
100   guint            pack   : 1;
101 } CellInfo;
102
103 static CellInfo  *cell_info_new  (GtkCellRenderer *renderer, 
104                                   gboolean         expand,
105                                   GtkPackType      pack);
106 static void       cell_info_free (CellInfo        *info);
107 static gint       cell_info_find (CellInfo        *info,
108                                   GtkCellRenderer *renderer);
109
110
111 struct _GtkCellAreaBoxPrivate
112 {
113   GtkOrientation orientation;
114
115   GList *cells;
116 };
117
118 enum {
119   PROP_0,
120   PROP_ORIENTATION
121 };
122
123 G_DEFINE_TYPE_WITH_CODE (GtkCellAreaBox, gtk_cell_area_box, GTK_TYPE_CELL_AREA,
124                          G_IMPLEMENT_INTERFACE (GTK_TYPE_CELL_LAYOUT,
125                                                 gtk_cell_area_box_cell_layout_init)
126                          G_IMPLEMENT_INTERFACE (GTK_TYPE_ORIENTABLE, NULL));
127
128 static void
129 gtk_cell_area_box_init (GtkCellAreaBox *box)
130 {
131   GtkCellAreaBoxPrivate *priv;
132
133   box->priv = G_TYPE_INSTANCE_GET_PRIVATE (box,
134                                            GTK_TYPE_CELL_AREA_BOX,
135                                            GtkCellAreaBoxPrivate);
136   priv = box->priv;
137
138   priv->orientation = GTK_ORIENTATION_HORIZONTAL;
139   priv->cells       = NULL;
140 }
141
142 static void 
143 gtk_cell_area_box_class_init (GtkCellAreaBoxClass *class)
144 {
145   GObjectClass     *object_class = G_OBJECT_CLASS (class);
146   GtkCellAreaClass *area_class   = GTK_CELL_AREA_CLASS (class);
147
148   /* GObjectClass */
149   object_class->finalize     = gtk_cell_area_box_finalize;
150   object_class->dispose      = gtk_cell_area_box_dispose;
151   object_class->set_property = gtk_cell_area_box_set_property;
152   object_class->get_property = gtk_cell_area_box_get_property;
153
154   /* GtkCellAreaClass */
155   area_class->add                            = gtk_cell_area_box_add;
156   area_class->remove                         = gtk_cell_area_box_remove;
157   area_class->forall                         = gtk_cell_area_box_forall;
158   area_class->event                          = gtk_cell_area_box_event;
159   area_class->render                         = gtk_cell_area_box_render;
160   
161   area_class->create_iter                    = gtk_cell_area_box_create_iter;
162   area_class->get_request_mode               = gtk_cell_area_box_get_request_mode;
163   area_class->get_preferred_width            = gtk_cell_area_box_get_preferred_width;
164   area_class->get_preferred_height           = gtk_cell_area_box_get_preferred_height;
165   area_class->get_preferred_height_for_width = gtk_cell_area_box_get_preferred_height_for_width;
166   area_class->get_preferred_width_for_height = gtk_cell_area_box_get_preferred_width_for_height;
167
168   g_object_class_override_property (object_class, PROP_ORIENTATION, "orientation");
169
170
171   g_type_class_add_private (object_class, sizeof (GtkCellAreaBoxPrivate));
172 }
173
174
175 /*************************************************************
176  *                    CellInfo Basics                        *
177  *************************************************************/
178 static CellInfo *
179 cell_info_new  (GtkCellRenderer *renderer, 
180                 gboolean         expand,
181                 GtkPackType      pack)
182 {
183   CellInfo *info = g_slice_new (CellInfo);
184   
185   info->renderer = g_object_ref_sink (renderer);
186   info->expand   = expand;
187   info->pack     = pack;
188
189   return info;
190 }
191
192 static void
193 cell_info_free (CellInfo *info)
194 {
195   g_object_unref (info->renderer);
196
197   g_slice_free (CellInfo, info);
198 }
199
200 static gint
201 cell_info_find (CellInfo        *info,
202                 GtkCellRenderer *renderer)
203 {
204   return (info->renderer == renderer) ? 0 : -1;
205 }
206
207 /*************************************************************
208  *                      GObjectClass                         *
209  *************************************************************/
210 static void
211 gtk_cell_area_box_finalize (GObject *object)
212 {
213   G_OBJECT_CLASS (gtk_cell_area_box_parent_class)->finalize (object);
214 }
215
216 static void
217 gtk_cell_area_box_dispose (GObject *object)
218 {
219   G_OBJECT_CLASS (gtk_cell_area_box_parent_class)->dispose (object);
220 }
221
222 static void
223 gtk_cell_area_box_set_property (GObject       *object,
224                                 guint          prop_id,
225                                 const GValue  *value,
226                                 GParamSpec    *pspec)
227 {
228
229 }
230
231 static void
232 gtk_cell_area_box_get_property (GObject     *object,
233                                 guint        prop_id,
234                                 GValue      *value,
235                                 GParamSpec  *pspec)
236 {
237
238 }
239
240 /*************************************************************
241  *                    GtkCellAreaClass                       *
242  *************************************************************/
243 static void      
244 gtk_cell_area_box_add (GtkCellArea        *area,
245                        GtkCellRenderer    *renderer)
246 {
247   gtk_cell_area_box_pack_start (GTK_CELL_AREA_BOX (area),
248                                 renderer, FALSE);
249 }
250
251 static void
252 gtk_cell_area_box_remove (GtkCellArea        *area,
253                           GtkCellRenderer    *renderer)
254 {
255   GtkCellAreaBox        *box  = GTK_CELL_AREA_BOX (area);
256   GtkCellAreaBoxPrivate *priv = box->priv;
257   GList                 *node;
258
259   node = g_list_find_custom (priv->cells, renderer, 
260                              (GCompareFunc)cell_info_find);
261
262   if (node)
263     {
264       CellInfo *info = node->data;
265
266       cell_info_free (info);
267
268       priv->cells = g_list_delete_link (priv->cells, node);
269     }
270   else
271     g_warning ("Trying to remove a cell renderer that is not present GtkCellAreaBox");
272 }
273
274 static void
275 gtk_cell_area_box_forall (GtkCellArea        *area,
276                           GtkCellCallback     callback,
277                           gpointer            callback_data)
278 {
279   GtkCellAreaBox        *box  = GTK_CELL_AREA_BOX (area);
280   GtkCellAreaBoxPrivate *priv = box->priv;
281   GList                 *list;
282
283   for (list = priv->cells; list; list = list->next)
284     {
285       CellInfo *info = list->data;
286
287       callback (info->renderer, callback_data);
288     }
289 }
290
291 static gint
292 gtk_cell_area_box_event (GtkCellArea        *area,
293                          GtkWidget          *widget,
294                          GdkEvent           *event,
295                          const GdkRectangle *cell_area)
296 {
297
298
299   return 0;
300 }
301
302 static void
303 gtk_cell_area_box_render (GtkCellArea        *area,
304                           cairo_t            *cr,
305                           GtkWidget          *widget,
306                           const GdkRectangle *cell_area)
307 {
308
309 }
310
311 static GtkCellAreaIter *
312 gtk_cell_area_box_create_iter (GtkCellArea *area)
313 {
314   return NULL;
315 }
316
317 static GtkSizeRequestMode 
318 gtk_cell_area_box_get_request_mode (GtkCellArea *area)
319 {
320   GtkCellAreaBox        *box  = GTK_CELL_AREA_BOX (area);
321   GtkCellAreaBoxPrivate *priv = box->priv;
322
323   return (priv->orientation) == GTK_ORIENTATION_HORIZONTAL ?
324     GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH :
325     GTK_SIZE_REQUEST_WIDTH_FOR_HEIGHT;
326 }
327
328 static void
329 gtk_cell_area_box_get_preferred_width (GtkCellArea        *area,
330                                        GtkCellAreaIter    *iter,
331                                        GtkWidget          *widget,
332                                        gint               *minimum_width,
333                                        gint               *natural_width)
334 {
335
336 }
337
338 static void
339 gtk_cell_area_box_get_preferred_height (GtkCellArea        *area,
340                                         GtkCellAreaIter    *iter,
341                                         GtkWidget          *widget,
342                                         gint               *minimum_height,
343                                         gint               *natural_height)
344 {
345
346
347 }
348
349 static void
350 gtk_cell_area_box_get_preferred_height_for_width (GtkCellArea        *area,
351                                                   GtkCellAreaIter    *iter,
352                                                   GtkWidget          *widget,
353                                                   gint                width,
354                                                   gint               *minimum_height,
355                                                   gint               *natural_height)
356 {
357
358 }
359
360 static void
361 gtk_cell_area_box_get_preferred_width_for_height (GtkCellArea        *area,
362                                                   GtkCellAreaIter    *iter,
363                                                   GtkWidget          *widget,
364                                                   gint                height,
365                                                   gint               *minimum_width,
366                                                   gint               *natural_width)
367 {
368
369 }
370
371
372 /*************************************************************
373  *                    GtkCellLayoutIface                     *
374  *************************************************************/
375 static void
376 gtk_cell_area_box_cell_layout_init (GtkCellLayoutIface *iface)
377 {
378   iface->pack_start = gtk_cell_area_box_layout_pack_start;
379   iface->pack_end   = gtk_cell_area_box_layout_pack_end;
380   iface->reorder    = gtk_cell_area_box_layout_reorder;
381 }
382
383 static void
384 gtk_cell_area_box_layout_pack_start (GtkCellLayout      *cell_layout,
385                                      GtkCellRenderer    *renderer,
386                                      gboolean            expand)
387 {
388   gtk_cell_area_box_pack_start (GTK_CELL_AREA_BOX (cell_layout), renderer, expand);
389 }
390
391 static void
392 gtk_cell_area_box_layout_pack_end (GtkCellLayout      *cell_layout,
393                                    GtkCellRenderer    *renderer,
394                                    gboolean            expand)
395 {
396   gtk_cell_area_box_pack_end (GTK_CELL_AREA_BOX (cell_layout), renderer, expand);
397 }
398
399 static void
400 gtk_cell_area_box_layout_reorder (GtkCellLayout      *cell_layout,
401                                   GtkCellRenderer    *renderer,
402                                   gint                position)
403 {
404   GtkCellAreaBox        *box  = GTK_CELL_AREA_BOX (cell_layout);
405   GtkCellAreaBoxPrivate *priv = box->priv;
406   GList                 *node;
407   CellInfo              *info;
408   
409   node = g_list_find_custom (priv->cells, renderer, 
410                              (GCompareFunc)cell_info_find);
411
412   if (node)
413     {
414       info = node->data;
415
416       priv->cells = g_list_delete_link (priv->cells, node);
417       priv->cells = g_list_insert (priv->cells, info, position);
418     }
419 }
420
421 /*************************************************************
422  *                            API                            *
423  *************************************************************/
424 GtkCellArea *
425 gtk_cell_area_box_new (void)
426 {
427   return (GtkCellArea *)g_object_new (GTK_TYPE_CELL_AREA_BOX, NULL);
428 }
429
430 void
431 gtk_cell_area_box_pack_start  (GtkCellAreaBox  *box,
432                                GtkCellRenderer *renderer,
433                                gboolean         expand)
434 {
435   GtkCellAreaBoxPrivate *priv;
436   CellInfo              *info;
437
438   g_return_if_fail (GTK_IS_CELL_AREA_BOX (box));
439   g_return_if_fail (GTK_IS_CELL_RENDERER (renderer));
440
441   priv = box->priv;
442
443   if (g_list_find_custom (priv->cells, renderer, 
444                           (GCompareFunc)cell_info_find))
445     {
446       g_warning ("Refusing to add the same cell renderer to a GtkCellAreaBox twice");
447       return;
448     }
449
450   info = cell_info_new (renderer, expand, GTK_PACK_START);
451
452   priv->cells = g_list_append (priv->cells, info);
453 }
454
455 void
456 gtk_cell_area_box_pack_end (GtkCellAreaBox  *box,
457                             GtkCellRenderer *renderer,
458                             gboolean         expand)
459 {
460   GtkCellAreaBoxPrivate *priv;
461   CellInfo              *info;
462
463   g_return_if_fail (GTK_IS_CELL_AREA_BOX (box));
464   g_return_if_fail (GTK_IS_CELL_RENDERER (renderer));
465
466   priv = box->priv;
467
468   if (g_list_find_custom (priv->cells, renderer, 
469                           (GCompareFunc)cell_info_find))
470     {
471       g_warning ("Refusing to add the same cell renderer to a GtkCellArea twice");
472       return;
473     }
474
475   info = cell_info_new (renderer, expand, GTK_PACK_END);
476
477   priv->cells = g_list_append (priv->cells, info);
478 }