3 * Copyright (C) 2010 Openismus GmbH
6 * Tristan Van Berkom <tristanvb@openismus.com>
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.
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.
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.
24 #include "gtkorientable.h"
25 #include "gtkcelllayout.h"
26 #include "gtkcellareabox.h"
27 #include "gtkcellareaboxiter.h"
30 static void gtk_cell_area_box_finalize (GObject *object);
31 static void gtk_cell_area_box_dispose (GObject *object);
32 static void gtk_cell_area_box_set_property (GObject *object,
36 static void gtk_cell_area_box_get_property (GObject *object,
41 /* GtkCellAreaClass */
42 static void gtk_cell_area_box_add (GtkCellArea *area,
43 GtkCellRenderer *renderer);
44 static void gtk_cell_area_box_remove (GtkCellArea *area,
45 GtkCellRenderer *renderer);
46 static void gtk_cell_area_box_forall (GtkCellArea *area,
47 GtkCellCallback callback,
48 gpointer callback_data);
49 static gint gtk_cell_area_box_event (GtkCellArea *area,
52 const GdkRectangle *cell_area);
53 static void gtk_cell_area_box_render (GtkCellArea *area,
56 const GdkRectangle *cell_area);
58 static GtkCellAreaIter *gtk_cell_area_box_create_iter (GtkCellArea *area);
59 static GtkSizeRequestMode gtk_cell_area_box_get_request_mode (GtkCellArea *area);
60 static void gtk_cell_area_box_get_preferred_width (GtkCellArea *area,
61 GtkCellAreaIter *iter,
65 static void gtk_cell_area_box_get_preferred_height (GtkCellArea *area,
66 GtkCellAreaIter *iter,
69 gint *natural_height);
70 static void gtk_cell_area_box_get_preferred_height_for_width (GtkCellArea *area,
71 GtkCellAreaIter *iter,
75 gint *natural_height);
76 static void gtk_cell_area_box_get_preferred_width_for_height (GtkCellArea *area,
77 GtkCellAreaIter *iter,
83 /* GtkCellLayoutIface */
84 static void gtk_cell_area_box_cell_layout_init (GtkCellLayoutIface *iface);
85 static void gtk_cell_area_box_layout_pack_start (GtkCellLayout *cell_layout,
86 GtkCellRenderer *renderer,
88 static void gtk_cell_area_box_layout_pack_end (GtkCellLayout *cell_layout,
89 GtkCellRenderer *renderer,
91 static void gtk_cell_area_box_layout_reorder (GtkCellLayout *cell_layout,
92 GtkCellRenderer *renderer,
96 /* CellInfo metadata handling */
98 GtkCellRenderer *renderer;
104 static CellInfo *cell_info_new (GtkCellRenderer *renderer,
107 static void cell_info_free (CellInfo *info);
108 static gint cell_info_find (CellInfo *info,
109 GtkCellRenderer *renderer);
112 struct _GtkCellAreaBoxPrivate
114 GtkOrientation orientation;
124 G_DEFINE_TYPE_WITH_CODE (GtkCellAreaBox, gtk_cell_area_box, GTK_TYPE_CELL_AREA,
125 G_IMPLEMENT_INTERFACE (GTK_TYPE_CELL_LAYOUT,
126 gtk_cell_area_box_cell_layout_init)
127 G_IMPLEMENT_INTERFACE (GTK_TYPE_ORIENTABLE, NULL));
130 gtk_cell_area_box_init (GtkCellAreaBox *box)
132 GtkCellAreaBoxPrivate *priv;
134 box->priv = G_TYPE_INSTANCE_GET_PRIVATE (box,
135 GTK_TYPE_CELL_AREA_BOX,
136 GtkCellAreaBoxPrivate);
139 priv->orientation = GTK_ORIENTATION_HORIZONTAL;
144 gtk_cell_area_box_class_init (GtkCellAreaBoxClass *class)
146 GObjectClass *object_class = G_OBJECT_CLASS (class);
147 GtkCellAreaClass *area_class = GTK_CELL_AREA_CLASS (class);
150 object_class->finalize = gtk_cell_area_box_finalize;
151 object_class->dispose = gtk_cell_area_box_dispose;
152 object_class->set_property = gtk_cell_area_box_set_property;
153 object_class->get_property = gtk_cell_area_box_get_property;
155 /* GtkCellAreaClass */
156 area_class->add = gtk_cell_area_box_add;
157 area_class->remove = gtk_cell_area_box_remove;
158 area_class->forall = gtk_cell_area_box_forall;
159 area_class->event = gtk_cell_area_box_event;
160 area_class->render = gtk_cell_area_box_render;
162 area_class->create_iter = gtk_cell_area_box_create_iter;
163 area_class->get_request_mode = gtk_cell_area_box_get_request_mode;
164 area_class->get_preferred_width = gtk_cell_area_box_get_preferred_width;
165 area_class->get_preferred_height = gtk_cell_area_box_get_preferred_height;
166 area_class->get_preferred_height_for_width = gtk_cell_area_box_get_preferred_height_for_width;
167 area_class->get_preferred_width_for_height = gtk_cell_area_box_get_preferred_width_for_height;
169 g_object_class_override_property (object_class, PROP_ORIENTATION, "orientation");
172 g_type_class_add_private (object_class, sizeof (GtkCellAreaBoxPrivate));
176 /*************************************************************
178 *************************************************************/
180 cell_info_new (GtkCellRenderer *renderer,
184 CellInfo *info = g_slice_new (CellInfo);
186 info->renderer = g_object_ref_sink (renderer);
187 info->expand = expand;
194 cell_info_free (CellInfo *info)
196 g_object_unref (info->renderer);
198 g_slice_free (CellInfo, info);
202 cell_info_find (CellInfo *info,
203 GtkCellRenderer *renderer)
205 return (info->renderer == renderer) ? 0 : -1;
208 /*************************************************************
210 *************************************************************/
212 gtk_cell_area_box_finalize (GObject *object)
214 G_OBJECT_CLASS (gtk_cell_area_box_parent_class)->finalize (object);
218 gtk_cell_area_box_dispose (GObject *object)
220 G_OBJECT_CLASS (gtk_cell_area_box_parent_class)->dispose (object);
224 gtk_cell_area_box_set_property (GObject *object,
233 gtk_cell_area_box_get_property (GObject *object,
241 /*************************************************************
243 *************************************************************/
245 gtk_cell_area_box_add (GtkCellArea *area,
246 GtkCellRenderer *renderer)
248 gtk_cell_area_box_pack_start (GTK_CELL_AREA_BOX (area),
253 gtk_cell_area_box_remove (GtkCellArea *area,
254 GtkCellRenderer *renderer)
256 GtkCellAreaBox *box = GTK_CELL_AREA_BOX (area);
257 GtkCellAreaBoxPrivate *priv = box->priv;
260 node = g_list_find_custom (priv->cells, renderer,
261 (GCompareFunc)cell_info_find);
265 CellInfo *info = node->data;
267 cell_info_free (info);
269 priv->cells = g_list_delete_link (priv->cells, node);
272 g_warning ("Trying to remove a cell renderer that is not present GtkCellAreaBox");
276 gtk_cell_area_box_forall (GtkCellArea *area,
277 GtkCellCallback callback,
278 gpointer callback_data)
280 GtkCellAreaBox *box = GTK_CELL_AREA_BOX (area);
281 GtkCellAreaBoxPrivate *priv = box->priv;
284 for (list = priv->cells; list; list = list->next)
286 CellInfo *info = list->data;
288 callback (info->renderer, callback_data);
293 gtk_cell_area_box_event (GtkCellArea *area,
296 const GdkRectangle *cell_area)
304 gtk_cell_area_box_render (GtkCellArea *area,
307 const GdkRectangle *cell_area)
312 static GtkCellAreaIter *
313 gtk_cell_area_box_create_iter (GtkCellArea *area)
315 return (GtkCellAreaIter *)g_object_new (GTK_TYPE_CELL_AREA_BOX_ITER, NULL);
318 static GtkSizeRequestMode
319 gtk_cell_area_box_get_request_mode (GtkCellArea *area)
321 GtkCellAreaBox *box = GTK_CELL_AREA_BOX (area);
322 GtkCellAreaBoxPrivate *priv = box->priv;
324 return (priv->orientation) == GTK_ORIENTATION_HORIZONTAL ?
325 GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH :
326 GTK_SIZE_REQUEST_WIDTH_FOR_HEIGHT;
330 gtk_cell_area_box_get_preferred_width (GtkCellArea *area,
331 GtkCellAreaIter *iter,
336 g_return_if_fail (GTK_IS_CELL_AREA_BOX_ITER (iter));
340 gtk_cell_area_box_get_preferred_height (GtkCellArea *area,
341 GtkCellAreaIter *iter,
343 gint *minimum_height,
344 gint *natural_height)
346 g_return_if_fail (GTK_IS_CELL_AREA_BOX_ITER (iter));
352 gtk_cell_area_box_get_preferred_height_for_width (GtkCellArea *area,
353 GtkCellAreaIter *iter,
356 gint *minimum_height,
357 gint *natural_height)
359 g_return_if_fail (GTK_IS_CELL_AREA_BOX_ITER (iter));
364 gtk_cell_area_box_get_preferred_width_for_height (GtkCellArea *area,
365 GtkCellAreaIter *iter,
371 g_return_if_fail (GTK_IS_CELL_AREA_BOX_ITER (iter));
376 /*************************************************************
377 * GtkCellLayoutIface *
378 *************************************************************/
380 gtk_cell_area_box_cell_layout_init (GtkCellLayoutIface *iface)
382 iface->pack_start = gtk_cell_area_box_layout_pack_start;
383 iface->pack_end = gtk_cell_area_box_layout_pack_end;
384 iface->reorder = gtk_cell_area_box_layout_reorder;
388 gtk_cell_area_box_layout_pack_start (GtkCellLayout *cell_layout,
389 GtkCellRenderer *renderer,
392 gtk_cell_area_box_pack_start (GTK_CELL_AREA_BOX (cell_layout), renderer, expand);
396 gtk_cell_area_box_layout_pack_end (GtkCellLayout *cell_layout,
397 GtkCellRenderer *renderer,
400 gtk_cell_area_box_pack_end (GTK_CELL_AREA_BOX (cell_layout), renderer, expand);
404 gtk_cell_area_box_layout_reorder (GtkCellLayout *cell_layout,
405 GtkCellRenderer *renderer,
408 GtkCellAreaBox *box = GTK_CELL_AREA_BOX (cell_layout);
409 GtkCellAreaBoxPrivate *priv = box->priv;
413 node = g_list_find_custom (priv->cells, renderer,
414 (GCompareFunc)cell_info_find);
420 priv->cells = g_list_delete_link (priv->cells, node);
421 priv->cells = g_list_insert (priv->cells, info, position);
425 /*************************************************************
427 *************************************************************/
429 gtk_cell_area_box_new (void)
431 return (GtkCellArea *)g_object_new (GTK_TYPE_CELL_AREA_BOX, NULL);
435 gtk_cell_area_box_pack_start (GtkCellAreaBox *box,
436 GtkCellRenderer *renderer,
439 GtkCellAreaBoxPrivate *priv;
442 g_return_if_fail (GTK_IS_CELL_AREA_BOX (box));
443 g_return_if_fail (GTK_IS_CELL_RENDERER (renderer));
447 if (g_list_find_custom (priv->cells, renderer,
448 (GCompareFunc)cell_info_find))
450 g_warning ("Refusing to add the same cell renderer to a GtkCellAreaBox twice");
454 info = cell_info_new (renderer, expand, GTK_PACK_START);
456 priv->cells = g_list_append (priv->cells, info);
460 gtk_cell_area_box_pack_end (GtkCellAreaBox *box,
461 GtkCellRenderer *renderer,
464 GtkCellAreaBoxPrivate *priv;
467 g_return_if_fail (GTK_IS_CELL_AREA_BOX (box));
468 g_return_if_fail (GTK_IS_CELL_RENDERER (renderer));
472 if (g_list_find_custom (priv->cells, renderer,
473 (GCompareFunc)cell_info_find))
475 g_warning ("Refusing to add the same cell renderer to a GtkCellArea twice");
479 info = cell_info_new (renderer, expand, GTK_PACK_END);
481 priv->cells = g_list_append (priv->cells, info);