]> Pileus Git - ~andy/gtk/blob - gtk/gtkcellareaboxiter.c
Added the majority of the allocate machinery to GtkCellAreaIter[Box].
[~andy/gtk] / gtk / gtkcellareaboxiter.c
1 /* gtkcellareaboxiter.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 #include "config.h"
25 #include "gtkintl.h"
26 #include "gtkcellareabox.h"
27 #include "gtkcellareaboxiter.h"
28 #include "gtkorientable.h"
29
30 /* GObjectClass */
31 static void      gtk_cell_area_box_iter_finalize                         (GObject            *object);
32
33 /* GtkCellAreaIterClass */
34 static void      gtk_cell_area_box_iter_flush_preferred_width            (GtkCellAreaIter *iter);
35 static void      gtk_cell_area_box_iter_flush_preferred_height_for_width (GtkCellAreaIter *iter,
36                                                                           gint             width);
37 static void      gtk_cell_area_box_iter_flush_preferred_height           (GtkCellAreaIter *iter);
38 static void      gtk_cell_area_box_iter_flush_preferred_width_for_height (GtkCellAreaIter *iter,
39                                                                           gint             height);
40 static void      gtk_cell_area_box_iter_flush_allocation                 (GtkCellAreaIter *iter);
41 static void      gtk_cell_area_box_iter_sum_preferred_width              (GtkCellAreaIter *iter);
42 static void      gtk_cell_area_box_iter_sum_preferred_height_for_width   (GtkCellAreaIter *iter,
43                                                                           gint             width);
44 static void      gtk_cell_area_box_iter_sum_preferred_height             (GtkCellAreaIter *iter);
45 static void      gtk_cell_area_box_iter_sum_preferred_width_for_height   (GtkCellAreaIter *iter,
46                                                                           gint             height);
47 static void      gtk_cell_area_box_iter_allocate_width                   (GtkCellAreaIter *iter,
48                                                                           gint             width);
49 static void      gtk_cell_area_box_iter_allocate_height                  (GtkCellAreaIter *iter,
50                                                                           gint             height);
51
52
53
54 /* CachedSize management */
55 typedef struct {
56   gint min_size;
57   gint nat_size;
58 } CachedSize;
59
60 static CachedSize *cached_size_new  (gint min_size, gint nat_size);
61 static void        cached_size_free (CachedSize *size);
62
63 struct _GtkCellAreaBoxIterPrivate
64 {
65   /* Table of per renderer CachedSizes */
66   GHashTable *base_widths;
67   GHashTable *base_heights;
68
69   /* Table of per height/width hash tables of per renderer CachedSizes */
70   GHashTable *widths;
71   GHashTable *heights;
72
73   /* Allocation info for this iter if any */
74   gint                      alloc_width;
75   gint                      alloc_height;
76   gint                      n_orientation_allocs;
77   GtkCellAreaBoxAllocation *orientation_allocs;
78 };
79
80 G_DEFINE_TYPE (GtkCellAreaBoxIter, gtk_cell_area_box_iter, GTK_TYPE_CELL_AREA_ITER);
81
82 static void
83 gtk_cell_area_box_iter_init (GtkCellAreaBoxIter *box_iter)
84 {
85   GtkCellAreaBoxIterPrivate *priv;
86
87   box_iter->priv = G_TYPE_INSTANCE_GET_PRIVATE (box_iter,
88                                                 GTK_TYPE_CELL_AREA_BOX_ITER,
89                                                 GtkCellAreaBoxIterPrivate);
90   priv = box_iter->priv;
91
92   priv->base_widths  = g_hash_table_new_full (g_direct_hash, g_direct_equal,
93                                               NULL, (GDestroyNotify)cached_size_free);
94   priv->base_heights = g_hash_table_new_full (g_direct_hash, g_direct_equal,
95                                               NULL, (GDestroyNotify)cached_size_free);
96
97   priv->widths       = g_hash_table_new_full (g_direct_hash, g_direct_equal,
98                                               NULL, (GDestroyNotify)g_hash_table_destroy);
99   priv->heights      = g_hash_table_new_full (g_direct_hash, g_direct_equal,
100                                               NULL, (GDestroyNotify)g_hash_table_destroy);
101
102   priv->alloc_width  = 0;
103   priv->alloc_height = 0;
104   priv->orientation_allocs   = NULL;
105   priv->n_orientation_allocs = 0;
106 }
107
108 static void 
109 gtk_cell_area_box_iter_class_init (GtkCellAreaBoxIterClass *class)
110 {
111   GObjectClass         *object_class = G_OBJECT_CLASS (class);
112   GtkCellAreaIterClass *iter_class   = GTK_CELL_AREA_ITER_CLASS (class);
113
114   /* GObjectClass */
115   object_class->finalize = gtk_cell_area_box_iter_finalize;
116
117   iter_class->flush_preferred_width            = gtk_cell_area_box_iter_flush_preferred_width;
118   iter_class->flush_preferred_height_for_width = gtk_cell_area_box_iter_flush_preferred_height_for_width;
119   iter_class->flush_preferred_height           = gtk_cell_area_box_iter_flush_preferred_height;
120   iter_class->flush_preferred_width_for_height = gtk_cell_area_box_iter_flush_preferred_width_for_height;
121   iter_class->flush_allocation                 = gtk_cell_area_box_iter_flush_allocation;
122
123   iter_class->sum_preferred_width            = gtk_cell_area_box_iter_sum_preferred_width;
124   iter_class->sum_preferred_height_for_width = gtk_cell_area_box_iter_sum_preferred_height_for_width;
125   iter_class->sum_preferred_height           = gtk_cell_area_box_iter_sum_preferred_height;
126   iter_class->sum_preferred_width_for_height = gtk_cell_area_box_iter_sum_preferred_width_for_height;
127
128   iter_class->allocate_width  = gtk_cell_area_box_iter_allocate_width;
129   iter_class->allocate_height = gtk_cell_area_box_iter_allocate_height;
130
131   g_type_class_add_private (object_class, sizeof (GtkCellAreaBoxIterPrivate));
132 }
133
134 /*************************************************************
135  *                      Cached Sizes                         *
136  *************************************************************/
137 static CachedSize *
138 cached_size_new (gint min_size, 
139                  gint nat_size)
140 {
141   CachedSize *size = g_slice_new (CachedSize);
142
143   size->min_size = min_size;
144   size->nat_size = nat_size;
145
146   return size;
147 }
148
149 static void
150 cached_size_free (CachedSize *size)
151 {
152   g_slice_free (CachedSize, size);
153 }
154
155 /*************************************************************
156  *                      GObjectClass                         *
157  *************************************************************/
158 static void
159 gtk_cell_area_box_iter_finalize (GObject *object)
160 {
161   GtkCellAreaBoxIter        *box_iter = GTK_CELL_AREA_BOX_ITER (object);
162   GtkCellAreaBoxIterPrivate *priv     = box_iter->priv;
163
164   g_hash_table_destroy (priv->base_widths);
165   g_hash_table_destroy (priv->base_heights);
166   g_hash_table_destroy (priv->widths);
167   g_hash_table_destroy (priv->heights);
168
169   g_free (priv->orientation_allocs);
170
171   G_OBJECT_CLASS (gtk_cell_area_box_iter_parent_class)->finalize (object);
172 }
173
174 /*************************************************************
175  *                    GtkCellAreaIterClass                   *
176  *************************************************************/
177 static void
178 gtk_cell_area_box_iter_flush_preferred_width (GtkCellAreaIter *iter)
179 {
180   GtkCellAreaBoxIter        *box_iter = GTK_CELL_AREA_BOX_ITER (iter);
181   GtkCellAreaBoxIterPrivate *priv     = box_iter->priv;
182   
183   g_hash_table_remove_all (priv->base_widths);
184
185   GTK_CELL_AREA_ITER_GET_CLASS
186     (gtk_cell_area_box_iter_parent_class)->flush_preferred_width (iter);
187 }
188
189 static void
190 gtk_cell_area_box_iter_flush_preferred_height_for_width (GtkCellAreaIter *iter,
191                                                          gint             width)
192 {
193   GtkCellAreaBoxIter        *box_iter = GTK_CELL_AREA_BOX_ITER (iter);
194   GtkCellAreaBoxIterPrivate *priv     = box_iter->priv;
195
196   /* Flush all sizes for special -1 value */
197   if (width < 0)
198     g_hash_table_remove_all (priv->heights);
199   else
200     g_hash_table_remove (priv->heights, GINT_TO_POINTER (width));
201
202   GTK_CELL_AREA_ITER_GET_CLASS
203     (gtk_cell_area_box_iter_parent_class)->flush_preferred_height_for_width (iter, width);
204 }
205
206 static void
207 gtk_cell_area_box_iter_flush_preferred_height (GtkCellAreaIter *iter)
208 {
209   GtkCellAreaBoxIter        *box_iter = GTK_CELL_AREA_BOX_ITER (iter);
210   GtkCellAreaBoxIterPrivate *priv     = box_iter->priv;
211   
212   g_hash_table_remove_all (priv->base_heights);
213
214   GTK_CELL_AREA_ITER_GET_CLASS
215     (gtk_cell_area_box_iter_parent_class)->flush_preferred_height (iter);
216 }
217
218 static void
219 gtk_cell_area_box_iter_flush_preferred_width_for_height (GtkCellAreaIter *iter,
220                                                          gint             height)
221 {
222   GtkCellAreaBoxIter        *box_iter = GTK_CELL_AREA_BOX_ITER (iter);
223   GtkCellAreaBoxIterPrivate *priv     = box_iter->priv;
224
225   /* Flush all sizes for special -1 value */
226   if (height < 0)
227     g_hash_table_remove_all (priv->widths);
228   else
229     g_hash_table_remove (priv->widths, GINT_TO_POINTER (height));
230
231   GTK_CELL_AREA_ITER_GET_CLASS
232     (gtk_cell_area_box_iter_parent_class)->flush_preferred_width_for_height (iter, height);
233 }
234
235 static void
236 gtk_cell_area_box_iter_flush_allocation (GtkCellAreaIter *iter)
237 {
238   GtkCellAreaBoxIter        *box_iter = GTK_CELL_AREA_BOX_ITER (iter);
239   GtkCellAreaBoxIterPrivate *priv     = box_iter->priv;
240
241   g_free (priv->orientation_allocs);
242   priv->orientation_allocs   = NULL;
243   priv->n_orientation_allocs = 0;
244 }
245
246 typedef struct {
247   gint min_size;
248   gint nat_size;
249   gint spacing;
250 } AccumData;
251
252 static void
253 sum_base_size (gpointer    group_id,
254                CachedSize *size,
255                AccumData  *accum)
256 {
257   if (accum->min_size > 0)
258     {
259       accum->min_size += accum->spacing;
260       accum->nat_size += accum->spacing;
261     }
262
263   accum->min_size += size->min_size;
264   accum->nat_size += size->nat_size;
265 }
266
267 static void
268 sum_for_size (gpointer    group_id,
269               CachedSize *size,
270               AccumData  *accum)
271 {
272   accum->min_size = MAX (accum->min_size, size->min_size);
273   accum->nat_size = MAX (accum->nat_size, size->nat_size);
274 }
275
276 static void
277 gtk_cell_area_box_iter_sum_preferred_width (GtkCellAreaIter *iter)
278 {
279   GtkCellAreaBoxIter        *box_iter = GTK_CELL_AREA_BOX_ITER (iter);
280   GtkCellAreaBoxIterPrivate *priv     = box_iter->priv;
281   GtkCellArea               *area;
282   AccumData                  accum    = { 0, };
283
284   area          = gtk_cell_area_iter_get_area (iter);
285   accum.spacing = gtk_cell_area_box_get_spacing (GTK_CELL_AREA_BOX (area));
286
287   g_hash_table_foreach (priv->base_widths, (GHFunc)sum_base_size, &accum);
288   gtk_cell_area_iter_push_preferred_width (iter, accum.min_size, accum.nat_size);
289 }
290
291 static void
292 gtk_cell_area_box_iter_sum_preferred_height_for_width (GtkCellAreaIter *iter,
293                                                        gint             width)
294 {
295   GtkCellAreaBoxIter        *box_iter = GTK_CELL_AREA_BOX_ITER (iter);
296   GtkCellAreaBoxIterPrivate *priv     = box_iter->priv;
297   GHashTable                *group_table;
298   AccumData                  accum    = { 0, };
299
300   group_table = g_hash_table_lookup (priv->heights, GINT_TO_POINTER (width));
301
302   if (group_table)
303     {
304       g_hash_table_foreach (priv->base_widths, (GHFunc)sum_for_size, &accum);
305       gtk_cell_area_iter_push_preferred_height_for_width (iter, width, accum.min_size, accum.nat_size);
306     }
307 }
308
309 static void
310 gtk_cell_area_box_iter_sum_preferred_height (GtkCellAreaIter *iter)
311 {
312   GtkCellAreaBoxIter        *box_iter = GTK_CELL_AREA_BOX_ITER (iter);
313   GtkCellAreaBoxIterPrivate *priv     = box_iter->priv;
314   GtkCellArea               *area;
315   AccumData                  accum    = { 0, };
316
317   area          = gtk_cell_area_iter_get_area (iter);
318   accum.spacing = gtk_cell_area_box_get_spacing (GTK_CELL_AREA_BOX (area));
319
320   g_hash_table_foreach (priv->base_heights, (GHFunc)sum_base_size, &accum);
321   gtk_cell_area_iter_push_preferred_width (iter, accum.min_size, accum.nat_size);
322 }
323
324 static void
325 gtk_cell_area_box_iter_sum_preferred_width_for_height (GtkCellAreaIter *iter,
326                                                        gint             height)
327 {
328   GtkCellAreaBoxIter        *box_iter = GTK_CELL_AREA_BOX_ITER (iter);
329   GtkCellAreaBoxIterPrivate *priv     = box_iter->priv;
330   GHashTable                *group_table;
331   AccumData                  accum    = { 0, };
332
333   group_table = g_hash_table_lookup (priv->widths, GINT_TO_POINTER (height));
334
335   if (group_table)
336     {
337       g_hash_table_foreach (priv->base_widths, (GHFunc)sum_for_size, &accum);
338       gtk_cell_area_iter_push_preferred_width_for_height (iter, height, accum.min_size, accum.nat_size);
339     }
340 }
341
342 static void
343 gtk_cell_area_box_iter_allocate_width (GtkCellAreaIter *iter,
344                                        gint             width)
345 {
346   GtkCellAreaBoxIter        *box_iter = GTK_CELL_AREA_BOX_ITER (iter);
347   GtkCellAreaBoxIterPrivate *priv     = box_iter->priv;
348   GtkCellArea               *area;
349   GtkOrientation             orientation;
350
351   area        = gtk_cell_area_iter_get_area (iter);
352   orientation = gtk_orientable_get_orientation (GTK_ORIENTABLE (area));
353
354   if (orientation == GTK_ORIENTATION_HORIZONTAL)
355     {
356       g_free (priv->orientation_allocs);
357
358       priv->orientation_allocs = 
359         gtk_cell_area_box_allocate (GTK_CELL_AREA_BOX (area), box_iter, width, 
360                                     &priv->n_orientation_allocs);
361     }
362
363   GTK_CELL_AREA_ITER_GET_CLASS (iter)->allocate_width (iter, width);
364 }
365
366 static void
367 gtk_cell_area_box_iter_allocate_height (GtkCellAreaIter *iter,
368                                         gint             height)
369 {
370   GtkCellAreaBoxIter        *box_iter = GTK_CELL_AREA_BOX_ITER (iter);
371   GtkCellAreaBoxIterPrivate *priv     = box_iter->priv;
372   GtkCellArea               *area;
373   GtkOrientation             orientation;
374
375   area        = gtk_cell_area_iter_get_area (iter);
376   orientation = gtk_orientable_get_orientation (GTK_ORIENTABLE (area));
377
378   if (orientation == GTK_ORIENTATION_VERTICAL)
379     {
380       g_free (priv->orientation_allocs);
381
382       priv->orientation_allocs = 
383         gtk_cell_area_box_allocate (GTK_CELL_AREA_BOX (area), box_iter, height, 
384                                     &priv->n_orientation_allocs);
385     }
386
387   GTK_CELL_AREA_ITER_GET_CLASS (iter)->allocate_height (iter, height);
388 }
389
390 /*************************************************************
391  *                            API                            *
392  *************************************************************/
393
394 void
395 gtk_cell_area_box_iter_push_group_width (GtkCellAreaBoxIter *box_iter,
396                                          gint                group_id,
397                                          gint                minimum_width,
398                                          gint                natural_width)
399 {
400   GtkCellAreaBoxIterPrivate *priv;
401   CachedSize                *size;
402
403   g_return_if_fail (GTK_IS_CELL_AREA_BOX_ITER (box_iter));
404
405   priv = box_iter->priv;
406   size = g_hash_table_lookup (priv->base_widths, GINT_TO_POINTER (group_id));
407
408   if (!size)
409     {
410       size = cached_size_new (minimum_width, natural_width);
411       g_hash_table_insert (priv->base_widths, GINT_TO_POINTER (group_id), size);
412     }
413   else
414     {
415       size->min_size = MAX (size->min_size, minimum_width);
416       size->nat_size = MAX (size->nat_size, natural_width);
417     }
418 }
419
420 void
421 gtk_cell_area_box_iter_push_group_height_for_width  (GtkCellAreaBoxIter *box_iter,
422                                                      gint                group_id,
423                                                      gint                for_width,
424                                                      gint                minimum_height,
425                                                      gint                natural_height)
426 {
427   GtkCellAreaBoxIterPrivate *priv;
428   GHashTable                *group_table;
429   CachedSize                *size;
430
431   g_return_if_fail (GTK_IS_CELL_AREA_BOX_ITER (box_iter));
432
433   priv        = box_iter->priv;
434   group_table = g_hash_table_lookup (priv->heights, GINT_TO_POINTER (for_width));
435
436   if (!group_table)
437     {
438       group_table = g_hash_table_new_full (g_direct_hash, g_direct_equal,
439                                           NULL, (GDestroyNotify)cached_size_free);
440
441       g_hash_table_insert (priv->heights, GINT_TO_POINTER (for_width), group_table);
442     }
443
444   size = g_hash_table_lookup (group_table, GINT_TO_POINTER (group_id));
445
446   if (!size)
447     {
448       size = cached_size_new (minimum_height, natural_height);
449       g_hash_table_insert (group_table, GINT_TO_POINTER (group_id), size);
450     }
451   else
452     {
453       size->min_size = MAX (size->min_size, minimum_height);
454       size->nat_size = MAX (size->nat_size, natural_height);
455     }
456 }
457
458 void
459 gtk_cell_area_box_iter_push_group_height (GtkCellAreaBoxIter *box_iter,
460                                           gint                group_id,
461                                           gint                minimum_height,
462                                           gint                natural_height)
463 {
464   GtkCellAreaBoxIterPrivate *priv;
465   CachedSize                *size;
466
467   g_return_if_fail (GTK_IS_CELL_AREA_BOX_ITER (box_iter));
468
469   priv = box_iter->priv;
470   size = g_hash_table_lookup (priv->base_heights, GINT_TO_POINTER (group_id));
471
472   if (!size)
473     {
474       size = cached_size_new (minimum_height, natural_height);
475       g_hash_table_insert (priv->base_widths, GINT_TO_POINTER (group_id), size);
476     }
477   else
478     {
479       size->min_size = MAX (size->min_size, minimum_height);
480       size->nat_size = MAX (size->nat_size, natural_height);
481     }
482 }
483
484 void
485 gtk_cell_area_box_iter_push_group_width_for_height (GtkCellAreaBoxIter *box_iter,
486                                                     gint                group_id,
487                                                     gint                for_height,
488                                                     gint                minimum_width,
489                                                     gint                natural_width)
490 {
491   GtkCellAreaBoxIterPrivate *priv;
492   GHashTable                *group_table;
493   CachedSize                *size;
494
495   g_return_if_fail (GTK_IS_CELL_AREA_BOX_ITER (box_iter));
496
497   priv        = box_iter->priv;
498   group_table = g_hash_table_lookup (priv->widths, GINT_TO_POINTER (for_height));
499
500   if (!group_table)
501     {
502       group_table = g_hash_table_new_full (g_direct_hash, g_direct_equal,
503                                           NULL, (GDestroyNotify)cached_size_free);
504
505       g_hash_table_insert (priv->widths, GINT_TO_POINTER (for_height), group_table);
506     }
507
508   size = g_hash_table_lookup (group_table, GINT_TO_POINTER (group_id));
509
510   if (!size)
511     {
512       size = cached_size_new (minimum_width, natural_width);
513       g_hash_table_insert (group_table, GINT_TO_POINTER (group_id), size);
514     }
515   else
516     {
517       size->min_size = MAX (size->min_size, minimum_width);
518       size->nat_size = MAX (size->nat_size, natural_width);
519     }
520 }
521
522 void
523 gtk_cell_area_box_iter_get_group_width (GtkCellAreaBoxIter *box_iter,
524                                         gint                group_id,
525                                         gint               *minimum_width,
526                                         gint               *natural_width)
527 {
528   GtkCellAreaBoxIterPrivate *priv;
529   CachedSize                *size;
530
531   g_return_if_fail (GTK_IS_CELL_AREA_BOX_ITER (box_iter));
532
533   priv = box_iter->priv;
534   size = g_hash_table_lookup (priv->base_widths, GINT_TO_POINTER (group_id));
535
536   if (size)
537     {
538       if (minimum_width)
539         *minimum_width = size->min_size;
540
541       if (natural_width)
542         *natural_width = size->nat_size;
543     }
544   else
545     {
546       if (minimum_width)
547         *minimum_width = -1;
548
549       if (natural_width)
550         *natural_width = -1;      
551     }
552 }
553
554 void
555 gtk_cell_area_box_iter_get_group_height_for_width (GtkCellAreaBoxIter *box_iter,
556                                                    gint                group_id,
557                                                    gint                for_width,
558                                                    gint               *minimum_height,
559                                                    gint               *natural_height)
560 {
561   GtkCellAreaBoxIterPrivate *priv;
562   GHashTable                *group_table;
563   CachedSize                *size = NULL;
564
565   g_return_if_fail (GTK_IS_CELL_AREA_BOX_ITER (box_iter));
566
567   priv        = box_iter->priv;
568   group_table = g_hash_table_lookup (priv->heights, GINT_TO_POINTER (for_width));
569
570   if (group_table)
571     size = g_hash_table_lookup (group_table, GINT_TO_POINTER (group_id));
572
573   if (size)
574     {
575       if (minimum_height)
576         *minimum_height = size->min_size;
577
578       if (natural_height)
579         *natural_height = size->nat_size;
580     }
581   else
582     {
583       if (minimum_height)
584         *minimum_height = -1;
585
586       if (natural_height)
587         *natural_height = -1;      
588     }
589 }
590
591 void
592 gtk_cell_area_box_iter_get_group_height (GtkCellAreaBoxIter *box_iter,
593                                          gint                group_id,
594                                          gint               *minimum_height,
595                                          gint               *natural_height)
596 {
597   GtkCellAreaBoxIterPrivate *priv;
598   CachedSize                *size;
599
600   g_return_if_fail (GTK_IS_CELL_AREA_BOX_ITER (box_iter));
601
602   priv = box_iter->priv;
603   size = g_hash_table_lookup (priv->base_heights, GINT_TO_POINTER (group_id));
604
605   if (size)
606     {
607       if (minimum_height)
608         *minimum_height = size->min_size;
609
610       if (natural_height)
611         *natural_height = size->nat_size;
612     }
613   else
614     {
615       if (minimum_height)
616         *minimum_height = -1;
617
618       if (natural_height)
619         *natural_height = -1;      
620     }
621 }
622
623 void
624 gtk_cell_area_box_iter_get_group_width_for_height (GtkCellAreaBoxIter *box_iter,
625                                                    gint                group_id,
626                                                    gint                for_height,
627                                                    gint               *minimum_width,
628                                                    gint               *natural_width)
629 {
630   GtkCellAreaBoxIterPrivate *priv;
631   GHashTable                *group_table;
632   CachedSize                *size = NULL;
633
634   g_return_if_fail (GTK_IS_CELL_AREA_BOX_ITER (box_iter));
635
636   priv        = box_iter->priv;
637   group_table = g_hash_table_lookup (priv->widths, GINT_TO_POINTER (for_height));
638
639   if (group_table)
640     size = g_hash_table_lookup (group_table, GINT_TO_POINTER (group_id));
641
642   if (size)
643     {
644       if (minimum_width)
645         *minimum_width = size->min_size;
646
647       if (natural_width)
648         *natural_width = size->nat_size;
649     }
650   else
651     {
652       if (minimum_width)
653         *minimum_width = -1;
654
655       if (natural_width)
656         *natural_width = -1;      
657     }
658 }
659
660 static void
661 fill_requested_sizes (gpointer          group_id_ptr,
662                       CachedSize       *cached_size,
663                       GtkRequestedSize *requested)
664 {
665   gint group_id = GPOINTER_TO_INT (group_id_ptr);
666
667   requested[group_id].data         = group_id_ptr;
668   requested[group_id].minimum_size = cached_size->min_size;
669   requested[group_id].natural_size = cached_size->nat_size;
670 }
671
672 GtkRequestedSize *
673 gtk_cell_area_box_iter_get_widths (GtkCellAreaBoxIter *box_iter,
674                                    gint               *n_widths)
675 {
676   GtkCellAreaBoxIterPrivate *priv;
677   GtkRequestedSize          *widths;
678
679   g_return_val_if_fail (GTK_IS_CELL_AREA_BOX_ITER (box_iter), NULL);
680
681   priv = box_iter->priv;
682
683   *n_widths = g_hash_table_size (priv->widths);
684   widths    = g_new (GtkRequestedSize, *n_widths);
685
686   g_hash_table_foreach (priv->widths, (GHFunc)fill_requested_sizes, widths);
687
688   return widths;
689 }
690
691 GtkRequestedSize *
692 gtk_cell_area_box_iter_get_heights (GtkCellAreaBoxIter *box_iter,
693                                     gint               *n_heights)
694 {
695   GtkCellAreaBoxIterPrivate *priv;
696   GtkRequestedSize          *heights;
697
698   g_return_val_if_fail (GTK_IS_CELL_AREA_BOX_ITER (box_iter), NULL);
699
700   priv = box_iter->priv;
701
702   *n_heights = g_hash_table_size (priv->heights);
703   heights    = g_new (GtkRequestedSize, *n_heights);
704
705   g_hash_table_foreach (priv->heights, (GHFunc)fill_requested_sizes, heights);
706
707   return heights;
708 }
709
710 G_CONST_RETURN GtkCellAreaBoxAllocation *
711 gtk_cell_area_box_iter_get_orientation_allocs (GtkCellAreaBoxIter *iter,
712                                                gint               *n_allocs)
713 {
714   GtkCellAreaBoxIterPrivate *priv;
715
716   g_return_val_if_fail (GTK_IS_CELL_AREA_BOX_ITER (iter), NULL);
717   
718   priv = iter->priv;
719
720   *n_allocs = priv->n_orientation_allocs;
721
722   return priv->orientation_allocs;
723 }