]> Pileus Git - ~andy/gtk/blob - gtk/gtkcellareacontext.c
Added gtk-doc to GtkCellArea & GtkCellAreaContext.
[~andy/gtk] / gtk / gtkcellareacontext.c
1 /* gtkcellareacontext.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 /**
25  * SECTION:gtkcellareacontext
26  * @Short_Description: An object for a #GtkCellArea to store geometrical information for a series of rows.
27  * @Title: GtkCellAreaContext
28  *
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.
32  *
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().
37  */
38 #include "config.h"
39 #include "gtkintl.h"
40 #include "gtkmarshalers.h"
41 #include "gtkcellareacontext.h"
42 #include "gtkprivate.h"
43
44 /* GObjectClass */
45 static void      gtk_cell_area_context_dispose         (GObject            *object);
46 static void      gtk_cell_area_context_get_property    (GObject            *object,
47                                                         guint               prop_id,
48                                                         GValue             *value,
49                                                         GParamSpec         *pspec);
50 static void      gtk_cell_area_context_set_property    (GObject            *object,
51                                                         guint               prop_id,
52                                                         const GValue       *value,
53                                                         GParamSpec         *pspec);
54
55 /* GtkCellAreaContextClass */
56 static void      gtk_cell_area_context_real_reset      (GtkCellAreaContext *context);
57 static void      gtk_cell_area_context_real_allocate   (GtkCellAreaContext *context,
58                                                         gint                width,
59                                                         gint                height);
60
61 struct _GtkCellAreaContextPrivate
62 {
63   GtkCellArea *cell_area;
64
65   gint         min_width;
66   gint         nat_width;
67   gint         min_height;
68   gint         nat_height;
69   gint         alloc_width;
70   gint         alloc_height;
71 };
72
73 enum {
74   PROP_0,
75   PROP_CELL_AREA,
76   PROP_MIN_WIDTH,
77   PROP_NAT_WIDTH,
78   PROP_MIN_HEIGHT,
79   PROP_NAT_HEIGHT
80 };
81
82 G_DEFINE_TYPE (GtkCellAreaContext, gtk_cell_area_context, G_TYPE_OBJECT);
83
84 static void
85 gtk_cell_area_context_init (GtkCellAreaContext *context)
86 {
87   GtkCellAreaContextPrivate *priv;
88
89   context->priv = G_TYPE_INSTANCE_GET_PRIVATE (context,
90                                                GTK_TYPE_CELL_AREA_CONTEXT,
91                                                GtkCellAreaContextPrivate);
92   priv = context->priv;
93
94   priv->min_width  = -1;
95   priv->nat_width  = -1;
96   priv->min_height = -1;
97   priv->nat_height = -1;
98 }
99
100 static void 
101 gtk_cell_area_context_class_init (GtkCellAreaContextClass *class)
102 {
103   GObjectClass     *object_class = G_OBJECT_CLASS (class);
104
105   /* GObjectClass */
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;
109
110   /* GtkCellAreaContextClass */
111   class->reset    = gtk_cell_area_context_real_reset;
112   class->allocate = gtk_cell_area_context_real_allocate;
113
114   /**
115    * GtkCellAreaContext:area:
116    *
117    * The #GtkCellArea this context was created by
118    *
119    * Since: 3.0
120    */
121   g_object_class_install_property (object_class,
122                                    PROP_CELL_AREA,
123                                    g_param_spec_object ("area",
124                                                         P_("Area"),
125                                                         P_("The Cell Area this context was created for"),
126                                                         GTK_TYPE_CELL_AREA,
127                                                         GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
128
129   /**
130    * GtkCellAreaContext:minimum-width:
131    *
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().
135    *
136    * Since: 3.0
137    */
138   g_object_class_install_property (object_class,
139                                    PROP_MIN_WIDTH,
140                                    g_param_spec_int ("minimum-width",
141                                                      P_("Minimum Width"),
142                                                      P_("Minimum cached width"),
143                                                      -1,
144                                                      G_MAXINT,
145                                                      -1,
146                                                      G_PARAM_READABLE));
147
148   /**
149    * GtkCellAreaContext:natural-width:
150    *
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().
154    *
155    * Since: 3.0
156    */
157   g_object_class_install_property (object_class,
158                                    PROP_NAT_WIDTH,
159                                    g_param_spec_int ("natural-width",
160                                                      P_("Minimum Width"),
161                                                      P_("Minimum cached width"),
162                                                      -1,
163                                                      G_MAXINT,
164                                                      -1,
165                                                      G_PARAM_READABLE));
166
167   /**
168    * GtkCellAreaContext:minimum-height:
169    *
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().
173    *
174    * Since: 3.0
175    */
176   g_object_class_install_property (object_class,
177                                    PROP_MIN_HEIGHT,
178                                    g_param_spec_int ("minimum-height",
179                                                      P_("Minimum Height"),
180                                                      P_("Minimum cached height"),
181                                                      -1,
182                                                      G_MAXINT,
183                                                      -1,
184                                                      G_PARAM_READABLE));
185
186   /**
187    * GtkCellAreaContext:natural-height:
188    *
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().
192    *
193    * Since: 3.0
194    */
195   g_object_class_install_property (object_class,
196                                    PROP_NAT_HEIGHT,
197                                    g_param_spec_int ("natural-height",
198                                                      P_("Minimum Height"),
199                                                      P_("Minimum cached height"),
200                                                      -1,
201                                                      G_MAXINT,
202                                                      -1,
203                                                      G_PARAM_READABLE));
204
205   g_type_class_add_private (object_class, sizeof (GtkCellAreaContextPrivate));
206 }
207
208 /*************************************************************
209  *                      GObjectClass                         *
210  *************************************************************/
211 static void
212 gtk_cell_area_context_dispose (GObject *object)
213 {
214   GtkCellAreaContext        *context = GTK_CELL_AREA_CONTEXT (object);
215   GtkCellAreaContextPrivate *priv = context->priv;
216
217   if (priv->cell_area)
218     {
219       g_object_unref (priv->cell_area);
220
221       priv->cell_area = NULL;
222     }
223
224   G_OBJECT_CLASS (gtk_cell_area_context_parent_class)->dispose (object);
225 }
226
227 static void
228 gtk_cell_area_context_set_property (GObject      *object,
229                                     guint         prop_id,
230                                     const GValue *value,
231                                     GParamSpec   *pspec)
232 {
233   GtkCellAreaContext        *context = GTK_CELL_AREA_CONTEXT (object);
234   GtkCellAreaContextPrivate *priv = context->priv;
235
236   switch (prop_id)
237     {
238     case PROP_CELL_AREA:
239       priv->cell_area = g_value_dup_object (value);
240       break;
241     default:
242       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
243       break;
244     }
245 }
246
247 static void
248 gtk_cell_area_context_get_property (GObject     *object,
249                                     guint        prop_id,
250                                     GValue      *value,
251                                     GParamSpec  *pspec)
252 {
253   GtkCellAreaContext        *context = GTK_CELL_AREA_CONTEXT (object);
254   GtkCellAreaContextPrivate *priv = context->priv;
255
256   switch (prop_id)
257     {
258     case PROP_CELL_AREA:
259       g_value_set_object (value, priv->cell_area);
260       break;
261     case PROP_MIN_WIDTH:
262       g_value_set_int (value, priv->min_width);
263       break;
264     case PROP_NAT_WIDTH:
265       g_value_set_int (value, priv->nat_width);
266       break;
267     case PROP_MIN_HEIGHT:
268       g_value_set_int (value, priv->min_height);
269       break;
270     case PROP_NAT_HEIGHT:
271       g_value_set_int (value, priv->nat_height);
272       break;
273     default:
274       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
275       break;
276     }
277 }
278
279 /*************************************************************
280  *                    GtkCellAreaContextClass                   *
281  *************************************************************/
282 static void
283 gtk_cell_area_context_real_reset (GtkCellAreaContext *context)
284 {
285   GtkCellAreaContextPrivate *priv = context->priv;
286   
287   priv->min_width    = -1;
288   priv->nat_width    = -1;
289   priv->min_height   = -1;
290   priv->nat_height   = -1;
291   priv->alloc_width  = 0;
292   priv->alloc_height = 0;
293
294   g_object_freeze_notify (G_OBJECT (context));
295   g_object_notify (G_OBJECT (context), "minimum-width");
296   g_object_notify (G_OBJECT (context), "natural-width");
297   g_object_notify (G_OBJECT (context), "minimum-height");
298   g_object_notify (G_OBJECT (context), "natural-height");
299   g_object_thaw_notify (G_OBJECT (context));
300 }
301
302 static void
303 gtk_cell_area_context_real_allocate (GtkCellAreaContext *context,
304                                      gint                width,
305                                      gint                height)
306 {
307   GtkCellAreaContextPrivate *priv = context->priv;
308
309   priv->alloc_width  = width;
310   priv->alloc_height = height;
311 }
312
313 /*************************************************************
314  *                            API                            *
315  *************************************************************/
316 /**
317  * gtk_cell_area_context_get_area:
318  * @context: a #GtkCellAreaContext
319  *
320  * Fetches the #GtkCellArea this @context was created by.
321  *
322  * This is generally unneeded by layouting widgets however
323  * its important for the context implementation itself to
324  * fetch information about the area it is being used for.
325  *
326  * For instance at #GtkCellAreaContextClass.allocate() time
327  * it's important to know details about any cell spacing
328  * that the #GtkCellArea is configured with in order to 
329  * compute a proper allocation.
330  *
331  * Return value: the #GtkCellArea this context was created by.
332  *
333  * Since: 3.0
334  */
335 GtkCellArea *
336 gtk_cell_area_context_get_area (GtkCellAreaContext *context)
337 {
338   GtkCellAreaContextPrivate *priv;
339
340   g_return_val_if_fail (GTK_IS_CELL_AREA_CONTEXT (context), NULL);
341
342   priv = context->priv;
343
344   return priv->cell_area;
345 }
346
347 /**
348  * gtk_cell_area_context_reset:
349  * @context: a #GtkCellAreaContext
350  *
351  * Resets any previously cached request and allocation
352  * data. 
353  *
354  * When underlying #GtkTreeModel data changes it's 
355  * important to reset the context if the content
356  * size is allowed to shrink. If the content size
357  * is only allowed to grow (this is usually an option
358  * for views rendering large data stores as a measure
359  * of optimization), then only the row that changed
360  * or was inserted needs to be (re)requested with 
361  * gtk_cell_area_get_preferred_width().
362  *
363  * When the new overall size of the context requires
364  * that the allocated size changes (or whenever this
365  * allocation changes at all), the variable row
366  * sizes need to be re-requested for every row.
367  *
368  * For instance, if the rows are displayed all with
369  * the same width from top to bottom then a change
370  * in the allocated width necessitates a recalculation
371  * of all the displayed row heights using
372  * gtk_cell_area_get_preferred_height_for_width().
373  *
374  * Since 3.0
375  */
376 void
377 gtk_cell_area_context_reset (GtkCellAreaContext *context)
378 {
379   g_return_if_fail (GTK_IS_CELL_AREA_CONTEXT (context));
380
381   GTK_CELL_AREA_CONTEXT_GET_CLASS (context)->reset (context);
382 }
383
384 /**
385  * gtk_cell_area_context_allocate:
386  * @context: a #GtkCellAreaContext
387  * @width: the allocated width for all #GtkTreeModel rows rendered with @context, or -1.
388  * @height: the allocated height for all #GtkTreeModel rows rendered with @context, or -1.
389  *
390  * Allocates a width and/or a height for all rows which are to be rendered with @context.
391  *
392  * Usually allocation is performed only horizontally or sometimes vertically since
393  * a group of rows are usually rendered side by side vertically or horizontally and 
394  * share either the same width or the same hieght. Sometimes they are allocated in
395  * both horizontal and vertical orientations producing a homogenious effect of the
396  * rows. This is generally the case for #GtkTreeView when #GtkTreeView:fixed-height-mode
397  * is enabled.
398  *
399  * Since 3.0
400  */
401 void
402 gtk_cell_area_context_allocate (GtkCellAreaContext *context,
403                                 gint                width,
404                                 gint                height)
405 {
406   g_return_if_fail (GTK_IS_CELL_AREA_CONTEXT (context));
407
408   GTK_CELL_AREA_CONTEXT_GET_CLASS (context)->allocate (context, width, height);
409 }
410
411 /**
412  * gtk_cell_area_context_get_preferred_width:
413  * @context: a #GtkCellAreaContext
414  * @minimum_width: (out) (allow-none): location to store the minimum width, or %NULL
415  * @natural_width: (out) (allow-none): location to store the natural width, or %NULL
416  *
417  * Gets the accumulative preferred width for all rows which have been requested
418  * with this context.
419  *
420  * After gtk_cell_area_context_reset() is called and/or before ever requesting
421  * the size of a #GtkCellArea, the returned values are -1.
422  *
423  * Since: 3.0 
424  */
425 void
426 gtk_cell_area_context_get_preferred_width (GtkCellAreaContext *context,
427                                            gint               *minimum_width,
428                                            gint               *natural_width)
429 {
430   GtkCellAreaContextPrivate *priv;
431
432   g_return_if_fail (GTK_IS_CELL_AREA_CONTEXT (context));
433
434   priv = context->priv;
435
436   if (minimum_width)
437     *minimum_width = priv->min_width;
438
439   if (natural_width)
440     *natural_width = priv->nat_width;
441 }
442
443 /**
444  * gtk_cell_area_context_get_preferred_height:
445  * @context: a #GtkCellAreaContext
446  * @minimum_height: (out) (allow-none): location to store the minimum height, or %NULL
447  * @natural_height: (out) (allow-none): location to store the natural height, or %NULL
448  *
449  * Gets the accumulative preferred height for all rows which have been requested
450  * with this context.
451  *
452  * After gtk_cell_area_context_reset() is called and/or before ever requesting
453  * the size of a #GtkCellArea, the returned values are -1.
454  *
455  * Since: 3.0
456  */
457 void
458 gtk_cell_area_context_get_preferred_height (GtkCellAreaContext *context,
459                                             gint               *minimum_height,
460                                             gint               *natural_height)
461 {
462   GtkCellAreaContextPrivate *priv;
463
464   g_return_if_fail (GTK_IS_CELL_AREA_CONTEXT (context));
465
466   priv = context->priv;
467
468   if (minimum_height)
469     *minimum_height = priv->min_height;
470
471   if (natural_height)
472     *natural_height = priv->nat_height;
473 }
474
475 /**
476  * gtk_cell_area_context_get_allocation:
477  * @context: a #GtkCellAreaContext
478  * @width: (out) (allow-none): location to store the allocated width, or %NULL.
479  * @height: (out) (allow-none): location to store the allocated height, or %NULL.
480  *
481  * Fetches the current allocation size for @context.
482  *
483  * If the context was not allocated in width or height, or if the
484  * context was recently reset with gtk_cell_area_context_reset(),
485  * the returned value will be -1.
486  *
487  * Since: 3.0
488  */
489 void
490 gtk_cell_area_context_get_allocation (GtkCellAreaContext *context,
491                                       gint               *width,
492                                       gint               *height)
493 {
494   GtkCellAreaContextPrivate *priv;
495
496   g_return_if_fail (GTK_IS_CELL_AREA_CONTEXT (context));
497
498   priv = context->priv;
499
500   if (width)
501     *width = priv->alloc_width;
502
503   if (height)
504     *height = priv->alloc_height;
505 }
506
507 /**
508  * gtk_cell_area_context_push_preferred_width:
509  * @context: a #GtkCellAreaContext
510  * @minimum_width: the proposed new minimum width for @context.
511  * @natural_width: the proposed new natural width for @context.
512  *
513  * Causes the minimum and/or natural width to grow if the new
514  * proposed sizes exceed the current minimum and natural width.
515  *
516  * This is used by #GtkCellAreaContext implementations during
517  * the request process over a series of #GtkTreeModel rows to
518  * progressively push the requested width over a series of
519  * gtk_cell_area_get_preferred_width() requests.
520  *
521  * Since: 3.0
522  */
523 void
524 gtk_cell_area_context_push_preferred_width (GtkCellAreaContext *context,
525                                             gint                minimum_width,
526                                             gint                natural_width)
527 {
528   GtkCellAreaContextPrivate *priv;
529
530   g_return_if_fail (GTK_IS_CELL_AREA_CONTEXT (context));
531
532   priv = context->priv;
533
534   g_object_freeze_notify (G_OBJECT (context));
535
536   if (minimum_width > priv->min_width)
537     {
538       priv->min_width = minimum_width;
539
540       g_object_notify (G_OBJECT (context), "minimum-width");
541     }
542
543   if (natural_width > priv->nat_width)
544     {
545       priv->nat_width = natural_width;
546
547       g_object_notify (G_OBJECT (context), "natural-width");
548     }
549
550   g_object_thaw_notify (G_OBJECT (context));
551 }
552
553 /**
554  * gtk_cell_area_context_push_preferred_height:
555  * @context: a #GtkCellAreaContext
556  * @minimum_height: the proposed new minimum height for @context.
557  * @natural_height: the proposed new natural height for @context.
558  *
559  * Causes the minimum and/or natural height to grow if the new
560  * proposed sizes exceed the current minimum and natural height.
561  *
562  * This is used by #GtkCellAreaContext implementations during
563  * the request process over a series of #GtkTreeModel rows to
564  * progressively push the requested height over a series of
565  * gtk_cell_area_get_preferred_height() requests.
566  *
567  * Since: 3.0
568  */
569 void
570 gtk_cell_area_context_push_preferred_height (GtkCellAreaContext *context,
571                                              gint                minimum_height,
572                                              gint                natural_height)
573 {
574   GtkCellAreaContextPrivate *priv;
575   
576   g_return_if_fail (GTK_IS_CELL_AREA_CONTEXT (context));
577
578   priv = context->priv;
579
580   g_object_freeze_notify (G_OBJECT (context));
581
582   if (minimum_height > priv->min_height)
583     {
584       priv->min_height = minimum_height;
585
586       g_object_notify (G_OBJECT (context), "minimum-height");
587     }
588
589   if (natural_height > priv->nat_height)
590     {
591       priv->nat_height = natural_height;
592
593       g_object_notify (G_OBJECT (context), "natural-height");
594     }
595
596   g_object_thaw_notify (G_OBJECT (context));
597 }