diff options
Diffstat (limited to 'gtk/gtktable.c')
-rw-r--r-- | gtk/gtktable.c | 1178 |
1 files changed, 1178 insertions, 0 deletions
diff --git a/gtk/gtktable.c b/gtk/gtktable.c new file mode 100644 index 000000000..7711524de --- /dev/null +++ b/gtk/gtktable.c @@ -0,0 +1,1178 @@ +/* GTK - The GIMP Toolkit + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * 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 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include "gtktable.h" + + +static void gtk_table_class_init (GtkTableClass *klass); +static void gtk_table_init (GtkTable *table); +static void gtk_table_destroy (GtkObject *object); +static void gtk_table_map (GtkWidget *widget); +static void gtk_table_unmap (GtkWidget *widget); +static void gtk_table_draw (GtkWidget *widget, + GdkRectangle *area); +static gint gtk_table_expose (GtkWidget *widget, + GdkEventExpose *event); +static void gtk_table_size_request (GtkWidget *widget, + GtkRequisition *requisition); +static void gtk_table_size_allocate (GtkWidget *widget, + GtkAllocation *allocation); +static void gtk_table_add (GtkContainer *container, + GtkWidget *widget); +static void gtk_table_remove (GtkContainer *container, + GtkWidget *widget); +static void gtk_table_foreach (GtkContainer *container, + GtkCallback callback, + gpointer callback_data); + +static void gtk_table_size_request_init (GtkTable *table); +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); + + +static GtkContainerClass *parent_class = NULL; + + +guint +gtk_table_get_type () +{ + static guint table_type = 0; + + if (!table_type) + { + GtkTypeInfo table_info = + { + "GtkTable", + sizeof (GtkTable), + sizeof (GtkTableClass), + (GtkClassInitFunc) gtk_table_class_init, + (GtkObjectInitFunc) gtk_table_init, + (GtkArgFunc) NULL, + }; + + table_type = gtk_type_unique (gtk_container_get_type (), &table_info); + } + + return table_type; +} + +static void +gtk_table_class_init (GtkTableClass *class) +{ + GtkObjectClass *object_class; + GtkWidgetClass *widget_class; + GtkContainerClass *container_class; + + object_class = (GtkObjectClass*) class; + widget_class = (GtkWidgetClass*) class; + container_class = (GtkContainerClass*) class; + + parent_class = gtk_type_class (gtk_container_get_type ()); + + object_class->destroy = gtk_table_destroy; + + widget_class->map = gtk_table_map; + widget_class->unmap = gtk_table_unmap; + widget_class->draw = gtk_table_draw; + widget_class->expose_event = gtk_table_expose; + widget_class->size_request = gtk_table_size_request; + widget_class->size_allocate = gtk_table_size_allocate; + + container_class->add = gtk_table_add; + container_class->remove = gtk_table_remove; + container_class->foreach = gtk_table_foreach; +} + +static void +gtk_table_init (GtkTable *table) +{ + GTK_WIDGET_SET_FLAGS (table, GTK_NO_WINDOW | GTK_BASIC); + + table->children = NULL; + table->rows = NULL; + table->cols = NULL; + table->nrows = 0; + table->ncols = 0; + table->homogeneous = FALSE; +} + +GtkWidget* +gtk_table_new (gint rows, + gint columns, + gint homogeneous) +{ + GtkTable *table; + gint row, col; + + table = gtk_type_new (gtk_table_get_type ()); + + table->nrows = rows; + table->ncols = columns; + table->homogeneous = (homogeneous ? TRUE : FALSE); + + table->rows = g_new (GtkTableRowCol, table->nrows); + table->cols = g_new (GtkTableRowCol, table->ncols); + + for (row = 0; row < table->nrows; row++) + { + table->rows[row].requisition = 0; + table->rows[row].allocation = 0; + table->rows[row].spacing = 0; + table->rows[row].need_expand = 0; + table->rows[row].need_shrink = 0; + table->rows[row].expand = 0; + table->rows[row].shrink = 0; + } + + for (col = 0; col < table->ncols; col++) + { + table->cols[col].requisition = 0; + table->cols[col].allocation = 0; + table->cols[col].spacing = 0; + table->cols[col].need_expand = 0; + table->cols[col].need_shrink = 0; + table->cols[col].expand = 0; + table->cols[col].shrink = 0; + } + + return GTK_WIDGET (table); +} + +void +gtk_table_attach (GtkTable *table, + GtkWidget *child, + gint left_attach, + gint right_attach, + gint top_attach, + gint bottom_attach, + gint xoptions, + gint yoptions, + gint xpadding, + gint ypadding) +{ + GtkTableChild *table_child; + + g_return_if_fail (table != NULL); + g_return_if_fail (GTK_IS_TABLE (table)); + g_return_if_fail (child != NULL); + + g_return_if_fail ((left_attach >= 0) && (left_attach < table->ncols)); + g_return_if_fail ((left_attach < right_attach) && (right_attach <= table->ncols)); + g_return_if_fail ((top_attach >= 0) && (top_attach < table->nrows)); + g_return_if_fail ((top_attach < bottom_attach) && (bottom_attach <= table->nrows)); + + 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; + + table->children = g_list_prepend (table->children, table_child); + + gtk_widget_set_parent (child, GTK_WIDGET (table)); + + if (GTK_WIDGET_VISIBLE (GTK_WIDGET (table))) + { + if (GTK_WIDGET_REALIZED (GTK_WIDGET (table)) && + !GTK_WIDGET_REALIZED (child)) + gtk_widget_realize (child); + + if (GTK_WIDGET_MAPPED (GTK_WIDGET (table)) && + !GTK_WIDGET_MAPPED (child)) + gtk_widget_map (child); + } + + if (GTK_WIDGET_VISIBLE (child) && GTK_WIDGET_VISIBLE (table)) + gtk_widget_queue_resize (child); +} + +void +gtk_table_attach_defaults (GtkTable *table, + GtkWidget *widget, + gint left_attach, + gint right_attach, + gint top_attach, + gint bottom_attach) +{ + 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, + gint row, + gint spacing) +{ + g_return_if_fail (table != NULL); + g_return_if_fail (GTK_IS_TABLE (table)); + g_return_if_fail ((row >= 0) && (row < (table->nrows - 1))); + + if (table->rows[row].spacing != spacing) + { + table->rows[row].spacing = spacing; + + if (GTK_WIDGET_VISIBLE (table)) + gtk_widget_queue_resize (GTK_WIDGET (table)); + } +} + +void +gtk_table_set_col_spacing (GtkTable *table, + gint column, + gint spacing) +{ + g_return_if_fail (table != NULL); + g_return_if_fail (GTK_IS_TABLE (table)); + g_return_if_fail ((column >= 0) && (column < (table->ncols - 1))); + + if (table->cols[column].spacing != spacing) + { + table->cols[column].spacing = spacing; + + if (GTK_WIDGET_VISIBLE (table)) + gtk_widget_queue_resize (GTK_WIDGET (table)); + } +} + +void +gtk_table_set_row_spacings (GtkTable *table, + gint spacing) +{ + gint row; + + g_return_if_fail (table != NULL); + g_return_if_fail (GTK_IS_TABLE (table)); + + for (row = 0; row < table->nrows - 1; row++) + table->rows[row].spacing = spacing; + + if (GTK_WIDGET_VISIBLE (table)) + gtk_widget_queue_resize (GTK_WIDGET (table)); +} + +void +gtk_table_set_col_spacings (GtkTable *table, + gint spacing) +{ + gint col; + + g_return_if_fail (table != NULL); + g_return_if_fail (GTK_IS_TABLE (table)); + + for (col = 0; col < table->ncols - 1; col++) + table->cols[col].spacing = spacing; + + if (GTK_WIDGET_VISIBLE (table)) + gtk_widget_queue_resize (GTK_WIDGET (table)); +} + + +static void +gtk_table_destroy (GtkObject *object) +{ + GtkTable *table; + GtkTableChild *child; + GList *children; + + g_return_if_fail (object != NULL); + g_return_if_fail (GTK_IS_TABLE (object)); + + table = GTK_TABLE (object); + + children = table->children; + while (children) + { + child = children->data; + children = children->next; + + child->widget->parent = NULL; + gtk_object_unref (GTK_OBJECT (child->widget)); + gtk_widget_destroy (child->widget); + g_free (child); + } + + g_list_free (table->children); + g_free (table->rows); + g_free (table->cols); + + if (GTK_OBJECT_CLASS (parent_class)->destroy) + (* GTK_OBJECT_CLASS (parent_class)->destroy) (object); +} + +static void +gtk_table_map (GtkWidget *widget) +{ + GtkTable *table; + GtkTableChild *child; + GList *children; + + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_TABLE (widget)); + + table = GTK_TABLE (widget); + GTK_WIDGET_SET_FLAGS (table, GTK_MAPPED); + + children = table->children; + while (children) + { + child = children->data; + children = children->next; + + if (GTK_WIDGET_VISIBLE (child->widget) && + !GTK_WIDGET_MAPPED (child->widget)) + gtk_widget_map (child->widget); + } +} + +static void +gtk_table_unmap (GtkWidget *widget) +{ + GtkTable *table; + GtkTableChild *child; + GList *children; + + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_TABLE (widget)); + + table = GTK_TABLE (widget); + GTK_WIDGET_UNSET_FLAGS (table, GTK_MAPPED); + + children = table->children; + while (children) + { + child = children->data; + children = children->next; + + if (GTK_WIDGET_VISIBLE (child->widget) && + GTK_WIDGET_MAPPED (child->widget)) + gtk_widget_unmap (child->widget); + } +} + +static void +gtk_table_draw (GtkWidget *widget, + GdkRectangle *area) +{ + GtkTable *table; + GtkTableChild *child; + GList *children; + GdkRectangle child_area; + + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_TABLE (widget)); + + if (GTK_WIDGET_VISIBLE (widget) && GTK_WIDGET_MAPPED (widget)) + { + table = GTK_TABLE (widget); + + children = table->children; + while (children) + { + child = children->data; + children = children->next; + + if (gtk_widget_intersect (child->widget, area, &child_area)) + gtk_widget_draw (child->widget, &child_area); + } + } +} + +static gint +gtk_table_expose (GtkWidget *widget, + GdkEventExpose *event) +{ + GtkTable *table; + GtkTableChild *child; + GList *children; + GdkEventExpose child_event; + + g_return_val_if_fail (widget != NULL, FALSE); + g_return_val_if_fail (GTK_IS_TABLE (widget), FALSE); + + if (GTK_WIDGET_VISIBLE (widget) && GTK_WIDGET_MAPPED (widget)) + { + table = GTK_TABLE (widget); + + child_event = *event; + + children = table->children; + while (children) + { + child = children->data; + children = children->next; + + if (GTK_WIDGET_NO_WINDOW (child->widget) && + gtk_widget_intersect (child->widget, &event->area, &child_event.area)) + gtk_widget_event (child->widget, (GdkEvent*) &child_event); + } + } + + return FALSE; +} + +static void +gtk_table_size_request (GtkWidget *widget, + GtkRequisition *requisition) +{ + GtkTable *table; + gint row, col; + + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_TABLE (widget)); + g_return_if_fail (requisition != NULL); + + table = GTK_TABLE (widget); + + requisition->width = 0; + requisition->height = 0; + + 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); + + for (col = 0; col < table->ncols; col++) + requisition->width += table->cols[col].requisition; + for (col = 0; col < table->ncols - 1; col++) + requisition->width += table->cols[col].spacing; + + for (row = 0; row < table->nrows; row++) + requisition->height += table->rows[row].requisition; + for (row = 0; row < table->nrows - 1; row++) + requisition->height += table->rows[row].spacing; + + requisition->width += GTK_CONTAINER (table)->border_width * 2; + requisition->height += GTK_CONTAINER (table)->border_width * 2; +} + +static void +gtk_table_size_allocate (GtkWidget *widget, + GtkAllocation *allocation) +{ + GtkTable *table; + + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_TABLE (widget)); + g_return_if_fail (allocation != NULL); + + widget->allocation = *allocation; + table = GTK_TABLE (widget); + + 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) +{ + g_return_if_fail (container != NULL); + g_return_if_fail (GTK_IS_TABLE (container)); + g_return_if_fail (widget != NULL); + + gtk_table_attach_defaults (GTK_TABLE (container), widget, 0, 1, 0, 1); +} + +static void +gtk_table_remove (GtkContainer *container, + GtkWidget *widget) +{ + GtkTable *table; + GtkTableChild *child; + GList *children; + + g_return_if_fail (container != NULL); + g_return_if_fail (GTK_IS_TABLE (container)); + g_return_if_fail (widget != NULL); + + table = GTK_TABLE (container); + children = table->children; + + while (children) + { + child = children->data; + children = children->next; + + if (child->widget == widget) + { + gtk_widget_unparent (widget); + + table->children = g_list_remove (table->children, child); + g_free (child); + + if (GTK_WIDGET_VISIBLE (widget) && GTK_WIDGET_VISIBLE (container)) + gtk_widget_queue_resize (GTK_WIDGET (container)); + break; + } + } +} + +static void +gtk_table_foreach (GtkContainer *container, + GtkCallback callback, + gpointer callback_data) +{ + GtkTable *table; + GtkTableChild *child; + GList *children; + + g_return_if_fail (container != NULL); + g_return_if_fail (GTK_IS_TABLE (container)); + g_return_if_fail (callback != NULL); + + table = GTK_TABLE (container); + children = table->children; + + while (children) + { + child = children->data; + children = children->next; + + (* callback) (child->widget, callback_data); + } +} + +static void +gtk_table_size_request_init (GtkTable *table) +{ + GtkTableChild *child; + GList *children; + gint row, col; + + for (row = 0; row < table->nrows; row++) + table->rows[row].requisition = 0; + for (col = 0; col < table->ncols; col++) + table->cols[col].requisition = 0; + + children = table->children; + while (children) + { + child = children->data; + children = children->next; + + if (GTK_WIDGET_VISIBLE (child->widget)) + gtk_widget_size_request (child->widget, &child->widget->requisition); + } +} + +static void +gtk_table_size_request_pass1 (GtkTable *table) +{ + GtkTableChild *child; + GList *children; + gint width; + gint height; + + children = table->children; + while (children) + { + child = children->data; + children = children->next; + + if (GTK_WIDGET_VISIBLE (child->widget)) + { + /* Child spans a single column. + */ + if (child->left_attach == (child->right_attach - 1)) + { + width = child->widget->requisition.width + child->xpadding * 2; + table->cols[child->left_attach].requisition = MAX (table->cols[child->left_attach].requisition, width); + } + + /* Child spans a single row. + */ + if (child->top_attach == (child->bottom_attach - 1)) + { + height = child->widget->requisition.height + child->ypadding * 2; + table->rows[child->top_attach].requisition = MAX (table->rows[child->top_attach].requisition, height); + } + } + } +} + +static void +gtk_table_size_request_pass2 (GtkTable *table) +{ + gint max_width; + gint max_height; + gint row, col; + + if (table->homogeneous) + { + max_width = 0; + max_height = 0; + + for (col = 0; col < table->ncols; col++) + max_width = MAX (max_width, table->cols[col].requisition); + for (row = 0; row < table->nrows; row++) + max_height = MAX (max_height, table->rows[row].requisition); + + for (col = 0; col < table->ncols; col++) + table->cols[col].requisition = max_width; + for (row = 0; row < table->nrows; row++) + table->rows[row].requisition = max_height; + } +} + +static void +gtk_table_size_request_pass3 (GtkTable *table) +{ + GtkTableChild *child; + GList *children; + gint width, height; + gint row, col; + gint extra; + + children = table->children; + while (children) + { + child = children->data; + children = children->next; + + if (GTK_WIDGET_VISIBLE (child->widget)) + { + /* Child spans multiple columns. + */ + if (child->left_attach != (child->right_attach - 1)) + { + /* Check and see if there is already enough space + * for the child. + */ + width = 0; + for (col = child->left_attach; col < child->right_attach; col++) + { + width += table->cols[col].requisition; + if ((col + 1) < child->right_attach) + width += table->cols[col].spacing; + } + + /* If we need to request more space for this child to fill + * its requisition, then divide up the needed space evenly + * amongst the columns it spans. + */ + if (width < child->widget->requisition.width) + { + width = child->widget->requisition.width - width; + extra = width / (child->right_attach - child->left_attach); + + for (col = child->left_attach; col < child->right_attach; col++) + { + if ((col + 1) < child->right_attach) + table->cols[col].requisition += extra; + else + table->cols[col].requisition += width; + width -= extra; + } + } + } + + /* Child spans multiple rows. + */ + if (child->top_attach != (child->bottom_attach - 1)) + { + /* Check and see if there is already enough space + * for the child. + */ + height = 0; + for (row = child->top_attach; row < child->bottom_attach; row++) + { + height += table->rows[row].requisition; + if ((row + 1) < child->bottom_attach) + height += table->rows[row].spacing; + } + + /* If we need to request more space for this child to fill + * its requisition, then divide up the needed space evenly + * amongst the columns it spans. + */ + if (height < child->widget->requisition.height) + { + height = child->widget->requisition.height - height; + extra = height / (child->bottom_attach - child->top_attach); + + for (row = child->top_attach; row < child->bottom_attach; row++) + { + if ((row + 1) < child->bottom_attach) + table->rows[row].requisition += extra; + else + table->rows[row].requisition += height; + height -= extra; + } + } + } + } + } +} + +static void +gtk_table_size_allocate_init (GtkTable *table) +{ + GtkTableChild *child; + GList *children; + gint row, col; + gint has_expand; + gint has_shrink; + + /* Initialize the rows and cols. + * By default, rows and cols do not expand and do shrink. + * Those values are modified by the children that occupy + * the rows and cols. + */ + for (col = 0; col < table->ncols; col++) + { + table->cols[col].allocation = table->cols[col].requisition; + table->cols[col].need_expand = FALSE; + table->cols[col].need_shrink = TRUE; + table->cols[col].expand = FALSE; + table->cols[col].shrink = TRUE; + } + for (row = 0; row < table->nrows; row++) + { + table->rows[row].allocation = table->rows[row].requisition; + table->rows[row].need_expand = FALSE; + table->rows[row].need_shrink = TRUE; + table->rows[row].expand = FALSE; + table->rows[row].shrink = TRUE; + } + + /* Loop over all the children and adjust the row and col values + * based on whether the children want to be allowed to expand + * or shrink. This loop handles children that occupy a single + * row or column. + */ + children = table->children; + while (children) + { + child = children->data; + children = children->next; + + if (GTK_WIDGET_VISIBLE (child->widget)) + { + if (child->left_attach == (child->right_attach - 1)) + { + if (child->xexpand) + table->cols[child->left_attach].expand = TRUE; + + if (!child->xshrink) + table->cols[child->left_attach].shrink = FALSE; + } + + if (child->top_attach == (child->bottom_attach - 1)) + { + if (child->yexpand) + table->rows[child->top_attach].expand = TRUE; + + if (!child->yshrink) + table->rows[child->top_attach].shrink = FALSE; + } + } + } + + /* Loop over all the children again and this time handle children + * which span multiple rows or columns. + */ + children = table->children; + while (children) + { + child = children->data; + children = children->next; + + if (GTK_WIDGET_VISIBLE (child->widget)) + { + if (child->left_attach != (child->right_attach - 1)) + { + if (child->xexpand) + { + has_expand = FALSE; + for (col = child->left_attach; col < child->right_attach; col++) + if (table->cols[col].expand) + { + has_expand = TRUE; + break; + } + + if (!has_expand) + for (col = child->left_attach; col < child->right_attach; col++) + table->cols[col].need_expand = TRUE; + } + + if (!child->xshrink) + { + has_shrink = TRUE; + for (col = child->left_attach; col < child->right_attach; col++) + if (!table->cols[col].shrink) + { + has_shrink = FALSE; + break; + } + + if (has_shrink) + for (col = child->left_attach; col < child->right_attach; col++) + table->cols[col].need_shrink = FALSE; + } + } + + if (child->top_attach != (child->bottom_attach - 1)) + { + if (child->yexpand) + { + has_expand = FALSE; + for (row = child->top_attach; row < child->bottom_attach; row++) + if (table->rows[row].expand) + { + has_expand = TRUE; + break; + } + + if (!has_expand) + for (row = child->top_attach; row < child->bottom_attach; row++) + table->rows[row].need_expand = TRUE; + } + + if (!child->yshrink) + { + has_shrink = TRUE; + for (row = child->top_attach; row < child->bottom_attach; row++) + if (!table->rows[row].shrink) + { + has_shrink = FALSE; + break; + } + + if (has_shrink) + for (row = child->top_attach; row < child->bottom_attach; row++) + table->rows[row].need_shrink = FALSE; + } + } + } + } + + /* Loop over the columns and set the expand and shrink values + * if the column can be expanded or shrunk. + */ + for (col = 0; col < table->ncols; col++) + { + if (table->cols[col].need_expand) + table->cols[col].expand = TRUE; + if (!table->cols[col].need_shrink) + table->cols[col].shrink = FALSE; + } + + /* Loop over the rows and set the expand and shrink values + * if the row can be expanded or shrunk. + */ + for (row = 0; row < table->nrows; row++) + { + if (table->rows[row].need_expand) + table->rows[row].expand = TRUE; + if (!table->rows[row].need_shrink) + table->rows[row].shrink = FALSE; + } +} + +static void +gtk_table_size_allocate_pass1 (GtkTable *table) +{ + gint real_width; + gint real_height; + gint width, height; + gint row, col; + gint nexpand; + gint nshrink; + gint extra; + + /* If we were allocated more space than we requested + * then we have to expand any expandable rows and columns + * to fill in the extra space. + */ + + real_width = GTK_WIDGET (table)->allocation.width - GTK_CONTAINER (table)->border_width * 2; + real_height = GTK_WIDGET (table)->allocation.height - GTK_CONTAINER (table)->border_width * 2; + + if (table->homogeneous) + { + nexpand = 0; + for (col = 0; col < table->ncols; col++) + if (table->cols[col].expand) + { + nexpand += 1; + break; + } + + if (nexpand > 0) + { + width = real_width; + + for (col = 0; col < table->ncols - 1; col++) + width -= table->cols[col].spacing; + + extra = width / table->ncols; + + for (col = 0; col < table->ncols; col++) + { + if ((col + 1) == table->ncols) + table->cols[col].allocation = width; + else + table->cols[col].allocation = extra; + + width -= extra; + } + } + } + else + { + width = 0; + nexpand = 0; + nshrink = 0; + + for (col = 0; col < table->ncols; col++) + { + width += table->cols[col].requisition; + if (table->cols[col].expand) + nexpand += 1; + if (table->cols[col].shrink) + nshrink += 1; + } + for (col = 0; col < table->ncols - 1; col++) + width += table->cols[col].spacing; + + /* Check to see if we were allocated more width than we requested. + */ + if ((width < real_width) && (nexpand >= 1)) + { + width = real_width - width; + extra = width / nexpand; + + for (col = 0; col < table->ncols; col++) + if (table->cols[col].expand) + { + if (nexpand == 1) + table->cols[col].allocation += width; + else + table->cols[col].allocation += extra; + + width -= extra; + nexpand -= 1; + } + } + + /* Check to see if we were allocated less width than we requested. + */ + if ((width > real_width) && (nshrink >= 1)) + { + width = width - real_width; + extra = width / nshrink; + + for (col = 0; col < table->ncols; col++) + if (table->cols[col].shrink) + { + if (nshrink == 1) + table->cols[col].allocation -= width; + else + table->cols[col].allocation -= extra; + + width -= extra; + nshrink -= 1; + } + } + } + + if (table->homogeneous) + { + nexpand = 0; + for (row = 0; row < table->nrows; row++) + if (table->rows[row].expand) + { + nexpand += 1; + break; + } + + if (nexpand > 0) + { + height = real_height; + + for (row = 0; row < table->nrows - 1; row++) + height -= table->rows[row].spacing; + + extra = height / table->nrows; + + for (row = 0; row < table->nrows; row++) + { + if ((row + 1) == table->nrows) + table->rows[row].allocation = height; + else + table->rows[row].allocation = extra; + + height -= extra; + } + } + } + else + { + height = 0; + nexpand = 0; + nshrink = 0; + + for (row = 0; row < table->nrows; row++) + { + height += table->rows[row].requisition; + if (table->rows[row].expand) + nexpand += 1; + if (table->rows[row].shrink) + nshrink += 1; + } + for (row = 0; row < table->nrows - 1; row++) + height += table->rows[row].spacing; + + /* Check to see if we were allocated more height than we requested. + */ + if ((height < real_height) && (nexpand >= 1)) + { + height = real_height - height; + extra = height / nexpand; + + for (row = 0; row < table->nrows; row++) + if (table->rows[row].expand) + { + if (nexpand == 1) + table->rows[row].allocation += height; + else + table->rows[row].allocation += extra; + + height -= extra; + nexpand -= 1; + } + } + + /* Check to see if we were allocated less height than we requested. + */ + if ((height > real_height) && (nshrink >= 1)) + { + height = height - real_height; + extra = height / nshrink; + + for (row = 0; row < table->nrows; row++) + if (table->rows[row].shrink) + { + if (nshrink == 1) + table->rows[row].allocation -= height; + else + table->rows[row].allocation -= extra; + + height -= extra; + nshrink -= 1; + } + } + } +} + +static void +gtk_table_size_allocate_pass2 (GtkTable *table) +{ + GtkTableChild *child; + GList *children; + gint max_width; + gint max_height; + gint x, y; + gint row, col; + GtkAllocation allocation; + + children = table->children; + while (children) + { + child = children->data; + children = children->next; + + if (GTK_WIDGET_VISIBLE (child->widget)) + { + x = GTK_WIDGET (table)->allocation.x + GTK_CONTAINER (table)->border_width; + y = GTK_WIDGET (table)->allocation.y + GTK_CONTAINER (table)->border_width; + max_width = 0; + max_height = 0; + + for (col = 0; col < child->left_attach; col++) + { + x += table->cols[col].allocation; + x += table->cols[col].spacing; + } + + for (col = child->left_attach; col < child->right_attach; col++) + { + max_width += table->cols[col].allocation; + if ((col + 1) < child->right_attach) + max_width += table->cols[col].spacing; + } + + for (row = 0; row < child->top_attach; row++) + { + y += table->rows[row].allocation; + y += table->rows[row].spacing; + } + + for (row = child->top_attach; row < child->bottom_attach; row++) + { + max_height += table->rows[row].allocation; + if ((row + 1) < child->bottom_attach) + max_height += table->rows[row].spacing; + } + + if (child->xfill) + { + allocation.width = max_width - child->xpadding * 2; + allocation.x = x + (max_width - allocation.width) / 2; + } + else + { + allocation.width = child->widget->requisition.width; + allocation.x = x + (max_width - allocation.width) / 2; + } + + if (child->yfill) + { + allocation.height = max_height - child->ypadding * 2; + allocation.y = y + (max_height - allocation.height) / 2; + } + else + { + allocation.height = child->widget->requisition.height; + allocation.y = y + (max_height - allocation.height) / 2; + } + + gtk_widget_size_allocate (child->widget, &allocation); + } + } +} |