diff options
Diffstat (limited to 'e-util')
-rw-r--r-- | e-util/ChangeLog | 8 | ||||
-rw-r--r-- | e-util/Makefile.am | 4 | ||||
-rw-r--r-- | e-util/e-paned.c | 227 | ||||
-rw-r--r-- | e-util/e-paned.h | 45 |
4 files changed, 283 insertions, 1 deletions
diff --git a/e-util/ChangeLog b/e-util/ChangeLog index e3d13ef2b3..de6a388a16 100644 --- a/e-util/ChangeLog +++ b/e-util/ChangeLog @@ -1,3 +1,11 @@ +2000-04-24 Matt Loper <matt@helixcode.com> + + * e-paned.c: New file. Makes a GtkPaned with more than two + children. + * e-paned.h: same. + + * Makefile.am: added e-paned.[ch]. + 2000-04-19 Christopher James Lahey <clahey@helixcode.com> * e-xml-utils.c, e-xml-utils.h: Added diff --git a/e-util/Makefile.am b/e-util/Makefile.am index 77a6c5eec0..3dc32f3ab3 100644 --- a/e-util/Makefile.am +++ b/e-util/Makefile.am @@ -19,4 +19,6 @@ libeutil_la_SOURCES = \ e-xml-utils.c \ e-xml-utils.h \ e-sexp.c \ - e-sexp.h + e-sexp.h \ + e-paned.c \ + e-paned.h diff --git a/e-util/e-paned.c b/e-util/e-paned.c new file mode 100644 index 0000000000..c00c98ac53 --- /dev/null +++ b/e-util/e-paned.c @@ -0,0 +1,227 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * E-pane.c: A paned window which accepts more than one child + * + * Author: + * Matt Loper (matt@helixcode.com) + * + * Copyright 2000, Helix Code, Inc + */ + +#include "e-paned.h" +#include "e-util.h" + +#define PARENT_TYPE gtk_frame_get_type () +static GtkObjectClass *e_paned_parent_class; + +/*----------------------------------------------------------------------* + * (un)parenting functions + *----------------------------------------------------------------------*/ + +static void +unparent_all_children (EPaned *paned) +{ + GList *l; + + for (l = paned->children; l != NULL; l = l->next) { + GtkWidget *child = GTK_WIDGET (l->data); + + gtk_widget_ref (child); + gtk_container_remove (GTK_CONTAINER (child->parent), + child); + } + + if (paned->toplevel_paned) { + GtkWidget* parent = + GTK_WIDGET (paned->toplevel_paned)->parent; + + gtk_container_remove (GTK_CONTAINER (parent), + GTK_WIDGET (paned->toplevel_paned)); + } + + + paned->toplevel_paned = NULL; +} + +static GtkPaned* +new_gtk_paned (EPaned *paned) +{ + return paned->horizontal? + GTK_PANED (gtk_hpaned_new ()): + GTK_PANED (gtk_vpaned_new ()); +} + + +static void +reparent_all_children (EPaned *paned) +{ + GtkPaned *cur_gtk_paned; + GList *l = paned->children; + int requested_size; + + g_assert (E_IS_PANED (paned)); + + if (paned->toplevel_paned) + unparent_all_children (paned); + + if (!l) + return; + + /* if there's only one child in our list, we don't need a + splitter window; we can just show the one window */ + if (!l->next) + { + gtk_container_add (GTK_CONTAINER (paned), + GTK_WIDGET (l->data)); + return; + } + + /* create a gtk_paned, and put it in our toplevel EPaned */ + cur_gtk_paned = new_gtk_paned (paned); + paned->toplevel_paned = cur_gtk_paned; + gtk_container_add (GTK_CONTAINER (paned), + GTK_WIDGET (paned->toplevel_paned)); + + /* put the first widget in the left part of our pane, + and give it the amount of space requested */ + gtk_paned_add1 (cur_gtk_paned, GTK_WIDGET (l->data)); + requested_size = (int)gtk_object_get_data ( + GTK_OBJECT (l->data), + "e_paned_requested_size"); + gtk_paned_set_position (GTK_PANED (cur_gtk_paned), + requested_size); + + l = l->next; + + for (; l != NULL; l = l->next) { + + if (l->next) { + + GtkPaned *sub_gtk_paned = + new_gtk_paned (paned); + GtkWidget *w = GTK_WIDGET (l->data); + + /* add our widget to the new subpane, + on the left */ + gtk_paned_add1 (sub_gtk_paned, w); + + requested_size = (int)gtk_object_get_data ( + GTK_OBJECT (w), + "e_paned_requested_size"); + gtk_paned_set_position (GTK_PANED (sub_gtk_paned), + requested_size); + + gtk_paned_add2 (cur_gtk_paned, + GTK_WIDGET (sub_gtk_paned)); + cur_gtk_paned = sub_gtk_paned; + } + else { + gtk_paned_add2 (cur_gtk_paned, + GTK_WIDGET (l->data)); + } + } +} + +/*----------------------------------------------------------------------* + * Exposed regular functions + *----------------------------------------------------------------------*/ + + +/** + * e_paned_insert: + * @paned: the #EPaned object + * @pos: the position where we should insert the widget + * @child: the widget to insert in the #EPaned object + * @requested_size: the requested span of the widget, which will be + * width of the #EPaned is horizontal, or height if it's vertical + * + * Inserts a widget into the #EPaned window, given a requested size + * and a position; the position specifies where, among the other + * widgets, the widget should be placed. + * + **/ +void +e_paned_insert (EPaned *paned, int pos, GtkWidget *child, int requested_size) +{ + g_assert (GTK_IS_WIDGET (child)); + g_assert (E_IS_PANED (paned)); + + unparent_all_children (paned); + + paned->children = g_list_insert (paned->children, child, pos); + gtk_object_set_data (GTK_OBJECT (child), + "e_paned_requested_size", + (gpointer)requested_size); + + reparent_all_children (paned); + + g_print ("%s: %s(): exiting, length is %i\n", + __FILE__, __FUNCTION__, g_list_length (paned->children)); +} + +/** + * e_paned_remove: + * @paned: the #EPaned object + * @removed_child: the widget to remove + * + * Removes a widget from an #EPaned widget. + * + **/ +void +e_paned_remove (EPaned *paned, GtkWidget *removed_child) +{ + unparent_all_children (paned); + paned->children = g_list_remove (paned->children, removed_child); + gtk_widget_unref (GTK_WIDGET (removed_child)); + reparent_all_children (paned); +} + + +/*----------------------------------------------------------------------* + * Standard Gtk+ Class functions + *----------------------------------------------------------------------*/ + +void +e_paned_construct (EPaned *e_paned, + gboolean horizontal) +{ + g_return_if_fail (e_paned != NULL); + g_return_if_fail (E_IS_PANED (e_paned)); + + + e_paned->horizontal = horizontal; +} + +GtkWidget* +e_paned_new (gboolean horizontal) +{ + EPaned *e_paned; + + e_paned = gtk_type_new (e_paned_get_type ()); + + e_paned_construct (e_paned, horizontal); + + g_assert (E_IS_PANED (e_paned)); + + return GTK_WIDGET (e_paned); +} + +static void +e_paned_init (GtkObject *object) +{ + EPaned *e_paned; + + e_paned = E_PANED (object); + + e_paned->children = NULL; + e_paned->toplevel_paned = NULL; + e_paned->horizontal = FALSE; +} + +static void +e_paned_class_init (GtkObjectClass *object_class) +{ + e_paned_parent_class = gtk_type_class (PARENT_TYPE); +} + +E_MAKE_TYPE(e_paned, "EPaned", EPaned, e_paned_class_init, e_paned_init, PARENT_TYPE); diff --git a/e-util/e-paned.h b/e-util/e-paned.h new file mode 100644 index 0000000000..df981ca7f8 --- /dev/null +++ b/e-util/e-paned.h @@ -0,0 +1,45 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ + +#ifndef __E_PANED_H__ +#define __E_PANED_H__ + +#include <gdk/gdk.h> +#include <gtk/gtkframe.h> +#include <gtk/gtkhpaned.h> +#include <gtk/gtkvpaned.h> + + +#define E_PANED_TYPE (e_paned_get_type ()) +#define E_PANED(obj) (GTK_CHECK_CAST ((obj), E_PANED_TYPE, EPaned)) +#define E_PANED_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), E_PANED_TYPE, EPanedClass)) +#define E_IS_PANED(obj) (GTK_CHECK_TYPE ((obj), E_PANED_TYPE)) +#define E_IS_PANED_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), E_PANED_TYPE)) + + +typedef struct _EPaned EPaned; +typedef struct _EPanedClass EPanedClass; + + +struct _EPaned +{ + GtkFrame container; + + GList *children; + GtkPaned *toplevel_paned; + gboolean horizontal; +}; + +struct _EPanedClass +{ + GtkFrameClass parent_class; +}; + +void e_paned_insert (EPaned *paned, int pos, GtkWidget *child, + int requested_size); +void e_paned_remove (EPaned *paned, GtkWidget *child); + +GtkWidget *e_paned_new (gboolean horizontal); +void e_paned_construct (EPaned *e_paned, gboolean horizontal); +GtkType e_paned_get_type (void); + +#endif /* __E_PANED_H__ */ |