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: An object for a #GtkCellArea to store geometrical information for a series of rows.
27 * @Title: GtkCellAreaContext
29 * The #GtkCellAreaContext object is created by a given #GtkCellArea implementation via it's
30 * #GtkCellAreaClass.create_context() virtual method and is used to store cell sizes and alignments
31 * for a series of #GtkTreeModel rows that are requested and rendered in the same context.
33 * #GtkCellLayout widgets can create any number of contexts in which to request and render
34 * groups of data rows. However its important that the same context which was used to
35 * request sizes for a given #GtkTreeModel row also be used for the same row when calling
36 * other #GtkCellArea apis such as gtk_cell_area_render() and gtk_cell_area_event().
40 #include "gtkmarshalers.h"
41 #include "gtkcellareacontext.h"
42 #include "gtkprivate.h"
45 static void gtk_cell_area_context_dispose (GObject *object);
46 static void gtk_cell_area_context_get_property (GObject *object,
50 static void gtk_cell_area_context_set_property (GObject *object,
55 /* GtkCellAreaContextClass */
56 static void gtk_cell_area_context_real_reset (GtkCellAreaContext *context);
57 static void gtk_cell_area_context_real_allocate (GtkCellAreaContext *context,
61 struct _GtkCellAreaContextPrivate
63 GtkCellArea *cell_area;
82 G_DEFINE_TYPE (GtkCellAreaContext, gtk_cell_area_context, G_TYPE_OBJECT);
85 gtk_cell_area_context_init (GtkCellAreaContext *context)
87 GtkCellAreaContextPrivate *priv;
89 context->priv = G_TYPE_INSTANCE_GET_PRIVATE (context,
90 GTK_TYPE_CELL_AREA_CONTEXT,
91 GtkCellAreaContextPrivate);
96 priv->min_height = -1;
97 priv->nat_height = -1;
101 gtk_cell_area_context_class_init (GtkCellAreaContextClass *class)
103 GObjectClass *object_class = G_OBJECT_CLASS (class);
106 object_class->dispose = gtk_cell_area_context_dispose;
107 object_class->get_property = gtk_cell_area_context_get_property;
108 object_class->set_property = gtk_cell_area_context_set_property;
110 /* GtkCellAreaContextClass */
111 class->reset = gtk_cell_area_context_real_reset;
112 class->allocate = gtk_cell_area_context_real_allocate;
115 * GtkCellAreaContext:area:
117 * The #GtkCellArea this context was created by
121 g_object_class_install_property (object_class,
123 g_param_spec_object ("area",
125 P_("The Cell Area this context was created for"),
127 GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
130 * GtkCellAreaContext:minimum-width:
132 * The minimum width for the #GtkCellArea in this context
133 * for all #GtkTreeModel rows that this context was requested
134 * for using gtk_cell_area_get_preferred_width().
138 g_object_class_install_property (object_class,
140 g_param_spec_int ("minimum-width",
142 P_("Minimum cached width"),
149 * GtkCellAreaContext:natural-width:
151 * The natural width for the #GtkCellArea in this context
152 * for all #GtkTreeModel rows that this context was requested
153 * for using gtk_cell_area_get_preferred_width().
157 g_object_class_install_property (object_class,
159 g_param_spec_int ("natural-width",
161 P_("Minimum cached width"),
168 * GtkCellAreaContext:minimum-height:
170 * The minimum height for the #GtkCellArea in this context
171 * for all #GtkTreeModel rows that this context was requested
172 * for using gtk_cell_area_get_preferred_height().
176 g_object_class_install_property (object_class,
178 g_param_spec_int ("minimum-height",
179 P_("Minimum Height"),
180 P_("Minimum cached height"),
187 * GtkCellAreaContext:natural-height:
189 * The natural height for the #GtkCellArea in this context
190 * for all #GtkTreeModel rows that this context was requested
191 * for using gtk_cell_area_get_preferred_height().
195 g_object_class_install_property (object_class,
197 g_param_spec_int ("natural-height",
198 P_("Minimum Height"),
199 P_("Minimum cached height"),
205 g_type_class_add_private (object_class, sizeof (GtkCellAreaContextPrivate));
208 /*************************************************************
210 *************************************************************/
212 gtk_cell_area_context_dispose (GObject *object)
214 GtkCellAreaContext *context = GTK_CELL_AREA_CONTEXT (object);
215 GtkCellAreaContextPrivate *priv = context->priv;
219 g_object_unref (priv->cell_area);
221 priv->cell_area = NULL;
224 G_OBJECT_CLASS (gtk_cell_area_context_parent_class)->dispose (object);
228 gtk_cell_area_context_set_property (GObject *object,
233 GtkCellAreaContext *context = GTK_CELL_AREA_CONTEXT (object);
234 GtkCellAreaContextPrivate *priv = context->priv;
239 priv->cell_area = g_value_dup_object (value);
242 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
248 gtk_cell_area_context_get_property (GObject *object,
253 GtkCellAreaContext *context = GTK_CELL_AREA_CONTEXT (object);
254 GtkCellAreaContextPrivate *priv = context->priv;
259 g_value_set_object (value, priv->cell_area);
262 g_value_set_int (value, priv->min_width);
265 g_value_set_int (value, priv->nat_width);
267 case PROP_MIN_HEIGHT:
268 g_value_set_int (value, priv->min_height);
270 case PROP_NAT_HEIGHT:
271 g_value_set_int (value, priv->nat_height);
274 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
279 /*************************************************************
280 * GtkCellAreaContextClass *
281 *************************************************************/
283 gtk_cell_area_context_real_reset (GtkCellAreaContext *context)
285 GtkCellAreaContextPrivate *priv = context->priv;
287 g_object_freeze_notify (G_OBJECT (context));
289 if (priv->min_width != -1)
291 priv->min_width = -1;
292 g_object_notify (G_OBJECT (context), "minimum-width");
295 if (priv->nat_width != -1)
297 priv->nat_width = -1;
298 g_object_notify (G_OBJECT (context), "natural-width");
301 if (priv->min_height != -1)
303 priv->min_height = -1;
304 g_object_notify (G_OBJECT (context), "minimum-height");
307 if (priv->nat_height != -1)
309 priv->nat_height = -1;
310 g_object_notify (G_OBJECT (context), "natural-height");
313 priv->alloc_width = 0;
314 priv->alloc_height = 0;
316 g_object_thaw_notify (G_OBJECT (context));
320 gtk_cell_area_context_real_allocate (GtkCellAreaContext *context,
324 GtkCellAreaContextPrivate *priv = context->priv;
326 priv->alloc_width = width;
327 priv->alloc_height = height;
330 /*************************************************************
332 *************************************************************/
334 * gtk_cell_area_context_get_area:
335 * @context: a #GtkCellAreaContext
337 * Fetches the #GtkCellArea this @context was created by.
339 * This is generally unneeded by layouting widgets however
340 * its important for the context implementation itself to
341 * fetch information about the area it is being used for.
343 * For instance at #GtkCellAreaContextClass.allocate() time
344 * it's important to know details about any cell spacing
345 * that the #GtkCellArea is configured with in order to
346 * compute a proper allocation.
348 * Return value: the #GtkCellArea this context was created by.
353 gtk_cell_area_context_get_area (GtkCellAreaContext *context)
355 GtkCellAreaContextPrivate *priv;
357 g_return_val_if_fail (GTK_IS_CELL_AREA_CONTEXT (context), NULL);
359 priv = context->priv;
361 return priv->cell_area;
365 * gtk_cell_area_context_reset:
366 * @context: a #GtkCellAreaContext
368 * Resets any previously cached request and allocation
371 * When underlying #GtkTreeModel data changes it's
372 * important to reset the context if the content
373 * size is allowed to shrink. If the content size
374 * is only allowed to grow (this is usually an option
375 * for views rendering large data stores as a measure
376 * of optimization), then only the row that changed
377 * or was inserted needs to be (re)requested with
378 * gtk_cell_area_get_preferred_width().
380 * When the new overall size of the context requires
381 * that the allocated size changes (or whenever this
382 * allocation changes at all), the variable row
383 * sizes need to be re-requested for every row.
385 * For instance, if the rows are displayed all with
386 * the same width from top to bottom then a change
387 * in the allocated width necessitates a recalculation
388 * of all the displayed row heights using
389 * gtk_cell_area_get_preferred_height_for_width().
394 gtk_cell_area_context_reset (GtkCellAreaContext *context)
396 g_return_if_fail (GTK_IS_CELL_AREA_CONTEXT (context));
398 GTK_CELL_AREA_CONTEXT_GET_CLASS (context)->reset (context);
402 * gtk_cell_area_context_allocate:
403 * @context: a #GtkCellAreaContext
404 * @width: the allocated width for all #GtkTreeModel rows rendered with @context, or -1.
405 * @height: the allocated height for all #GtkTreeModel rows rendered with @context, or -1.
407 * Allocates a width and/or a height for all rows which are to be rendered with @context.
409 * Usually allocation is performed only horizontally or sometimes vertically since
410 * a group of rows are usually rendered side by side vertically or horizontally and
411 * share either the same width or the same hieght. Sometimes they are allocated in
412 * both horizontal and vertical orientations producing a homogenious effect of the
413 * rows. This is generally the case for #GtkTreeView when #GtkTreeView:fixed-height-mode
419 gtk_cell_area_context_allocate (GtkCellAreaContext *context,
423 g_return_if_fail (GTK_IS_CELL_AREA_CONTEXT (context));
425 GTK_CELL_AREA_CONTEXT_GET_CLASS (context)->allocate (context, width, height);
429 * gtk_cell_area_context_get_preferred_width:
430 * @context: a #GtkCellAreaContext
431 * @minimum_width: (out) (allow-none): location to store the minimum width, or %NULL
432 * @natural_width: (out) (allow-none): location to store the natural width, or %NULL
434 * Gets the accumulative preferred width for all rows which have been requested
437 * After gtk_cell_area_context_reset() is called and/or before ever requesting
438 * the size of a #GtkCellArea, the returned values are -1.
443 gtk_cell_area_context_get_preferred_width (GtkCellAreaContext *context,
447 GtkCellAreaContextPrivate *priv;
449 g_return_if_fail (GTK_IS_CELL_AREA_CONTEXT (context));
451 priv = context->priv;
454 *minimum_width = priv->min_width;
457 *natural_width = priv->nat_width;
461 * gtk_cell_area_context_get_preferred_height:
462 * @context: a #GtkCellAreaContext
463 * @minimum_height: (out) (allow-none): location to store the minimum height, or %NULL
464 * @natural_height: (out) (allow-none): location to store the natural height, or %NULL
466 * Gets the accumulative preferred height for all rows which have been requested
469 * After gtk_cell_area_context_reset() is called and/or before ever requesting
470 * the size of a #GtkCellArea, the returned values are -1.
475 gtk_cell_area_context_get_preferred_height (GtkCellAreaContext *context,
476 gint *minimum_height,
477 gint *natural_height)
479 GtkCellAreaContextPrivate *priv;
481 g_return_if_fail (GTK_IS_CELL_AREA_CONTEXT (context));
483 priv = context->priv;
486 *minimum_height = priv->min_height;
489 *natural_height = priv->nat_height;
493 * gtk_cell_area_context_get_preferred_height_for_width:
494 * @context: a #GtkCellAreaContext
495 * @width: a proposed width for allocation
496 * @minimum_height: (out) (allow-none): location to store the minimum height, or %NULL
497 * @natural_height: (out) (allow-none): location to store the natural height, or %NULL
499 * Gets the accumulative preferred height for @width for all rows which have been
500 * requested for the same said @width with this context.
502 * After gtk_cell_area_context_reset() is called and/or before ever requesting
503 * the size of a #GtkCellArea, the returned values are -1.
508 gtk_cell_area_context_get_preferred_height_for_width (GtkCellAreaContext *context,
510 gint *minimum_height,
511 gint *natural_height)
513 g_return_if_fail (GTK_IS_CELL_AREA_CONTEXT (context));
515 if (GTK_CELL_AREA_CONTEXT_GET_CLASS (context)->get_preferred_height_for_width)
516 GTK_CELL_AREA_CONTEXT_GET_CLASS (context)->get_preferred_height_for_width (context,
523 * gtk_cell_area_context_get_preferred_width_for_height:
524 * @context: a #GtkCellAreaContext
525 * @height: a proposed height for allocation
526 * @minimum_width: (out) (allow-none): location to store the minimum width, or %NULL
527 * @natural_width: (out) (allow-none): location to store the natural width, or %NULL
529 * Gets the accumulative preferred width for @height for all rows which have
530 * been requested for the same said @height with this context.
532 * After gtk_cell_area_context_reset() is called and/or before ever requesting
533 * the size of a #GtkCellArea, the returned values are -1.
538 gtk_cell_area_context_get_preferred_width_for_height (GtkCellAreaContext *context,
543 g_return_if_fail (GTK_IS_CELL_AREA_CONTEXT (context));
545 if (GTK_CELL_AREA_CONTEXT_GET_CLASS (context)->get_preferred_width_for_height)
546 GTK_CELL_AREA_CONTEXT_GET_CLASS (context)->get_preferred_width_for_height (context,
553 * gtk_cell_area_context_get_allocation:
554 * @context: a #GtkCellAreaContext
555 * @width: (out) (allow-none): location to store the allocated width, or %NULL.
556 * @height: (out) (allow-none): location to store the allocated height, or %NULL.
558 * Fetches the current allocation size for @context.
560 * If the context was not allocated in width or height, or if the
561 * context was recently reset with gtk_cell_area_context_reset(),
562 * the returned value will be -1.
567 gtk_cell_area_context_get_allocation (GtkCellAreaContext *context,
571 GtkCellAreaContextPrivate *priv;
573 g_return_if_fail (GTK_IS_CELL_AREA_CONTEXT (context));
575 priv = context->priv;
578 *width = priv->alloc_width;
581 *height = priv->alloc_height;
585 * gtk_cell_area_context_push_preferred_width:
586 * @context: a #GtkCellAreaContext
587 * @minimum_width: the proposed new minimum width for @context.
588 * @natural_width: the proposed new natural width for @context.
590 * Causes the minimum and/or natural width to grow if the new
591 * proposed sizes exceed the current minimum and natural width.
593 * This is used by #GtkCellAreaContext implementations during
594 * the request process over a series of #GtkTreeModel rows to
595 * progressively push the requested width over a series of
596 * gtk_cell_area_get_preferred_width() requests.
601 gtk_cell_area_context_push_preferred_width (GtkCellAreaContext *context,
605 GtkCellAreaContextPrivate *priv;
607 g_return_if_fail (GTK_IS_CELL_AREA_CONTEXT (context));
609 priv = context->priv;
611 g_object_freeze_notify (G_OBJECT (context));
613 if (minimum_width > priv->min_width)
615 priv->min_width = minimum_width;
617 g_object_notify (G_OBJECT (context), "minimum-width");
620 if (natural_width > priv->nat_width)
622 priv->nat_width = natural_width;
624 g_object_notify (G_OBJECT (context), "natural-width");
627 g_object_thaw_notify (G_OBJECT (context));
631 * gtk_cell_area_context_push_preferred_height:
632 * @context: a #GtkCellAreaContext
633 * @minimum_height: the proposed new minimum height for @context.
634 * @natural_height: the proposed new natural height for @context.
636 * Causes the minimum and/or natural height to grow if the new
637 * proposed sizes exceed the current minimum and natural height.
639 * This is used by #GtkCellAreaContext implementations during
640 * the request process over a series of #GtkTreeModel rows to
641 * progressively push the requested height over a series of
642 * gtk_cell_area_get_preferred_height() requests.
647 gtk_cell_area_context_push_preferred_height (GtkCellAreaContext *context,
651 GtkCellAreaContextPrivate *priv;
653 g_return_if_fail (GTK_IS_CELL_AREA_CONTEXT (context));
655 priv = context->priv;
657 g_object_freeze_notify (G_OBJECT (context));
659 if (minimum_height > priv->min_height)
661 priv->min_height = minimum_height;
663 g_object_notify (G_OBJECT (context), "minimum-height");
666 if (natural_height > priv->nat_height)
668 priv->nat_height = natural_height;
670 g_object_notify (G_OBJECT (context), "natural-height");
673 g_object_thaw_notify (G_OBJECT (context));