source: trunk/third/gtk/gtk/gtktable.c @ 15781

Revision 15781, 40.4 KB checked in by ghudson, 24 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r15780, which included commits to RCS files with non-trunk default branches.
RevLine 
[14481]1/* GTK - The GIMP Toolkit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
18 */
19
20/*
21 * Modified by the GTK+ Team and others 1997-1999.  See the AUTHORS
22 * file for a list of people on the GTK+ Team.  See the ChangeLog
23 * files for a list of changes.  These files are distributed with
24 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
25 */
26
27#include "gtktable.h"
28
29enum
30{
31  ARG_0,
32  ARG_N_ROWS,
33  ARG_N_COLUMNS,
34  ARG_COLUMN_SPACING,
35  ARG_ROW_SPACING,
36  ARG_HOMOGENEOUS
37};
38
39enum
40{
41  CHILD_ARG_0,
42  CHILD_ARG_LEFT_ATTACH,
43  CHILD_ARG_RIGHT_ATTACH,
44  CHILD_ARG_TOP_ATTACH,
45  CHILD_ARG_BOTTOM_ATTACH,
46  CHILD_ARG_X_OPTIONS,
47  CHILD_ARG_Y_OPTIONS,
48  CHILD_ARG_X_PADDING,
49  CHILD_ARG_Y_PADDING
50};
51 
52
53static void gtk_table_class_init    (GtkTableClass  *klass);
54static void gtk_table_init          (GtkTable       *table);
55static void gtk_table_finalize      (GtkObject      *object);
56static void gtk_table_map           (GtkWidget      *widget);
57static void gtk_table_unmap         (GtkWidget      *widget);
58static void gtk_table_draw          (GtkWidget      *widget,
59                                     GdkRectangle   *area);
60static gint gtk_table_expose        (GtkWidget      *widget,
61                                     GdkEventExpose *event);
62static void gtk_table_size_request  (GtkWidget      *widget,
63                                     GtkRequisition *requisition);
64static void gtk_table_size_allocate (GtkWidget      *widget,
65                                     GtkAllocation  *allocation);
66static void gtk_table_add           (GtkContainer   *container,
67                                     GtkWidget      *widget);
68static void gtk_table_remove        (GtkContainer   *container,
69                                     GtkWidget      *widget);
70static void gtk_table_forall        (GtkContainer   *container,
71                                     gboolean        include_internals,
72                                     GtkCallback     callback,
73                                     gpointer        callback_data);
74static void gtk_table_get_arg       (GtkObject      *object,
75                                     GtkArg         *arg,
76                                     guint           arg_id);
77static void gtk_table_set_arg       (GtkObject      *object,
78                                     GtkArg         *arg,
79                                     guint           arg_id);
80static void gtk_table_set_child_arg (GtkContainer   *container,
81                                     GtkWidget      *child,
82                                     GtkArg         *arg,
83                                     guint           arg_id);
84static void gtk_table_get_child_arg (GtkContainer   *container,
85                                     GtkWidget      *child,
86                                     GtkArg         *arg,
87                                     guint           arg_id);
88static GtkType gtk_table_child_type (GtkContainer   *container);
89
90
91static void gtk_table_size_request_init  (GtkTable *table);
92static void gtk_table_size_request_pass1 (GtkTable *table);
93static void gtk_table_size_request_pass2 (GtkTable *table);
94static void gtk_table_size_request_pass3 (GtkTable *table);
95
96static void gtk_table_size_allocate_init  (GtkTable *table);
97static void gtk_table_size_allocate_pass1 (GtkTable *table);
98static void gtk_table_size_allocate_pass2 (GtkTable *table);
99
100
101static GtkContainerClass *parent_class = NULL;
102
103
104GtkType
105gtk_table_get_type (void)
106{
107  static GtkType table_type = 0;
108 
109  if (!table_type)
110    {
111      static const GtkTypeInfo table_info =
112      {
113        "GtkTable",
114        sizeof (GtkTable),
115        sizeof (GtkTableClass),
116        (GtkClassInitFunc) gtk_table_class_init,
117        (GtkObjectInitFunc) gtk_table_init,
118        /* reserved_1 */ NULL,
119        /* reserved_2 */ NULL,
120        (GtkClassInitFunc) NULL,
121      };
122     
123      table_type = gtk_type_unique (gtk_container_get_type (), &table_info);
124    }
125 
126  return table_type;
127}
128
129static void
130gtk_table_class_init (GtkTableClass *class)
131{
132  GtkObjectClass *object_class;
133  GtkWidgetClass *widget_class;
134  GtkContainerClass *container_class;
135 
136  object_class = (GtkObjectClass*) class;
137  widget_class = (GtkWidgetClass*) class;
138  container_class = (GtkContainerClass*) class;
139 
140  parent_class = gtk_type_class (gtk_container_get_type ());
141 
142  gtk_object_add_arg_type ("GtkTable::n_rows", GTK_TYPE_UINT, GTK_ARG_READWRITE, ARG_N_ROWS);
143  gtk_object_add_arg_type ("GtkTable::n_columns", GTK_TYPE_UINT, GTK_ARG_READWRITE, ARG_N_COLUMNS);
144  gtk_object_add_arg_type ("GtkTable::row_spacing", GTK_TYPE_UINT, GTK_ARG_READWRITE, ARG_ROW_SPACING);
145  gtk_object_add_arg_type ("GtkTable::column_spacing", GTK_TYPE_UINT, GTK_ARG_READWRITE, ARG_COLUMN_SPACING);
146  gtk_object_add_arg_type ("GtkTable::homogeneous", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_HOMOGENEOUS);
147  gtk_container_add_child_arg_type ("GtkTable::left_attach", GTK_TYPE_UINT, GTK_ARG_READWRITE, CHILD_ARG_LEFT_ATTACH);
148  gtk_container_add_child_arg_type ("GtkTable::right_attach", GTK_TYPE_UINT, GTK_ARG_READWRITE, CHILD_ARG_RIGHT_ATTACH);
149  gtk_container_add_child_arg_type ("GtkTable::top_attach", GTK_TYPE_UINT, GTK_ARG_READWRITE, CHILD_ARG_TOP_ATTACH);
150  gtk_container_add_child_arg_type ("GtkTable::bottom_attach", GTK_TYPE_UINT, GTK_ARG_READWRITE, CHILD_ARG_BOTTOM_ATTACH);
151  gtk_container_add_child_arg_type ("GtkTable::x_options", GTK_TYPE_ATTACH_OPTIONS, GTK_ARG_READWRITE, CHILD_ARG_X_OPTIONS);
152  gtk_container_add_child_arg_type ("GtkTable::y_options", GTK_TYPE_ATTACH_OPTIONS, GTK_ARG_READWRITE, CHILD_ARG_Y_OPTIONS);
153  gtk_container_add_child_arg_type ("GtkTable::x_padding", GTK_TYPE_UINT, GTK_ARG_READWRITE, CHILD_ARG_X_PADDING);
154  gtk_container_add_child_arg_type ("GtkTable::y_padding", GTK_TYPE_UINT, GTK_ARG_READWRITE, CHILD_ARG_Y_PADDING);
155
156  object_class->get_arg = gtk_table_get_arg;
157  object_class->set_arg = gtk_table_set_arg;
158  object_class->finalize = gtk_table_finalize;
159 
160  widget_class->map = gtk_table_map;
161  widget_class->unmap = gtk_table_unmap;
162  widget_class->draw = gtk_table_draw;
163  widget_class->expose_event = gtk_table_expose;
164  widget_class->size_request = gtk_table_size_request;
165  widget_class->size_allocate = gtk_table_size_allocate;
166 
167  container_class->add = gtk_table_add;
168  container_class->remove = gtk_table_remove;
169  container_class->forall = gtk_table_forall;
170  container_class->child_type = gtk_table_child_type;
171  container_class->set_child_arg = gtk_table_set_child_arg;
172  container_class->get_child_arg = gtk_table_get_child_arg;
173}
174
175static GtkType
176gtk_table_child_type (GtkContainer   *container)
177{
178  return GTK_TYPE_WIDGET;
179}
180
181static void
182gtk_table_get_arg (GtkObject      *object,
183                   GtkArg         *arg,
184                   guint           arg_id)
185{
186  GtkTable *table;
187
188  table = GTK_TABLE (object);
189
190  switch (arg_id)
191    {
192    case ARG_N_ROWS:
193      GTK_VALUE_UINT (*arg) = table->nrows;
194      break;
195    case ARG_N_COLUMNS:
196      GTK_VALUE_UINT (*arg) = table->ncols;
197      break;
198    case ARG_ROW_SPACING:
199      GTK_VALUE_UINT (*arg) = table->row_spacing;
200      break;
201    case ARG_COLUMN_SPACING:
202      GTK_VALUE_UINT (*arg) = table->column_spacing;
203      break;
204    case ARG_HOMOGENEOUS:
205      GTK_VALUE_BOOL (*arg) = table->homogeneous;
206      break;
207    default:
208      arg->type = GTK_TYPE_INVALID;
209      break;
210    }
211}
212
213static void
214gtk_table_set_arg (GtkObject      *object,
215                   GtkArg         *arg,
216                   guint           arg_id)
217{
218  GtkTable *table;
219
220  table = GTK_TABLE (object);
221
222  switch (arg_id)
223    {
224    case ARG_N_ROWS:
225      gtk_table_resize (table, GTK_VALUE_UINT (*arg), table->ncols);
226      break;
227    case ARG_N_COLUMNS:
228      gtk_table_resize (table, table->nrows, GTK_VALUE_UINT (*arg));
229      break;
230    case ARG_ROW_SPACING:
231      gtk_table_set_row_spacings (table, GTK_VALUE_UINT (*arg));
232      break;
233    case ARG_COLUMN_SPACING:
234      gtk_table_set_col_spacings (table, GTK_VALUE_UINT (*arg));
235      break;
236    case ARG_HOMOGENEOUS:
237      gtk_table_set_homogeneous (table, GTK_VALUE_BOOL (*arg));
238      break;
239    default:
240      break;
241    }
242}
243
244static void
245gtk_table_set_child_arg (GtkContainer   *container,
246                         GtkWidget      *child,
247                         GtkArg         *arg,
248                         guint           arg_id)
249{
250  GtkTable *table;
251  GtkTableChild *table_child;
252  GList *list;
253
254  table = GTK_TABLE (container);
255  table_child = NULL;
256  for (list = table->children; list; list = list->next)
257    {
258      table_child = list->data;
259
260      if (table_child->widget == child)
261        break;
262    }
263  if (!list)
264    return;
265
266  switch (arg_id)
267    {
268    case CHILD_ARG_LEFT_ATTACH:
269      table_child->left_attach = GTK_VALUE_UINT (*arg);
270      if (table_child->right_attach <= table_child->left_attach)
271        table_child->right_attach = table_child->left_attach + 1;
272      if (table_child->right_attach >= table->ncols)
273        gtk_table_resize (table, table->ncols, table_child->right_attach);
274      break;
275    case CHILD_ARG_RIGHT_ATTACH:
276      if (GTK_VALUE_UINT (*arg) > 0)
277        {
278          table_child->right_attach = GTK_VALUE_UINT (*arg);
279          if (table_child->right_attach <= table_child->left_attach)
280            table_child->left_attach = table_child->right_attach - 1;
281          if (table_child->right_attach >= table->ncols)
282            gtk_table_resize (table, table->ncols, table_child->right_attach);
283        }
284      break;
285    case CHILD_ARG_TOP_ATTACH:
286      table_child->top_attach = GTK_VALUE_UINT (*arg);
287      if (table_child->bottom_attach <= table_child->top_attach)
288        table_child->bottom_attach = table_child->top_attach + 1;
289      if (table_child->bottom_attach >= table->nrows)
290        gtk_table_resize (table, table_child->bottom_attach, table->ncols);
291      break;
292    case CHILD_ARG_BOTTOM_ATTACH:
293      if (GTK_VALUE_UINT (*arg) > 0)
294        {
295          table_child->bottom_attach = GTK_VALUE_UINT (*arg);
296          if (table_child->bottom_attach <= table_child->top_attach)
297            table_child->top_attach = table_child->bottom_attach - 1;
298          if (table_child->bottom_attach >= table->nrows)
299            gtk_table_resize (table, table_child->bottom_attach, table->ncols);
300        }
301      break;
302    case CHILD_ARG_X_OPTIONS:
303      table_child->xexpand = (GTK_VALUE_FLAGS (*arg) & GTK_EXPAND) != 0;
304      table_child->xshrink = (GTK_VALUE_FLAGS (*arg) & GTK_SHRINK) != 0;
305      table_child->xfill = (GTK_VALUE_FLAGS (*arg) & GTK_FILL) != 0;
306      break;
307    case CHILD_ARG_Y_OPTIONS:
308      table_child->yexpand = (GTK_VALUE_FLAGS (*arg) & GTK_EXPAND) != 0;
309      table_child->yshrink = (GTK_VALUE_FLAGS (*arg) & GTK_SHRINK) != 0;
310      table_child->yfill = (GTK_VALUE_FLAGS (*arg) & GTK_FILL) != 0;
311      break;
312    case CHILD_ARG_X_PADDING:
313      table_child->xpadding = GTK_VALUE_UINT (*arg);
314      break;
315    case CHILD_ARG_Y_PADDING:
316      table_child->ypadding = GTK_VALUE_UINT (*arg);
317      break;
318    default:
319      break;
320    }
321  if (GTK_WIDGET_VISIBLE (child) && GTK_WIDGET_VISIBLE (table))
322    gtk_widget_queue_resize (child);
323}
324
325static void
326gtk_table_get_child_arg (GtkContainer   *container,
327                         GtkWidget      *child,
328                         GtkArg         *arg,
329                         guint           arg_id)
330{
331  GtkTable *table;
332  GtkTableChild *table_child;
333  GList *list;
334
335  table = GTK_TABLE (container);
336  table_child = NULL;
337  for (list = table->children; list; list = list->next)
338    {
339      table_child = list->data;
340
341      if (table_child->widget == child)
342        break;
343    }
344  if (!list)
345    return;
346
347  switch (arg_id)
348    {
349    case CHILD_ARG_LEFT_ATTACH:
350      GTK_VALUE_UINT (*arg) = table_child->left_attach;
351      break;
352    case CHILD_ARG_RIGHT_ATTACH:
353      GTK_VALUE_UINT (*arg) = table_child->right_attach;
354      break;
355    case CHILD_ARG_TOP_ATTACH:
356      GTK_VALUE_UINT (*arg) = table_child->top_attach;
357      break;
358    case CHILD_ARG_BOTTOM_ATTACH:
359      GTK_VALUE_UINT (*arg) = table_child->bottom_attach;
360      break;
361    case CHILD_ARG_X_OPTIONS:
362      GTK_VALUE_FLAGS (*arg) = (table_child->xexpand * GTK_EXPAND |
363                                table_child->xshrink * GTK_SHRINK |
364                                table_child->xfill * GTK_FILL);
365      break;
366    case CHILD_ARG_Y_OPTIONS:
367      GTK_VALUE_FLAGS (*arg) = (table_child->yexpand * GTK_EXPAND |
368                                table_child->yshrink * GTK_SHRINK |
369                                table_child->yfill * GTK_FILL);
370      break;
371    case CHILD_ARG_X_PADDING:
372      GTK_VALUE_UINT (*arg) = table_child->xpadding;
373      break;
374    case CHILD_ARG_Y_PADDING:
375      GTK_VALUE_UINT (*arg) = table_child->ypadding;
376      break;
377    default:
378      arg->type = GTK_TYPE_INVALID;
379      break;
380    }
381}
382
383static void
384gtk_table_init (GtkTable *table)
385{
386  GTK_WIDGET_SET_FLAGS (table, GTK_NO_WINDOW);
387 
388  table->children = NULL;
389  table->rows = NULL;
390  table->cols = NULL;
391  table->nrows = 0;
392  table->ncols = 0;
393  table->column_spacing = 0;
394  table->row_spacing = 0;
395  table->homogeneous = FALSE;
396
397  gtk_table_resize (table, 1, 1);
398}
399
400GtkWidget*
401gtk_table_new (guint    rows,
402               guint    columns,
403               gboolean homogeneous)
404{
405  GtkTable *table;
406
407  if (rows == 0)
408          rows = 1;
409  if (columns == 0)
410          columns = 1;
411 
412  table = gtk_type_new (gtk_table_get_type ());
413 
414  table->homogeneous = (homogeneous ? TRUE : FALSE);
415
416  gtk_table_resize (table, rows, columns);
417 
418  return GTK_WIDGET (table);
419}
420
421void
422gtk_table_resize (GtkTable *table,
423                  guint     n_rows,
424                  guint     n_cols)
425{
426  g_return_if_fail (table != NULL);
427  g_return_if_fail (GTK_IS_TABLE (table));
428
429  n_rows = MAX (n_rows, 1);
430  n_cols = MAX (n_cols, 1);
431 
432  if (n_rows != table->nrows ||
433      n_cols != table->ncols)
434    {
435      GList *list;
436     
437      for (list = table->children; list; list = list->next)
438        {
439          GtkTableChild *child;
440         
441          child = list->data;
442         
443          n_rows = MAX (n_rows, child->bottom_attach);
444          n_cols = MAX (n_cols, child->right_attach);
445        }
446     
447      if (n_rows != table->nrows)
448        {
449          guint i;
450
451          i = table->nrows;
452          table->nrows = n_rows;
453          table->rows = g_realloc (table->rows, table->nrows * sizeof (GtkTableRowCol));
454         
455          for (; i < table->nrows; i++)
456            {
457              table->rows[i].requisition = 0;
458              table->rows[i].allocation = 0;
459              table->rows[i].spacing = table->row_spacing;
460              table->rows[i].need_expand = 0;
461              table->rows[i].need_shrink = 0;
462              table->rows[i].expand = 0;
463              table->rows[i].shrink = 0;
464            }
465        }
466
467      if (n_cols != table->ncols)
468        {
469          guint i;
470
471          i = table->ncols;
472          table->ncols = n_cols;
473          table->cols = g_realloc (table->cols, table->ncols * sizeof (GtkTableRowCol));
474         
475          for (; i < table->ncols; i++)
476            {
477              table->cols[i].requisition = 0;
478              table->cols[i].allocation = 0;
479              table->cols[i].spacing = table->column_spacing;
480              table->cols[i].need_expand = 0;
481              table->cols[i].need_shrink = 0;
482              table->cols[i].expand = 0;
483              table->cols[i].shrink = 0;
484            }
485        }
486    }
487}
488
489void
490gtk_table_attach (GtkTable        *table,
491                  GtkWidget       *child,
492                  guint            left_attach,
493                  guint            right_attach,
494                  guint            top_attach,
495                  guint            bottom_attach,
496                  GtkAttachOptions xoptions,
497                  GtkAttachOptions yoptions,
498                  guint            xpadding,
499                  guint            ypadding)
500{
501  GtkTableChild *table_child;
502 
503  g_return_if_fail (table != NULL);
504  g_return_if_fail (GTK_IS_TABLE (table));
505  g_return_if_fail (child != NULL);
506  g_return_if_fail (GTK_IS_WIDGET (child));
507  g_return_if_fail (child->parent == NULL);
508 
509  /* g_return_if_fail (left_attach >= 0); */
510  g_return_if_fail (left_attach < right_attach);
511  /* g_return_if_fail (top_attach >= 0); */
512  g_return_if_fail (top_attach < bottom_attach);
513 
514  if (right_attach >= table->ncols)
515    gtk_table_resize (table, table->nrows, right_attach);
516 
517  if (bottom_attach >= table->nrows)
518    gtk_table_resize (table, bottom_attach, table->ncols);
519 
520  table_child = g_new (GtkTableChild, 1);
521  table_child->widget = child;
522  table_child->left_attach = left_attach;
523  table_child->right_attach = right_attach;
524  table_child->top_attach = top_attach;
525  table_child->bottom_attach = bottom_attach;
526  table_child->xexpand = (xoptions & GTK_EXPAND) != 0;
527  table_child->xshrink = (xoptions & GTK_SHRINK) != 0;
528  table_child->xfill = (xoptions & GTK_FILL) != 0;
529  table_child->xpadding = xpadding;
530  table_child->yexpand = (yoptions & GTK_EXPAND) != 0;
531  table_child->yshrink = (yoptions & GTK_SHRINK) != 0;
532  table_child->yfill = (yoptions & GTK_FILL) != 0;
533  table_child->ypadding = ypadding;
534 
535  table->children = g_list_prepend (table->children, table_child);
536 
537  gtk_widget_set_parent (child, GTK_WIDGET (table));
538 
539  if (GTK_WIDGET_REALIZED (child->parent))
540    gtk_widget_realize (child);
541
542  if (GTK_WIDGET_VISIBLE (child->parent) && GTK_WIDGET_VISIBLE (child))
543    {
544      if (GTK_WIDGET_MAPPED (child->parent))
545        gtk_widget_map (child);
546
547      gtk_widget_queue_resize (child);
548    }
549}
550
551void
552gtk_table_attach_defaults (GtkTable  *table,
553                           GtkWidget *widget,
554                           guint      left_attach,
555                           guint      right_attach,
556                           guint      top_attach,
557                           guint      bottom_attach)
558{
559  gtk_table_attach (table, widget,
560                    left_attach, right_attach,
561                    top_attach, bottom_attach,
562                    GTK_EXPAND | GTK_FILL,
563                    GTK_EXPAND | GTK_FILL,
564                    0, 0);
565}
566
567void
568gtk_table_set_row_spacing (GtkTable *table,
569                           guint     row,
570                           guint     spacing)
571{
572  g_return_if_fail (table != NULL);
573  g_return_if_fail (GTK_IS_TABLE (table));
[15780]574  g_return_if_fail (row < table->nrows);
[14481]575 
576  if (table->rows[row].spacing != spacing)
577    {
578      table->rows[row].spacing = spacing;
579     
580      if (GTK_WIDGET_VISIBLE (table))
581        gtk_widget_queue_resize (GTK_WIDGET (table));
582    }
583}
584
585void
586gtk_table_set_col_spacing (GtkTable *table,
587                           guint     column,
588                           guint     spacing)
589{
590  g_return_if_fail (table != NULL);
591  g_return_if_fail (GTK_IS_TABLE (table));
[15780]592  g_return_if_fail (column < table->ncols);
[14481]593 
594  if (table->cols[column].spacing != spacing)
595    {
596      table->cols[column].spacing = spacing;
597     
598      if (GTK_WIDGET_VISIBLE (table))
599        gtk_widget_queue_resize (GTK_WIDGET (table));
600    }
601}
602
603void
604gtk_table_set_row_spacings (GtkTable *table,
605                            guint     spacing)
606{
607  guint row;
608 
609  g_return_if_fail (table != NULL);
610  g_return_if_fail (GTK_IS_TABLE (table));
611 
612  table->row_spacing = spacing;
[15780]613  for (row = 0; row < table->nrows; row++)
[14481]614    table->rows[row].spacing = spacing;
615 
616  if (GTK_WIDGET_VISIBLE (table))
617    gtk_widget_queue_resize (GTK_WIDGET (table));
618}
619
620void
621gtk_table_set_col_spacings (GtkTable *table,
622                            guint     spacing)
623{
624  guint col;
625 
626  g_return_if_fail (table != NULL);
627  g_return_if_fail (GTK_IS_TABLE (table));
628 
629  table->column_spacing = spacing;
[15780]630  for (col = 0; col < table->ncols; col++)
[14481]631    table->cols[col].spacing = spacing;
632 
633  if (GTK_WIDGET_VISIBLE (table))
634    gtk_widget_queue_resize (GTK_WIDGET (table));
635}
636
637void
638gtk_table_set_homogeneous (GtkTable *table,
639                           gboolean  homogeneous)
640{
641  g_return_if_fail (table != NULL);
642  g_return_if_fail (GTK_IS_TABLE (table));
643
644  homogeneous = (homogeneous != 0);
645  if (homogeneous != table->homogeneous)
646    {
647      table->homogeneous = homogeneous;
648     
649      if (GTK_WIDGET_VISIBLE (table))
650        gtk_widget_queue_resize (GTK_WIDGET (table));
651    }
652}
653
654static void
655gtk_table_finalize (GtkObject *object)
656{
657  GtkTable *table;
658 
659  g_return_if_fail (object != NULL);
660  g_return_if_fail (GTK_IS_TABLE (object));
661 
662  table = GTK_TABLE (object);
663 
664  g_free (table->rows);
665  g_free (table->cols);
666 
667  (* GTK_OBJECT_CLASS (parent_class)->finalize) (object);
668}
669
670static void
671gtk_table_map (GtkWidget *widget)
672{
673  GtkTable *table;
674  GtkTableChild *child;
675  GList *children;
676 
677  g_return_if_fail (widget != NULL);
678  g_return_if_fail (GTK_IS_TABLE (widget));
679 
680  table = GTK_TABLE (widget);
681  GTK_WIDGET_SET_FLAGS (table, GTK_MAPPED);
682 
683  children = table->children;
684  while (children)
685    {
686      child = children->data;
687      children = children->next;
688     
689      if (GTK_WIDGET_VISIBLE (child->widget) &&
690          !GTK_WIDGET_MAPPED (child->widget))
691        gtk_widget_map (child->widget);
692    }
693}
694
695static void
696gtk_table_unmap (GtkWidget *widget)
697{
698  GtkTable *table;
699  GtkTableChild *child;
700  GList *children;
701 
702  g_return_if_fail (widget != NULL);
703  g_return_if_fail (GTK_IS_TABLE (widget));
704 
705  table = GTK_TABLE (widget);
706  GTK_WIDGET_UNSET_FLAGS (table, GTK_MAPPED);
707 
708  children = table->children;
709  while (children)
710    {
711      child = children->data;
712      children = children->next;
713     
714      if (GTK_WIDGET_VISIBLE (child->widget) &&
715          GTK_WIDGET_MAPPED (child->widget))
716        gtk_widget_unmap (child->widget);
717    }
718}
719
720static void
721gtk_table_draw (GtkWidget    *widget,
722                GdkRectangle *area)
723{
724  GtkTable *table;
725  GtkTableChild *child;
726  GList *children;
727  GdkRectangle child_area;
728 
729  g_return_if_fail (widget != NULL);
730  g_return_if_fail (GTK_IS_TABLE (widget));
731 
732  if (GTK_WIDGET_VISIBLE (widget) && GTK_WIDGET_MAPPED (widget))
733    {
734      table = GTK_TABLE (widget);
735     
736      children = table->children;
737      while (children)
738        {
739          child = children->data;
740          children = children->next;
741         
742          if (gtk_widget_intersect (child->widget, area, &child_area))
743            gtk_widget_draw (child->widget, &child_area);
744        }
745    }
746}
747
748static gint
749gtk_table_expose (GtkWidget      *widget,
750                  GdkEventExpose *event)
751{
752  GtkTable *table;
753  GtkTableChild *child;
754  GList *children;
755  GdkEventExpose child_event;
756 
757  g_return_val_if_fail (widget != NULL, FALSE);
758  g_return_val_if_fail (GTK_IS_TABLE (widget), FALSE);
759 
760  if (GTK_WIDGET_VISIBLE (widget) && GTK_WIDGET_MAPPED (widget))
761    {
762      table = GTK_TABLE (widget);
763     
764      child_event = *event;
765     
766      children = table->children;
767      while (children)
768        {
769          child = children->data;
770          children = children->next;
771         
772          if (GTK_WIDGET_NO_WINDOW (child->widget) &&
773              gtk_widget_intersect (child->widget, &event->area, &child_event.area))
774            gtk_widget_event (child->widget, (GdkEvent*) &child_event);
775        }
776    }
777 
778  return FALSE;
779}
780
781static void
782gtk_table_size_request (GtkWidget      *widget,
783                        GtkRequisition *requisition)
784{
785  GtkTable *table;
786  gint row, col;
787 
788  g_return_if_fail (widget != NULL);
789  g_return_if_fail (GTK_IS_TABLE (widget));
790  g_return_if_fail (requisition != NULL);
791 
792  table = GTK_TABLE (widget);
793 
794  requisition->width = 0;
795  requisition->height = 0;
796 
797  gtk_table_size_request_init (table);
798  gtk_table_size_request_pass1 (table);
799  gtk_table_size_request_pass2 (table);
800  gtk_table_size_request_pass3 (table);
801  gtk_table_size_request_pass2 (table);
802 
803  for (col = 0; col < table->ncols; col++)
804    requisition->width += table->cols[col].requisition;
805  for (col = 0; col + 1 < table->ncols; col++)
806    requisition->width += table->cols[col].spacing;
807 
808  for (row = 0; row < table->nrows; row++)
809    requisition->height += table->rows[row].requisition;
810  for (row = 0; row + 1 < table->nrows; row++)
811    requisition->height += table->rows[row].spacing;
812 
813  requisition->width += GTK_CONTAINER (table)->border_width * 2;
814  requisition->height += GTK_CONTAINER (table)->border_width * 2;
815}
816
817static void
818gtk_table_size_allocate (GtkWidget     *widget,
819                         GtkAllocation *allocation)
820{
821  GtkTable *table;
822 
823  g_return_if_fail (widget != NULL);
824  g_return_if_fail (GTK_IS_TABLE (widget));
825  g_return_if_fail (allocation != NULL);
826 
827  widget->allocation = *allocation;
828  table = GTK_TABLE (widget);
829 
830  gtk_table_size_allocate_init (table);
831  gtk_table_size_allocate_pass1 (table);
832  gtk_table_size_allocate_pass2 (table);
833}
834
835static void
836gtk_table_add (GtkContainer *container,
837               GtkWidget    *widget)
838{
839  g_return_if_fail (container != NULL);
840  g_return_if_fail (GTK_IS_TABLE (container));
841  g_return_if_fail (widget != NULL);
842 
843  gtk_table_attach_defaults (GTK_TABLE (container), widget, 0, 1, 0, 1);
844}
845
846static void
847gtk_table_remove (GtkContainer *container,
848                  GtkWidget    *widget)
849{
850  GtkTable *table;
851  GtkTableChild *child;
852  GList *children;
853 
854  g_return_if_fail (container != NULL);
855  g_return_if_fail (GTK_IS_TABLE (container));
856  g_return_if_fail (widget != NULL);
857 
858  table = GTK_TABLE (container);
859  children = table->children;
860 
861  while (children)
862    {
863      child = children->data;
864      children = children->next;
865     
866      if (child->widget == widget)
867        {
868          gboolean was_visible = GTK_WIDGET_VISIBLE (widget);
869         
870          gtk_widget_unparent (widget);
871         
872          table->children = g_list_remove (table->children, child);
873          g_free (child);
874         
875          if (was_visible && GTK_WIDGET_VISIBLE (container))
876            gtk_widget_queue_resize (GTK_WIDGET (container));
877          break;
878        }
879    }
880}
881
882static void
883gtk_table_forall (GtkContainer *container,
884                  gboolean      include_internals,
885                  GtkCallback   callback,
886                  gpointer      callback_data)
887{
888  GtkTable *table;
889  GtkTableChild *child;
890  GList *children;
891 
892  g_return_if_fail (container != NULL);
893  g_return_if_fail (GTK_IS_TABLE (container));
894  g_return_if_fail (callback != NULL);
895 
896  table = GTK_TABLE (container);
897  children = table->children;
898 
899  while (children)
900    {
901      child = children->data;
902      children = children->next;
903     
904      (* callback) (child->widget, callback_data);
905    }
906}
907
908static void
909gtk_table_size_request_init (GtkTable *table)
910{
911  GtkTableChild *child;
912  GList *children;
913  gint row, col;
914 
915  for (row = 0; row < table->nrows; row++)
916    table->rows[row].requisition = 0;
917  for (col = 0; col < table->ncols; col++)
918    table->cols[col].requisition = 0;
919 
920  children = table->children;
921  while (children)
922    {
923      child = children->data;
924      children = children->next;
925     
926      if (GTK_WIDGET_VISIBLE (child->widget))
927        gtk_widget_size_request (child->widget, NULL);
928    }
929}
930
931static void
932gtk_table_size_request_pass1 (GtkTable *table)
933{
934  GtkTableChild *child;
935  GList *children;
936  gint width;
937  gint height;
938 
939  children = table->children;
940  while (children)
941    {
942      child = children->data;
943      children = children->next;
944     
945      if (GTK_WIDGET_VISIBLE (child->widget))
946        {
947          GtkRequisition child_requisition;
948          gtk_widget_get_child_requisition (child->widget, &child_requisition);
949
950          /* Child spans a single column.
951           */
952          if (child->left_attach == (child->right_attach - 1))
953            {
954              width = child_requisition.width + child->xpadding * 2;
955              table->cols[child->left_attach].requisition = MAX (table->cols[child->left_attach].requisition, width);
956            }
957         
958          /* Child spans a single row.
959           */
960          if (child->top_attach == (child->bottom_attach - 1))
961            {
962              height = child_requisition.height + child->ypadding * 2;
963              table->rows[child->top_attach].requisition = MAX (table->rows[child->top_attach].requisition, height);
964            }
965        }
966    }
967}
968
969static void
970gtk_table_size_request_pass2 (GtkTable *table)
971{
972  gint max_width;
973  gint max_height;
974  gint row, col;
975 
976  if (table->homogeneous)
977    {
978      max_width = 0;
979      max_height = 0;
980     
981      for (col = 0; col < table->ncols; col++)
982        max_width = MAX (max_width, table->cols[col].requisition);
983      for (row = 0; row < table->nrows; row++)
984        max_height = MAX (max_height, table->rows[row].requisition);
985     
986      for (col = 0; col < table->ncols; col++)
987        table->cols[col].requisition = max_width;
988      for (row = 0; row < table->nrows; row++)
989        table->rows[row].requisition = max_height;
990    }
991}
992
993static void
994gtk_table_size_request_pass3 (GtkTable *table)
995{
996  GtkTableChild *child;
997  GList *children;
998  gint width, height;
999  gint row, col;
1000  gint extra;
1001 
1002  children = table->children;
1003  while (children)
1004    {
1005      child = children->data;
1006      children = children->next;
1007     
1008      if (GTK_WIDGET_VISIBLE (child->widget))
1009        {
1010          /* Child spans multiple columns.
1011           */
1012          if (child->left_attach != (child->right_attach - 1))
1013            {
1014              GtkRequisition child_requisition;
1015
1016              gtk_widget_get_child_requisition (child->widget, &child_requisition);
1017             
1018              /* Check and see if there is already enough space
1019               *  for the child.
1020               */
1021              width = 0;
1022              for (col = child->left_attach; col < child->right_attach; col++)
1023                {
1024                  width += table->cols[col].requisition;
1025                  if ((col + 1) < child->right_attach)
1026                    width += table->cols[col].spacing;
1027                }
1028             
1029              /* If we need to request more space for this child to fill
1030               *  its requisition, then divide up the needed space evenly
1031               *  amongst the columns it spans.
1032               */
1033              if (width < child_requisition.width + child->xpadding * 2)
1034                {
1035                  width = child_requisition.width + child->xpadding * 2 - width;
1036                 
1037                  for (col = child->left_attach; col < child->right_attach; col++)
1038                    {
1039                      extra = width / (child->right_attach - col);
1040                      table->cols[col].requisition += extra;
1041                      width -= extra;
1042                    }
1043                }
1044            }
1045         
1046          /* Child spans multiple rows.
1047           */
1048          if (child->top_attach != (child->bottom_attach - 1))
1049            {
1050              GtkRequisition child_requisition;
1051
1052              gtk_widget_get_child_requisition (child->widget, &child_requisition);
1053
1054              /* Check and see if there is already enough space
1055               *  for the child.
1056               */
1057              height = 0;
1058              for (row = child->top_attach; row < child->bottom_attach; row++)
1059                {
1060                  height += table->rows[row].requisition;
1061                  if ((row + 1) < child->bottom_attach)
1062                    height += table->rows[row].spacing;
1063                }
1064             
1065              /* If we need to request more space for this child to fill
1066               *  its requisition, then divide up the needed space evenly
1067               *  amongst the columns it spans.
1068               */
1069              if (height < child_requisition.height + child->ypadding * 2)
1070                {
1071                  height = child_requisition.height + child->ypadding * 2 - height;
1072                 
1073                  for (row = child->top_attach; row < child->bottom_attach; row++)
1074                    {
1075                      extra = height / (child->bottom_attach - row);
1076                      table->rows[row].requisition += extra;
1077                      height -= extra;
1078                    }
1079                }
1080            }
1081        }
1082    }
1083}
1084
1085static void
1086gtk_table_size_allocate_init (GtkTable *table)
1087{
1088  GtkTableChild *child;
1089  GList *children;
1090  gint row, col;
1091  gint has_expand;
1092  gint has_shrink;
1093 
1094  /* Initialize the rows and cols.
1095   *  By default, rows and cols do not expand and do shrink.
1096   *  Those values are modified by the children that occupy
1097   *  the rows and cols.
1098   */
1099  for (col = 0; col < table->ncols; col++)
1100    {
1101      table->cols[col].allocation = table->cols[col].requisition;
1102      table->cols[col].need_expand = FALSE;
1103      table->cols[col].need_shrink = TRUE;
1104      table->cols[col].expand = FALSE;
1105      table->cols[col].shrink = TRUE;
1106      table->cols[col].empty = TRUE;
1107    }
1108  for (row = 0; row < table->nrows; row++)
1109    {
1110      table->rows[row].allocation = table->rows[row].requisition;
1111      table->rows[row].need_expand = FALSE;
1112      table->rows[row].need_shrink = TRUE;
1113      table->rows[row].expand = FALSE;
1114      table->rows[row].shrink = TRUE;
1115      table->rows[row].empty = TRUE;
1116    }
1117 
1118  /* Loop over all the children and adjust the row and col values
1119   *  based on whether the children want to be allowed to expand
1120   *  or shrink. This loop handles children that occupy a single
1121   *  row or column.
1122   */
1123  children = table->children;
1124  while (children)
1125    {
1126      child = children->data;
1127      children = children->next;
1128     
1129      if (GTK_WIDGET_VISIBLE (child->widget))
1130        {
1131          if (child->left_attach == (child->right_attach - 1))
1132            {
1133              if (child->xexpand)
1134                table->cols[child->left_attach].expand = TRUE;
1135             
1136              if (!child->xshrink)
1137                table->cols[child->left_attach].shrink = FALSE;
1138             
1139              table->cols[child->left_attach].empty = FALSE;
1140            }
1141         
1142          if (child->top_attach == (child->bottom_attach - 1))
1143            {
1144              if (child->yexpand)
1145                table->rows[child->top_attach].expand = TRUE;
1146             
1147              if (!child->yshrink)
1148                table->rows[child->top_attach].shrink = FALSE;
1149
1150              table->rows[child->top_attach].empty = FALSE;
1151            }
1152        }
1153    }
1154 
1155  /* Loop over all the children again and this time handle children
1156   *  which span multiple rows or columns.
1157   */
1158  children = table->children;
1159  while (children)
1160    {
1161      child = children->data;
1162      children = children->next;
1163     
1164      if (GTK_WIDGET_VISIBLE (child->widget))
1165        {
1166          if (child->left_attach != (child->right_attach - 1))
1167            {
1168              for (col = child->left_attach; col < child->right_attach; col++)
1169                table->cols[col].empty = FALSE;
1170
1171              if (child->xexpand)
1172                {
1173                  has_expand = FALSE;
1174                  for (col = child->left_attach; col < child->right_attach; col++)
1175                    if (table->cols[col].expand)
1176                      {
1177                        has_expand = TRUE;
1178                        break;
1179                      }
1180                 
1181                  if (!has_expand)
1182                    for (col = child->left_attach; col < child->right_attach; col++)
1183                      table->cols[col].need_expand = TRUE;
1184                }
1185             
1186              if (!child->xshrink)
1187                {
1188                  has_shrink = TRUE;
1189                  for (col = child->left_attach; col < child->right_attach; col++)
1190                    if (!table->cols[col].shrink)
1191                      {
1192                        has_shrink = FALSE;
1193                        break;
1194                      }
1195                 
1196                  if (has_shrink)
1197                    for (col = child->left_attach; col < child->right_attach; col++)
1198                      table->cols[col].need_shrink = FALSE;
1199                }
1200            }
1201         
1202          if (child->top_attach != (child->bottom_attach - 1))
1203            {
1204              for (row = child->top_attach; row < child->bottom_attach; row++)
1205                table->rows[row].empty = FALSE;
1206
1207              if (child->yexpand)
1208                {
1209                  has_expand = FALSE;
1210                  for (row = child->top_attach; row < child->bottom_attach; row++)
1211                    if (table->rows[row].expand)
1212                      {
1213                        has_expand = TRUE;
1214                        break;
1215                      }
1216                 
1217                  if (!has_expand)
1218                    for (row = child->top_attach; row < child->bottom_attach; row++)
1219                      table->rows[row].need_expand = TRUE;
1220                }
1221             
1222              if (!child->yshrink)
1223                {
1224                  has_shrink = TRUE;
1225                  for (row = child->top_attach; row < child->bottom_attach; row++)
1226                    if (!table->rows[row].shrink)
1227                      {
1228                        has_shrink = FALSE;
1229                        break;
1230                      }
1231                 
1232                  if (has_shrink)
1233                    for (row = child->top_attach; row < child->bottom_attach; row++)
1234                      table->rows[row].need_shrink = FALSE;
1235                }
1236            }
1237        }
1238    }
1239 
1240  /* Loop over the columns and set the expand and shrink values
1241   *  if the column can be expanded or shrunk.
1242   */
1243  for (col = 0; col < table->ncols; col++)
1244    {
1245      if (table->cols[col].empty)
1246        {
1247          table->cols[col].expand = FALSE;
1248          table->cols[col].shrink = FALSE;
1249        }
1250      else
1251        {
1252          if (table->cols[col].need_expand)
1253            table->cols[col].expand = TRUE;
1254          if (!table->cols[col].need_shrink)
1255            table->cols[col].shrink = FALSE;
1256        }
1257    }
1258 
1259  /* Loop over the rows and set the expand and shrink values
1260   *  if the row can be expanded or shrunk.
1261   */
1262  for (row = 0; row < table->nrows; row++)
1263    {
1264      if (table->rows[row].empty)
1265        {
1266          table->rows[row].expand = FALSE;
1267          table->rows[row].shrink = FALSE;
1268        }
1269      else
1270        {
1271          if (table->rows[row].need_expand)
1272            table->rows[row].expand = TRUE;
1273          if (!table->rows[row].need_shrink)
1274            table->rows[row].shrink = FALSE;
1275        }
1276    }
1277}
1278
1279static void
1280gtk_table_size_allocate_pass1 (GtkTable *table)
1281{
1282  gint real_width;
1283  gint real_height;
1284  gint width, height;
1285  gint row, col;
1286  gint nexpand;
1287  gint nshrink;
1288  gint extra;
1289 
1290  /* If we were allocated more space than we requested
1291   *  then we have to expand any expandable rows and columns
1292   *  to fill in the extra space.
1293   */
1294 
1295  real_width = GTK_WIDGET (table)->allocation.width - GTK_CONTAINER (table)->border_width * 2;
1296  real_height = GTK_WIDGET (table)->allocation.height - GTK_CONTAINER (table)->border_width * 2;
1297 
1298  if (table->homogeneous)
1299    {
1300      nexpand = 0;
1301      for (col = 0; col < table->ncols; col++)
1302        if (table->cols[col].expand)
1303          {
1304            nexpand += 1;
1305            break;
1306          }
1307     
1308      if (nexpand > 0)
1309        {
1310          width = real_width;
1311         
1312          for (col = 0; col + 1 < table->ncols; col++)
1313            width -= table->cols[col].spacing;
1314         
1315          for (col = 0; col < table->ncols; col++)
1316            {
1317              extra = width / (table->ncols - col);
1318              table->cols[col].allocation = MAX (1, extra);
1319              width -= extra;
1320            }
1321        }
1322    }
1323  else
1324    {
1325      width = 0;
1326      nexpand = 0;
1327      nshrink = 0;
1328     
1329      for (col = 0; col < table->ncols; col++)
1330        {
1331          width += table->cols[col].requisition;
1332          if (table->cols[col].expand)
1333            nexpand += 1;
1334          if (table->cols[col].shrink)
1335            nshrink += 1;
1336        }
1337      for (col = 0; col + 1 < table->ncols; col++)
1338        width += table->cols[col].spacing;
1339     
1340      /* Check to see if we were allocated more width than we requested.
1341       */
1342      if ((width < real_width) && (nexpand >= 1))
1343        {
1344          width = real_width - width;
1345         
1346          for (col = 0; col < table->ncols; col++)
1347            if (table->cols[col].expand)
1348              {
1349                extra = width / nexpand;
1350                table->cols[col].allocation += extra;
1351               
1352                width -= extra;
1353                nexpand -= 1;
1354              }
1355        }
1356     
1357      /* Check to see if we were allocated less width than we requested,
1358       * then shrink until we fit the size give.
1359       */
1360      if (width > real_width)
1361        {
1362          gint total_nshrink = nshrink;
1363
1364          extra = width - real_width;
1365          while (total_nshrink > 0 && extra > 0)
1366            {
1367              nshrink = total_nshrink;
1368              for (col = 0; col < table->ncols; col++)
1369                if (table->cols[col].shrink)
1370                  {
1371                    gint allocation = table->cols[col].allocation;
1372
1373                    table->cols[col].allocation = MAX (1, (gint) table->cols[col].allocation - extra / nshrink);
1374                    extra -= allocation - table->cols[col].allocation;
1375                    nshrink -= 1;
1376                    if (table->cols[col].allocation < 2)
1377                      {
1378                        total_nshrink -= 1;
1379                        table->cols[col].shrink = FALSE;
1380                      }
1381                  }
1382            }
1383        }
1384    }
1385 
1386  if (table->homogeneous)
1387    {
1388      nexpand = 0;
1389      for (row = 0; row < table->nrows; row++)
1390        if (table->rows[row].expand)
1391          {
1392            nexpand += 1;
1393            break;
1394          }
1395     
1396      if (nexpand > 0)
1397        {
1398          height = real_height;
1399         
1400          for (row = 0; row + 1 < table->nrows; row++)
1401            height -= table->rows[row].spacing;
1402         
1403         
1404          for (row = 0; row < table->nrows; row++)
1405            {
1406              extra = height / (table->nrows - row);
1407              table->rows[row].allocation = MAX (1, extra);
1408              height -= extra;
1409            }
1410        }
1411    }
1412  else
1413    {
1414      height = 0;
1415      nexpand = 0;
1416      nshrink = 0;
1417     
1418      for (row = 0; row < table->nrows; row++)
1419        {
1420          height += table->rows[row].requisition;
1421          if (table->rows[row].expand)
1422            nexpand += 1;
1423          if (table->rows[row].shrink)
1424            nshrink += 1;
1425        }
1426      for (row = 0; row + 1 < table->nrows; row++)
1427        height += table->rows[row].spacing;
1428     
1429      /* Check to see if we were allocated more height than we requested.
1430       */
1431      if ((height < real_height) && (nexpand >= 1))
1432        {
1433          height = real_height - height;
1434         
1435          for (row = 0; row < table->nrows; row++)
1436            if (table->rows[row].expand)
1437              {
1438                extra = height / nexpand;
1439                table->rows[row].allocation += extra;
1440               
1441                height -= extra;
1442                nexpand -= 1;
1443              }
1444        }
1445     
1446      /* Check to see if we were allocated less height than we requested.
1447       * then shrink until we fit the size give.
1448       */
1449      if (height > real_height)
1450        {
1451          gint total_nshrink = nshrink;
1452         
1453          extra = height - real_height;
1454          while (total_nshrink > 0 && extra > 0)
1455            {
1456              nshrink = total_nshrink;
1457              for (row = 0; row < table->nrows; row++)
1458                if (table->rows[row].shrink)
1459                  {
1460                    gint allocation = table->rows[row].allocation;
1461                   
1462                    table->rows[row].allocation = MAX (1, (gint) table->rows[row].allocation - extra / nshrink);
1463                    extra -= allocation - table->rows[row].allocation;
1464                    nshrink -= 1;
1465                    if (table->rows[row].allocation < 2)
1466                      {
1467                        total_nshrink -= 1;
1468                        table->rows[row].shrink = FALSE;
1469                      }
1470                  }
1471            }
1472        }
1473    }
1474}
1475
1476static void
1477gtk_table_size_allocate_pass2 (GtkTable *table)
1478{
1479  GtkTableChild *child;
1480  GList *children;
1481  gint max_width;
1482  gint max_height;
1483  gint x, y;
1484  gint row, col;
1485  GtkAllocation allocation;
1486 
1487  children = table->children;
1488  while (children)
1489    {
1490      child = children->data;
1491      children = children->next;
1492     
1493      if (GTK_WIDGET_VISIBLE (child->widget))
1494        {
1495          GtkRequisition child_requisition;
1496          gtk_widget_get_child_requisition (child->widget, &child_requisition);
1497
1498          x = GTK_WIDGET (table)->allocation.x + GTK_CONTAINER (table)->border_width;
1499          y = GTK_WIDGET (table)->allocation.y + GTK_CONTAINER (table)->border_width;
1500          max_width = 0;
1501          max_height = 0;
1502         
1503          for (col = 0; col < child->left_attach; col++)
1504            {
1505              x += table->cols[col].allocation;
1506              x += table->cols[col].spacing;
1507            }
1508         
1509          for (col = child->left_attach; col < child->right_attach; col++)
1510            {
1511              max_width += table->cols[col].allocation;
1512              if ((col + 1) < child->right_attach)
1513                max_width += table->cols[col].spacing;
1514            }
1515         
1516          for (row = 0; row < child->top_attach; row++)
1517            {
1518              y += table->rows[row].allocation;
1519              y += table->rows[row].spacing;
1520            }
1521         
1522          for (row = child->top_attach; row < child->bottom_attach; row++)
1523            {
1524              max_height += table->rows[row].allocation;
1525              if ((row + 1) < child->bottom_attach)
1526                max_height += table->rows[row].spacing;
1527            }
1528         
1529          if (child->xfill)
1530            {
1531              allocation.width = MAX (1, max_width - (gint)child->xpadding * 2);
1532              allocation.x = x + (max_width - allocation.width) / 2;
1533            }
1534          else
1535            {
1536              allocation.width = child_requisition.width;
1537              allocation.x = x + (max_width - allocation.width) / 2;
1538            }
1539         
1540          if (child->yfill)
1541            {
1542              allocation.height = MAX (1, max_height - (gint)child->ypadding * 2);
1543              allocation.y = y + (max_height - allocation.height) / 2;
1544            }
1545          else
1546            {
1547              allocation.height = child_requisition.height;
1548              allocation.y = y + (max_height - allocation.height) / 2;
1549            }
1550         
1551          gtk_widget_size_allocate (child->widget, &allocation);
1552        }
1553    }
1554}
Note: See TracBrowser for help on using the repository browser.