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