1 /* gtkcellareacontext.c
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, see <http://www.gnu.org/licenses/>.
23 * SECTION:gtkcellareacontext
24 * @Short_Description: Stores geometrical information for a series of rows in a GtkCellArea
25 * @Title: GtkCellAreaContext
27 * The #GtkCellAreaContext object is created by a given #GtkCellArea
28 * implementation via its #GtkCellAreaClass.create_context() virtual
29 * method and is used to store cell sizes and alignments for a series of
30 * #GtkTreeModel rows that are requested and rendered in the same context.
32 * #GtkCellLayout widgets can create any number of contexts in which to
33 * request and render groups of data rows. However its important that the
34 * same context which was used to request sizes for a given #GtkTreeModel
35 * row also be used for the same row when calling other #GtkCellArea APIs
36 * such as gtk_cell_area_render() and gtk_cell_area_event().
41 #include "gtkmarshalers.h"
42 #include "gtkcellareacontext.h"
43 #include "gtkprivate.h"
46 static void gtk_cell_area_context_dispose (GObject *object);
47 static void gtk_cell_area_context_get_property (GObject *object,
51 static void gtk_cell_area_context_set_property (GObject *object,
56 /* GtkCellAreaContextClass */
57 static void gtk_cell_area_context_real_reset (GtkCellAreaContext *context);
58 static void gtk_cell_area_context_real_allocate (GtkCellAreaContext *context,
62 struct _GtkCellAreaContextPrivate
64 GtkCellArea *cell_area;
83 G_DEFINE_TYPE (GtkCellAreaContext, gtk_cell_area_context, G_TYPE_OBJECT);
86 gtk_cell_area_context_init (GtkCellAreaContext *context)
88 context->priv = G_TYPE_INSTANCE_GET_PRIVATE (context,
89 GTK_TYPE_CELL_AREA_CONTEXT,
90 GtkCellAreaContextPrivate);
94 gtk_cell_area_context_class_init (GtkCellAreaContextClass *class)
96 GObjectClass *object_class = G_OBJECT_CLASS (class);
99 object_class->dispose = gtk_cell_area_context_dispose;
100 object_class->get_property = gtk_cell_area_context_get_property;
101 object_class->set_property = gtk_cell_area_context_set_property;
103 /* GtkCellAreaContextClass */
104 class->reset = gtk_cell_area_context_real_reset;
105 class->allocate = gtk_cell_area_context_real_allocate;
108 * GtkCellAreaContext:area:
110 * The #GtkCellArea this context was created by
114 g_object_class_install_property (object_class,
116 g_param_spec_object ("area",
118 P_("The Cell Area this context was created for"),
120 GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
123 * GtkCellAreaContext:minimum-width:
125 * The minimum width for the #GtkCellArea in this context
126 * for all #GtkTreeModel rows that this context was requested
127 * for using gtk_cell_area_get_preferred_width().
131 g_object_class_install_property (object_class,
133 g_param_spec_int ("minimum-width",
135 P_("Minimum cached width"),
142 * GtkCellAreaContext:natural-width:
144 * The natural width for the #GtkCellArea in this context
145 * for all #GtkTreeModel rows that this context was requested
146 * for using gtk_cell_area_get_preferred_width().
150 g_object_class_install_property (object_class,
152 g_param_spec_int ("natural-width",
154 P_("Minimum cached width"),
161 * GtkCellAreaContext:minimum-height:
163 * The minimum height for the #GtkCellArea in this context
164 * for all #GtkTreeModel rows that this context was requested
165 * for using gtk_cell_area_get_preferred_height().
169 g_object_class_install_property (object_class,
171 g_param_spec_int ("minimum-height",
172 P_("Minimum Height"),
173 P_("Minimum cached height"),
180 * GtkCellAreaContext:natural-height:
182 * The natural height for the #GtkCellArea in this context
183 * for all #GtkTreeModel rows that this context was requested
184 * for using gtk_cell_area_get_preferred_height().
188 g_object_class_install_property (object_class,
190 g_param_spec_int ("natural-height",
191 P_("Minimum Height"),
192 P_("Minimum cached height"),
198 g_type_class_add_private (object_class, sizeof (GtkCellAreaContextPrivate));
201 /*************************************************************
203 *************************************************************/
205 gtk_cell_area_context_dispose (GObject *object)
207 GtkCellAreaContext *context = GTK_CELL_AREA_CONTEXT (object);
208 GtkCellAreaContextPrivate *priv = context->priv;
212 g_object_unref (priv->cell_area);
214 priv->cell_area = NULL;
217 G_OBJECT_CLASS (gtk_cell_area_context_parent_class)->dispose (object);
221 gtk_cell_area_context_set_property (GObject *object,
226 GtkCellAreaContext *context = GTK_CELL_AREA_CONTEXT (object);
227 GtkCellAreaContextPrivate *priv = context->priv;
232 priv->cell_area = g_value_dup_object (value);
235 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
241 gtk_cell_area_context_get_property (GObject *object,
246 GtkCellAreaContext *context = GTK_CELL_AREA_CONTEXT (object);
247 GtkCellAreaContextPrivate *priv = context->priv;
252 g_value_set_object (value, priv->cell_area);
255 g_value_set_int (value, priv->min_width);
258 g_value_set_int (value, priv->nat_width);
260 case PROP_MIN_HEIGHT:
261 g_value_set_int (value, priv->min_height);
263 case PROP_NAT_HEIGHT:
264 g_value_set_int (value, priv->nat_height);
267 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
272 /*************************************************************
273 * GtkCellAreaContextClass *
274 *************************************************************/
276 gtk_cell_area_context_real_reset (GtkCellAreaContext *context)
278 GtkCellAreaContextPrivate *priv = context->priv;
280 g_object_freeze_notify (G_OBJECT (context));
282 if (priv->min_width != 0)
285 g_object_notify (G_OBJECT (context), "minimum-width");
288 if (priv->nat_width != 0)
291 g_object_notify (G_OBJECT (context), "natural-width");
294 if (priv->min_height != 0)
296 priv->min_height = 0;
297 g_object_notify (G_OBJECT (context), "minimum-height");
300 if (priv->nat_height != 0)
302 priv->nat_height = 0;
303 g_object_notify (G_OBJECT (context), "natural-height");
306 priv->alloc_width = 0;
307 priv->alloc_height = 0;
309 g_object_thaw_notify (G_OBJECT (context));
313 gtk_cell_area_context_real_allocate (GtkCellAreaContext *context,
317 GtkCellAreaContextPrivate *priv = context->priv;
319 priv->alloc_width = width;
320 priv->alloc_height = height;
323 /*************************************************************
325 *************************************************************/
327 * gtk_cell_area_context_get_area:
328 * @context: a #GtkCellAreaContext
330 * Fetches the #GtkCellArea this @context was created by.
332 * This is generally unneeded by layouting widgets; however
333 * it is important for the context implementation itself to
334 * fetch information about the area it is being used for.
336 * For instance at #GtkCellAreaContextClass.allocate() time
337 * its important to know details about any cell spacing
338 * that the #GtkCellArea is configured with in order to
339 * compute a proper allocation.
341 * Return value: (transfer none): the #GtkCellArea this context was created by.
346 gtk_cell_area_context_get_area (GtkCellAreaContext *context)
348 GtkCellAreaContextPrivate *priv;
350 g_return_val_if_fail (GTK_IS_CELL_AREA_CONTEXT (context), NULL);
352 priv = context->priv;
354 return priv->cell_area;
358 * gtk_cell_area_context_reset:
359 * @context: a #GtkCellAreaContext
361 * Resets any previously cached request and allocation
364 * When underlying #GtkTreeModel data changes its
365 * important to reset the context if the content
366 * size is allowed to shrink. If the content size
367 * is only allowed to grow (this is usually an option
368 * for views rendering large data stores as a measure
369 * of optimization), then only the row that changed
370 * or was inserted needs to be (re)requested with
371 * gtk_cell_area_get_preferred_width().
373 * When the new overall size of the context requires
374 * that the allocated size changes (or whenever this
375 * allocation changes at all), the variable row
376 * sizes need to be re-requested for every row.
378 * For instance, if the rows are displayed all with
379 * the same width from top to bottom then a change
380 * in the allocated width necessitates a recalculation
381 * of all the displayed row heights using
382 * gtk_cell_area_get_preferred_height_for_width().
387 gtk_cell_area_context_reset (GtkCellAreaContext *context)
389 g_return_if_fail (GTK_IS_CELL_AREA_CONTEXT (context));
391 GTK_CELL_AREA_CONTEXT_GET_CLASS (context)->reset (context);
395 * gtk_cell_area_context_allocate:
396 * @context: a #GtkCellAreaContext
397 * @width: the allocated width for all #GtkTreeModel rows rendered
398 * with @context, or -1.
399 * @height: the allocated height for all #GtkTreeModel rows rendered
400 * with @context, or -1.
402 * Allocates a width and/or a height for all rows which are to be
403 * rendered with @context.
405 * Usually allocation is performed only horizontally or sometimes
406 * vertically since a group of rows are usually rendered side by
407 * side vertically or horizontally and share either the same width
408 * or the same height. Sometimes they are allocated in both horizontal
409 * and vertical orientations producing a homogeneous effect of the
410 * rows. This is generally the case for #GtkTreeView when
411 * #GtkTreeView:fixed-height-mode is enabled.
416 gtk_cell_area_context_allocate (GtkCellAreaContext *context,
420 g_return_if_fail (GTK_IS_CELL_AREA_CONTEXT (context));
422 GTK_CELL_AREA_CONTEXT_GET_CLASS (context)->allocate (context, width, height);
426 * gtk_cell_area_context_get_preferred_width:
427 * @context: a #GtkCellAreaContext
428 * @minimum_width: (out) (allow-none): location to store the minimum width,
430 * @natural_width: (out) (allow-none): location to store the natural width,
433 * Gets the accumulative preferred width for all rows which have been
434 * requested with this context.
436 * After gtk_cell_area_context_reset() is called and/or before ever
437 * requesting the size of a #GtkCellArea, the returned values are 0.
442 gtk_cell_area_context_get_preferred_width (GtkCellAreaContext *context,
446 GtkCellAreaContextPrivate *priv;
448 g_return_if_fail (GTK_IS_CELL_AREA_CONTEXT (context));
450 priv = context->priv;
453 *minimum_width = priv->min_width;
456 *natural_width = priv->nat_width;
460 * gtk_cell_area_context_get_preferred_height:
461 * @context: a #GtkCellAreaContext
462 * @minimum_height: (out) (allow-none): location to store the minimum height,
464 * @natural_height: (out) (allow-none): location to store the natural height,
467 * Gets the accumulative preferred height for all rows which have been
468 * requested with this context.
470 * After gtk_cell_area_context_reset() is called and/or before ever
471 * requesting the size of a #GtkCellArea, the returned values are 0.
476 gtk_cell_area_context_get_preferred_height (GtkCellAreaContext *context,
477 gint *minimum_height,
478 gint *natural_height)
480 GtkCellAreaContextPrivate *priv;
482 g_return_if_fail (GTK_IS_CELL_AREA_CONTEXT (context));
484 priv = context->priv;
487 *minimum_height = priv->min_height;
490 *natural_height = priv->nat_height;
494 * gtk_cell_area_context_get_preferred_height_for_width:
495 * @context: a #GtkCellAreaContext
496 * @width: a proposed width for allocation
497 * @minimum_height: (out) (allow-none): location to store the minimum height,
499 * @natural_height: (out) (allow-none): location to store the natural height,
502 * Gets the accumulative preferred height for @width for all rows
503 * which have been requested for the same said @width with this context.
505 * After gtk_cell_area_context_reset() is called and/or before ever
506 * requesting the size of a #GtkCellArea, the returned values are -1.
511 gtk_cell_area_context_get_preferred_height_for_width (GtkCellAreaContext *context,
513 gint *minimum_height,
514 gint *natural_height)
516 g_return_if_fail (GTK_IS_CELL_AREA_CONTEXT (context));
518 if (GTK_CELL_AREA_CONTEXT_GET_CLASS (context)->get_preferred_height_for_width)
519 GTK_CELL_AREA_CONTEXT_GET_CLASS (context)->get_preferred_height_for_width (context,
526 * gtk_cell_area_context_get_preferred_width_for_height:
527 * @context: a #GtkCellAreaContext
528 * @height: a proposed height for allocation
529 * @minimum_width: (out) (allow-none): location to store the minimum width,
531 * @natural_width: (out) (allow-none): location to store the natural width,
534 * Gets the accumulative preferred width for @height for all rows which
535 * have been requested for the same said @height with this context.
537 * After gtk_cell_area_context_reset() is called and/or before ever
538 * requesting the size of a #GtkCellArea, the returned values are -1.
543 gtk_cell_area_context_get_preferred_width_for_height (GtkCellAreaContext *context,
548 g_return_if_fail (GTK_IS_CELL_AREA_CONTEXT (context));
550 if (GTK_CELL_AREA_CONTEXT_GET_CLASS (context)->get_preferred_width_for_height)
551 GTK_CELL_AREA_CONTEXT_GET_CLASS (context)->get_preferred_width_for_height (context,
558 * gtk_cell_area_context_get_allocation:
559 * @context: a #GtkCellAreaContext
560 * @width: (out) (allow-none): location to store the allocated width, or %NULL
561 * @height: (out) (allow-none): location to store the allocated height, or %NULL
563 * Fetches the current allocation size for @context.
565 * If the context was not allocated in width or height, or if the
566 * context was recently reset with gtk_cell_area_context_reset(),
567 * the returned value will be -1.
572 gtk_cell_area_context_get_allocation (GtkCellAreaContext *context,
576 GtkCellAreaContextPrivate *priv;
578 g_return_if_fail (GTK_IS_CELL_AREA_CONTEXT (context));
580 priv = context->priv;
583 *width = priv->alloc_width;
586 *height = priv->alloc_height;
590 * gtk_cell_area_context_push_preferred_width:
591 * @context: a #GtkCellAreaContext
592 * @minimum_width: the proposed new minimum width for @context
593 * @natural_width: the proposed new natural width for @context
595 * Causes the minimum and/or natural width to grow if the new
596 * proposed sizes exceed the current minimum and natural width.
598 * This is used by #GtkCellAreaContext implementations during
599 * the request process over a series of #GtkTreeModel rows to
600 * progressively push the requested width over a series of
601 * gtk_cell_area_get_preferred_width() requests.
606 gtk_cell_area_context_push_preferred_width (GtkCellAreaContext *context,
610 GtkCellAreaContextPrivate *priv;
612 g_return_if_fail (GTK_IS_CELL_AREA_CONTEXT (context));
614 priv = context->priv;
616 g_object_freeze_notify (G_OBJECT (context));
618 if (minimum_width > priv->min_width)
620 priv->min_width = minimum_width;
622 g_object_notify (G_OBJECT (context), "minimum-width");
625 if (natural_width > priv->nat_width)
627 priv->nat_width = natural_width;
629 g_object_notify (G_OBJECT (context), "natural-width");
632 g_object_thaw_notify (G_OBJECT (context));
636 * gtk_cell_area_context_push_preferred_height:
637 * @context: a #GtkCellAreaContext
638 * @minimum_height: the proposed new minimum height for @context
639 * @natural_height: the proposed new natural height for @context
641 * Causes the minimum and/or natural height to grow if the new
642 * proposed sizes exceed the current minimum and natural height.
644 * This is used by #GtkCellAreaContext implementations during
645 * the request process over a series of #GtkTreeModel rows to
646 * progressively push the requested height over a series of
647 * gtk_cell_area_get_preferred_height() requests.
652 gtk_cell_area_context_push_preferred_height (GtkCellAreaContext *context,
656 GtkCellAreaContextPrivate *priv;
658 g_return_if_fail (GTK_IS_CELL_AREA_CONTEXT (context));
660 priv = context->priv;
662 g_object_freeze_notify (G_OBJECT (context));
664 if (minimum_height > priv->min_height)
666 priv->min_height = minimum_height;
668 g_object_notify (G_OBJECT (context), "minimum-height");
671 if (natural_height > priv->nat_height)
673 priv->nat_height = natural_height;
675 g_object_notify (G_OBJECT (context), "natural-height");
678 g_object_thaw_notify (G_OBJECT (context));