/* mguru.c - Multiway guru widget.
Copyright (C) 1999 Perry Piplani. Idea inspired by Havoc
Pennington's gnome-guru widget, but is a re-implemention
from scratch.
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, or
(at your option) any later version.
This program 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 program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA. */
#include <gnome.h>
#include "mguru.h"
enum
{
CANCEL,
APPLY,
PREV,
NEXT,
MGURU_CLICK,
LAST_SIGNAL
};
typedef void (*GnomeMGuruSignal2) (GtkObject *object,
gint arg1, gint arg2, gpointer data);
typedef void (*GnomeMGuruSignal1) (GtkObject *object,
gint arg1, gpointer data);
static void gnome_mguru_class_init (GnomeMGuruClass *klass);
static void gnome_mguru_init (GnomeMGuru *mguru);
static void gnome_mguru_marshal_signal1 (GtkObject *object,
GtkSignalFunc func,
gpointer func_data,
GtkArg *args);
static void gnome_mguru_marshal_signal2 (GtkObject *object,
GtkSignalFunc func,
gpointer func_data,
GtkArg *args);
static void gnome_mguru_destroy (GtkObject *object);
static void mguru_clicked_cb (GtkWidget *widget, gpointer guru);
static void gnome_mguru_auto_state(GnomeMGuru *mguru);
static GtkVBoxClass *parent_class = NULL;
static gint mguru_signals [LAST_SIGNAL] = { 0 };
guint gnome_mguru_get_type (void)
{
static guint mguru_type = 0;
if (!mguru_type){
GtkTypeInfo mguru_info = {
"GnomeMGuru",
sizeof (GnomeMGuru),
sizeof (GnomeMGuruClass),
(GtkClassInitFunc) gnome_mguru_class_init,
(GtkObjectInitFunc) gnome_mguru_init,
(GtkArgSetFunc) NULL,
(GtkArgGetFunc) NULL
};
mguru_type = gtk_type_unique (gtk_vbox_get_type (),
&mguru_info);
}
return mguru_type;
}
static void
gnome_mguru_class_init (GnomeMGuruClass *klass)
{
GtkObjectClass *object_class;
GtkWidgetClass *widget_class;
object_class = (GtkObjectClass*) klass;
widget_class = (GtkWidgetClass*) klass;
object_class->destroy = gnome_mguru_destroy;
parent_class = gtk_type_class (gtk_vbox_get_type ());
mguru_signals[CANCEL] =
gtk_signal_new ("cancel",
GTK_RUN_LAST,
object_class->type,
GTK_SIGNAL_OFFSET (GnomeMGuruClass,
cancel),
gnome_mguru_marshal_signal1,
GTK_TYPE_NONE,
1, GTK_TYPE_INT);
mguru_signals[APPLY] =
gtk_signal_new ("apply",
GTK_RUN_LAST,
object_class->type,
GTK_SIGNAL_OFFSET (GnomeMGuruClass,
apply),
gnome_mguru_marshal_signal1,
GTK_TYPE_NONE,
1, GTK_TYPE_INT);
mguru_signals[PREV] =
gtk_signal_new ("prev",
GTK_RUN_LAST,
object_class->type,
GTK_SIGNAL_OFFSET (GnomeMGuruClass,
prev),
gnome_mguru_marshal_signal1,
GTK_TYPE_NONE,
1, GTK_TYPE_INT);
mguru_signals[NEXT] =
gtk_signal_new ("next",
GTK_RUN_LAST,
object_class->type,
GTK_SIGNAL_OFFSET (GnomeMGuruClass,
next),
gnome_mguru_marshal_signal1,
GTK_TYPE_NONE,
1, GTK_TYPE_INT);
mguru_signals[MGURU_CLICK] =
gtk_signal_new ("mguru_click",
GTK_RUN_LAST,
object_class->type,
GTK_SIGNAL_OFFSET (GnomeMGuruClass,
mguru_click),
gnome_mguru_marshal_signal2,
GTK_TYPE_NONE,
2, GTK_TYPE_INT, GTK_TYPE_INT);
gtk_object_class_add_signals (object_class, mguru_signals,
LAST_SIGNAL);
klass->mguru_click = NULL;
klass->cancel = NULL;
klass->apply = NULL;
klass->prev = NULL;
klass->next = NULL;
}
static void
gnome_mguru_marshal_signal1 (GtkObject *object,
GtkSignalFunc func,
gpointer func_data,
GtkArg *args)
{
GnomeMGuruSignal1 rfunc;
rfunc = (GnomeMGuruSignal1) func;
(* rfunc) (object, GTK_VALUE_INT (args[0]) ,func_data);
}
static void
gnome_mguru_marshal_signal2 (GtkObject *object,
GtkSignalFunc func,
gpointer func_data,
GtkArg *args)
{
GnomeMGuruSignal2 rfunc;
rfunc = (GnomeMGuruSignal2) func;
(* rfunc) (object, GTK_VALUE_INT (args[0]),
GTK_VALUE_INT (args[1]),func_data);
}
static void
gnome_mguru_init (GnomeMGuru *mguru)
{
mguru->notebook = gtk_notebook_new ();
gtk_notebook_set_show_tabs(GTK_NOTEBOOK (mguru->notebook),FALSE);
gtk_notebook_set_show_border(GTK_NOTEBOOK (mguru->notebook),FALSE);
}
static void
gnome_mguru_destroy (GtkObject *object)
{
GnomeMGuru *mguru;
g_return_if_fail (object != NULL);
g_return_if_fail (GNOME_IS_MGURU (object));
mguru = GNOME_MGURU (object);
GTK_OBJECT_CLASS (parent_class)->destroy (object);
}
GtkWidget *gnome_mguru_new (gint multiway,
GnomeDialog *dialog,
GtkWidget * graphic){
GtkWidget *mguru;
GList *button_list;
gint i=0;
GtkWidget *buttonbox;
GtkWidget *hbox;
mguru = gtk_type_new (gnome_mguru_get_type ());
GNOME_MGURU(mguru)->multi = multiway;
hbox=gtk_hbox_new(FALSE,0);
gtk_box_pack_start (GTK_BOX(mguru),
hbox,
TRUE, TRUE, 0);
if(!dialog)
gtk_container_border_width (GTK_CONTAINER (hbox), 5);
gtk_widget_show (hbox);
if (graphic) {
GtkWidget* frame;
frame = gtk_frame_new(NULL);
gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_IN);
gtk_widget_show (frame);
gtk_container_add(GTK_CONTAINER(frame),
graphic);
gtk_widget_show (graphic);
gtk_box_pack_start (GTK_BOX(hbox),
frame,
FALSE, FALSE, 0);
}
gtk_box_pack_start (GTK_BOX(hbox),
GNOME_MGURU(mguru)->notebook,
TRUE, TRUE, 0);
gtk_widget_show (GNOME_MGURU(mguru)->notebook);
if(dialog){
GNOME_MGURU(mguru)->dialog = GTK_WIDGET(dialog);
gnome_dialog_append_buttons (GNOME_DIALOG (dialog),
GNOME_STOCK_BUTTON_CANCEL,
GNOME_STOCK_BUTTON_PREV,
GNOME_STOCK_BUTTON_NEXT,
GNOME_STOCK_BUTTON_APPLY,
NULL);
button_list = GNOME_DIALOG(dialog)->buttons;
while(button_list){
GNOME_MGURU(mguru)->button[i] = GTK_WIDGET(button_list->data);
gtk_signal_connect(GTK_OBJECT(GNOME_MGURU(mguru)->button[i]),
"clicked",
GTK_SIGNAL_FUNC(mguru_clicked_cb),
mguru);
button_list = button_list->next;
i++;
}
gtk_box_pack_start(GTK_BOX(GNOME_DIALOG(dialog)->vbox),
mguru, TRUE, TRUE, 0);
}
else{
buttonbox = gtk_hbutton_box_new();
gtk_container_set_border_width(GTK_CONTAINER(buttonbox),
GNOME_PAD_SMALL);
gtk_box_pack_end(GTK_BOX(mguru),
buttonbox,
FALSE, FALSE, 0);
GNOME_MGURU(mguru)->button[MGURU_BUTTON_CANCEL] = gnome_stock_button(GNOME_STOCK_BUTTON_CANCEL);
GNOME_MGURU(mguru)->button[MGURU_BUTTON_PREV] = gnome_stock_button(GNOME_STOCK_BUTTON_PREV);
GNOME_MGURU(mguru)->button[MGURU_BUTTON_NEXT] = gnome_stock_button(GNOME_STOCK_BUTTON_NEXT);
GNOME_MGURU(mguru)->button[MGURU_BUTTON_APPLY] = gnome_stock_button(GNOME_STOCK_BUTTON_APPLY);
for(i=0;i < MGURU_LAST_BUTTON; i++){
gtk_box_pack_start(GTK_BOX(buttonbox),
GNOME_MGURU(mguru)->button[i],
FALSE, FALSE, 0);
gtk_signal_connect(GTK_OBJECT(GNOME_MGURU(mguru)->button[i]),
"clicked",
GTK_SIGNAL_FUNC(mguru_clicked_cb),
mguru);
}
gtk_widget_show_all(buttonbox);
}
return mguru;
}
static void
mguru_clicked_cb(GtkWidget *widget, gpointer guru){
gint page;
gint butt;
GnomeMGuru *mguru;
mguru = GNOME_MGURU (guru);
page=gnome_mguru_get_page(mguru);
for(butt = 3; butt >= 0; butt--)
if(mguru->button[butt] == widget)
break;
gtk_widget_ref(GTK_WIDGET(mguru));
if(butt == 0)
gtk_signal_emit (GTK_OBJECT (mguru),
mguru_signals[CANCEL],
page);
if(butt == 1)
gtk_signal_emit (GTK_OBJECT (mguru),
mguru_signals[PREV],
page);
if(butt == 2)
gtk_signal_emit (GTK_OBJECT (mguru),
mguru_signals[NEXT],
page);
if(butt == 3)
gtk_signal_emit (GTK_OBJECT (mguru),
mguru_signals[APPLY],
page);
gtk_signal_emit (GTK_OBJECT (mguru),
mguru_signals[MGURU_CLICK],
page,
butt);
if(!mguru->multi){
switch(butt){
case 1:
gnome_mguru_prev_page(mguru);
break;
case 2:
gnome_mguru_next_page(mguru);
break;
}
}
gtk_widget_unref(GTK_WIDGET(mguru));
return;
}
gint gnome_mguru_append_page (GnomeMGuru *mguru,
GtkWidget *child,
gchar *title){
GtkWidget *frame;
g_return_val_if_fail (mguru != NULL, -1);
g_return_val_if_fail (GNOME_IS_MGURU (mguru), -1);
g_return_val_if_fail (child != NULL, -1);
g_return_val_if_fail (GTK_IS_WIDGET (child), -1);
frame = gtk_frame_new (title);
gtk_container_border_width (GTK_CONTAINER (frame), 10);
gtk_notebook_append_page (GTK_NOTEBOOK (mguru->notebook),
frame, NULL);
gtk_widget_show (frame);
gtk_container_add (GTK_CONTAINER (frame), child);
if(!mguru->multi)
gnome_mguru_auto_state(mguru);
return g_list_length (
GTK_NOTEBOOK(mguru->notebook)->children) - 1;
}
void gnome_mguru_set_page(GnomeMGuru *mguru, gint page){
g_return_if_fail (mguru != NULL);
g_return_if_fail (GNOME_IS_MGURU (mguru));
gtk_notebook_set_page(GTK_NOTEBOOK(mguru->notebook),page);
if(!mguru->multi)
gnome_mguru_auto_state(mguru);
return;
}
gint gnome_mguru_get_page(GnomeMGuru *mguru){
g_return_val_if_fail (mguru != NULL, -1);
g_return_val_if_fail (GNOME_IS_MGURU (mguru), -1);
return gtk_notebook_get_current_page(GTK_NOTEBOOK(mguru->notebook));
}
GtkWidget *gnome_mguru_get_page_child(GnomeMGuru *mguru, gint page){
GtkWidget *frame;
g_return_val_if_fail (mguru != NULL, NULL);
g_return_val_if_fail (GNOME_IS_MGURU (mguru), NULL);
frame = gtk_notebook_get_nth_page(GTK_NOTEBOOK(mguru->notebook),page);
return GTK_BIN(frame)->child;
}
void gnome_mguru_next_page(GnomeMGuru *mguru){
g_return_if_fail (mguru != NULL);
g_return_if_fail (GNOME_IS_MGURU (mguru));
gtk_notebook_next_page(GTK_NOTEBOOK(mguru->notebook));
if(!mguru->multi)
gnome_mguru_auto_state(mguru);
return;
}
void gnome_mguru_prev_page(GnomeMGuru *mguru){
g_return_if_fail (mguru != NULL);
g_return_if_fail (GNOME_IS_MGURU (mguru));
gtk_notebook_prev_page(GTK_NOTEBOOK(mguru->notebook));
if(!mguru->multi)
gnome_mguru_auto_state(mguru);
return;
}
void gnome_mguru_set_state(GnomeMGuru *mguru, GnomeMGuruState state){
g_return_if_fail (mguru != NULL);
g_return_if_fail (GNOME_IS_MGURU (mguru));
switch(state){
case GNOME_MGURU_START:
gtk_widget_set_sensitive(mguru->button[1],FALSE);
gtk_widget_set_sensitive(mguru->button[2],TRUE);
gtk_widget_set_sensitive(mguru->button[3],FALSE);
break;
case GNOME_MGURU_MIDDLE:
gtk_widget_set_sensitive(mguru->button[1],TRUE);
gtk_widget_set_sensitive(mguru->button[2],TRUE);
gtk_widget_set_sensitive(mguru->button[3],FALSE);
break;
case GNOME_MGURU_LAST:
gtk_widget_set_sensitive(mguru->button[1],TRUE);
gtk_widget_set_sensitive(mguru->button[2],FALSE);
gtk_widget_set_sensitive(mguru->button[3],TRUE);
break;
case GNOME_MGURU_ONLY:
gtk_widget_set_sensitive(mguru->button[1],FALSE);
gtk_widget_set_sensitive(mguru->button[2],FALSE);
gtk_widget_set_sensitive(mguru->button[3],TRUE);
break;
}
mguru->state=state;
}
void gnome_mguru_auto_state(GnomeMGuru *mguru){
int length;
int current;
length = g_list_length (GTK_NOTEBOOK(mguru->notebook)->children);
if(!length)
return;
if(length == 1){
gnome_mguru_set_state(mguru,GNOME_MGURU_ONLY);
return;
}
current = gnome_mguru_get_page(mguru);
if(current < 1)
gnome_mguru_set_state(mguru,GNOME_MGURU_START);
else if(current == length-1)
gnome_mguru_set_state(mguru,GNOME_MGURU_LAST);
else
gnome_mguru_set_state(mguru,GNOME_MGURU_MIDDLE);
return;
}
syntax highlighted by Code2HTML, v. 0.9.1