/* $Id: guppi-multiview.c,v 1.8 2001/07/10 02:53:26 trow Exp $ */
/* guppi-multiview.c
*
* Copyright (C) 2000 Jonathan Blandford
*
* Modified for use in Guppi by Jon Trowbridge
*
* 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 <config.h>
#include "guppi-multiview.h"
/* #include <gtk/gtk.h> */
#include "guppi-memory.h"
static void guppi_multiview_init (GuppiMultiview * multiview);
static void guppi_multiview_class_init (GuppiMultiviewClass * klass);
static void guppi_multiview_size_request (GtkWidget * widget,
GtkRequisition * requisition);
static void guppi_multiview_size_allocate (GtkWidget * widget,
GtkAllocation * allocation);
static void guppi_multiview_map (GtkWidget * widget);
static void guppi_multiview_unmap (GtkWidget * widget);
static int guppi_multiview_expose (GtkWidget * widget,
GdkEventExpose * event);
static GtkType guppi_multiview_child_type (GtkContainer * container);
static void guppi_multiview_forall (GtkContainer * container,
gboolean include_internals,
GtkCallback callback,
gpointer callback_data);
static void guppi_multiview_add (GtkContainer * widget, GtkWidget * child);
static void guppi_multiview_remove (GtkContainer * widget, GtkWidget * child);
static GtkContainerClass *parent_class = NULL;
GtkType
guppi_multiview_get_type (void)
{
static GtkType multiview_type = 0;
if (!multiview_type) {
static const GtkTypeInfo multiview_info = {
"GuppiMultiview",
sizeof (GuppiMultiview),
sizeof (GuppiMultiviewClass),
(GtkClassInitFunc) guppi_multiview_class_init,
(GtkObjectInitFunc) guppi_multiview_init,
/* reserved_1 */ NULL,
/* reserved_2 */ NULL,
(GtkClassInitFunc) NULL,
};
multiview_type =
gtk_type_unique (gtk_container_get_type (), &multiview_info);
}
return multiview_type;
}
static void
guppi_multiview_init (GuppiMultiview * multiview)
{
GTK_WIDGET_SET_FLAGS (GTK_WIDGET (multiview), GTK_NO_WINDOW);
multiview->current = NULL;
multiview->children = NULL;
}
static void
finalize (GtkObject *obj)
{
guppi_finalized (obj);
if (GTK_OBJECT_CLASS (parent_class)->finalize)
GTK_OBJECT_CLASS (parent_class)->finalize (obj);
}
static void
guppi_multiview_class_init (GuppiMultiviewClass * klass)
{
GtkObjectClass *object_class;
GtkWidgetClass *widget_class;
GtkContainerClass *container_class;
object_class = (GtkObjectClass *) klass;
widget_class = (GtkWidgetClass *) klass;
container_class = (GtkContainerClass *) klass;
parent_class = gtk_type_class (gtk_container_get_type ());
object_class->finalize = finalize;
widget_class->size_request = guppi_multiview_size_request;
widget_class->size_allocate = guppi_multiview_size_allocate;
widget_class->map = guppi_multiview_map;
widget_class->unmap = guppi_multiview_unmap;
widget_class->expose_event = guppi_multiview_expose;
container_class->forall = guppi_multiview_forall;
container_class->add = guppi_multiview_add;
container_class->remove = guppi_multiview_remove;
container_class->child_type = guppi_multiview_child_type;
}
static void
guppi_multiview_size_request (GtkWidget * widget,
GtkRequisition * requisition)
{
GList *tmp_list;
GuppiMultiview *multiview;
GtkRequisition child_requisition;
GtkWidget *child;
multiview = GUPPI_MULTIVIEW (widget);
requisition->width = 0;
requisition->height = 0;
/* We find the maximum size of all children widgets */
tmp_list = multiview->children;
while (tmp_list) {
child = GTK_WIDGET (tmp_list->data);
tmp_list = tmp_list->next;
if (GTK_WIDGET_VISIBLE (child)) {
gtk_widget_size_request (child, &child_requisition);
requisition->width = MAX (requisition->width, child_requisition.width);
requisition->height =
MAX (requisition->height, child_requisition.height);
if (GTK_WIDGET_MAPPED (child) && child != multiview->current) {
gtk_widget_unmap (GTK_WIDGET (child));
}
}
}
}
static void
guppi_multiview_size_allocate (GtkWidget * widget, GtkAllocation * allocation)
{
GuppiMultiview *multiview;
GList *tmp_list;
GtkWidget *child;
g_return_if_fail (widget != NULL);
g_return_if_fail (GUPPI_IS_MULTIVIEW (widget));
multiview = GUPPI_MULTIVIEW (widget);
widget->allocation = *allocation;
tmp_list = multiview->children;
while (tmp_list) {
child = GTK_WIDGET (tmp_list->data);
tmp_list = tmp_list->next;
if (GTK_WIDGET_VISIBLE (child)) {
gtk_widget_size_allocate (child, allocation);
}
}
}
static void
guppi_multiview_map (GtkWidget * widget)
{
GuppiMultiview *multiview;
g_return_if_fail (widget != NULL);
g_return_if_fail (GUPPI_IS_MULTIVIEW (widget));
multiview = GUPPI_MULTIVIEW (widget);
GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
if (multiview->current &&
GTK_WIDGET_VISIBLE (multiview->current) &&
!GTK_WIDGET_MAPPED (multiview->current)) {
gtk_widget_map (GTK_WIDGET (multiview->current));
}
}
static void
guppi_multiview_unmap (GtkWidget * widget)
{
GuppiMultiview *multiview;
g_return_if_fail (widget != NULL);
g_return_if_fail (GUPPI_IS_MULTIVIEW (widget));
multiview = GUPPI_MULTIVIEW (widget);
GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
if (multiview->current &&
GTK_WIDGET_VISIBLE (multiview->current) &&
GTK_WIDGET_MAPPED (multiview->current)) {
gtk_widget_unmap (GTK_WIDGET (multiview->current));
}
}
static gint
guppi_multiview_expose (GtkWidget * widget, GdkEventExpose * event)
{
GuppiMultiview *multiview;
GtkWidget *child;
GList *tmp_list;
GdkEventExpose child_event;
g_return_val_if_fail (widget != NULL, FALSE);
g_return_val_if_fail (GUPPI_IS_MULTIVIEW (widget), FALSE);
g_return_val_if_fail (event != NULL, FALSE);
if (GTK_WIDGET_DRAWABLE (widget)) {
multiview = GUPPI_MULTIVIEW (widget);
child_event = *event;
tmp_list = multiview->children;
while (tmp_list) {
child = GTK_WIDGET (tmp_list->data);
tmp_list = tmp_list->next;
if (GTK_WIDGET_DRAWABLE (child) && GTK_WIDGET_NO_WINDOW (child)) {
gtk_widget_event (child, (GdkEvent *) event);
}
}
}
return FALSE;
}
static GtkType
guppi_multiview_child_type (GtkContainer * container)
{
return gtk_widget_get_type ();
}
static void
guppi_multiview_forall (GtkContainer * container,
gboolean include_internals,
GtkCallback callback, gpointer callback_data)
{
GtkWidget *child;
GuppiMultiview *multiview;
GList *tmp_list;
g_return_if_fail (container != NULL);
g_return_if_fail (GUPPI_IS_MULTIVIEW (container));
g_return_if_fail (callback != NULL);
multiview = GUPPI_MULTIVIEW (container);
tmp_list = multiview->children;
while (tmp_list) {
child = tmp_list->data;
tmp_list = tmp_list->next;
(*callback) (GTK_WIDGET (child), callback_data);
}
}
static void
guppi_multiview_add (GtkContainer * container, GtkWidget * child)
{
g_return_if_fail (container != NULL);
g_return_if_fail (GUPPI_IS_MULTIVIEW (container));
g_return_if_fail (child != NULL);
g_return_if_fail (GTK_IS_WIDGET (child));
guppi_multiview_append_child (GUPPI_MULTIVIEW (container), child);
}
static void
guppi_multiview_remove (GtkContainer * container, GtkWidget * child)
{
GuppiMultiview *multiview;
GList *list;
g_return_if_fail (container != NULL);
g_return_if_fail (GUPPI_IS_MULTIVIEW (container));
g_return_if_fail (child != NULL);
multiview = GUPPI_MULTIVIEW (container);
list = g_list_find (multiview->children, child);
g_return_if_fail (list != NULL);
/* If we are mapped and visible, we want to deal with changing the page. */
if ((GTK_WIDGET_MAPPED (GTK_WIDGET (container))) &&
(list->data == (gpointer) multiview->current)) {
if (list->next != NULL)
guppi_multiview_set_current (multiview, GTK_WIDGET (list->next->data));
else
multiview->current = NULL;
}
multiview->children = g_list_remove (multiview->children, child);
gtk_widget_unparent (child);
}
/* Public Functions */
GtkWidget *
guppi_multiview_new (void)
{
return GTK_WIDGET (guppi_type_new (guppi_multiview_get_type ()));
}
void
guppi_multiview_prepend_child (GuppiMultiview * multiview, GtkWidget * child)
{
g_return_if_fail (multiview != NULL);
g_return_if_fail (GUPPI_IS_MULTIVIEW (multiview));
g_return_if_fail (child != NULL);
g_return_if_fail (GTK_IS_WIDGET (child));
guppi_multiview_insert_child (multiview, NULL, child);
}
void
guppi_multiview_insert_child (GuppiMultiview * multiview,
GtkWidget * back_child, GtkWidget * child)
{
GList *list;
g_return_if_fail (multiview != NULL);
g_return_if_fail (GUPPI_IS_MULTIVIEW (multiview));
g_return_if_fail (child != NULL);
g_return_if_fail (GTK_IS_WIDGET (child));
list = g_list_find (multiview->children, back_child);
if (list == NULL) {
multiview->children = g_list_prepend (multiview->children, child);
} else {
GList *new_el = g_list_alloc ();
new_el->next = list->next;
new_el->prev = list;
if (new_el->next)
new_el->next->prev = new_el;
new_el->prev->next = new_el;
new_el->data = (gpointer) child;
}
gtk_widget_set_parent (GTK_WIDGET (child), GTK_WIDGET (multiview));
if (GTK_WIDGET_REALIZED (GTK_WIDGET (multiview)))
gtk_widget_realize (GTK_WIDGET (child));
if (GTK_WIDGET_VISIBLE (GTK_WIDGET (multiview))
&& GTK_WIDGET_VISIBLE (GTK_WIDGET (child))) {
if (GTK_WIDGET_MAPPED (GTK_WIDGET (child)))
gtk_widget_unmap (GTK_WIDGET (child));
gtk_widget_queue_resize (GTK_WIDGET (multiview));
}
/* if it's the first and only entry, we want to bring it to the foreground. */
if (multiview->children->next == NULL)
guppi_multiview_set_current (multiview, child);
}
void
guppi_multiview_append_child (GuppiMultiview * multiview, GtkWidget * child)
{
GList *list;
g_return_if_fail (multiview != NULL);
g_return_if_fail (GUPPI_IS_MULTIVIEW (multiview));
g_return_if_fail (child != NULL);
g_return_if_fail (GTK_IS_WIDGET (child));
list = g_list_last (multiview->children);
if (list) {
guppi_multiview_insert_child (multiview, GTK_WIDGET (list->data), child);
} else {
guppi_multiview_insert_child (multiview, NULL, child);
}
}
gboolean
guppi_multiview_contains (GuppiMultiview * multiview, GtkWidget * child)
{
g_return_val_if_fail (multiview != NULL, FALSE);
g_return_val_if_fail (GUPPI_IS_MULTIVIEW (multiview), FALSE);
g_return_val_if_fail (child != NULL, FALSE);
g_return_val_if_fail (GTK_IS_WIDGET (child), FALSE);
return g_list_find (multiview->children, child) != NULL;
}
void
guppi_multiview_set_current (GuppiMultiview * multiview, GtkWidget * child)
{
GList *list;
GtkWidget *old = NULL;
g_return_if_fail (multiview != NULL);
g_return_if_fail (GUPPI_IS_MULTIVIEW (multiview));
g_return_if_fail (child != NULL);
g_return_if_fail (GTK_IS_WIDGET (child));
if (multiview->current == child)
return;
list = g_list_find (multiview->children, child);
g_return_if_fail (list != NULL);
if ((multiview->current) &&
(GTK_WIDGET_VISIBLE (multiview->current)) &&
(GTK_WIDGET_MAPPED (multiview))) {
old = GTK_WIDGET (multiview->current);
}
multiview->current = GTK_WIDGET (list->data);
if (GTK_WIDGET_VISIBLE (multiview->current) &&
(GTK_WIDGET_MAPPED (multiview))) {
gtk_widget_map (multiview->current);
}
if (old && GTK_WIDGET_MAPPED (old))
gtk_widget_unmap (old);
gtk_widget_show_all (multiview->current);
}
syntax highlighted by Code2HTML, v. 0.9.1