aboutsummaryrefslogblamecommitdiffstats
path: root/e-util/e-paned.c
blob: c00c98ac5341de9c91fc534756356d8ffabd353d (plain) (tree)


































































































































































































































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