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, write to the
20 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 * Boston, MA 02111-1307, USA.
25 * SECTION:gtkcellareacontext
26 * @Short_Description: Stores geometrical information for a series of rows in a GtkCellArea
27 * @Title: GtkCellAreaContext
29 * The #GtkCellAreaContext object is created by a given #GtkCellArea
30 * implementation via its #GtkCellAreaClass.create_context() virtual
31 * method and is used to store cell sizes and alignments for a series of
32 * #GtkTreeModel rows that are requested and rendered in the same context.
34 * #GtkCellLayout widgets can create any number of contexts in which to
35 * request and render groups of data rows. However its important that the
36 * same context which was used to request sizes for a given #GtkTreeModel
37 * row also be used for the same row when calling other #GtkCellArea APIs
38 * such as gtk_cell_area_render() and gtk_cell_area_event().
43 #include "gtkmarshalers.h"
44 #include "gtkcellareacontext.h"
45 #include "gtkprivate.h"
48 static void gtk_cell_area_context_dispose (GObject *object);
49 static void gtk_cell_area_context_get_property (GObject *object,
53 static void gtk_cell_area_context_set_property (GObject *object,
58 /* GtkCellAreaContextClass */
59 static void gtk_cell_area_context_real_reset (GtkCellAreaContext *context);
60 static void gtk_cell_area_context_real_allocate (GtkCellAreaContext *context,
64 struct _GtkCellAreaContextPrivate
66 GtkCellArea *cell_area;
85 G_DEFINE_TYPE (GtkCellAreaContext, gtk_cell_area_context, G_TYPE_OBJECT);
88 gtk_cell_area_context_init (GtkCellAreaContext *context)
90 context->priv = G_TYPE_INSTANCE_GET_PRIVATE (context,
91 GTK_TYPE_CELL_AREA_CONTEXT,
92 GtkCellAreaContextPrivate);
96 gtk_cell_area_context_class_init (GtkCellAreaContextClass *class)
98 GObjectClass *object_class = G_OBJECT_CLASS (class);
101 object_class->dispose = gtk_cell_area_context_dispose;
102 object_class->get_property = gtk_cell_area_context_get_property;
103 object_class->set_property = gtk_cell_area_context_set_property;
105 /* GtkCellAreaContextClass */
106 class->reset = gtk_cell_area_context_real_reset;
107 class->allocate = gtk_cell_area_context_real_allocate;
110 * GtkCellAreaContext:area:
112 * The #GtkCellArea this context was created by
116 g_object_class_install_property (object_class,
118 g_param_spec_object ("area",
120 P_("The Cell Area this context was created for"),
122 GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
125 * GtkCellAreaContext:minimum-width:
127 * The minimum width for the #GtkCellArea in this context
128 * for all #GtkTreeModel rows that this context was requested
129 * for using gtk_cell_area_get_preferred_width().
133 g_object_class_install_property (object_class,
135 g_param_spec_int ("minimum-width",
137 P_("Minimum cached width"),
144 * GtkCellAreaContext:natural-width:
146 * The natural width for the #GtkCellArea in this context
147 * for all #GtkTreeModel rows that this context was requested
148 * for using gtk_cell_area_get_preferred_width().
152 g_object_class_install_property (object_class,
154 g_param_spec_int ("natural-width",
156 P_("Minimum cached width"),
163 * GtkCellAreaContext:minimum-height:
165 * The minimum height for the #GtkCellArea in this context
166 * for all #GtkTreeModel rows that this context was requested
167 * for using gtk_cell_area_get_preferred_height().
171 g_object_class_install_property (object_class,
173 g_param_spec_int ("minimum-height",
174 P_("Minimum Height"),
175 P_("Minimum cached height"),
182 * GtkCellAreaContext:natural-height:
184 * The natural height for the #GtkCellArea in this context
185 * for all #GtkTreeModel rows that this context was requested
186 * for using gtk_cell_area_get_preferred_height().
190 g_object_class_install_property (object_class,
192 g_param_spec_int ("natural-height",
193 P_("Minimum Height"),
194 P_("Minimum cached height"),
200 g_type_class_add_private (object_class, sizeof (GtkCellAreaContextPrivate));
203 /*************************************************************
205 *************************************************************/
207 gtk_cell_area_context_dispose (GObject *object)
209 GtkCellAreaContext *context = GTK_CELL_AREA_CONTEXT (object);
210 GtkCellAreaContextPrivate *priv = context->priv;
214 g_object_unref (priv->cell_area);
216 priv->cell_area = NULL;
219 G_OBJECT_CLASS (gtk_cell_area_context_parent_class)->dispose (object);
223 gtk_cell_area_context_set_property (GObject *object,
228 GtkCellAreaContext *context = GTK_CELL_AREA_CONTEXT (object);
229 GtkCellAreaContextPrivate *priv = context->priv;
234 priv->cell_area = g_value_dup_object (value);
237 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
243 gtk_cell_area_context_get_property (GObject *object,
248 GtkCellAreaContext *context = GTK_CELL_AREA_CONTEXT (object);
249 GtkCellAreaContextPrivate *priv = context->priv;
254 g_value_set_object (value, priv->cell_area);
257 g_value_set_int (value, priv->min_width);
260 g_value_set_int (value, priv->nat_width);
262 case PROP_MIN_HEIGHT:
263 g_value_set_int (value, priv->min_height);
265 case PROP_NAT_HEIGHT:
266 g_value_set_int (value, priv->nat_height);
269 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
274 /*************************************************************
275 * GtkCellAreaContextClass *
276 *************************************************************/
278 gtk_cell_area_context_real_reset (GtkCellAreaContext *context)
280 GtkCellAreaContextPrivate *priv = context->priv;
282 g_object_freeze_notify (G_OBJECT (context));
284 if (priv->min_width != 0)
287 g_object_notify (G_OBJECT (context), "minimum-width");
290 if (priv->nat_width != 0)
293 g_object_notify (G_OBJECT (context), "natural-width");
296 if (priv->min_height != 0)
298 priv->min_height = 0;
299 g_object_notify (G_OBJECT (context), "minimum-height");
302 if (priv->nat_height != 0)
304 priv->nat_height = 0;
305 g_object_notify (G_OBJECT (context), "natural-height");
308 priv->alloc_width = 0;
309 priv->alloc_height = 0;
311 g_object_thaw_notify (G_OBJECT (context));
315 gtk_cell_area_context_real_allocate (GtkCellAreaContext *context,
319 GtkCellAreaContextPrivate *priv = context->priv;
321 priv->alloc_width = width;
322 priv->alloc_height = height;
325 /*************************************************************
327 *************************************************************/
329 * gtk_cell_area_context_get_area:
330 * @context: a #GtkCellAreaContext
332 * Fetches the #GtkCellArea this @context was created by.
334 * This is generally unneeded by layouting widgets; however
335 * it is important for the context implementation itself to
336 * fetch information about the area it is being used for.
338 * For instance at #GtkCellAreaContextClass.allocate() time
339 * its important to know details about any cell spacing
340 * that the #GtkCellArea is configured with in order to
341 * compute a proper allocation.
343 * Return value: (transfer none): the #GtkCellArea this context was created by.
348 gtk_cell_area_context_get_area (GtkCellAreaContext *context)
350 GtkCellAreaContextPrivate *priv;
352 g_return_val_if_fail (GTK_IS_CELL_AREA_CONTEXT (context), NULL);
354 priv = context->priv;
356 return priv->cell_area;
360 * gtk_cell_area_context_reset:
361 * @context: a #GtkCellAreaContext
363 * Resets any previously cached request and allocation
366 * When underlying #GtkTreeModel data changes its
367 * important to reset the context if the content
368 * size is allowed to shrink. If the content size
369 * is only allowed to grow (this is usually an option
370 * for views rendering large data stores as a measure
371 * of optimization), then only the row that changed
372 * or was inserted needs to be (re)requested with
373 * gtk_cell_area_get_preferred_width().
375 * When the new overall size of the context requires
376 * that the allocated size changes (or whenever this
377 * allocation changes at all), the variable row
378 * sizes need to be re-requested for every row.
380 * For instance, if the rows are displayed all with
381 * the same width from top to bottom then a change
382 * in the allocated width necessitates a recalculation
383 * of all the displayed row heights using
384 * gtk_cell_area_get_preferred_height_for_width().
389 gtk_cell_area_context_reset (GtkCellAreaContext *context)
391 g_return_if_fail (GTK_IS_CELL_AREA_CONTEXT (context));
393 GTK_CELL_AREA_CONTEXT_GET_CLASS (context)->reset (context);
397 * gtk_cell_area_context_allocate:
398 * @context: a #GtkCellAreaContext
399 * @width: the allocated width for all #GtkTreeModel rows rendered
400 * with @context, or -1.
401 * @height: the allocated height for all #GtkTreeModel rows rendered
402 * with @context, or -1.
404 * Allocates a width and/or a height for all rows which are to be
405 * rendered with @context.
407 * Usually allocation is performed only horizontally or sometimes
408 * vertically since a group of rows are usually rendered side by
409 * side vertically or horizontally and share either the same width
410 * or the same height. Sometimes they are allocated in both horizontal
411 * and vertical orientations producing a homogeneous effect of the
412 * rows. This is generally the case for #GtkTreeView when
413 * #GtkTreeView:fixed-height-mode is enabled.
418 gtk_cell_area_context_allocate (GtkCellAreaContext *context,
422 g_return_if_fail (GTK_IS_CELL_AREA_CONTEXT (context));
424 GTK_CELL_AREA_CONTEXT_GET_CLASS (context)->allocate (context, width, height);
428 * gtk_cell_area_context_get_preferred_width:
429 * @context: a #GtkCellAreaContext
430 * @minimum_width: (out) (allow-none): location to store the minimum width,
432 * @natural_width: (out) (allow-none): location to store the natural width,
435 * Gets the accumulative preferred width for all rows which have been
436 * requested with this context.
438 * After gtk_cell_area_context_reset() is called and/or before ever
439 * requesting the size of a #GtkCellArea, the returned values are 0.
444 gtk_cell_area_context_get_preferred_width (GtkCellAreaContext *context,
448 GtkCellAreaContextPrivate *priv;
450 g_return_if_fail (GTK_IS_CELL_AREA_CONTEXT (context));
452 priv = context->priv;
455 *minimum_width = priv->min_width;
458 *natural_width = priv->nat_width;
462 * gtk_cell_area_context_get_preferred_height:
463 * @context: a #GtkCellAreaContext
464 * @minimum_height: (out) (allow-none): location to store the minimum height,
466 * @natural_height: (out) (allow-none): location to store the natural height,
469 * Gets the accumulative preferred height for all rows which have been
470 * requested with this context.
472 * After gtk_cell_area_context_reset() is called and/or before ever
473 * requesting the size of a #GtkCellArea, the returned values are 0.
478 gtk_cell_area_context_get_preferred_height (GtkCellAreaContext *context,
479 gint *minimum_height,
480 gint *natural_height)
482 GtkCellAreaContextPrivate *priv;
484 g_return_if_fail (GTK_IS_CELL_AREA_CONTEXT (context));
486 priv = context->priv;
489 *minimum_height = priv->min_height;
492 *natural_height = priv->nat_height;
496 * gtk_cell_area_context_get_preferred_height_for_width:
497 * @context: a #GtkCellAreaContext
498 * @width: a proposed width for allocation
499 * @minimum_height: (out) (allow-none): location to store the minimum height,
501 * @natural_height: (out) (allow-none): location to store the natural height,
504 * Gets the accumulative preferred height for @width for all rows
505 * which have been requested for the same said @width with this context.
507 * After gtk_cell_area_context_reset() is called and/or before ever
508 * requesting the size of a #GtkCellArea, the returned values are -1.
513 gtk_cell_area_context_get_preferred_height_for_width (GtkCellAreaContext *context,
515 gint *minimum_height,
516 gint *natural_height)
518 g_return_if_fail (GTK_IS_CELL_AREA_CONTEXT (context));
520 if (GTK_CELL_AREA_CONTEXT_GET_CLASS (context)->get_preferred_height_for_width)
521 GTK_CELL_AREA_CONTEXT_GET_CLASS (context)->get_preferred_height_for_width (context,
528 * gtk_cell_area_context_get_preferred_width_for_height:
529 * @context: a #GtkCellAreaContext
530 * @height: a proposed height for allocation
531 * @minimum_width: (out) (allow-none): location to store the minimum width,
533 * @natural_width: (out) (allow-none): location to store the natural width,
536 * Gets the accumulative preferred width for @height for all rows which
537 * have been requested for the same said @height with this context.
539 * After gtk_cell_area_context_reset() is called and/or before ever
540 * requesting the size of a #GtkCellArea, the returned values are -1.
545 gtk_cell_area_context_get_preferred_width_for_height (GtkCellAreaContext *context,
550 g_return_if_fail (GTK_IS_CELL_AREA_CONTEXT (context));
552 if (GTK_CELL_AREA_CONTEXT_GET_CLASS (context)->get_preferred_width_for_height)
553 GTK_CELL_AREA_CONTEXT_GET_CLASS (context)->get_preferred_width_for_height (context,
560 * gtk_cell_area_context_get_allocation:
561 * @context: a #GtkCellAreaContext
562 * @width: (out) (allow-none): location to store the allocated width, or %NULL
563 * @height: (out) (allow-none): location to store the allocated height, or %NULL
565 * Fetches the current allocation size for @context.
567 * If the context was not allocated in width or height, or if the
568 * context was recently reset with gtk_cell_area_context_reset(),
569 * the returned value will be -1.
574 gtk_cell_area_context_get_allocation (GtkCellAreaContext *context,
578 GtkCellAreaContextPrivate *priv;
580 g_return_if_fail (GTK_IS_CELL_AREA_CONTEXT (context));
582 priv = context->priv;
585 *width = priv->alloc_width;
588 *height = priv->alloc_height;
592 * gtk_cell_area_context_push_preferred_width:
593 * @context: a #GtkCellAreaContext
594 * @minimum_width: the proposed new minimum width for @context
595 * @natural_width: the proposed new natural width for @context
597 * Causes the minimum and/or natural width to grow if the new
598 * proposed sizes exceed the current minimum and natural width.
600 * This is used by #GtkCellAreaContext implementations during
601 * the request process over a series of #GtkTreeModel rows to
602 * progressively push the requested width over a series of
603 * gtk_cell_area_get_preferred_width() requests.
608 gtk_cell_area_context_push_preferred_width (GtkCellAreaContext *context,
612 GtkCellAreaContextPrivate *priv;
614 g_return_if_fail (GTK_IS_CELL_AREA_CONTEXT (context));
616 priv = context->priv;
618 g_object_freeze_notify (G_OBJECT (context));
620 if (minimum_width > priv->min_width)
622 priv->min_width = minimum_width;
624 g_object_notify (G_OBJECT (context), "minimum-width");
627 if (natural_width > priv->nat_width)
629 priv->nat_width = natural_width;
631 g_object_notify (G_OBJECT (context), "natural-width");
634 g_object_thaw_notify (G_OBJECT (context));
638 * gtk_cell_area_context_push_preferred_height:
639 * @context: a #GtkCellAreaContext
640 * @minimum_height: the proposed new minimum height for @context
641 * @natural_height: the proposed new natural height for @context
643 * Causes the minimum and/or natural height to grow if the new
644 * proposed sizes exceed the current minimum and natural height.
646 * This is used by #GtkCellAreaContext implementations during
647 * the request process over a series of #GtkTreeModel rows to
648 * progressively push the requested height over a series of
649 * gtk_cell_area_get_preferred_height() requests.
654 gtk_cell_area_context_push_preferred_height (GtkCellAreaContext *context,
658 GtkCellAreaContextPrivate *priv;
660 g_return_if_fail (GTK_IS_CELL_AREA_CONTEXT (context));
662 priv = context->priv;
664 g_object_freeze_notify (G_OBJECT (context));
666 if (minimum_height > priv->min_height)
668 priv->min_height = minimum_height;
670 g_object_notify (G_OBJECT (context), "minimum-height");
673 if (natural_height > priv->nat_height)
675 priv->nat_height = natural_height;
677 g_object_notify (G_OBJECT (context), "natural-height");
680 g_object_thaw_notify (G_OBJECT (context));