gtktable.c 47.2 KB
Newer Older
Cody Russell's avatar
Cody Russell committed
1
/* GTK - The GIMP Toolkit
Elliot Lee's avatar
Elliot Lee committed
2 3 4
 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
 *
 * This library is free software; you can redistribute it and/or
5
 * modify it under the terms of the GNU Lesser General Public
Elliot Lee's avatar
Elliot Lee committed
6 7 8 9 10
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
12
 * Lesser General Public License for more details.
Elliot Lee's avatar
Elliot Lee committed
13
 *
14
 * You should have received a copy of the GNU Lesser General Public
15 16 17
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
Elliot Lee's avatar
Elliot Lee committed
18
 */
19 20

/*
21
 * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
22 23 24 25 26
 * file for a list of people on the GTK+ Team.  See the ChangeLog
 * files for a list of changes.  These files are distributed with
 * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
 */

27
#include "config.h"
28

Elliot Lee's avatar
Elliot Lee committed
29
#include "gtktable.h"
30

31
#include "gtktypebuiltins.h"
32
#include "gtkprivate.h"
Alexander Larsson's avatar
Alexander Larsson committed
33
#include "gtkintl.h"
34

Elliot Lee's avatar
Elliot Lee committed
35

36

37
struct _GtkTablePrivate
38 39 40 41 42 43 44 45 46 47 48 49 50 51
{
  GtkTableRowCol *cols;
  GtkTableRowCol *rows;

  GList          *children;

  guint16         column_spacing;
  guint16         ncols;
  guint16         nrows;
  guint16         row_spacing;

  guint           homogeneous : 1;
};

52 53
enum
{
Alexander Larsson's avatar
Alexander Larsson committed
54 55 56 57 58 59
  PROP_0,
  PROP_N_ROWS,
  PROP_N_COLUMNS,
  PROP_COLUMN_SPACING,
  PROP_ROW_SPACING,
  PROP_HOMOGENEOUS
60 61 62 63
};

enum
{
Tim Janik's avatar
Tim Janik committed
64 65 66 67 68 69 70 71 72
  CHILD_PROP_0,
  CHILD_PROP_LEFT_ATTACH,
  CHILD_PROP_RIGHT_ATTACH,
  CHILD_PROP_TOP_ATTACH,
  CHILD_PROP_BOTTOM_ATTACH,
  CHILD_PROP_X_OPTIONS,
  CHILD_PROP_Y_OPTIONS,
  CHILD_PROP_X_PADDING,
  CHILD_PROP_Y_PADDING
73 74
};
  
Elliot Lee's avatar
Elliot Lee committed
75

76
static void gtk_table_finalize	    (GObject	    *object);
77
static void gtk_table_size_request  (GtkWidget	    *widget,
Elliot Lee's avatar
Elliot Lee committed
78
				     GtkRequisition *requisition);
79
static void gtk_table_size_allocate (GtkWidget	    *widget,
Elliot Lee's avatar
Elliot Lee committed
80
				     GtkAllocation  *allocation);
81 82 83
static void gtk_table_compute_expand (GtkWidget     *widget,
                                      gboolean      *hexpand,
                                      gboolean      *vexpand);
84 85 86 87
static void gtk_table_add	    (GtkContainer   *container,
				     GtkWidget	    *widget);
static void gtk_table_remove	    (GtkContainer   *container,
				     GtkWidget	    *widget);
88 89
static void gtk_table_forall	    (GtkContainer   *container,
				     gboolean	     include_internals,
Elliot Lee's avatar
Elliot Lee committed
90
				     GtkCallback     callback,
91
				     gpointer	     callback_data);
Alexander Larsson's avatar
Alexander Larsson committed
92 93 94 95 96 97 98 99
static void gtk_table_get_property  (GObject         *object,
				     guint            prop_id,
				     GValue          *value,
				     GParamSpec      *pspec);
static void gtk_table_set_property  (GObject         *object,
				     guint            prop_id,
				     const GValue    *value,
				     GParamSpec      *pspec);
Tim Janik's avatar
Tim Janik committed
100 101 102 103 104 105 106 107 108 109
static void gtk_table_set_child_property (GtkContainer    *container,
					  GtkWidget       *child,
					  guint            property_id,
					  const GValue    *value,
					  GParamSpec      *pspec);
static void gtk_table_get_child_property (GtkContainer    *container,
					  GtkWidget       *child,
					  guint            property_id,
					  GValue          *value,
					  GParamSpec      *pspec);
Manish Singh's avatar
Manish Singh committed
110
static GType gtk_table_child_type   (GtkContainer   *container);
111 112 113


static void gtk_table_size_request_init	 (GtkTable *table);
Elliot Lee's avatar
Elliot Lee committed
114 115 116 117 118 119 120 121 122
static void gtk_table_size_request_pass1 (GtkTable *table);
static void gtk_table_size_request_pass2 (GtkTable *table);
static void gtk_table_size_request_pass3 (GtkTable *table);

static void gtk_table_size_allocate_init  (GtkTable *table);
static void gtk_table_size_allocate_pass1 (GtkTable *table);
static void gtk_table_size_allocate_pass2 (GtkTable *table);


Matthias Clasen's avatar
Matthias Clasen committed
123
G_DEFINE_TYPE (GtkTable, gtk_table, GTK_TYPE_CONTAINER)
Elliot Lee's avatar
Elliot Lee committed
124 125 126 127

static void
gtk_table_class_init (GtkTableClass *class)
{
128
  GObjectClass *gobject_class = G_OBJECT_CLASS (class);
Tim Janik's avatar
Tim Janik committed
129 130
  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
  GtkContainerClass *container_class = GTK_CONTAINER_CLASS (class);
131
  
132
  gobject_class->finalize = gtk_table_finalize;
Elliot Lee's avatar
Elliot Lee committed
133

Alexander Larsson's avatar
Alexander Larsson committed
134 135
  gobject_class->get_property = gtk_table_get_property;
  gobject_class->set_property = gtk_table_set_property;
136
  
Elliot Lee's avatar
Elliot Lee committed
137 138
  widget_class->size_request = gtk_table_size_request;
  widget_class->size_allocate = gtk_table_size_allocate;
139
  widget_class->compute_expand = gtk_table_compute_expand;
140
  
Elliot Lee's avatar
Elliot Lee committed
141 142
  container_class->add = gtk_table_add;
  container_class->remove = gtk_table_remove;
143
  container_class->forall = gtk_table_forall;
144
  container_class->child_type = gtk_table_child_type;
Tim Janik's avatar
Tim Janik committed
145 146
  container_class->set_child_property = gtk_table_set_child_property;
  container_class->get_child_property = gtk_table_get_child_property;
147
  gtk_container_class_handle_border_width (container_class);
Alexander Larsson's avatar
Alexander Larsson committed
148 149 150

  g_object_class_install_property (gobject_class,
                                   PROP_N_ROWS,
151
                                   g_param_spec_uint ("n-rows",
152 153
						     P_("Rows"),
						     P_("The number of rows in the table"),
154
						     1,
155
						     65535,
156
						     1,
157
						     GTK_PARAM_READWRITE));
Alexander Larsson's avatar
Alexander Larsson committed
158 159
  g_object_class_install_property (gobject_class,
                                   PROP_N_COLUMNS,
160
                                   g_param_spec_uint ("n-columns",
161 162
						     P_("Columns"),
						     P_("The number of columns in the table"),
163
						     1,
164
						     65535,
165
						     1,
166
						     GTK_PARAM_READWRITE));
Alexander Larsson's avatar
Alexander Larsson committed
167 168
  g_object_class_install_property (gobject_class,
                                   PROP_ROW_SPACING,
169
                                   g_param_spec_uint ("row-spacing",
170 171
						     P_("Row spacing"),
						     P_("The amount of space between two consecutive rows"),
Alexander Larsson's avatar
Alexander Larsson committed
172
						     0,
173
						     65535,
Alexander Larsson's avatar
Alexander Larsson committed
174
						     0,
175
						     GTK_PARAM_READWRITE));
Alexander Larsson's avatar
Alexander Larsson committed
176 177
  g_object_class_install_property (gobject_class,
                                   PROP_COLUMN_SPACING,
178
                                   g_param_spec_uint ("column-spacing",
179 180
						     P_("Column spacing"),
						     P_("The amount of space between two consecutive columns"),
Alexander Larsson's avatar
Alexander Larsson committed
181
						     0,
182
						     65535,
Alexander Larsson's avatar
Alexander Larsson committed
183
						     0,
184
						     GTK_PARAM_READWRITE));
Alexander Larsson's avatar
Alexander Larsson committed
185 186 187
  g_object_class_install_property (gobject_class,
                                   PROP_HOMOGENEOUS,
                                   g_param_spec_boolean ("homogeneous",
188 189
							 P_("Homogeneous"),
							 P_("If TRUE, the table cells are all the same width/height"),
Alexander Larsson's avatar
Alexander Larsson committed
190
							 FALSE,
191
							 GTK_PARAM_READWRITE));
Alexander Larsson's avatar
Alexander Larsson committed
192

Tim Janik's avatar
Tim Janik committed
193 194
  gtk_container_class_install_child_property (container_class,
					      CHILD_PROP_LEFT_ATTACH,
195
					      g_param_spec_uint ("left-attach", 
196 197
								 P_("Left attachment"), 
								 P_("The column number to attach the left side of the child to"),
Tim Janik's avatar
Tim Janik committed
198
								 0, 65535, 0,
199
								 GTK_PARAM_READWRITE));
Tim Janik's avatar
Tim Janik committed
200 201
  gtk_container_class_install_child_property (container_class,
					      CHILD_PROP_RIGHT_ATTACH,
202
					      g_param_spec_uint ("right-attach", 
203 204
								 P_("Right attachment"), 
								 P_("The column number to attach the right side of a child widget to"),
Tim Janik's avatar
Tim Janik committed
205
								 1, 65535, 1,
206
								 GTK_PARAM_READWRITE));
Tim Janik's avatar
Tim Janik committed
207 208
  gtk_container_class_install_child_property (container_class,
					      CHILD_PROP_TOP_ATTACH,
209
					      g_param_spec_uint ("top-attach", 
210 211
								 P_("Top attachment"), 
								 P_("The row number to attach the top of a child widget to"),
Tim Janik's avatar
Tim Janik committed
212
								 0, 65535, 0,
213
								 GTK_PARAM_READWRITE));
Tim Janik's avatar
Tim Janik committed
214 215
  gtk_container_class_install_child_property (container_class,
					      CHILD_PROP_BOTTOM_ATTACH,
216
					      g_param_spec_uint ("bottom-attach",
217 218
								 P_("Bottom attachment"), 
								 P_("The row number to attach the bottom of the child to"),
Tim Janik's avatar
Tim Janik committed
219
								 1, 65535, 1,
220
								 GTK_PARAM_READWRITE));
Tim Janik's avatar
Tim Janik committed
221 222
  gtk_container_class_install_child_property (container_class,
					      CHILD_PROP_X_OPTIONS,
223
					      g_param_spec_flags ("x-options", 
224 225
								  P_("Horizontal options"), 
								  P_("Options specifying the horizontal behaviour of the child"),
Tim Janik's avatar
Tim Janik committed
226
								  GTK_TYPE_ATTACH_OPTIONS, GTK_EXPAND | GTK_FILL,
227
								  GTK_PARAM_READWRITE));
Tim Janik's avatar
Tim Janik committed
228 229
  gtk_container_class_install_child_property (container_class,
					      CHILD_PROP_Y_OPTIONS,
230
					      g_param_spec_flags ("y-options", 
231 232
								  P_("Vertical options"), 
								  P_("Options specifying the vertical behaviour of the child"),
Tim Janik's avatar
Tim Janik committed
233
								  GTK_TYPE_ATTACH_OPTIONS, GTK_EXPAND | GTK_FILL,
234
								  GTK_PARAM_READWRITE));
Tim Janik's avatar
Tim Janik committed
235 236
  gtk_container_class_install_child_property (container_class,
					      CHILD_PROP_X_PADDING,
237
					      g_param_spec_uint ("x-padding", 
238 239
								 P_("Horizontal padding"), 
								 P_("Extra space to put between the child and its left and right neighbors, in pixels"),
Tim Janik's avatar
Tim Janik committed
240
								 0, 65535, 0,
241
								 GTK_PARAM_READWRITE));
Tim Janik's avatar
Tim Janik committed
242 243
  gtk_container_class_install_child_property (container_class,
					      CHILD_PROP_Y_PADDING,
244
					      g_param_spec_uint ("y-padding", 
245 246
								 P_("Vertical padding"), 
								 P_("Extra space to put between the child and its upper and lower neighbors, in pixels"),
Tim Janik's avatar
Tim Janik committed
247
								 0, 65535, 0,
248
								 GTK_PARAM_READWRITE));
249

250
  g_type_class_add_private (class, sizeof (GtkTablePrivate));
251 252
}

253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289
static void
gtk_table_compute_expand (GtkWidget *widget,
                          gboolean  *hexpand_p,
                          gboolean  *vexpand_p)
{
  GtkTable *table = GTK_TABLE (widget);
  GtkTablePrivate *priv = table->priv;
  GList *list;
  GtkTableChild *child;
  gboolean hexpand;
  gboolean vexpand;

  hexpand = FALSE;
  vexpand = FALSE;

  for (list = priv->children; list; list = list->next)
    {
      child = list->data;

      if (!hexpand)
        hexpand = child->xexpand ||
                  gtk_widget_compute_expand (child->widget,
                                             GTK_ORIENTATION_HORIZONTAL);

      if (!vexpand)
        vexpand = child->yexpand ||
                  gtk_widget_compute_expand (child->widget,
                                             GTK_ORIENTATION_VERTICAL);

      if (hexpand && vexpand)
        break;
    }

  *hexpand_p = hexpand;
  *vexpand_p = vexpand;
}

Manish Singh's avatar
Manish Singh committed
290
static GType
291 292 293
gtk_table_child_type (GtkContainer   *container)
{
  return GTK_TYPE_WIDGET;
Elliot Lee's avatar
Elliot Lee committed
294 295 296
}

static void
Alexander Larsson's avatar
Alexander Larsson committed
297 298 299 300
gtk_table_get_property (GObject      *object,
			guint         prop_id,
			GValue       *value,
			GParamSpec   *pspec)
Elliot Lee's avatar
Elliot Lee committed
301
{
302
  GtkTable *table = GTK_TABLE (object);
303
  GtkTablePrivate *priv = table->priv;
304

Alexander Larsson's avatar
Alexander Larsson committed
305
  switch (prop_id)
306
    {
Alexander Larsson's avatar
Alexander Larsson committed
307
    case PROP_N_ROWS:
308
      g_value_set_uint (value, priv->nrows);
309
      break;
Alexander Larsson's avatar
Alexander Larsson committed
310
    case PROP_N_COLUMNS:
311
      g_value_set_uint (value, priv->ncols);
312
      break;
Alexander Larsson's avatar
Alexander Larsson committed
313
    case PROP_ROW_SPACING:
314
      g_value_set_uint (value, priv->row_spacing);
315
      break;
Alexander Larsson's avatar
Alexander Larsson committed
316
    case PROP_COLUMN_SPACING:
317
      g_value_set_uint (value, priv->column_spacing);
318
      break;
Alexander Larsson's avatar
Alexander Larsson committed
319
    case PROP_HOMOGENEOUS:
320
      g_value_set_boolean (value, priv->homogeneous);
321 322
      break;
    default:
Alexander Larsson's avatar
Alexander Larsson committed
323
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
324 325
      break;
    }
Elliot Lee's avatar
Elliot Lee committed
326 327
}

328
static void
Alexander Larsson's avatar
Alexander Larsson committed
329 330 331 332
gtk_table_set_property (GObject      *object,
			guint         prop_id,
			const GValue *value,
			GParamSpec   *pspec)
Elliot Lee's avatar
Elliot Lee committed
333
{
334
  GtkTable *table = GTK_TABLE (object);
335
  GtkTablePrivate *priv = table->priv;
Elliot Lee's avatar
Elliot Lee committed
336

Alexander Larsson's avatar
Alexander Larsson committed
337
  switch (prop_id)
Elliot Lee's avatar
Elliot Lee committed
338
    {
Alexander Larsson's avatar
Alexander Larsson committed
339
    case PROP_N_ROWS:
340
      gtk_table_resize (table, g_value_get_uint (value), priv->ncols);
341
      break;
Alexander Larsson's avatar
Alexander Larsson committed
342
    case PROP_N_COLUMNS:
343
      gtk_table_resize (table, priv->nrows, g_value_get_uint (value));
344
      break;
Alexander Larsson's avatar
Alexander Larsson committed
345 346
    case PROP_ROW_SPACING:
      gtk_table_set_row_spacings (table, g_value_get_uint (value));
347
      break;
Alexander Larsson's avatar
Alexander Larsson committed
348 349
    case PROP_COLUMN_SPACING:
      gtk_table_set_col_spacings (table, g_value_get_uint (value));
350
      break;
Alexander Larsson's avatar
Alexander Larsson committed
351 352
    case PROP_HOMOGENEOUS:
      gtk_table_set_homogeneous (table, g_value_get_boolean (value));
353 354
      break;
    default:
Alexander Larsson's avatar
Alexander Larsson committed
355
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
356
      break;
Elliot Lee's avatar
Elliot Lee committed
357
    }
358
}
Elliot Lee's avatar
Elliot Lee committed
359

360
static void
Tim Janik's avatar
Tim Janik committed
361 362 363 364 365
gtk_table_set_child_property (GtkContainer    *container,
			      GtkWidget       *child,
			      guint            property_id,
			      const GValue    *value,
			      GParamSpec      *pspec)
366
{
Tim Janik's avatar
Tim Janik committed
367
  GtkTable *table = GTK_TABLE (container);
368
  GtkTablePrivate *priv = table->priv;
369 370 371 372
  GtkTableChild *table_child;
  GList *list;

  table_child = NULL;
373
  for (list = priv->children; list; list = list->next)
374 375 376 377 378 379 380
    {
      table_child = list->data;

      if (table_child->widget == child)
	break;
    }
  if (!list)
Tim Janik's avatar
Tim Janik committed
381 382 383 384
    {
      GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec);
      return;
    }
385

Tim Janik's avatar
Tim Janik committed
386
  switch (property_id)
Elliot Lee's avatar
Elliot Lee committed
387
    {
Tim Janik's avatar
Tim Janik committed
388 389
    case CHILD_PROP_LEFT_ATTACH:
      table_child->left_attach = g_value_get_uint (value);
390 391
      if (table_child->right_attach <= table_child->left_attach)
	table_child->right_attach = table_child->left_attach + 1;
392 393
      if (table_child->right_attach >= priv->ncols)
	gtk_table_resize (table, priv->nrows, table_child->right_attach);
394
      break;
Tim Janik's avatar
Tim Janik committed
395 396 397 398
    case CHILD_PROP_RIGHT_ATTACH:
      table_child->right_attach = g_value_get_uint (value);
      if (table_child->right_attach <= table_child->left_attach)
	table_child->left_attach = table_child->right_attach - 1;
399 400
      if (table_child->right_attach >= priv->ncols)
	gtk_table_resize (table, priv->nrows, table_child->right_attach);
401
      break;
Tim Janik's avatar
Tim Janik committed
402 403
    case CHILD_PROP_TOP_ATTACH:
      table_child->top_attach = g_value_get_uint (value);
404 405
      if (table_child->bottom_attach <= table_child->top_attach)
	table_child->bottom_attach = table_child->top_attach + 1;
406 407
      if (table_child->bottom_attach >= priv->nrows)
	gtk_table_resize (table, table_child->bottom_attach, priv->ncols);
408
      break;
Tim Janik's avatar
Tim Janik committed
409 410 411 412
    case CHILD_PROP_BOTTOM_ATTACH:
      table_child->bottom_attach = g_value_get_uint (value);
      if (table_child->bottom_attach <= table_child->top_attach)
	table_child->top_attach = table_child->bottom_attach - 1;
413 414
      if (table_child->bottom_attach >= priv->nrows)
	gtk_table_resize (table, table_child->bottom_attach, priv->ncols);
415
      break;
Tim Janik's avatar
Tim Janik committed
416
    case CHILD_PROP_X_OPTIONS:
417 418 419 420 421 422 423 424 425 426 427 428 429 430
      {
        gboolean xexpand;

        xexpand = (g_value_get_flags (value) & GTK_EXPAND) != 0;

        if (table_child->xexpand != xexpand)
          {
            table_child->xexpand = xexpand;
            gtk_widget_queue_compute_expand (GTK_WIDGET (table));
          }

        table_child->xshrink = (g_value_get_flags (value) & GTK_SHRINK) != 0;
        table_child->xfill = (g_value_get_flags (value) & GTK_FILL) != 0;
      }
431
      break;
Tim Janik's avatar
Tim Janik committed
432
    case CHILD_PROP_Y_OPTIONS:
433 434 435 436 437 438 439 440 441 442 443 444 445 446
      {
        gboolean yexpand;

        yexpand = (g_value_get_flags (value) & GTK_EXPAND) != 0;

        if (table_child->yexpand != yexpand)
          {
            table_child->yexpand = yexpand;
            gtk_widget_queue_compute_expand (GTK_WIDGET (table));
          }

        table_child->yshrink = (g_value_get_flags (value) & GTK_SHRINK) != 0;
        table_child->yfill = (g_value_get_flags (value) & GTK_FILL) != 0;
      }
447
      break;
Tim Janik's avatar
Tim Janik committed
448 449
    case CHILD_PROP_X_PADDING:
      table_child->xpadding = g_value_get_uint (value);
450
      break;
Tim Janik's avatar
Tim Janik committed
451 452
    case CHILD_PROP_Y_PADDING:
      table_child->ypadding = g_value_get_uint (value);
453 454
      break;
    default:
Tim Janik's avatar
Tim Janik committed
455
      GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec);
456
      break;
Elliot Lee's avatar
Elliot Lee committed
457
    }
458 459
  if (gtk_widget_get_visible (child) &&
      gtk_widget_get_visible (GTK_WIDGET (table)))
460
    gtk_widget_queue_resize (child);
461 462
}

463
static void
Tim Janik's avatar
Tim Janik committed
464 465 466 467 468
gtk_table_get_child_property (GtkContainer    *container,
			      GtkWidget       *child,
			      guint            property_id,
			      GValue          *value,
			      GParamSpec      *pspec)
469
{
Tim Janik's avatar
Tim Janik committed
470
  GtkTable *table = GTK_TABLE (container);
471
  GtkTablePrivate *priv = table->priv;
472 473
  GtkTableChild *table_child;
  GList *list;
474

475
  table_child = NULL;
476
  for (list = priv->children; list; list = list->next)
477 478
    {
      table_child = list->data;
479

480 481 482 483
      if (table_child->widget == child)
	break;
    }
  if (!list)
Tim Janik's avatar
Tim Janik committed
484 485 486 487
    {
      GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec);
      return;
    }
488

Tim Janik's avatar
Tim Janik committed
489
  switch (property_id)
490
    {
Tim Janik's avatar
Tim Janik committed
491 492
    case CHILD_PROP_LEFT_ATTACH:
      g_value_set_uint (value, table_child->left_attach);
493
      break;
Tim Janik's avatar
Tim Janik committed
494 495
    case CHILD_PROP_RIGHT_ATTACH:
      g_value_set_uint (value, table_child->right_attach);
496
      break;
Tim Janik's avatar
Tim Janik committed
497 498
    case CHILD_PROP_TOP_ATTACH:
      g_value_set_uint (value, table_child->top_attach);
499
      break;
Tim Janik's avatar
Tim Janik committed
500 501
    case CHILD_PROP_BOTTOM_ATTACH:
      g_value_set_uint (value, table_child->bottom_attach);
502
      break;
Tim Janik's avatar
Tim Janik committed
503 504 505 506
    case CHILD_PROP_X_OPTIONS:
      g_value_set_flags (value, (table_child->xexpand * GTK_EXPAND |
				 table_child->xshrink * GTK_SHRINK |
				 table_child->xfill * GTK_FILL));
507
      break;
Tim Janik's avatar
Tim Janik committed
508 509 510 511
    case CHILD_PROP_Y_OPTIONS:
      g_value_set_flags (value, (table_child->yexpand * GTK_EXPAND |
				 table_child->yshrink * GTK_SHRINK |
				 table_child->yfill * GTK_FILL));
512
      break;
Tim Janik's avatar
Tim Janik committed
513 514
    case CHILD_PROP_X_PADDING:
      g_value_set_uint (value, table_child->xpadding);
515
      break;
Tim Janik's avatar
Tim Janik committed
516 517
    case CHILD_PROP_Y_PADDING:
      g_value_set_uint (value, table_child->ypadding);
518 519
      break;
    default:
Tim Janik's avatar
Tim Janik committed
520
      GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec);
521 522 523 524 525 526 527
      break;
    }
}

static void
gtk_table_init (GtkTable *table)
{
528
  GtkTablePrivate *priv;
529 530 531

  table->priv = G_TYPE_INSTANCE_GET_PRIVATE (table,
                                             GTK_TYPE_TABLE,
532
                                             GtkTablePrivate);
533 534
  priv = table->priv;

535
  gtk_widget_set_has_window (GTK_WIDGET (table), FALSE);
536
  gtk_widget_set_redraw_on_allocate (GTK_WIDGET (table), FALSE);
537 538 539 540 541 542 543 544 545

  priv->children = NULL;
  priv->rows = NULL;
  priv->cols = NULL;
  priv->nrows = 0;
  priv->ncols = 0;
  priv->column_spacing = 0;
  priv->row_spacing = 0;
  priv->homogeneous = FALSE;
546 547

  gtk_table_resize (table, 1, 1);
548 549 550 551 552 553 554 555
}

GtkWidget*
gtk_table_new (guint	rows,
	       guint	columns,
	       gboolean homogeneous)
{
  GtkTable *table;
556
  GtkTablePrivate *priv;
557

558
  if (rows == 0)
Manish Singh's avatar
Manish Singh committed
559
    rows = 1;
560
  if (columns == 0)
Manish Singh's avatar
Manish Singh committed
561
    columns = 1;
562
  
Manish Singh's avatar
Manish Singh committed
563
  table = g_object_new (GTK_TYPE_TABLE, NULL);
564 565 566
  priv = table->priv;

  priv->homogeneous = (homogeneous ? TRUE : FALSE);
Elliot Lee's avatar
Elliot Lee committed
567

568 569
  gtk_table_resize (table, rows, columns);
  
Elliot Lee's avatar
Elliot Lee committed
570 571 572
  return GTK_WIDGET (table);
}

573 574 575 576
void
gtk_table_resize (GtkTable *table,
		  guint     n_rows,
		  guint     n_cols)
577
{
578
  GtkTablePrivate *priv;
579

580
  g_return_if_fail (GTK_IS_TABLE (table));
581 582
  g_return_if_fail (n_rows > 0 && n_rows <= 65535);
  g_return_if_fail (n_cols > 0 && n_cols <= 65535);
583

584 585
  priv = table->priv;

586 587
  n_rows = MAX (n_rows, 1);
  n_cols = MAX (n_cols, 1);
588

589 590
  if (n_rows != priv->nrows ||
      n_cols != priv->ncols)
591 592 593
    {
      GList *list;
      
594
      for (list = priv->children; list; list = list->next)
595 596 597 598 599
	{
	  GtkTableChild *child;
	  
	  child = list->data;
	  
600 601
	  n_rows = MAX (n_rows, child->bottom_attach);
	  n_cols = MAX (n_cols, child->right_attach);
602
	}
603 604

      if (n_rows != priv->nrows)
605 606 607
	{
	  guint i;

608 609 610 611 612
	  i = priv->nrows;
	  priv->nrows = n_rows;
	  priv->rows = g_realloc (priv->rows, priv->nrows * sizeof (GtkTableRowCol));

	  for (; i < priv->nrows; i++)
613
	    {
614 615 616 617 618 619 620
	      priv->rows[i].requisition = 0;
	      priv->rows[i].allocation = 0;
	      priv->rows[i].spacing = priv->row_spacing;
	      priv->rows[i].need_expand = 0;
	      priv->rows[i].need_shrink = 0;
	      priv->rows[i].expand = 0;
	      priv->rows[i].shrink = 0;
621
	    }
Alexander Larsson's avatar
Alexander Larsson committed
622

623
	  g_object_notify (G_OBJECT (table), "n-rows");
624 625
	}

626
      if (n_cols != priv->ncols)
627 628 629
	{
	  guint i;

630 631 632 633 634
	  i = priv->ncols;
	  priv->ncols = n_cols;
	  priv->cols = g_realloc (priv->cols, priv->ncols * sizeof (GtkTableRowCol));

	  for (; i < priv->ncols; i++)
635
	    {
636 637 638 639 640 641 642
	      priv->cols[i].requisition = 0;
	      priv->cols[i].allocation = 0;
	      priv->cols[i].spacing = priv->column_spacing;
	      priv->cols[i].need_expand = 0;
	      priv->cols[i].need_shrink = 0;
	      priv->cols[i].expand = 0;
	      priv->cols[i].shrink = 0;
643
	    }
Alexander Larsson's avatar
Alexander Larsson committed
644

645
	  g_object_notify (G_OBJECT (table), "n-columns");
646 647
	}
    }
648 649
}

Elliot Lee's avatar
Elliot Lee committed
650
void
651 652 653 654 655 656 657 658 659 660
gtk_table_attach (GtkTable	  *table,
		  GtkWidget	  *child,
		  guint		   left_attach,
		  guint		   right_attach,
		  guint		   top_attach,
		  guint		   bottom_attach,
		  GtkAttachOptions xoptions,
		  GtkAttachOptions yoptions,
		  guint		   xpadding,
		  guint		   ypadding)
Elliot Lee's avatar
Elliot Lee committed
661
{
662
  GtkTablePrivate *priv = table->priv;
Elliot Lee's avatar
Elliot Lee committed
663
  GtkTableChild *table_child;
664
  
Elliot Lee's avatar
Elliot Lee committed
665
  g_return_if_fail (GTK_IS_TABLE (table));
666
  g_return_if_fail (GTK_IS_WIDGET (child));
667 668
  g_return_if_fail (gtk_widget_get_parent (child) == NULL);

669
  /* g_return_if_fail (left_attach >= 0); */
670
  g_return_if_fail (left_attach < right_attach);
671
  /* g_return_if_fail (top_attach >= 0); */
672
  g_return_if_fail (top_attach < bottom_attach);
673 674 675 676 677 678 679 680 681

  priv = table->priv;

  if (right_attach >= priv->ncols)
    gtk_table_resize (table, priv->nrows, right_attach);

  if (bottom_attach >= priv->nrows)
    gtk_table_resize (table, bottom_attach, priv->ncols);

Elliot Lee's avatar
Elliot Lee committed
682 683 684 685 686 687 688 689 690 691 692 693 694 695
  table_child = g_new (GtkTableChild, 1);
  table_child->widget = child;
  table_child->left_attach = left_attach;
  table_child->right_attach = right_attach;
  table_child->top_attach = top_attach;
  table_child->bottom_attach = bottom_attach;
  table_child->xexpand = (xoptions & GTK_EXPAND) != 0;
  table_child->xshrink = (xoptions & GTK_SHRINK) != 0;
  table_child->xfill = (xoptions & GTK_FILL) != 0;
  table_child->xpadding = xpadding;
  table_child->yexpand = (yoptions & GTK_EXPAND) != 0;
  table_child->yshrink = (yoptions & GTK_SHRINK) != 0;
  table_child->yfill = (yoptions & GTK_FILL) != 0;
  table_child->ypadding = ypadding;
696 697 698

  priv->children = g_list_prepend (priv->children, table_child);

Elliot Lee's avatar
Elliot Lee committed
699 700 701 702 703 704
  gtk_widget_set_parent (child, GTK_WIDGET (table));
}

void
gtk_table_attach_defaults (GtkTable  *table,
			   GtkWidget *widget,
705 706 707 708
			   guint      left_attach,
			   guint      right_attach,
			   guint      top_attach,
			   guint      bottom_attach)
Elliot Lee's avatar
Elliot Lee committed
709 710 711 712 713 714 715 716 717 718 719
{
  gtk_table_attach (table, widget,
		    left_attach, right_attach,
		    top_attach, bottom_attach,
		    GTK_EXPAND | GTK_FILL,
		    GTK_EXPAND | GTK_FILL,
		    0, 0);
}

void
gtk_table_set_row_spacing (GtkTable *table,
720 721
			   guint     row,
			   guint     spacing)
Elliot Lee's avatar
Elliot Lee committed
722
{
723
  GtkTablePrivate *priv;
724

Elliot Lee's avatar
Elliot Lee committed
725
  g_return_if_fail (GTK_IS_TABLE (table));
726 727 728 729 730 731

  priv = table->priv;

  g_return_if_fail (row < priv->nrows);

  if (priv->rows[row].spacing != spacing)
Elliot Lee's avatar
Elliot Lee committed
732
    {
733 734
      priv->rows[row].spacing = spacing;

735
      if (gtk_widget_get_visible (GTK_WIDGET (table)))
Elliot Lee's avatar
Elliot Lee committed
736 737 738 739
	gtk_widget_queue_resize (GTK_WIDGET (table));
    }
}

740 741 742 743 744 745 746 747 748 749 750 751 752 753
/**
 * gtk_table_get_row_spacing:
 * @table: a #GtkTable
 * @row: a row in the table, 0 indicates the first row
 *
 * Gets the amount of space between row @row, and
 * row @row + 1. See gtk_table_set_row_spacing().
 *
 * Return value: the row spacing
 **/
guint
gtk_table_get_row_spacing (GtkTable *table,
			   guint     row)
{
754
  GtkTablePrivate *priv;
755

756
  g_return_val_if_fail (GTK_IS_TABLE (table), 0);
757 758 759 760 761 762

  priv = table->priv;

  g_return_val_if_fail (row < priv->nrows - 1, 0);

  return priv->rows[row].spacing;
763 764
}

Elliot Lee's avatar
Elliot Lee committed
765 766
void
gtk_table_set_col_spacing (GtkTable *table,
767 768
			   guint     column,
			   guint     spacing)
Elliot Lee's avatar
Elliot Lee committed
769
{
770
  GtkTablePrivate *priv;
771

Elliot Lee's avatar
Elliot Lee committed
772
  g_return_if_fail (GTK_IS_TABLE (table));
773 774 775 776 777 778

  priv = table->priv;

  g_return_if_fail (column < priv->ncols);

  if (priv->cols[column].spacing != spacing)
Elliot Lee's avatar
Elliot Lee committed
779
    {
780 781
      priv->cols[column].spacing = spacing;

782
      if (gtk_widget_get_visible (GTK_WIDGET (table)))
Elliot Lee's avatar
Elliot Lee committed
783 784 785 786
	gtk_widget_queue_resize (GTK_WIDGET (table));
    }
}

787 788 789
/**
 * gtk_table_get_col_spacing:
 * @table: a #GtkTable
790
 * @column: a column in the table, 0 indicates the first column
791 792 793 794 795 796 797 798 799 800
 *
 * Gets the amount of space between column @col, and
 * column @col + 1. See gtk_table_set_col_spacing().
 *
 * Return value: the column spacing
 **/
guint
gtk_table_get_col_spacing (GtkTable *table,
			   guint     column)
{
801
  GtkTablePrivate *priv;
802

803 804
  g_return_val_if_fail (GTK_IS_TABLE (table), 0);

805 806 807 808 809
  priv = table->priv;

  g_return_val_if_fail (column < priv->ncols, 0);

  return priv->cols[column].spacing;
810 811
}

Elliot Lee's avatar
Elliot Lee committed
812 813
void
gtk_table_set_row_spacings (GtkTable *table,
814
			    guint     spacing)
Elliot Lee's avatar
Elliot Lee committed
815
{
816
  GtkTablePrivate *priv;
817 818
  guint row;
  
Elliot Lee's avatar
Elliot Lee committed
819
  g_return_if_fail (GTK_IS_TABLE (table));
820 821 822 823 824 825 826

  priv = table->priv;

  priv->row_spacing = spacing;
  for (row = 0; row < priv->nrows; row++)
    priv->rows[row].spacing = spacing;

827
  if (gtk_widget_get_visible (GTK_WIDGET (table)))
Elliot Lee's avatar
Elliot Lee committed
828
    gtk_widget_queue_resize (GTK_WIDGET (table));
829

830
  g_object_notify (G_OBJECT (table), "row-spacing");
Elliot Lee's avatar
Elliot Lee committed
831 832
}

833 834 835 836 837 838 839 840
/**
 * gtk_table_get_default_row_spacing:
 * @table: a #GtkTable
 *
 * Gets the default row spacing for the table. This is
 * the spacing that will be used for newly added rows.
 * (See gtk_table_set_row_spacings())
 *
841
 * Return value: the default row spacing
842 843 844 845 846 847
 **/
guint
gtk_table_get_default_row_spacing (GtkTable *table)
{
  g_return_val_if_fail (GTK_IS_TABLE (table), 0);

848
  return table->priv->row_spacing;
849 850
}

Elliot Lee's avatar
Elliot Lee committed
851 852
void
gtk_table_set_col_spacings (GtkTable *table,
853
			    guint     spacing)
Elliot Lee's avatar
Elliot Lee committed
854
{
855
  GtkTablePrivate *priv;
856
  guint col;
857

Elliot Lee's avatar
Elliot Lee committed
858
  g_return_if_fail (GTK_IS_TABLE (table));
859 860 861 862 863 864 865

  priv = table->priv;

  priv->column_spacing = spacing;
  for (col = 0; col < priv->ncols; col++)
    priv->cols[col].spacing = spacing;

866
  if (gtk_widget_get_visible (GTK_WIDGET (table)))
Elliot Lee's avatar
Elliot Lee committed
867
    gtk_widget_queue_resize (GTK_WIDGET (table));
868

869
  g_object_notify (G_OBJECT (table), "column-spacing");
Elliot Lee's avatar
Elliot Lee committed
870 871
}

872 873 874 875 876 877 878 879
/**
 * gtk_table_get_default_col_spacing:
 * @table: a #GtkTable
 *
 * Gets the default column spacing for the table. This is
 * the spacing that will be used for newly added columns.
 * (See gtk_table_set_col_spacings())
 *
880
 * Return value: the default column spacing
881 882 883 884 885 886
 **/
guint
gtk_table_get_default_col_spacing (GtkTable *table)
{
  g_return_val_if_fail (GTK_IS_TABLE (table), 0);

887
  return table->priv->column_spacing;
888 889
}

890 891
void
gtk_table_set_homogeneous (GtkTable *table,
892
			   gboolean  homogeneous)
893
{
894
  GtkTablePrivate *priv;
895

896 897
  g_return_if_fail (GTK_IS_TABLE (table));

898 899
  priv = table->priv;

900
  homogeneous = (homogeneous != 0);
901
  if (homogeneous != priv->homogeneous)
902
    {
903
      priv->homogeneous = homogeneous;
904
      
905
      if (gtk_widget_get_visible (GTK_WIDGET (table)))
906
	gtk_widget_queue_resize (GTK_WIDGET (table));
907 908

      g_object_notify (G_OBJECT (table), "homogeneous");
909
    }
910 911
}

912 913 914 915 916 917 918 919 920 921 922 923 924 925
/**
 * gtk_table_get_homogeneous:
 * @table: a #GtkTable
 *
 * Returns whether the table cells are all constrained to the same
 * width and height. (See gtk_table_set_homogenous ())
 *
 * Return value: %TRUE if the cells are all constrained to the same size
 **/
gboolean
gtk_table_get_homogeneous (GtkTable *table)
{
  g_return_val_if_fail (GTK_IS_TABLE (table), FALSE);

926
  return table->priv->homogeneous;
927 928
}

929 930 931
/**
 * gtk_table_get_size:
 * @table: a #GtkTable
932
 * @rows: (out) (allow-none): return location for the number of
933
 *   rows, or %NULL
934
 * @columns: (out) (allow-none): return location for the number
935 936 937 938 939 940 941 942 943 944 945
 *   of columns, or %NULL
 *
 * Returns the number of rows and columns in the table.
 *
 * Since: 2.22
 **/
void
gtk_table_get_size (GtkTable *table,
                    guint    *rows,
                    guint    *columns)
{
946
  GtkTablePrivate *priv;
947

948 949
  g_return_if_fail (GTK_IS_TABLE (table));

950 951
  priv = table->priv;

952
  if (rows)
953
    *rows = priv->nrows;
954 955

  if (columns)
956
    *columns = priv->ncols;
957 958
}

Elliot Lee's avatar
Elliot Lee committed
959
static void
960
gtk_table_finalize (GObject *object)
Elliot Lee's avatar
Elliot Lee committed
961
{
962
  GtkTable *table = GTK_TABLE (object);
963
  GtkTablePrivate *priv = table->priv;
964 965 966

  g_free (priv->rows);
  g_free (priv->cols);
967

Matthias Clasen's avatar
Matthias Clasen committed
968
  G_OBJECT_CLASS (gtk_table_parent_class)->finalize (object);
Elliot Lee's avatar
Elliot Lee committed
969 970 971 972 973 974
}

static void
gtk_table_size_request (GtkWidget      *widget,
			GtkRequisition *requisition)
{
975
  GtkTable *table = GTK_TABLE (widget);
976
  GtkTablePrivate *priv = table->priv;
Elliot Lee's avatar
Elliot Lee committed
977
  gint row, col;
978

Elliot Lee's avatar
Elliot Lee committed
979 980
  requisition->width = 0;
  requisition->height = 0;
981
  
Elliot Lee's avatar
Elliot Lee committed
982 983 984 985 986
  gtk_table_size_request_init (table);
  gtk_table_size_request_pass1 (table);
  gtk_table_size_request_pass2 (table);
  gtk_table_size_request_pass3 (table);
  gtk_table_size_request_pass2 (table);
987 988 989 990 991 992 993 994 995 996

  for (col = 0; col < priv->ncols; col++)
    requisition->width += priv->cols[col].requisition;
  for (col = 0; col + 1 < priv->ncols; col++)
    requisition->width += priv->cols[col].spacing;

  for (row = 0; row < priv->nrows; row++)
    requisition->height += priv->rows[row].requisition;
  for (row = 0; row + 1 < priv->nrows; row++)
    requisition->height += priv->rows[row].spacing;
Elliot Lee's avatar
Elliot Lee committed
997 998 999 1000 1001 1002
}

static void
gtk_table_size_allocate (GtkWidget     *widget,
			 GtkAllocation *allocation)
{
1003 1004
  GtkTable *table = GTK_TABLE (widget);

1005
  gtk_widget_set_allocation (widget, allocation);
1006

Elliot Lee's avatar
Elliot Lee committed
1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022
  gtk_table_size_allocate_init (table);
  gtk_table_size_allocate_pass1 (table);
  gtk_table_size_allocate_pass2 (table);
}

static void
gtk_table_add (GtkContainer *container,
	       GtkWidget    *widget)
{
  gtk_table_attach_defaults (GTK_TABLE (container), widget, 0, 1, 0, 1);
}

static void
gtk_table_remove (GtkContainer *container,
		  GtkWidget    *widget)
{
1023
  GtkTable *table = GTK_TABLE (container);
1024
  GtkTablePrivate *priv = table->priv;
Elliot Lee's avatar
Elliot Lee committed
1025
  GtkTableChild *child;
1026
  GtkWidget *widget_container = GTK_WIDGET (container);
Elliot Lee's avatar
Elliot Lee committed
1027
  GList *children;
1028

1029 1030
  children = priv->children;

Elliot Lee's avatar
Elliot Lee committed
1031 1032 1033 1034
  while (children)
    {
      child = children->data;
      children = children->next;
1035
      
Elliot Lee's avatar
Elliot Lee committed
1036
      if (child->widget == widget)
1037
	{
1038
	  gboolean was_visible = gtk_widget_get_visible (widget);
1039
	  
Elliot Lee's avatar
Elliot Lee committed
1040
	  gtk_widget_unparent (widget);
1041 1042

	  priv->children = g_list_remove (priv->children, child);
1043 1044
	  g_free (child);
	  
1045 1046
	  if (was_visible && gtk_widget_get_visible (widget_container))
	    gtk_widget_queue_resize (widget_container);
1047 1048
	  break;
	}
Elliot Lee's avatar
Elliot Lee committed
1049 1050 1051 1052
    }
}

static void
1053 1054 1055 1056
gtk_table_forall (GtkContainer *container,
		  gboolean	include_internals,
		  GtkCallback	callback,
		  gpointer	callback_data)
Elliot Lee's avatar
Elliot Lee committed
1057
{
1058
  GtkTable *table = GTK_TABLE (container);
1059
  GtkTablePrivate *priv = table->priv;
Elliot Lee's avatar
Elliot Lee committed
1060 1061
  GtkTableChild *child;
  GList *children;
1062

1063 1064
  children = priv->children;

Elliot Lee's avatar
Elliot Lee committed
1065 1066 1067 1068
  while (children)
    {
      child = children->data;
      children = children->next;
1069
      
Elliot Lee's avatar
Elliot Lee committed
1070 1071 1072 1073 1074 1075 1076
      (* callback) (child->widget, callback_data);
    }
}

static void
gtk_table_size_request_init (GtkTable *table)
{
1077
  GtkTablePrivate *priv = table->priv;
Elliot Lee's avatar
Elliot Lee committed
1078 1079 1080
  GtkTableChild *child;
  GList *children;
  gint row, col;
1081 1082

  for (row = 0; row < priv->nrows; row++)
1083
    {
1084 1085
      priv->rows[row].requisition = 0;
      priv->rows[row].expand = FALSE;
1086
    }
1087
  for (col = 0; col < priv->ncols; col++)
1088
    {
1089 1090
      priv->cols[col].requisition = 0;
      priv->cols[col].expand = FALSE;
1091
    }
1092
  
1093
  children = priv->children;
Elliot Lee's avatar
Elliot Lee committed
1094 1095 1096 1097
  while (children)
    {
      child = children->data;
      children = children->next;
1098 1099 1100

      if (child->left_attach == (child->right_attach - 1) &&
          (child->xexpand || gtk_widget_compute_expand (child->widget, GTK_ORIENTATION_HORIZONTAL)))
1101
	priv->cols[child->left_attach].expand = TRUE;
1102
      
1103 1104
      if (child->top_attach == (child->bottom_attach - 1) &&
          (child->yexpand || gtk_widget_compute_expand (child->widget, GTK_ORIENTATION_VERTICAL)))
1105
	priv->rows[child->top_attach].expand = TRUE;
Elliot Lee's avatar
Elliot Lee committed
1106 1107 1108 1109 1110 1111
    }
}

static void
gtk_table_size_request_pass1 (GtkTable *table)
{
1112
  GtkTablePrivate *priv = table->priv;
Elliot Lee's avatar
Elliot Lee committed
1113 1114 1115 1116
  GtkTableChild *child;
  GList *children;
  gint width;
  gint height;
1117 1118

  children = priv->children;
Elliot Lee's avatar
Elliot Lee committed
1119 1120 1121 1122
  while (children)
    {
      child = children->data;
      children = children->next;
1123
      
1124
      if (gtk_widget_get_visible (child->widget))
1125
	{
1126
	  GtkRequisition child_requisition;
1127

1128
          gtk_widget_get_preferred_size (child->widget, &child_requisition, NULL);
1129

1130 1131 1132 1133
	  /* Child spans a single column.
	   */
	  if (child->left_attach == (child->right_attach - 1))
	    {
1134
	      width = child_requisition.width + child->xpadding * 2;
1135
	      priv->cols[child->left_attach].requisition = MAX (priv->cols[child->left_attach].requisition, width);
1136 1137 1138 1139 1140 1141
	    }
	  
	  /* Child spans a single row.
	   */
	  if (child->top_attach == (child->bottom_attach - 1))
	    {
1142
	      height = child_requisition.height + child->ypadding * 2;
1143
	      priv->rows[child->top_attach].requisition = MAX (priv->rows[child->top_attach].requisition, height);
1144 1145
	    }
	}
Elliot Lee's avatar
Elliot Lee committed
1146 1147 1148 1149 1150 1151
    }
}

static void
gtk_table_size_request_pass2 (GtkTable *table)
{
1152
  GtkTablePrivate *priv = table->priv;
Elliot Lee's avatar
Elliot Lee committed
1153 1154 1155
  gint max_width;
  gint max_height;
  gint row, col;
1156 1157

  if (priv->homogeneous)
Elliot Lee's avatar
Elliot Lee committed
1158 1159 1160
    {
      max_width = 0;
      max_height = 0;
1161 1162 1163 1164 1165 1166 1167 1168 1169 1170

      for (col = 0; col < priv->ncols; col++)
	max_width = MAX (max_width, priv->cols[col].requisition);
      for (row = 0; row < priv->nrows; row++)
	max_height = MAX (max_height, priv->rows[row].requisition);

      for (col = 0; col < priv->ncols; col++)
	priv->cols[col].requisition = max_width;
      for (row = 0; row < priv->nrows; row++)
	priv->rows[row].requisition = max_height;
Elliot Lee's avatar
Elliot Lee committed
1171 1172 1173 1174 1175 1176
    }
}

static void
gtk_table_size_request_pass3 (GtkTable *table)
{
1177
  GtkTablePrivate *priv = table->priv;
Elliot Lee's avatar
Elliot Lee committed
1178 1179 1180 1181 1182
  GtkTableChild *child;
  GList *children;
  gint width, height;
  gint row, col;
  gint extra;
1183 1184

  children = priv->children;
Elliot Lee's avatar
Elliot Lee committed
1185 1186 1187 1188
  while (children)
    {
      child = children->data;
      children = children->next;
1189
      
1190
      if (gtk_widget_get_visible (child->widget))
1191 1192 1193 1194 1195
	{
	  /* Child spans multiple columns.
	   */
	  if (child->left_attach != (child->right_attach - 1))
	    {
1196 1197
	      GtkRequisition child_requisition;

1198 1199
              gtk_widget_get_preferred_size (child->widget,
                                             &child_requisition, NULL);
1200

1201 1202 1203 1204 1205 1206
	      /* Check and see if there is already enough space
	       *  for the child.
	       */
	      width = 0;
	      for (col = child->left_attach; col < child->right_attach; col++)
		{
1207
		  width += priv->cols[col].requisition;
1208
		  if ((col + 1) < child->right_attach)
1209
		    width += priv->cols[col].spacing;
1210 1211 1212
		}
	      
	      /* If we need to request more space for this child to fill
1213 1214
	       *  its requisition, then divide up the needed space amongst the
	       *  columns it spans, favoring expandable columns if any.
1215
	       */
1216
	      if (width < child_requisition.width + child->xpadding * 2)
1217
		{
1218 1219
		  gint n_expand = 0;
		  gboolean force_expand = FALSE;
1220
		  
1221 1222
		  width = child_requisition.width + child->xpadding * 2 - width;

1223
		  for (col = child->left_attach; col < child->right_attach; col++)
1224
		    if (priv->cols[col].expand)
1225 1226 1227
		      n_expand++;

		  if (n_expand == 0)
1228
		    {
Owen Taylor's avatar