summaryrefslogtreecommitdiff
path: root/cut-n-paste-code/widgets
diff options
context:
space:
mode:
authorRebecca Schulman <rebecka@eazel.com>2000-11-28 23:21:50 +0000
committerRebecca Schulman <rebecka@src.gnome.org>2000-11-28 23:21:50 +0000
commitc9505cccbe416b9e74d386d86ea35af6b72622c8 (patch)
tree819d428d194c53d941416afa7a89422a92b68fdd /cut-n-paste-code/widgets
parentf3c4b254f31421d146292cf0476465fbc0f1f813 (diff)
downloadnautilus-c9505cccbe416b9e74d386d86ea35af6b72622c8.tar.gz
Fixes for bugs 2376, 4553, and 3799 This should make the complex search
2000-11-28 Rebecca Schulman <rebecka@eazel.com> Fixes for bugs 2376, 4553, and 3799 This should make the complex search bar usable and visible. reviewed by: Maciej Stachowiak <mjs@eazel.com> * configure.in: * libnautilus-extensions/Makefile.am: * cut-n-paste-code/widgets/Makefile.am: * cut-n-paste-code/widgets/gimphwrapbox/.cvsignore: * cut-n-paste-code/widgets/gimphwrapbox/Makefile.am: * cut-n-paste-code/widgets/gimphwrapbox/gtkhwrapbox.c: (gtk_hwrap_box_get_type), (gtk_hwrap_box_class_init), (gtk_hwrap_box_init), (gtk_hwrap_box_new), (get_child_requisition), (_gtk_hwrap_box_size_request), (get_layout_size), (gtk_hwrap_box_size_request), (reverse_list_row_children), (layout_row), (layout_rows), (gtk_hwrap_box_size_allocate): * cut-n-paste-code/widgets/gimphwrapbox/gtkhwrapbox.h: * cut-n-paste-code/widgets/gimphwrapbox/gtkwrapbox.c: (gtk_wrap_box_get_type), (gtk_wrap_box_class_init), (gtk_wrap_box_init), (gtk_wrap_box_set_arg), (gtk_wrap_box_get_arg), (gtk_wrap_box_set_child_arg), (gtk_wrap_box_get_child_arg), (gtk_wrap_box_child_type), (gtk_wrap_box_set_homogeneous), (gtk_wrap_box_set_hspacing), (gtk_wrap_box_set_vspacing), (gtk_wrap_box_set_justify), (gtk_wrap_box_set_line_justify), (gtk_wrap_box_set_aspect_ratio), (gtk_wrap_box_pack), (gtk_wrap_box_reorder_child), (gtk_wrap_box_query_child_packing), (gtk_wrap_box_query_child_forced_break), (gtk_wrap_box_set_child_packing), (gtk_wrap_box_set_child_forced_break), (gtk_wrap_box_query_line_lengths), (gtk_wrap_box_map), (gtk_wrap_box_unmap), (gtk_wrap_box_draw), (gtk_wrap_box_expose), (gtk_wrap_box_add), (gtk_wrap_box_remove), (gtk_wrap_box_forall): * cut-n-paste-code/widgets/gimphwrapbox/gtkwrapbox.h: Copied and pasted the wrapping hbox from the Gimp. I made a few modifications, including some resizing requests, when the chosen size is not the right one for the actual space available. Sizing wrapping boxes is a tricky problem with gtk, because they have nonstandard sizing requests (they can request x or y or z) and my solution is probably not optimal, since some of the sizing adjustments are visible on screen. However, a better fix is a lot more time consuming, and should probably wait for past 1.0. * src/nautilus-complex-search-bar.c: (search_bar_criterion_type_changed_callback), (queue_search_bar_resize_callback), (nautilus_complex_search_bar_initialize_class), (nautilus_complex_search_bar_initialize), (real_activate), (nautilus_complex_search_bar_queue_resize), (attach_criterion_to_search_bar), (unattach_criterion_from_search_bar), (load_find_them_pixmap_widget), (more_options_callback), (fewer_options_callback), (update_options_buttons_state): * src/nautilus-complex-search-bar.h: Changed the criteria layout to be in a vbox instead of a table, so that we can insert wrapping hboxes. Added a new function that will effectively resize the complex search bar, and we call it at appropriate points. Switched the packing order of the buttons, since the wrap box has only one packing function, and it is a pack_start, rather than a pack_end function * src/nautilus-search-bar-criterion-private.h: * src/nautilus-search-bar-criterion.c: (queue_bar_resize_callback), (nautilus_search_bar_criterion_new_from_values), (nautilus_search_bar_criterion_show), (nautilus_search_bar_criterion_hide), (nautilus_search_bar_criterion_update_valid_criteria_choices), (hide_date_widget), (show_date_widget), (make_emblem_value_menu): Put the criteria into wrapping boxes as part of their creation, and trigger a resize of the complex search bar when the wrapping box complains about its allocated size.
Diffstat (limited to 'cut-n-paste-code/widgets')
-rw-r--r--cut-n-paste-code/widgets/Makefile.am1
-rw-r--r--cut-n-paste-code/widgets/gimphwrapbox/.cvsignore6
-rw-r--r--cut-n-paste-code/widgets/gimphwrapbox/Makefile.am21
-rw-r--r--cut-n-paste-code/widgets/gimphwrapbox/gtkhwrapbox.c663
-rw-r--r--cut-n-paste-code/widgets/gimphwrapbox/gtkhwrapbox.h78
-rw-r--r--cut-n-paste-code/widgets/gimphwrapbox/gtkwrapbox.c848
-rw-r--r--cut-n-paste-code/widgets/gimphwrapbox/gtkwrapbox.h149
7 files changed, 1766 insertions, 0 deletions
diff --git a/cut-n-paste-code/widgets/Makefile.am b/cut-n-paste-code/widgets/Makefile.am
index d86aab756..b97e9437b 100644
--- a/cut-n-paste-code/widgets/Makefile.am
+++ b/cut-n-paste-code/widgets/Makefile.am
@@ -3,4 +3,5 @@ NULL=
SUBDIRS =\
nautilusclist \
e-paned \
+ gimphwrapbox \
$(NULL)
diff --git a/cut-n-paste-code/widgets/gimphwrapbox/.cvsignore b/cut-n-paste-code/widgets/gimphwrapbox/.cvsignore
new file mode 100644
index 000000000..799fc9785
--- /dev/null
+++ b/cut-n-paste-code/widgets/gimphwrapbox/.cvsignore
@@ -0,0 +1,6 @@
+.deps
+.libs
+*.lo
+*.la
+Makefile
+Makefile.in
diff --git a/cut-n-paste-code/widgets/gimphwrapbox/Makefile.am b/cut-n-paste-code/widgets/gimphwrapbox/Makefile.am
new file mode 100644
index 000000000..ede15114b
--- /dev/null
+++ b/cut-n-paste-code/widgets/gimphwrapbox/Makefile.am
@@ -0,0 +1,21 @@
+NULL=
+
+noinst_LTLIBRARIES = libgtkhwrapbox.la
+
+INCLUDES = \
+ -I$(top_srcdir)/cut-n-paste-code \
+ $(GNOME_CFLAGS) \
+ $(NULL)
+
+libgtkhwrapbox_la_LDFLAGS = -static
+
+libgtkhwrapbox_la_SOURCES = \
+ gtkhwrapbox.c \
+ gtkwrapbox.c \
+ $(NULL)
+
+# Everything is private for now
+noinst_HEADERS =\
+ gtkhwrapbox.h \
+ gtkwrapbox.h \
+ $(NULL)
diff --git a/cut-n-paste-code/widgets/gimphwrapbox/gtkhwrapbox.c b/cut-n-paste-code/widgets/gimphwrapbox/gtkhwrapbox.c
new file mode 100644
index 000000000..cf442f4f2
--- /dev/null
+++ b/cut-n-paste-code/widgets/gimphwrapbox/gtkhwrapbox.c
@@ -0,0 +1,663 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * GtkHWrapBox: Horizontal wrapping box widget
+ * Copyright (C) 1999 Tim Janik
+ *
+ * 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., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#include "gtkhwrapbox.h"
+#include <gtk/gtksignal.h>
+#include <math.h>
+
+
+/* --- prototypes --- */
+static void gtk_hwrap_box_class_init (GtkHWrapBoxClass *klass);
+static void gtk_hwrap_box_init (GtkHWrapBox *hwbox);
+static void gtk_hwrap_box_size_request (GtkWidget *widget,
+ GtkRequisition *requisition);
+static void gtk_hwrap_box_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation);
+static GSList* reverse_list_row_children (GtkWrapBox *wbox,
+ GtkWrapBoxChild **child_p,
+ GtkAllocation *area,
+ guint *max_height,
+ gboolean *can_vexpand);
+
+
+/* --- variables --- */
+static gpointer parent_class = NULL;
+
+
+/* --- functions --- */
+GtkType
+gtk_hwrap_box_get_type (void)
+{
+ static GtkType hwrap_box_type = 0;
+
+ if (!hwrap_box_type)
+ {
+ static const GtkTypeInfo hwrap_box_info =
+ {
+ "GtkHWrapBox",
+ sizeof (GtkHWrapBox),
+ sizeof (GtkHWrapBoxClass),
+ (GtkClassInitFunc) gtk_hwrap_box_class_init,
+ (GtkObjectInitFunc) gtk_hwrap_box_init,
+ /* reserved_1 */ NULL,
+ /* reserved_2 */ NULL,
+ (GtkClassInitFunc) NULL,
+ };
+
+ hwrap_box_type = gtk_type_unique (GTK_TYPE_WRAP_BOX, &hwrap_box_info);
+ }
+
+ return hwrap_box_type;
+}
+
+static void
+gtk_hwrap_box_class_init (GtkHWrapBoxClass *class)
+{
+ GtkObjectClass *object_class;
+ GtkWidgetClass *widget_class;
+ GtkContainerClass *container_class;
+ GtkWrapBoxClass *wrap_box_class;
+
+ object_class = GTK_OBJECT_CLASS (class);
+ widget_class = GTK_WIDGET_CLASS (class);
+ container_class = GTK_CONTAINER_CLASS (class);
+ wrap_box_class = GTK_WRAP_BOX_CLASS (class);
+
+ parent_class = gtk_type_class (GTK_TYPE_WRAP_BOX);
+
+ widget_class->size_request = gtk_hwrap_box_size_request;
+ widget_class->size_allocate = gtk_hwrap_box_size_allocate;
+
+ wrap_box_class->rlist_line_children = reverse_list_row_children;
+}
+
+static void
+gtk_hwrap_box_init (GtkHWrapBox *hwbox)
+{
+ hwbox->max_child_width = 0;
+ hwbox->max_child_height = 0;
+ hwbox->request_stored_height = FALSE;
+}
+
+GtkWidget*
+gtk_hwrap_box_new (gboolean homogeneous)
+{
+ GtkHWrapBox *hwbox;
+
+ hwbox = GTK_HWRAP_BOX (gtk_widget_new (GTK_TYPE_HWRAP_BOX, NULL));
+
+ GTK_WRAP_BOX (hwbox)->homogeneous = homogeneous ? TRUE : FALSE;
+
+ return GTK_WIDGET (hwbox);
+}
+
+static inline void
+get_child_requisition (GtkWrapBox *wbox,
+ GtkWidget *child,
+ GtkRequisition *child_requisition)
+{
+ if (wbox->homogeneous)
+ {
+ GtkHWrapBox *hwbox = GTK_HWRAP_BOX (wbox);
+
+ child_requisition->width = hwbox->max_child_width;
+ child_requisition->height = hwbox->max_child_height;
+ }
+ else
+ gtk_widget_get_child_requisition (child, child_requisition);
+}
+
+#if 0
+static void
+_gtk_hwrap_box_size_request (GtkWidget *widget,
+ GtkRequisition *requisition)
+{
+ GtkHWrapBox *this = GTK_HWRAP_BOX (widget);
+ GtkWrapBox *wbox = GTK_WRAP_BOX (widget);
+ GtkWrapBoxChild *child;
+ guint area = 0;
+
+ g_return_if_fail (requisition != NULL);
+
+ /*<h2v-off>*/
+ requisition->width = 0;
+ requisition->height = 0;
+ this->max_child_width = 0;
+ this->max_child_height = 0;
+
+ for (child = wbox->children; child; child = child->next)
+ if (GTK_WIDGET_VISIBLE (child->widget))
+ {
+ GtkRequisition child_requisition;
+
+ gtk_widget_size_request (child->widget, &child_requisition);
+
+ area += child_requisition.width * child_requisition.height;
+ this->max_child_width = MAX (this->max_child_width, child_requisition.width);
+ this->max_child_height = MAX (this->max_child_height, child_requisition.height);
+ }
+ if (wbox->homogeneous)
+ area = this->max_child_width * this->max_child_height * wbox->n_children;
+
+ if (area)
+ {
+ requisition->width = sqrt (area * wbox->aspect_ratio);
+ requisition->height = area / requisition->width;
+ }
+ else
+ {
+ requisition->width = 0;
+ requisition->height = 0;
+ }
+
+ requisition->width += GTK_CONTAINER (wbox)->border_width * 2;
+ requisition->height += GTK_CONTAINER (wbox)->border_width * 2;
+ /*<h2v-on>*/
+}
+#endif
+
+static gfloat
+get_layout_size (GtkHWrapBox *this,
+ guint max_width,
+ guint *width_inc)
+{
+ GtkWrapBox *wbox = GTK_WRAP_BOX (this);
+ GtkWrapBoxChild *child;
+ guint n_rows, left_over = 0, total_height = 0;
+ gboolean last_row_filled = TRUE;
+
+ *width_inc = this->max_child_width + 1;
+
+ n_rows = 0;
+ for (child = wbox->children; child; child = child->next)
+ {
+ GtkWrapBoxChild *row_child;
+ GtkRequisition child_requisition;
+ guint row_width, row_height, n = 1;
+
+ if (!GTK_WIDGET_VISIBLE (child->widget))
+ continue;
+
+ get_child_requisition (wbox, child->widget, &child_requisition);
+ if (!last_row_filled)
+ *width_inc = MIN (*width_inc, child_requisition.width - left_over);
+ row_width = child_requisition.width;
+ row_height = child_requisition.height;
+ for (row_child = child->next; row_child && n < wbox->child_limit; row_child = row_child->next)
+ {
+ if (GTK_WIDGET_VISIBLE (row_child->widget))
+ {
+ get_child_requisition (wbox, row_child->widget, &child_requisition);
+ if (row_width + wbox->hspacing + child_requisition.width > max_width)
+ break;
+ row_width += wbox->hspacing + child_requisition.width;
+ row_height = MAX (row_height, (guint) child_requisition.height);
+ n++;
+ }
+ child = row_child;
+ }
+ last_row_filled = n >= wbox->child_limit;
+ left_over = last_row_filled ? 0 : max_width - (row_width + wbox->hspacing);
+ total_height += (n_rows ? wbox->vspacing : 0) + row_height;
+ n_rows++;
+ }
+
+ if (*width_inc > this->max_child_width)
+ *width_inc = 0;
+
+ return MAX (total_height, 1);
+}
+
+
+static void
+gtk_hwrap_box_size_request (GtkWidget *widget,
+ GtkRequisition *requisition)
+{
+ GtkHWrapBox *this = GTK_HWRAP_BOX (widget);
+ GtkWrapBox *wbox = GTK_WRAP_BOX (widget);
+ GtkWrapBoxChild *child;
+ gfloat ratio_dist, layout_width = 0;
+ guint row_inc = 0;
+
+ g_return_if_fail (requisition != NULL);
+
+ requisition->width = 0;
+ requisition->height = 0;
+ this->max_child_width = 0;
+ this->max_child_height = 0;
+
+
+ /* size_request all children */
+ for (child = wbox->children; child; child = child->next)
+ if (GTK_WIDGET_VISIBLE (child->widget))
+ {
+ GtkRequisition child_requisition;
+
+ gtk_widget_size_request (child->widget, &child_requisition);
+
+ this->max_child_width = MAX (this->max_child_width, child_requisition.width);
+ this->max_child_height = MAX (this->max_child_height, child_requisition.height);
+ }
+
+ /* figure all possible layouts */
+ ratio_dist = 32768;
+ layout_width = this->max_child_width;
+ do
+ {
+ gfloat layout_height;
+ gfloat ratio, dist;
+ GtkRequisition *saved_requisition;
+
+ layout_width += row_inc;
+ layout_height = get_layout_size (this, layout_width, &row_inc);
+ ratio = layout_width / layout_height; /*<h2v-skip>*/
+ dist = MAX (ratio, wbox->aspect_ratio) - MIN (ratio, wbox->aspect_ratio);
+ if (dist < ratio_dist ||
+ (this->request_stored_height &&
+ layout_height == this->request_this_height_next_time))
+ {
+ ratio_dist = dist;
+ requisition->width = layout_width;
+ requisition->height = layout_height;
+ }
+ saved_requisition = g_new0 (GtkRequisition, 1);
+ saved_requisition->width = layout_width;
+ saved_requisition->height = layout_height;
+ }
+ while (row_inc);
+ requisition->width += GTK_CONTAINER (wbox)->border_width * 2; /*<h2v-skip>*/
+ requisition->height += GTK_CONTAINER (wbox)->border_width * 2; /*<h2v-skip>*/
+}
+
+static GSList*
+reverse_list_row_children (GtkWrapBox *wbox,
+ GtkWrapBoxChild **child_p,
+ GtkAllocation *area,
+ guint *max_child_size,
+ gboolean *expand_line)
+{
+ GSList *slist = NULL;
+ guint width = 0, row_width = area->width;
+ GtkWrapBoxChild *child = *child_p;
+
+ *max_child_size = 0;
+ *expand_line = FALSE;
+
+ while (child && !GTK_WIDGET_VISIBLE (child->widget))
+ {
+ *child_p = child->next;
+ child = *child_p;
+ }
+
+ if (child)
+ {
+ GtkRequisition child_requisition;
+ guint n = 1;
+
+ get_child_requisition (wbox, child->widget, &child_requisition);
+ width += child_requisition.width;
+ *max_child_size = MAX (*max_child_size, (guint) child_requisition.height);
+ *expand_line |= child->vexpand;
+ slist = g_slist_prepend (slist, child);
+ *child_p = child->next;
+ child = *child_p;
+
+ while (child && n < wbox->child_limit)
+ {
+ if (GTK_WIDGET_VISIBLE (child->widget))
+ {
+ get_child_requisition (wbox, child->widget, &child_requisition);
+ if (width + wbox->hspacing + child_requisition.width > row_width ||
+ child->forced_break)
+ break;
+ width += wbox->hspacing + child_requisition.width;
+ *max_child_size = MAX (*max_child_size, (guint) child_requisition.height);
+ *expand_line |= child->vexpand;
+ slist = g_slist_prepend (slist, child);
+ n++;
+ }
+ *child_p = child->next;
+ child = *child_p;
+ }
+ }
+
+ return slist;
+}
+
+static void
+layout_row (GtkWrapBox *wbox,
+ GtkAllocation *area,
+ GSList *children,
+ guint children_per_line,
+ gboolean vexpand)
+{
+ GSList *slist;
+ guint n_children = 0, n_expand_children = 0, have_expand_children = 0, total_width = 0;
+ gfloat x, width, extra;
+ GtkAllocation child_allocation;
+
+ for (slist = children; slist; slist = slist->next)
+ {
+ GtkWrapBoxChild *child = slist->data;
+ GtkRequisition child_requisition;
+
+ n_children++;
+ if (child->hexpand)
+ n_expand_children++;
+
+ get_child_requisition (wbox, child->widget, &child_requisition);
+ total_width += child_requisition.width;
+ }
+
+ width = MAX (1, area->width - (n_children - 1) * wbox->hspacing);
+ if (width > total_width)
+ extra = width - total_width;
+ else
+ extra = 0;
+ have_expand_children = n_expand_children && extra;
+
+ x = area->x;
+ if (wbox->homogeneous)
+ {
+ width = MAX (1, area->width - (children_per_line - 1) * wbox->hspacing);
+ width /= ((gdouble) children_per_line);
+ extra = 0;
+ }
+ else if (have_expand_children && wbox->justify != GTK_JUSTIFY_FILL)
+ {
+ width = extra;
+ extra /= ((gdouble) n_expand_children);
+ }
+ else
+ {
+ if (wbox->justify == GTK_JUSTIFY_FILL)
+ {
+ width = extra;
+ have_expand_children = TRUE;
+ n_expand_children = n_children;
+ extra /= ((gdouble) n_expand_children);
+ }
+ else if (wbox->justify == GTK_JUSTIFY_CENTER)
+ {
+ x += extra / 2;
+ width = 0;
+ extra = 0;
+ }
+ else if (wbox->justify == GTK_JUSTIFY_LEFT)
+ {
+ width = 0;
+ extra = 0;
+ }
+ else if (wbox->justify == GTK_JUSTIFY_RIGHT)
+ {
+ x += extra;
+ width = 0;
+ extra = 0;
+ }
+ }
+
+ n_children = 0;
+ for (slist = children; slist; slist = slist->next)
+ {
+ GtkWrapBoxChild *child = slist->data;
+
+ child_allocation.x = x;
+ child_allocation.y = area->y;
+ if (wbox->homogeneous)
+ {
+ child_allocation.height = area->height;
+ child_allocation.width = width;
+ x += child_allocation.width + wbox->hspacing;
+ }
+ else
+ {
+ GtkRequisition child_requisition;
+
+ get_child_requisition (wbox, child->widget, &child_requisition);
+
+ if (child_requisition.height >= area->height)
+ child_allocation.height = area->height;
+ else
+ {
+ child_allocation.height = child_requisition.height;
+ if (wbox->line_justify == GTK_JUSTIFY_FILL || child->vfill)
+ child_allocation.height = area->height;
+ else if (child->vexpand || wbox->line_justify == GTK_JUSTIFY_CENTER)
+ child_allocation.y += (area->height - child_requisition.height) / 2;
+ else if (wbox->line_justify == GTK_JUSTIFY_BOTTOM)
+ child_allocation.y += area->height - child_requisition.height;
+ }
+
+ if (have_expand_children)
+ {
+ child_allocation.width = child_requisition.width;
+ if (child->hexpand || wbox->justify == GTK_JUSTIFY_FILL)
+ {
+ guint space;
+
+ n_expand_children--;
+ space = extra * n_expand_children;
+ space = width - space;
+ width -= space;
+ if (child->hfill)
+ child_allocation.width += space;
+ else
+ {
+ child_allocation.x += space / 2;
+ x += space;
+ }
+ }
+ }
+ else
+ {
+ /* g_print ("child_allocation.x %d += %d * %f ",
+ child_allocation.x, n_children, extra); */
+ child_allocation.x += n_children * extra;
+ /* g_print ("= %d\n",
+ child_allocation.x); */
+ child_allocation.width = MIN (child_requisition.width,
+ area->width - child_allocation.x + area->x);
+ }
+ }
+
+ x += child_allocation.width + wbox->hspacing;
+ gtk_widget_size_allocate (child->widget, &child_allocation);
+ n_children++;
+ }
+}
+
+typedef struct _Line Line;
+struct _Line
+{
+ GSList *children;
+ guint16 min_size;
+ guint expand : 1;
+ Line *next;
+};
+
+
+static void
+layout_rows (GtkWrapBox *wbox,
+ GtkAllocation *area)
+{
+ GtkWrapBoxChild *next_child;
+ guint min_height;
+ gboolean vexpand;
+ GSList *slist;
+ gfloat shrink_height;
+ guint children_per_line;
+ Line *line_list = NULL;
+ guint total_height = 0, n_expand_lines = 0, n_lines = 0;
+
+ next_child = wbox->children;
+ slist = GTK_WRAP_BOX_GET_CLASS (wbox)->rlist_line_children (wbox,
+ &next_child,
+ area,
+ &min_height,
+ &vexpand);
+ slist = g_slist_reverse (slist);
+
+ children_per_line = g_slist_length (slist);
+ while (slist)
+ {
+ Line *line = g_new (Line, 1);
+
+ line->children = slist;
+ line->min_size = min_height;
+ total_height += min_height;
+ line->expand = vexpand;
+ if (vexpand)
+ n_expand_lines++;
+ line->next = line_list;
+ line_list = line;
+ n_lines++;
+
+ slist = GTK_WRAP_BOX_GET_CLASS (wbox)->rlist_line_children (wbox,
+ &next_child,
+ area,
+ &min_height,
+ &vexpand);
+ slist = g_slist_reverse (slist);
+ }
+ GTK_HWRAP_BOX (wbox)->request_this_height_next_time = total_height;
+ if (!(GTK_HWRAP_BOX (wbox)->request_stored_height )) {
+ gtk_signal_emit_by_name (GTK_OBJECT (wbox), "need_reallocation", NULL);
+ GTK_HWRAP_BOX (wbox)->request_stored_height = TRUE;
+ }
+ if (total_height > area->height) {
+ shrink_height = total_height - area->height;
+ gtk_signal_emit_by_name (GTK_OBJECT (wbox), "need_reallocation", NULL);
+ }
+ else
+ shrink_height = 0;
+
+
+ if (1) /* reverse lines and shrink */
+ {
+ Line *prev = NULL, *last = NULL;
+ gfloat n_shrink_lines = n_lines;
+
+ while (line_list)
+ {
+ Line *tmp = line_list->next;
+
+ if (shrink_height)
+ {
+ Line *line = line_list;
+ guint shrink_fract = shrink_height / n_shrink_lines + 0.5;
+
+ if (line->min_size > shrink_fract)
+ {
+ shrink_height -= shrink_fract;
+ line->min_size -= shrink_fract;
+ }
+ else
+ {
+ shrink_height -= line->min_size - 1;
+ line->min_size = 1;
+ }
+ }
+ n_shrink_lines--;
+
+ last = line_list;
+ line_list->next = prev;
+ prev = line_list;
+ line_list = tmp;
+ }
+ line_list = last;
+ }
+
+ if (n_lines)
+ {
+ Line *line;
+ gfloat y, height, extra = 0;
+
+ height = area->height;
+ height = MAX (n_lines, height - (n_lines - 1) * wbox->vspacing);
+
+ if (wbox->homogeneous)
+ height /= ((gdouble) n_lines);
+ else if (n_expand_lines)
+ {
+ height = MAX (0, height - total_height);
+ extra = height / ((gdouble) n_expand_lines);
+ }
+ else
+ height = 0;
+
+ y = area->y;
+ line = line_list;
+ while (line)
+ {
+ GtkAllocation row_allocation;
+ Line *next_line = line->next;
+
+ row_allocation.x = area->x;
+ row_allocation.width = area->width;
+ if (wbox->homogeneous)
+ row_allocation.height = height;
+ else
+ {
+ row_allocation.height = line->min_size;
+
+ if (line->expand)
+ row_allocation.height += extra;
+ }
+
+ row_allocation.y = y;
+
+ y += row_allocation.height + wbox->vspacing;
+ layout_row (wbox,
+ &row_allocation,
+ line->children,
+ children_per_line,
+ line->expand);
+
+ g_slist_free (line->children);
+ g_free (line);
+ line = next_line;
+ }
+ }
+}
+
+static void
+gtk_hwrap_box_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation)
+{
+ GtkWrapBox *wbox = GTK_WRAP_BOX (widget);
+ GtkAllocation area;
+ guint border = GTK_CONTAINER (wbox)->border_width; /*<h2v-skip>*/
+
+ widget->allocation = *allocation;
+ area.x = allocation->x + border;
+ area.y = allocation->y + border;
+ area.width = MAX (1, (gint) allocation->width - border * 2);
+ area.height = MAX (1, (gint) allocation->height - border * 2);
+
+ /*<h2v-off>*/
+ /* g_print ("got: width %d, height %d\n",
+ allocation->width,
+ allocation->height);
+ */
+ /*<h2v-on>*/
+
+ layout_rows (wbox, &area);
+}
diff --git a/cut-n-paste-code/widgets/gimphwrapbox/gtkhwrapbox.h b/cut-n-paste-code/widgets/gimphwrapbox/gtkhwrapbox.h
new file mode 100644
index 000000000..b7b43ec71
--- /dev/null
+++ b/cut-n-paste-code/widgets/gimphwrapbox/gtkhwrapbox.h
@@ -0,0 +1,78 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * GtkHWrapBox: Horizontal wrapping box widget
+ * Copyright (C) 1999 Tim Janik
+ *
+ * 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., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#ifndef __GTK_HWRAP_BOX_H__
+#define __GTK_HWRAP_BOX_H__
+
+
+#include "gtkwrapbox.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+/* --- type macros --- */
+#define GTK_TYPE_HWRAP_BOX (gtk_hwrap_box_get_type ())
+#define GTK_HWRAP_BOX(obj) (GTK_CHECK_CAST ((obj), GTK_TYPE_HWRAP_BOX, GtkHWrapBox))
+#define GTK_HWRAP_BOX_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), GTK_TYPE_HWRAP_BOX, GtkHWrapBoxClass))
+#define GTK_IS_HWRAP_BOX(obj) (GTK_CHECK_TYPE ((obj), GTK_TYPE_HWRAP_BOX))
+#define GTK_IS_HWRAP_BOX_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GTK_TYPE_HWRAP_BOX))
+#define GTK_HWRAP_BOX_GET_CLASS(obj) (GTK_HWRAP_BOX_CLASS (((GtkObject*) (obj))->klass))
+
+
+/* --- typedefs --- */
+typedef struct _GtkHWrapBox GtkHWrapBox;
+typedef struct _GtkHWrapBoxClass GtkHWrapBoxClass;
+
+
+/* --- GtkHWrapBox --- */
+struct _GtkHWrapBox
+{
+ GtkWrapBox parent_widget;
+
+ /*<h2v-off>*/
+ guint16 max_child_width;
+ guint16 max_child_height;
+ /*<h2v-on>*/
+
+ gboolean request_stored_height;
+ guint16 request_this_height_next_time;
+};
+
+struct _GtkHWrapBoxClass
+{
+ GtkWrapBoxClass parent_class;
+};
+
+
+/* --- prototypes --- */
+GtkType gtk_hwrap_box_get_type (void);
+GtkWidget* gtk_hwrap_box_new (gboolean homogeneous);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GTK_HWRAP_BOX_H__ */
diff --git a/cut-n-paste-code/widgets/gimphwrapbox/gtkwrapbox.c b/cut-n-paste-code/widgets/gimphwrapbox/gtkwrapbox.c
new file mode 100644
index 000000000..49d5d5981
--- /dev/null
+++ b/cut-n-paste-code/widgets/gimphwrapbox/gtkwrapbox.c
@@ -0,0 +1,848 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * GtkWrapBox: Wrapping box widget
+ * Copyright (C) 1999 Tim Janik
+ *
+ * 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., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#include <math.h>
+#include <gtk/gtksignal.h>
+#include "gtkwrapbox.h"
+
+
+
+/* --- arguments --- */
+enum {
+ ARG_0,
+ ARG_HOMOGENEOUS,
+ ARG_JUSTIFY,
+ ARG_HSPACING,
+ ARG_VSPACING,
+ ARG_LINE_JUSTIFY,
+ ARG_ASPECT_RATIO,
+ ARG_CURRENT_RATIO,
+ ARG_CHILD_LIMIT
+};
+enum {
+ CHILD_ARG_0,
+ CHILD_ARG_POSITION,
+ CHILD_ARG_HEXPAND,
+ CHILD_ARG_HFILL,
+ CHILD_ARG_VEXPAND,
+ CHILD_ARG_VFILL,
+ CHILD_ARG_FORCED_BREAK
+};
+
+enum {
+ NEED_REALLOCATION,
+ LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL];
+
+/* --- prototypes --- */
+static void gtk_wrap_box_class_init (GtkWrapBoxClass *klass);
+static void gtk_wrap_box_init (GtkWrapBox *wbox);
+static void gtk_wrap_box_get_arg (GtkObject *object,
+ GtkArg *arg,
+ guint arg_id);
+static void gtk_wrap_box_set_arg (GtkObject *object,
+ GtkArg *arg,
+ guint arg_id);
+static void gtk_wrap_box_set_child_arg (GtkContainer *container,
+ GtkWidget *child,
+ GtkArg *arg,
+ guint arg_id);
+static void gtk_wrap_box_get_child_arg (GtkContainer *container,
+ GtkWidget *child,
+ GtkArg *arg,
+ guint arg_id);
+static void gtk_wrap_box_map (GtkWidget *widget);
+static void gtk_wrap_box_unmap (GtkWidget *widget);
+static void gtk_wrap_box_draw (GtkWidget *widget,
+ GdkRectangle *area);
+static gint gtk_wrap_box_expose (GtkWidget *widget,
+ GdkEventExpose *event);
+static void gtk_wrap_box_add (GtkContainer *container,
+ GtkWidget *widget);
+static void gtk_wrap_box_remove (GtkContainer *container,
+ GtkWidget *widget);
+static void gtk_wrap_box_forall (GtkContainer *container,
+ gboolean include_internals,
+ GtkCallback callback,
+ gpointer callback_data);
+static GtkType gtk_wrap_box_child_type (GtkContainer *container);
+
+
+/* --- variables --- */
+static gpointer parent_class = NULL;
+
+
+/* --- functions --- */
+GtkType
+gtk_wrap_box_get_type (void)
+{
+ static GtkType wrap_box_type = 0;
+
+ if (!wrap_box_type)
+ {
+ static const GtkTypeInfo wrap_box_info =
+ {
+ "GtkWrapBox",
+ sizeof (GtkWrapBox),
+ sizeof (GtkWrapBoxClass),
+ (GtkClassInitFunc) gtk_wrap_box_class_init,
+ (GtkObjectInitFunc) gtk_wrap_box_init,
+ /* reserved_1 */ NULL,
+ /* reserved_2 */ NULL,
+ (GtkClassInitFunc) NULL,
+ };
+
+ wrap_box_type = gtk_type_unique (GTK_TYPE_CONTAINER, &wrap_box_info);
+ }
+
+ return wrap_box_type;
+}
+
+static void
+gtk_wrap_box_class_init (GtkWrapBoxClass *class)
+{
+ GtkObjectClass *object_class;
+ GtkWidgetClass *widget_class;
+ GtkContainerClass *container_class;
+
+ object_class = GTK_OBJECT_CLASS (class);
+ widget_class = GTK_WIDGET_CLASS (class);
+ container_class = GTK_CONTAINER_CLASS (class);
+
+ parent_class = gtk_type_class (GTK_TYPE_CONTAINER);
+
+ object_class->set_arg = gtk_wrap_box_set_arg;
+ object_class->get_arg = gtk_wrap_box_get_arg;
+
+ widget_class->map = gtk_wrap_box_map;
+ widget_class->unmap = gtk_wrap_box_unmap;
+ widget_class->draw = gtk_wrap_box_draw;
+ widget_class->expose_event = gtk_wrap_box_expose;
+
+ container_class->add = gtk_wrap_box_add;
+ container_class->remove = gtk_wrap_box_remove;
+ container_class->forall = gtk_wrap_box_forall;
+ container_class->child_type = gtk_wrap_box_child_type;
+ container_class->set_child_arg = gtk_wrap_box_set_child_arg;
+ container_class->get_child_arg = gtk_wrap_box_get_child_arg;
+
+ class->rlist_line_children = NULL;
+
+ gtk_object_add_arg_type ("GtkWrapBox::homogeneous",
+ GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_HOMOGENEOUS);
+ gtk_object_add_arg_type ("GtkWrapBox::justify",
+ GTK_TYPE_JUSTIFICATION, GTK_ARG_READWRITE, ARG_JUSTIFY);
+ gtk_object_add_arg_type ("GtkWrapBox::hspacing",
+ GTK_TYPE_UINT, GTK_ARG_READWRITE, ARG_HSPACING);
+ gtk_object_add_arg_type ("GtkWrapBox::vspacing",
+ GTK_TYPE_UINT, GTK_ARG_READWRITE, ARG_VSPACING);
+ gtk_object_add_arg_type ("GtkWrapBox::line_justify",
+ GTK_TYPE_JUSTIFICATION, GTK_ARG_READWRITE, ARG_LINE_JUSTIFY);
+ gtk_object_add_arg_type ("GtkWrapBox::aspect_ratio",
+ GTK_TYPE_FLOAT, GTK_ARG_READWRITE, ARG_ASPECT_RATIO);
+ gtk_object_add_arg_type ("GtkWrapBox::current_ratio",
+ GTK_TYPE_FLOAT, GTK_ARG_READABLE, ARG_CURRENT_RATIO);
+ gtk_object_add_arg_type ("GtkWrapBox::max_children_per_line",
+ GTK_TYPE_UINT, GTK_ARG_READWRITE, ARG_CHILD_LIMIT);
+ gtk_container_add_child_arg_type ("GtkWrapBox::position",
+ GTK_TYPE_INT, GTK_ARG_READWRITE, CHILD_ARG_POSITION);
+ gtk_container_add_child_arg_type ("GtkWrapBox::hexpand",
+ GTK_TYPE_BOOL, GTK_ARG_READWRITE, CHILD_ARG_HEXPAND);
+ gtk_container_add_child_arg_type ("GtkWrapBox::hfill",
+ GTK_TYPE_BOOL, GTK_ARG_READWRITE, CHILD_ARG_HFILL);
+ gtk_container_add_child_arg_type ("GtkWrapBox::vexpand",
+ GTK_TYPE_BOOL, GTK_ARG_READWRITE, CHILD_ARG_VEXPAND);
+ gtk_container_add_child_arg_type ("GtkWrapBox::vfill",
+ GTK_TYPE_BOOL, GTK_ARG_READWRITE, CHILD_ARG_VFILL);
+ gtk_container_add_child_arg_type ("GtkWrapBox::forcebreak",
+ GTK_TYPE_BOOL, GTK_ARG_READWRITE, CHILD_ARG_FORCED_BREAK);
+
+ signals[NEED_REALLOCATION] = gtk_signal_new
+ ("need_reallocation",
+ GTK_RUN_LAST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GtkWrapBoxClass,
+ need_reallocation),
+ gtk_marshal_NONE__NONE,
+ GTK_TYPE_NONE, 0);
+
+ gtk_object_class_add_signals (object_class, signals, LAST_SIGNAL);
+}
+
+static void
+gtk_wrap_box_init (GtkWrapBox *wbox)
+{
+ GTK_WIDGET_SET_FLAGS (wbox, GTK_NO_WINDOW);
+
+ wbox->homogeneous = FALSE;
+ wbox->hspacing = 0;
+ wbox->vspacing = 0;
+ wbox->justify = GTK_JUSTIFY_LEFT;
+ wbox->line_justify = GTK_JUSTIFY_BOTTOM;
+ wbox->n_children = 0;
+ wbox->children = NULL;
+ wbox->aspect_ratio = 1;
+ wbox->child_limit = 32767;
+}
+
+static void
+gtk_wrap_box_set_arg (GtkObject *object,
+ GtkArg *arg,
+ guint arg_id)
+{
+ GtkWrapBox *wbox = GTK_WRAP_BOX (object);
+
+ switch (arg_id)
+ {
+ case ARG_HOMOGENEOUS:
+ gtk_wrap_box_set_homogeneous (wbox, GTK_VALUE_BOOL (*arg));
+ break;
+ case ARG_JUSTIFY:
+ gtk_wrap_box_set_justify (wbox, GTK_VALUE_ENUM (*arg));
+ break;
+ case ARG_LINE_JUSTIFY:
+ gtk_wrap_box_set_line_justify (wbox, GTK_VALUE_ENUM (*arg));
+ break;
+ case ARG_HSPACING:
+ gtk_wrap_box_set_hspacing (wbox, GTK_VALUE_UINT (*arg));
+ break;
+ case ARG_VSPACING:
+ gtk_wrap_box_set_vspacing (wbox, GTK_VALUE_UINT (*arg));
+ break;
+ case ARG_ASPECT_RATIO:
+ gtk_wrap_box_set_aspect_ratio (wbox, GTK_VALUE_FLOAT (*arg));
+ break;
+ case ARG_CHILD_LIMIT:
+ if (wbox->child_limit != GTK_VALUE_UINT (*arg))
+ {
+ wbox->child_limit = CLAMP (GTK_VALUE_UINT (*arg), 1, 32767);
+ gtk_widget_queue_resize (GTK_WIDGET (wbox));
+ }
+ break;
+ }
+}
+
+static void
+gtk_wrap_box_get_arg (GtkObject *object,
+ GtkArg *arg,
+ guint arg_id)
+{
+ GtkWrapBox *wbox = GTK_WRAP_BOX (object);
+ GtkWidget *widget = GTK_WIDGET (object);
+
+ switch (arg_id)
+ {
+ case ARG_HOMOGENEOUS:
+ GTK_VALUE_BOOL (*arg) = wbox->homogeneous;
+ break;
+ case ARG_JUSTIFY:
+ GTK_VALUE_ENUM (*arg) = wbox->justify;
+ break;
+ case ARG_LINE_JUSTIFY:
+ GTK_VALUE_ENUM (*arg) = wbox->line_justify;
+ break;
+ case ARG_HSPACING:
+ GTK_VALUE_UINT (*arg) = wbox->hspacing;
+ break;
+ case ARG_VSPACING:
+ GTK_VALUE_UINT (*arg) = wbox->vspacing;
+ break;
+ case ARG_ASPECT_RATIO:
+ GTK_VALUE_FLOAT (*arg) = wbox->aspect_ratio;
+ break;
+ case ARG_CURRENT_RATIO:
+ GTK_VALUE_FLOAT (*arg) = (((gfloat) widget->allocation.width) /
+ ((gfloat) widget->allocation.height));
+ break;
+ case ARG_CHILD_LIMIT:
+ GTK_VALUE_UINT (*arg) = wbox->child_limit;
+ break;
+ default:
+ arg->type = GTK_TYPE_INVALID;
+ break;
+ }
+}
+
+static void
+gtk_wrap_box_set_child_arg (GtkContainer *container,
+ GtkWidget *child,
+ GtkArg *arg,
+ guint arg_id)
+{
+ GtkWrapBox *wbox = GTK_WRAP_BOX (container);
+ gboolean hexpand = FALSE, hfill = FALSE, vexpand = FALSE, vfill = FALSE;
+
+ if (arg_id != CHILD_ARG_POSITION)
+ gtk_wrap_box_query_child_packing (wbox, child, &hexpand, &hfill, &vexpand, &vfill);
+
+ switch (arg_id)
+ {
+ case CHILD_ARG_POSITION:
+ gtk_wrap_box_reorder_child (wbox, child, GTK_VALUE_INT (*arg));
+ break;
+ case CHILD_ARG_HEXPAND:
+ gtk_wrap_box_set_child_packing (wbox, child,
+ GTK_VALUE_BOOL (*arg), hfill,
+ vexpand, vfill);
+ break;
+ case CHILD_ARG_HFILL:
+ gtk_wrap_box_set_child_packing (wbox, child,
+ hexpand, GTK_VALUE_BOOL (*arg),
+ vexpand, vfill);
+ break;
+ case CHILD_ARG_VEXPAND:
+ gtk_wrap_box_set_child_packing (wbox, child,
+ hexpand, hfill,
+ GTK_VALUE_BOOL (*arg), vfill);
+ break;
+ case CHILD_ARG_VFILL:
+ gtk_wrap_box_set_child_packing (wbox, child,
+ hexpand, hfill,
+ vexpand, GTK_VALUE_BOOL (*arg));
+ break;
+ case CHILD_ARG_FORCED_BREAK:
+ gtk_wrap_box_set_child_forced_break (wbox, child,
+ GTK_VALUE_BOOL (*arg));
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+gtk_wrap_box_get_child_arg (GtkContainer *container,
+ GtkWidget *child,
+ GtkArg *arg,
+ guint arg_id)
+{
+ GtkWrapBox *wbox = GTK_WRAP_BOX (container);
+ gboolean hexpand = FALSE, hfill = FALSE, vexpand = FALSE, vfill = FALSE;
+
+ if (arg_id != CHILD_ARG_POSITION)
+ gtk_wrap_box_query_child_packing (wbox, child, &hexpand, &hfill, &vexpand, &vfill);
+
+ switch (arg_id)
+ {
+ GtkWrapBoxChild *child_info;
+ case CHILD_ARG_POSITION:
+ GTK_VALUE_INT (*arg) = 0;
+ for (child_info = wbox->children; child_info; child_info = child_info->next)
+ {
+ if (child_info->widget == child)
+ break;
+ GTK_VALUE_INT (*arg)++;
+ }
+ if (!child_info)
+ GTK_VALUE_INT (*arg) = -1;
+ break;
+ case CHILD_ARG_HEXPAND:
+ GTK_VALUE_BOOL (*arg) = hexpand;
+ break;
+ case CHILD_ARG_HFILL:
+ GTK_VALUE_BOOL (*arg) = hfill;
+ break;
+ case CHILD_ARG_VEXPAND:
+ GTK_VALUE_BOOL (*arg) = vexpand;
+ break;
+ case CHILD_ARG_VFILL:
+ GTK_VALUE_BOOL (*arg) = vfill;
+ break;
+ default:
+ arg->type = GTK_TYPE_INVALID;
+ break;
+ }
+}
+
+static GtkType
+gtk_wrap_box_child_type (GtkContainer *container)
+{
+ return GTK_TYPE_WIDGET;
+}
+
+void
+gtk_wrap_box_set_homogeneous (GtkWrapBox *wbox,
+ gboolean homogeneous)
+{
+ g_return_if_fail (GTK_IS_WRAP_BOX (wbox));
+
+ homogeneous = homogeneous != FALSE;
+ if (wbox->homogeneous != homogeneous)
+ {
+ wbox->homogeneous = homogeneous;
+ gtk_widget_queue_resize (GTK_WIDGET (wbox));
+ }
+}
+
+void
+gtk_wrap_box_set_hspacing (GtkWrapBox *wbox,
+ guint hspacing)
+{
+ g_return_if_fail (GTK_IS_WRAP_BOX (wbox));
+
+ if (wbox->hspacing != hspacing)
+ {
+ wbox->hspacing = hspacing;
+ gtk_widget_queue_resize (GTK_WIDGET (wbox));
+ }
+}
+
+void
+gtk_wrap_box_set_vspacing (GtkWrapBox *wbox,
+ guint vspacing)
+{
+ g_return_if_fail (GTK_IS_WRAP_BOX (wbox));
+
+ if (wbox->vspacing != vspacing)
+ {
+ wbox->vspacing = vspacing;
+ gtk_widget_queue_resize (GTK_WIDGET (wbox));
+ }
+}
+
+void
+gtk_wrap_box_set_justify (GtkWrapBox *wbox,
+ GtkJustification justify)
+{
+ g_return_if_fail (GTK_IS_WRAP_BOX (wbox));
+ g_return_if_fail (justify <= GTK_JUSTIFY_FILL);
+
+ if (wbox->justify != justify)
+ {
+ wbox->justify = justify;
+ gtk_widget_queue_resize (GTK_WIDGET (wbox));
+ }
+}
+
+void
+gtk_wrap_box_set_line_justify (GtkWrapBox *wbox,
+ GtkJustification line_justify)
+{
+ g_return_if_fail (GTK_IS_WRAP_BOX (wbox));
+ g_return_if_fail (line_justify <= GTK_JUSTIFY_FILL);
+
+ if (wbox->line_justify != line_justify)
+ {
+ wbox->line_justify = line_justify;
+ gtk_widget_queue_resize (GTK_WIDGET (wbox));
+ }
+}
+
+void
+gtk_wrap_box_set_aspect_ratio (GtkWrapBox *wbox,
+ gfloat aspect_ratio)
+{
+ g_return_if_fail (GTK_IS_WRAP_BOX (wbox));
+
+ aspect_ratio = CLAMP (aspect_ratio, 1.0 / 256.0, 256.0);
+
+ if (wbox->aspect_ratio != aspect_ratio)
+ {
+ wbox->aspect_ratio = aspect_ratio;
+ gtk_widget_queue_resize (GTK_WIDGET (wbox));
+ }
+}
+
+void
+gtk_wrap_box_pack (GtkWrapBox *wbox,
+ GtkWidget *child,
+ gboolean hexpand,
+ gboolean hfill,
+ gboolean vexpand,
+ gboolean vfill)
+{
+ GtkWrapBoxChild *child_info;
+
+ g_return_if_fail (GTK_IS_WRAP_BOX (wbox));
+ g_return_if_fail (GTK_IS_WIDGET (child));
+ g_return_if_fail (child->parent == NULL);
+
+ child_info = g_new (GtkWrapBoxChild, 1);
+ child_info->widget = child;
+ child_info->hexpand = hexpand ? TRUE : FALSE;
+ child_info->hfill = hfill ? TRUE : FALSE;
+ child_info->vexpand = vexpand ? TRUE : FALSE;
+ child_info->vfill = vfill ? TRUE : FALSE;
+ child_info->forced_break = FALSE;
+ child_info->next = NULL;
+ if (wbox->children)
+ {
+ GtkWrapBoxChild *last = wbox->children;
+
+ while (last->next)
+ last = last->next;
+ last->next = child_info;
+ }
+ else
+ wbox->children = child_info;
+ wbox->n_children++;
+
+ gtk_widget_set_parent (child, GTK_WIDGET (wbox));
+
+ if (GTK_WIDGET_REALIZED (wbox))
+ gtk_widget_realize (child);
+
+ if (GTK_WIDGET_VISIBLE (wbox) && GTK_WIDGET_VISIBLE (child))
+ {
+ if (GTK_WIDGET_MAPPED (wbox))
+ gtk_widget_map (child);
+
+ gtk_widget_queue_resize (child);
+ }
+}
+
+void
+gtk_wrap_box_reorder_child (GtkWrapBox *wbox,
+ GtkWidget *child,
+ gint position)
+{
+ GtkWrapBoxChild *child_info, *last = NULL;
+
+ g_return_if_fail (GTK_IS_WRAP_BOX (wbox));
+ g_return_if_fail (GTK_IS_WIDGET (child));
+
+ for (child_info = wbox->children; child_info; last = child_info, child_info = last->next)
+ if (child_info->widget == child)
+ break;
+
+ if (child_info && wbox->children->next)
+ {
+ GtkWrapBoxChild *tmp;
+
+ if (last)
+ last->next = child_info->next;
+ else
+ wbox->children = child_info->next;
+
+ last = NULL;
+ tmp = wbox->children;
+ while (position && tmp->next)
+ {
+ position--;
+ last = tmp;
+ tmp = last->next;
+ }
+
+ if (position)
+ {
+ tmp->next = child_info;
+ child_info->next = NULL;
+ }
+ else
+ {
+ child_info->next = tmp;
+ if (last)
+ last->next = child_info;
+ else
+ wbox->children = child_info;
+ }
+
+ if (GTK_WIDGET_VISIBLE (child) && GTK_WIDGET_VISIBLE (wbox))
+ gtk_widget_queue_resize (child);
+ }
+}
+
+void
+gtk_wrap_box_query_child_packing (GtkWrapBox *wbox,
+ GtkWidget *child,
+ gboolean *hexpand,
+ gboolean *hfill,
+ gboolean *vexpand,
+ gboolean *vfill)
+{
+ GtkWrapBoxChild *child_info;
+
+ g_return_if_fail (GTK_IS_WRAP_BOX (wbox));
+ g_return_if_fail (GTK_IS_WIDGET (child));
+
+ for (child_info = wbox->children; child_info; child_info = child_info->next)
+ if (child_info->widget == child)
+ break;
+
+ if (child_info)
+ {
+ if (hexpand)
+ *hexpand = child_info->hexpand;
+ if (hfill)
+ *hfill = child_info->hfill;
+ if (vexpand)
+ *vexpand = child_info->vexpand;
+ if (vfill)
+ *vfill = child_info->vfill;
+ }
+}
+
+void
+gtk_wrap_box_query_child_forced_break (GtkWrapBox *wbox,
+ GtkWidget *child,
+ gboolean *forced_break)
+{
+ GtkWrapBoxChild *child_info;
+
+ g_return_if_fail (GTK_IS_WRAP_BOX (wbox));
+ g_return_if_fail (GTK_IS_WIDGET (child));
+
+ for (child_info = wbox->children; child_info; child_info = child_info->next)
+ if (child_info->widget == child)
+ break;
+
+ if (child_info)
+ {
+ if (forced_break)
+ *forced_break = child_info->forced_break;
+ }
+}
+
+void
+gtk_wrap_box_set_child_packing (GtkWrapBox *wbox,
+ GtkWidget *child,
+ gboolean hexpand,
+ gboolean hfill,
+ gboolean vexpand,
+ gboolean vfill)
+{
+ GtkWrapBoxChild *child_info;
+
+ g_return_if_fail (GTK_IS_WRAP_BOX (wbox));
+ g_return_if_fail (GTK_IS_WIDGET (child));
+
+ hexpand = hexpand != FALSE;
+ hfill = hfill != FALSE;
+ vexpand = vexpand != FALSE;
+ vfill = vfill != FALSE;
+
+ for (child_info = wbox->children; child_info; child_info = child_info->next)
+ if (child_info->widget == child)
+ break;
+
+ if (child_info &&
+ (child_info->hexpand != hexpand || child_info->vexpand != vexpand ||
+ child_info->hfill != hfill || child_info->vfill != vfill))
+ {
+ child_info->hexpand = hexpand;
+ child_info->hfill = hfill;
+ child_info->vexpand = vexpand;
+ child_info->vfill = vfill;
+
+ if (GTK_WIDGET_VISIBLE (child) && GTK_WIDGET_VISIBLE (wbox))
+ gtk_widget_queue_resize (child);
+ }
+}
+
+void
+gtk_wrap_box_set_child_forced_break (GtkWrapBox *wbox,
+ GtkWidget *child,
+ gboolean forced_break)
+{
+ GtkWrapBoxChild *child_info;
+
+ g_return_if_fail (GTK_IS_WRAP_BOX (wbox));
+ g_return_if_fail (GTK_IS_WIDGET (child));
+
+ forced_break = forced_break != FALSE;
+
+ for (child_info = wbox->children; child_info; child_info = child_info->next)
+ if (child_info->widget == child)
+ break;
+
+ if (child_info &&
+ (child_info->forced_break != forced_break))
+ {
+ child_info->forced_break = forced_break;
+
+ if (GTK_WIDGET_VISIBLE (child) && GTK_WIDGET_VISIBLE (wbox))
+ gtk_widget_queue_resize (child);
+ }
+}
+
+guint*
+gtk_wrap_box_query_line_lengths (GtkWrapBox *wbox,
+ guint *_n_lines)
+{
+ GtkWrapBoxChild *next_child = NULL;
+ GtkAllocation area, *allocation;
+ gboolean expand_line;
+ GSList *slist;
+ guint max_child_size, border, n_lines = 0, *lines = NULL;
+
+ if (_n_lines)
+ *_n_lines = 0;
+ g_return_val_if_fail (GTK_IS_WRAP_BOX (wbox), NULL);
+
+ allocation = &GTK_WIDGET (wbox)->allocation;
+ border = GTK_CONTAINER (wbox)->border_width;
+ area.x = allocation->x + border;
+ area.y = allocation->y + border;
+ area.width = MAX (1, (gint) allocation->width - border * 2);
+ area.height = MAX (1, (gint) allocation->height - border * 2);
+
+ next_child = wbox->children;
+ slist = GTK_WRAP_BOX_GET_CLASS (wbox)->rlist_line_children (wbox,
+ &next_child,
+ &area,
+ &max_child_size,
+ &expand_line);
+ while (slist)
+ {
+ guint l = n_lines++;
+
+ lines = g_renew (guint, lines, n_lines);
+ lines[l] = g_slist_length (slist);
+ g_slist_free (slist);
+
+ slist = GTK_WRAP_BOX_GET_CLASS (wbox)->rlist_line_children (wbox,
+ &next_child,
+ &area,
+ &max_child_size,
+ &expand_line);
+ }
+
+ if (_n_lines)
+ *_n_lines = n_lines;
+
+ return lines;
+}
+
+static void
+gtk_wrap_box_map (GtkWidget *widget)
+{
+ GtkWrapBox *wbox = GTK_WRAP_BOX (widget);
+ GtkWrapBoxChild *child;
+
+ GTK_WIDGET_SET_FLAGS (wbox, GTK_MAPPED);
+
+ for (child = wbox->children; child; child = child->next)
+ if (GTK_WIDGET_VISIBLE (child->widget) &&
+ !GTK_WIDGET_MAPPED (child->widget))
+ gtk_widget_map (child->widget);
+}
+
+static void
+gtk_wrap_box_unmap (GtkWidget *widget)
+{
+ GtkWrapBox *wbox = GTK_WRAP_BOX (widget);
+ GtkWrapBoxChild *child;
+
+ GTK_WIDGET_UNSET_FLAGS (wbox, GTK_MAPPED);
+
+ for (child = wbox->children; child; child = child->next)
+ if (GTK_WIDGET_VISIBLE (child->widget) &&
+ GTK_WIDGET_MAPPED (child->widget))
+ gtk_widget_unmap (child->widget);
+}
+
+static void
+gtk_wrap_box_draw (GtkWidget *widget,
+ GdkRectangle *area)
+{
+ GtkWrapBox *wbox = GTK_WRAP_BOX (widget);
+ GtkWrapBoxChild *child;
+ GdkRectangle child_area;
+
+ if (GTK_WIDGET_DRAWABLE (widget))
+ for (child = wbox->children; child; child = child->next)
+ if (GTK_WIDGET_DRAWABLE (child->widget) &&
+ gtk_widget_intersect (child->widget, area, &child_area))
+ gtk_widget_draw (child->widget, &child_area);
+}
+
+static gint
+gtk_wrap_box_expose (GtkWidget *widget,
+ GdkEventExpose *event)
+{
+ GtkWrapBox *wbox = GTK_WRAP_BOX (widget);
+ GtkWrapBoxChild *child;
+ GdkEventExpose child_event = *event;
+
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ if (GTK_WIDGET_DRAWABLE (widget))
+ for (child = wbox->children; child; child = child->next)
+ if (GTK_WIDGET_DRAWABLE (child->widget) &&
+ 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 TRUE;
+}
+
+static void
+gtk_wrap_box_add (GtkContainer *container,
+ GtkWidget *widget)
+{
+ gtk_wrap_box_pack (GTK_WRAP_BOX (container), widget, FALSE, TRUE, FALSE, TRUE);
+}
+
+static void
+gtk_wrap_box_remove (GtkContainer *container,
+ GtkWidget *widget)
+{
+ GtkWrapBox *wbox = GTK_WRAP_BOX (container);
+ GtkWrapBoxChild *child, *last = NULL;
+
+ child = wbox->children;
+ while (child)
+ {
+ if (child->widget == widget)
+ {
+ gboolean was_visible;
+
+ was_visible = GTK_WIDGET_VISIBLE (widget);
+ gtk_widget_unparent (widget);
+
+ if (last)
+ last->next = child->next;
+ else
+ wbox->children = child->next;
+ g_free (child);
+ wbox->n_children--;
+
+ if (was_visible)
+ gtk_widget_queue_resize (GTK_WIDGET (container));
+
+ break;
+ }
+
+ last = child;
+ child = last->next;
+ }
+}
+
+static void
+gtk_wrap_box_forall (GtkContainer *container,
+ gboolean include_internals,
+ GtkCallback callback,
+ gpointer callback_data)
+{
+ GtkWrapBox *wbox = GTK_WRAP_BOX (container);
+ GtkWrapBoxChild *child;
+
+ child = wbox->children;
+ while (child)
+ {
+ GtkWidget *widget = child->widget;
+
+ child = child->next;
+
+ callback (widget, callback_data);
+ }
+}
diff --git a/cut-n-paste-code/widgets/gimphwrapbox/gtkwrapbox.h b/cut-n-paste-code/widgets/gimphwrapbox/gtkwrapbox.h
new file mode 100644
index 000000000..85f392949
--- /dev/null
+++ b/cut-n-paste-code/widgets/gimphwrapbox/gtkwrapbox.h
@@ -0,0 +1,149 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * GtkWrapBox: Wrapping box widget
+ * Copyright (C) 1999 Tim Janik
+ *
+ * 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., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#ifndef __GTK_WRAP_BOX_H__
+#define __GTK_WRAP_BOX_H__
+
+
+#include <gdk/gdk.h>
+#include <gtk/gtkcontainer.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+/* --- type macros --- */
+#define GTK_TYPE_WRAP_BOX (gtk_wrap_box_get_type ())
+#define GTK_WRAP_BOX(obj) (GTK_CHECK_CAST ((obj), GTK_TYPE_WRAP_BOX, GtkWrapBox))
+#define GTK_WRAP_BOX_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), GTK_TYPE_WRAP_BOX, GtkWrapBoxClass))
+#define GTK_IS_WRAP_BOX(obj) (GTK_CHECK_TYPE ((obj), GTK_TYPE_WRAP_BOX))
+#define GTK_IS_WRAP_BOX_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GTK_TYPE_WRAP_BOX))
+#define GTK_WRAP_BOX_GET_CLASS(obj) (GTK_WRAP_BOX_CLASS (((GtkObject*) (obj))->klass))
+
+
+/* --- typedefs --- */
+typedef struct _GtkWrapBox GtkWrapBox;
+typedef struct _GtkWrapBoxClass GtkWrapBoxClass;
+typedef struct _GtkWrapBoxChild GtkWrapBoxChild;
+
+
+ /* For nautilus usage, we should decrement the
+ aspect ratio capability */
+/* --- GtkWrapBox --- */
+struct _GtkWrapBox
+{
+ GtkContainer container;
+
+ guint homogeneous : 1;
+ guint justify : 4;
+ guint line_justify : 4;
+ guint8 hspacing;
+ guint8 vspacing;
+ guint16 n_children;
+ GtkWrapBoxChild *children;
+ gfloat aspect_ratio; /* 1/256..256 */
+ guint child_limit;
+};
+struct _GtkWrapBoxClass
+{
+ GtkContainerClass parent_class;
+
+ GSList* (*rlist_line_children) (GtkWrapBox *wbox,
+ GtkWrapBoxChild **child_p,
+ GtkAllocation *area,
+ guint *max_child_size,
+ gboolean *expand_line);
+
+ /* This signal is added to tell parent widgets that
+ the box doesn't have enough space in the new configuration,
+ and that a resize is recommended. This can happen when a
+ layout changes the box's allocation. */
+ void (*need_reallocation) (GtkWrapBox *wbox);
+};
+struct _GtkWrapBoxChild
+{
+ GtkWidget *widget;
+ guint hexpand : 1;
+ guint hfill : 1;
+ guint vexpand : 1;
+ guint vfill : 1;
+ guint forced_break : 1;
+
+ GtkWrapBoxChild *next;
+};
+#define GTK_JUSTIFY_TOP GTK_JUSTIFY_LEFT
+#define GTK_JUSTIFY_BOTTOM GTK_JUSTIFY_RIGHT
+
+
+/* --- prototypes --- */
+GtkType gtk_wrap_box_get_type (void);
+void gtk_wrap_box_set_homogeneous (GtkWrapBox *wbox,
+ gboolean homogeneous);
+void gtk_wrap_box_set_hspacing (GtkWrapBox *wbox,
+ guint hspacing);
+void gtk_wrap_box_set_vspacing (GtkWrapBox *wbox,
+ guint vspacing);
+void gtk_wrap_box_set_justify (GtkWrapBox *wbox,
+ GtkJustification justify);
+void gtk_wrap_box_set_line_justify (GtkWrapBox *wbox,
+ GtkJustification line_justify);
+void gtk_wrap_box_set_aspect_ratio (GtkWrapBox *wbox,
+ gfloat aspect_ratio);
+void gtk_wrap_box_pack (GtkWrapBox *wbox,
+ GtkWidget *child,
+ gboolean hexpand,
+ gboolean hfill,
+ gboolean vexpand,
+ gboolean vfill);
+void gtk_wrap_box_reorder_child (GtkWrapBox *wbox,
+ GtkWidget *child,
+ gint position);
+void gtk_wrap_box_query_child_packing (GtkWrapBox *wbox,
+ GtkWidget *child,
+ gboolean *hexpand,
+ gboolean *hfill,
+ gboolean *vexpand,
+ gboolean *vfill);
+void gtk_wrap_box_query_child_forced_break (GtkWrapBox *wbox,
+ GtkWidget *child,
+ gboolean *forced_break);
+void gtk_wrap_box_set_child_packing (GtkWrapBox *wbox,
+ GtkWidget *child,
+ gboolean hexpand,
+ gboolean hfill,
+ gboolean vexpand,
+ gboolean vfill);
+void gtk_wrap_box_set_child_forced_break (GtkWrapBox *wbox,
+ GtkWidget *child,
+ gboolean forced_break);
+guint* gtk_wrap_box_query_line_lengths (GtkWrapBox *wbox,
+ guint *n_lines);
+
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GTK_WRAP_BOX_H__ */