add gimpmath.h

* libgimp/Makefile.am: add gimpmath.h

* app/gtkwrapbox.[ch]
* app/gtkhwrapbox.[ch]: wrapbox widget from gle

* app/Makefile.am: added those files

* app/interface.c: use an hwrapbox for the toolbar. Still not perfect
yet, working on it.

* app/gimpdrawable.c
* app/about_dialog.c
* app/airbrush.c
* app/blend.c: some minor code cleanup

-Yosh
This commit is contained in:
Manish Singh
1999-09-02 01:41:18 +00:00
parent e5411a8e68
commit 9fb081a7e6
27 changed files with 3189 additions and 48 deletions

View File

@ -1,3 +1,19 @@
Wed Sep 1 14:50:29 PDT 1999 Manish Singh <yosh@gimp.org>
* libgimp/Makefile.am: add gimpmath.h
* app/gtkwrapbox.[ch]
* app/gtkhwrapbox.[ch]: wrapbox widget from gle
* app/Makefile.am: added those files
* app/interface.c: use an hwrapbox for the toolbar
* app/gimpdrawable.c
* app/about_dialog.c
* app/airbrush.c
* app/blend.c: some minor code cleanup
1999-09-02 Tor Lillqvist <tml@iki.fi> 1999-09-02 Tor Lillqvist <tml@iki.fi>
* app/paintbrush.c (paintbrush_non_gui_default, * app/paintbrush.c (paintbrush_non_gui_default,
@ -44,6 +60,7 @@ Wed Sep 1 23:18:21 BST 1999 Andy Thomas <alt@gimp.org>
the area shown is smaller than the overall image size. Thanks to tml the area shown is smaller than the overall image size. Thanks to tml
for the idea. for the idea.
>>>>>>> 1.1481
Wed Sep 1 22:28:09 BST 1999 Adam D. Moss <adam@gimp.org> Wed Sep 1 22:28:09 BST 1999 Adam D. Moss <adam@gimp.org>
* app/gradient.c * app/gradient.c

View File

@ -227,6 +227,10 @@ gimp_SOURCES = \
gradient_select_cmds.c \ gradient_select_cmds.c \
gradient.h \ gradient.h \
gradient_cmds.c \ gradient_cmds.c \
gtkwrapbox.c \
gtkwrapbox.h \
gtkhwrapbox.c \
gtkhwrapbox.h \
guides_cmds.c \ guides_cmds.c \
gximage.c \ gximage.c \
gximage.h \ gximage.h \

View File

@ -368,14 +368,14 @@ about_dialog_load_logo (GtkWidget *window)
} }
static void static void
about_dialog_destroy () about_dialog_destroy (void)
{ {
about_dialog = NULL; about_dialog = NULL;
about_dialog_unmap (); about_dialog_unmap ();
} }
static void static void
about_dialog_unmap () about_dialog_unmap (void)
{ {
if (timer) if (timer)
{ {

View File

@ -167,7 +167,7 @@ airbrush_options_new (void)
} }
Tool * Tool *
tools_new_airbrush () tools_new_airbrush (void)
{ {
Tool * tool; Tool * tool;
PaintCore * private; PaintCore * private;

View File

@ -17,6 +17,8 @@
*/ */
#include "config.h" #include "config.h"
#include <stdlib.h>
#include "appenv.h" #include "appenv.h"
#include "asupsample.h" #include "asupsample.h"
#include "blend.h" #include "blend.h"

View File

@ -17,6 +17,8 @@
*/ */
#include "config.h" #include "config.h"
#include <stdlib.h>
#include "appenv.h" #include "appenv.h"
#include "asupsample.h" #include "asupsample.h"
#include "blend.h" #include "blend.h"

View File

@ -44,7 +44,7 @@ static GimpDrawableClass *parent_class = NULL;
GtkType GtkType
gimp_drawable_get_type () gimp_drawable_get_type (void)
{ {
static GtkType type; static GtkType type;
GIMP_TYPE_INIT(type, GIMP_TYPE_INIT(type,

View File

@ -368,14 +368,14 @@ about_dialog_load_logo (GtkWidget *window)
} }
static void static void
about_dialog_destroy () about_dialog_destroy (void)
{ {
about_dialog = NULL; about_dialog = NULL;
about_dialog_unmap (); about_dialog_unmap ();
} }
static void static void
about_dialog_unmap () about_dialog_unmap (void)
{ {
if (timer) if (timer)
{ {

View File

@ -35,6 +35,7 @@
#include "gimage.h" #include "gimage.h"
#include "gimpdnd.h" #include "gimpdnd.h"
#include "gimprc.h" #include "gimprc.h"
#include "gtkhwrapbox.h"
#include "indicator_area.h" #include "indicator_area.h"
#include "interface.h" #include "interface.h"
#include "menus.h" #include "menus.h"
@ -340,7 +341,7 @@ create_tool_pixmap (GtkWidget *parent,
static void static void
create_tools (GtkWidget *parent) create_tools (GtkWidget *parent)
{ {
GtkWidget *table; GtkWidget *wbox;
GtkWidget *button; GtkWidget *button;
GtkWidget *alignment; GtkWidget *alignment;
GtkWidget *pixmap; GtkWidget *pixmap;
@ -348,9 +349,11 @@ create_tools (GtkWidget *parent)
gint i, j; gint i, j;
/*create_logo (parent);*/ /*create_logo (parent);*/
table = gtk_table_new (ROWS, COLUMNS, TRUE); wbox = GTK_WIDGET (gtk_type_new (gtk_hwrap_box_get_type ()));
gtk_box_pack_start (GTK_BOX (parent), table, TRUE, TRUE, 0); gtk_wrap_box_set_aspect_ratio (GTK_WRAP_BOX (wbox), .36);
gtk_widget_realize (table); gtk_box_pack_start (GTK_BOX (parent), wbox, TRUE, TRUE, 0);
gtk_widget_realize (gtk_widget_get_toplevel (wbox));
group = NULL; group = NULL;
@ -365,18 +368,14 @@ create_tools (GtkWidget *parent)
gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (button), FALSE); gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (button), FALSE);
gtk_table_attach (GTK_TABLE (table), button, gtk_wrap_box_pack (GTK_WRAP_BOX (wbox), button,
(i % 3), (i % 3) + 1, FALSE, TRUE, FALSE, TRUE);
(i / 3), (i / 3) + 1,
GTK_EXPAND | GTK_SHRINK | GTK_FILL,
GTK_EXPAND | GTK_SHRINK | GTK_FILL,
0, 0);
alignment = gtk_alignment_new (0.5, 0.5, 0.0, 0.0); alignment = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
gtk_container_set_border_width (GTK_CONTAINER (alignment), 0); gtk_container_set_border_width (GTK_CONTAINER (alignment), 0);
gtk_container_add (GTK_CONTAINER (button), alignment); gtk_container_add (GTK_CONTAINER (button), alignment);
pixmap = create_pixmap_widget (table->window, tool_info[j].icon_data, 22, 22); pixmap = create_pixmap_widget (wbox->window, tool_info[j].icon_data, 22, 22);
gtk_container_add (GTK_CONTAINER (alignment), pixmap); gtk_container_add (GTK_CONTAINER (alignment), pixmap);
gtk_signal_connect (GTK_OBJECT (button), "toggled", gtk_signal_connect (GTK_OBJECT (button), "toggled",
@ -406,7 +405,7 @@ create_tools (GtkWidget *parent)
(gpointer) tool_info[j].tool_id); (gpointer) tool_info[j].tool_id);
} }
} }
gtk_widget_show (table); gtk_widget_show (wbox);
} }
static GdkPixmap * static GdkPixmap *

View File

@ -35,6 +35,7 @@
#include "gimage.h" #include "gimage.h"
#include "gimpdnd.h" #include "gimpdnd.h"
#include "gimprc.h" #include "gimprc.h"
#include "gtkhwrapbox.h"
#include "indicator_area.h" #include "indicator_area.h"
#include "interface.h" #include "interface.h"
#include "menus.h" #include "menus.h"
@ -340,7 +341,7 @@ create_tool_pixmap (GtkWidget *parent,
static void static void
create_tools (GtkWidget *parent) create_tools (GtkWidget *parent)
{ {
GtkWidget *table; GtkWidget *wbox;
GtkWidget *button; GtkWidget *button;
GtkWidget *alignment; GtkWidget *alignment;
GtkWidget *pixmap; GtkWidget *pixmap;
@ -348,9 +349,11 @@ create_tools (GtkWidget *parent)
gint i, j; gint i, j;
/*create_logo (parent);*/ /*create_logo (parent);*/
table = gtk_table_new (ROWS, COLUMNS, TRUE); wbox = GTK_WIDGET (gtk_type_new (gtk_hwrap_box_get_type ()));
gtk_box_pack_start (GTK_BOX (parent), table, TRUE, TRUE, 0); gtk_wrap_box_set_aspect_ratio (GTK_WRAP_BOX (wbox), .36);
gtk_widget_realize (table); gtk_box_pack_start (GTK_BOX (parent), wbox, TRUE, TRUE, 0);
gtk_widget_realize (gtk_widget_get_toplevel (wbox));
group = NULL; group = NULL;
@ -365,18 +368,14 @@ create_tools (GtkWidget *parent)
gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (button), FALSE); gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (button), FALSE);
gtk_table_attach (GTK_TABLE (table), button, gtk_wrap_box_pack (GTK_WRAP_BOX (wbox), button,
(i % 3), (i % 3) + 1, FALSE, TRUE, FALSE, TRUE);
(i / 3), (i / 3) + 1,
GTK_EXPAND | GTK_SHRINK | GTK_FILL,
GTK_EXPAND | GTK_SHRINK | GTK_FILL,
0, 0);
alignment = gtk_alignment_new (0.5, 0.5, 0.0, 0.0); alignment = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
gtk_container_set_border_width (GTK_CONTAINER (alignment), 0); gtk_container_set_border_width (GTK_CONTAINER (alignment), 0);
gtk_container_add (GTK_CONTAINER (button), alignment); gtk_container_add (GTK_CONTAINER (button), alignment);
pixmap = create_pixmap_widget (table->window, tool_info[j].icon_data, 22, 22); pixmap = create_pixmap_widget (wbox->window, tool_info[j].icon_data, 22, 22);
gtk_container_add (GTK_CONTAINER (alignment), pixmap); gtk_container_add (GTK_CONTAINER (alignment), pixmap);
gtk_signal_connect (GTK_OBJECT (button), "toggled", gtk_signal_connect (GTK_OBJECT (button), "toggled",
@ -406,7 +405,7 @@ create_tools (GtkWidget *parent)
(gpointer) tool_info[j].tool_id); (gpointer) tool_info[j].tool_id);
} }
} }
gtk_widget_show (table); gtk_widget_show (wbox);
} }
static GdkPixmap * static GdkPixmap *

View File

@ -44,7 +44,7 @@ static GimpDrawableClass *parent_class = NULL;
GtkType GtkType
gimp_drawable_get_type () gimp_drawable_get_type (void)
{ {
static GtkType type; static GtkType type;
GIMP_TYPE_INIT(type, GIMP_TYPE_INIT(type,

628
app/gtkhwrapbox.c Normal file
View File

@ -0,0 +1,628 @@
/* 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 <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);
/* --- 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;
}
static void
gtk_hwrap_box_init (GtkHWrapBox *hwbox)
{
hwbox->max_child_width = 0;
hwbox->max_child_height = 0;
}
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);
}
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>*/
}
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, 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;
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)
{
ratio_dist = dist;
requisition->width = layout_width;
requisition->height = layout_height;
}
/*<h2v-off>*/
g_print ("ratio for width %d height %d = %f\n",
(gint) layout_width,
(gint) layout_height,
ratio);
/*<h2v-on>*/
}
while (row_inc);
/*<h2v-off>*/
requisition->width += GTK_CONTAINER (wbox)->border_width * 2;
requisition->height += GTK_CONTAINER (wbox)->border_width * 2;
g_print ("choosen: width %d, height %d\n",
requisition->width,
requisition->height);
/*<h2v-on>*/
}
static GSList*
list_row_children (GtkWrapBox *wbox,
GtkWrapBoxChild **child_p,
guint row_width,
guint *max_height,
gboolean *can_vexpand)
{
GSList *slist = NULL;
guint width = 0;
GtkWrapBoxChild *child = *child_p;
*max_height = 0;
*can_vexpand = 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_height = MAX (*max_height, child_requisition.height);
*can_vexpand |= 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)
break;
width += wbox->hspacing + child_requisition.width;
*max_height = MAX (*max_height, child_requisition.height);
*can_vexpand |= child->vexpand;
slist = g_slist_prepend (slist, child);
n++;
}
*child_p = child->next;
child = *child_p;
}
}
return g_slist_reverse (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)
{
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;
Line *line_list = NULL;
guint total_height = 0, n_expand_lines = 0, n_lines = 0;
gfloat shrink_height;
guint children_per_line;
next_child = wbox->children;
slist = list_row_children (wbox, &next_child, area->width, &min_height, &vexpand);
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 = list_row_children (wbox,
&next_child,
area->width,
&min_height,
&vexpand);
}
if (total_height > area->height)
shrink_height = total_height - area->height;
else
shrink_height = 0;
if (1) /* reverse 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);
}

76
app/gtkhwrapbox.h Normal file
View File

@ -0,0 +1,76 @@
/* 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;
guint16 max_child_width;
guint16 max_child_height;
};
struct _GtkHWrapBoxClass
{
GtkWrapBoxClass parent_class;
};
/* --- prototypes --- */
GtkType gtk_hwrap_box_get_type (void);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __GTK_HWRAP_BOX_H__ */

724
app/gtkwrapbox.c Normal file
View File

@ -0,0 +1,724 @@
/* 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 "gtkwrapbox.h"
#include <math.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
};
/* --- 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;
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);
}
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;
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->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_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);
}
}
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 FALSE;
}
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);
}
}

129
app/gtkwrapbox.h Normal file
View File

@ -0,0 +1,129 @@
/* 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;
/* --- 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;
};
struct _GtkWrapBoxChild
{
GtkWidget *widget;
guint hexpand : 1;
guint hfill : 1;
guint vexpand : 1;
guint vfill : 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_set_child_packing (GtkWrapBox *wbox,
GtkWidget *child,
gboolean hexpand,
gboolean hfill,
gboolean vexpand,
gboolean vfill);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __GTK_WRAP_BOX_H__ */

View File

@ -368,14 +368,14 @@ about_dialog_load_logo (GtkWidget *window)
} }
static void static void
about_dialog_destroy () about_dialog_destroy (void)
{ {
about_dialog = NULL; about_dialog = NULL;
about_dialog_unmap (); about_dialog_unmap ();
} }
static void static void
about_dialog_unmap () about_dialog_unmap (void)
{ {
if (timer) if (timer)
{ {

View File

@ -35,6 +35,7 @@
#include "gimage.h" #include "gimage.h"
#include "gimpdnd.h" #include "gimpdnd.h"
#include "gimprc.h" #include "gimprc.h"
#include "gtkhwrapbox.h"
#include "indicator_area.h" #include "indicator_area.h"
#include "interface.h" #include "interface.h"
#include "menus.h" #include "menus.h"
@ -340,7 +341,7 @@ create_tool_pixmap (GtkWidget *parent,
static void static void
create_tools (GtkWidget *parent) create_tools (GtkWidget *parent)
{ {
GtkWidget *table; GtkWidget *wbox;
GtkWidget *button; GtkWidget *button;
GtkWidget *alignment; GtkWidget *alignment;
GtkWidget *pixmap; GtkWidget *pixmap;
@ -348,9 +349,11 @@ create_tools (GtkWidget *parent)
gint i, j; gint i, j;
/*create_logo (parent);*/ /*create_logo (parent);*/
table = gtk_table_new (ROWS, COLUMNS, TRUE); wbox = GTK_WIDGET (gtk_type_new (gtk_hwrap_box_get_type ()));
gtk_box_pack_start (GTK_BOX (parent), table, TRUE, TRUE, 0); gtk_wrap_box_set_aspect_ratio (GTK_WRAP_BOX (wbox), .36);
gtk_widget_realize (table); gtk_box_pack_start (GTK_BOX (parent), wbox, TRUE, TRUE, 0);
gtk_widget_realize (gtk_widget_get_toplevel (wbox));
group = NULL; group = NULL;
@ -365,18 +368,14 @@ create_tools (GtkWidget *parent)
gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (button), FALSE); gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (button), FALSE);
gtk_table_attach (GTK_TABLE (table), button, gtk_wrap_box_pack (GTK_WRAP_BOX (wbox), button,
(i % 3), (i % 3) + 1, FALSE, TRUE, FALSE, TRUE);
(i / 3), (i / 3) + 1,
GTK_EXPAND | GTK_SHRINK | GTK_FILL,
GTK_EXPAND | GTK_SHRINK | GTK_FILL,
0, 0);
alignment = gtk_alignment_new (0.5, 0.5, 0.0, 0.0); alignment = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
gtk_container_set_border_width (GTK_CONTAINER (alignment), 0); gtk_container_set_border_width (GTK_CONTAINER (alignment), 0);
gtk_container_add (GTK_CONTAINER (button), alignment); gtk_container_add (GTK_CONTAINER (button), alignment);
pixmap = create_pixmap_widget (table->window, tool_info[j].icon_data, 22, 22); pixmap = create_pixmap_widget (wbox->window, tool_info[j].icon_data, 22, 22);
gtk_container_add (GTK_CONTAINER (alignment), pixmap); gtk_container_add (GTK_CONTAINER (alignment), pixmap);
gtk_signal_connect (GTK_OBJECT (button), "toggled", gtk_signal_connect (GTK_OBJECT (button), "toggled",
@ -406,7 +405,7 @@ create_tools (GtkWidget *parent)
(gpointer) tool_info[j].tool_id); (gpointer) tool_info[j].tool_id);
} }
} }
gtk_widget_show (table); gtk_widget_show (wbox);
} }
static GdkPixmap * static GdkPixmap *

View File

@ -167,7 +167,7 @@ airbrush_options_new (void)
} }
Tool * Tool *
tools_new_airbrush () tools_new_airbrush (void)
{ {
Tool * tool; Tool * tool;
PaintCore * private; PaintCore * private;

View File

@ -167,7 +167,7 @@ airbrush_options_new (void)
} }
Tool * Tool *
tools_new_airbrush () tools_new_airbrush (void)
{ {
Tool * tool; Tool * tool;
PaintCore * private; PaintCore * private;

View File

@ -17,6 +17,8 @@
*/ */
#include "config.h" #include "config.h"
#include <stdlib.h>
#include "appenv.h" #include "appenv.h"
#include "asupsample.h" #include "asupsample.h"
#include "blend.h" #include "blend.h"

View File

@ -167,7 +167,7 @@ airbrush_options_new (void)
} }
Tool * Tool *
tools_new_airbrush () tools_new_airbrush (void)
{ {
Tool * tool; Tool * tool;
PaintCore * private; PaintCore * private;

View File

@ -17,6 +17,8 @@
*/ */
#include "config.h" #include "config.h"
#include <stdlib.h>
#include "appenv.h" #include "appenv.h"
#include "asupsample.h" #include "asupsample.h"
#include "blend.h" #include "blend.h"

628
app/widgets/gtkhwrapbox.c Normal file
View File

@ -0,0 +1,628 @@
/* 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 <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);
/* --- 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;
}
static void
gtk_hwrap_box_init (GtkHWrapBox *hwbox)
{
hwbox->max_child_width = 0;
hwbox->max_child_height = 0;
}
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);
}
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>*/
}
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, 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;
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)
{
ratio_dist = dist;
requisition->width = layout_width;
requisition->height = layout_height;
}
/*<h2v-off>*/
g_print ("ratio for width %d height %d = %f\n",
(gint) layout_width,
(gint) layout_height,
ratio);
/*<h2v-on>*/
}
while (row_inc);
/*<h2v-off>*/
requisition->width += GTK_CONTAINER (wbox)->border_width * 2;
requisition->height += GTK_CONTAINER (wbox)->border_width * 2;
g_print ("choosen: width %d, height %d\n",
requisition->width,
requisition->height);
/*<h2v-on>*/
}
static GSList*
list_row_children (GtkWrapBox *wbox,
GtkWrapBoxChild **child_p,
guint row_width,
guint *max_height,
gboolean *can_vexpand)
{
GSList *slist = NULL;
guint width = 0;
GtkWrapBoxChild *child = *child_p;
*max_height = 0;
*can_vexpand = 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_height = MAX (*max_height, child_requisition.height);
*can_vexpand |= 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)
break;
width += wbox->hspacing + child_requisition.width;
*max_height = MAX (*max_height, child_requisition.height);
*can_vexpand |= child->vexpand;
slist = g_slist_prepend (slist, child);
n++;
}
*child_p = child->next;
child = *child_p;
}
}
return g_slist_reverse (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)
{
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;
Line *line_list = NULL;
guint total_height = 0, n_expand_lines = 0, n_lines = 0;
gfloat shrink_height;
guint children_per_line;
next_child = wbox->children;
slist = list_row_children (wbox, &next_child, area->width, &min_height, &vexpand);
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 = list_row_children (wbox,
&next_child,
area->width,
&min_height,
&vexpand);
}
if (total_height > area->height)
shrink_height = total_height - area->height;
else
shrink_height = 0;
if (1) /* reverse 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);
}

76
app/widgets/gtkhwrapbox.h Normal file
View File

@ -0,0 +1,76 @@
/* 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;
guint16 max_child_width;
guint16 max_child_height;
};
struct _GtkHWrapBoxClass
{
GtkWrapBoxClass parent_class;
};
/* --- prototypes --- */
GtkType gtk_hwrap_box_get_type (void);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __GTK_HWRAP_BOX_H__ */

724
app/widgets/gtkwrapbox.c Normal file
View File

@ -0,0 +1,724 @@
/* 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 "gtkwrapbox.h"
#include <math.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
};
/* --- 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;
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);
}
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;
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->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_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);
}
}
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 FALSE;
}
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);
}
}

129
app/widgets/gtkwrapbox.h Normal file
View File

@ -0,0 +1,129 @@
/* 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;
/* --- 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;
};
struct _GtkWrapBoxChild
{
GtkWidget *widget;
guint hexpand : 1;
guint hfill : 1;
guint vexpand : 1;
guint vfill : 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_set_child_packing (GtkWrapBox *wbox,
GtkWidget *child,
gboolean hexpand,
gboolean hfill,
gboolean vexpand,
gboolean vfill);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __GTK_WRAP_BOX_H__ */

View File

@ -113,6 +113,7 @@ gimpinclude_HEADERS = \
gimpfeatures.h \ gimpfeatures.h \
gimpfileselection.h \ gimpfileselection.h \
gimplimits.h \ gimplimits.h \
gimpmath.h \
gimpmatrix.h \ gimpmatrix.h \
gimpmenu.h \ gimpmenu.h \
gimpmodule.h \ gimpmodule.h \