/* -*- 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);