/* 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 #include "choicebox.h" enum { CHOICE_MADE, LAST_SIGNAL }; typedef void (*GnomeChoiceBoxSignal) (GtkObject *object, gpointer data); static void gnome_choice_box_class_init (GnomeChoiceBoxClass *klass); static void gnome_choice_box_init (GnomeChoiceBox *choicebox); static void gnome_choice_box_marshal_signal (GtkObject *object, GtkSignalFunc func, gpointer func_data, GtkArg *args); static void gnome_choice_box_destroy (GtkObject *object); static void choice_box_toggled_cb (GtkWidget *radio, gpointer choicebox); static GtkVBoxClass *parent_class = NULL; static gint choice_box_signals [LAST_SIGNAL] = { 0 }; guint gnome_choice_box_get_type (void) { static guint choice_box_type = 0; if (!choice_box_type){ GtkTypeInfo choice_box_info = { "GnomeChoiceBox", sizeof (GnomeChoiceBox), sizeof (GnomeChoiceBoxClass), (GtkClassInitFunc) gnome_choice_box_class_init, (GtkObjectInitFunc) gnome_choice_box_init, (GtkArgSetFunc) NULL, (GtkArgGetFunc) NULL }; choice_box_type = gtk_type_unique (gtk_vbox_get_type (), &choice_box_info); } return choice_box_type; } static void gnome_choice_box_class_init (GnomeChoiceBoxClass *klass) { GtkObjectClass *object_class; GtkWidgetClass *widget_class; object_class = (GtkObjectClass*) klass; widget_class = (GtkWidgetClass*) klass; object_class->destroy = gnome_choice_box_destroy; parent_class = gtk_type_class (gtk_vbox_get_type ()); choice_box_signals[CHOICE_MADE] = gtk_signal_new ("choice_made", GTK_RUN_LAST, object_class->type, GTK_SIGNAL_OFFSET (GnomeChoiceBoxClass, choice_made), gnome_choice_box_marshal_signal, GTK_TYPE_NONE,0); gtk_object_class_add_signals (object_class, choice_box_signals, LAST_SIGNAL); klass->choice_made = NULL; } static void gnome_choice_box_marshal_signal (GtkObject *object, GtkSignalFunc func, gpointer func_data, GtkArg *args) { GnomeChoiceBoxSignal rfunc; rfunc = (GnomeChoiceBoxSignal) func; (* rfunc) (object, func_data); } static void gnome_choice_box_init (GnomeChoiceBox *choicebox) { choicebox->group=NULL; choicebox->choices=0; } static void gnome_choice_box_destroy (GtkObject *object) { GnomeChoiceBox *choicebox; g_return_if_fail (object != NULL); g_return_if_fail (GNOME_IS_CHOICE_BOX(object)); choicebox = GNOME_CHOICE_BOX(object); GTK_OBJECT_CLASS (parent_class)->destroy (object); } GtkWidget *gnome_choice_box_prep (GtkWidget *choicebox, ChoiceBoxLayout layout, gchar *question){ GtkWidget *hbox; GtkWidget *vbox; GtkWidget *label=NULL; if(question){ label = gtk_label_new(question); gtk_label_set_justify(GTK_LABEL(label),GTK_JUSTIFY_LEFT); } switch(layout){ case CHOICE_BOX_VV: if(question){ gtk_box_pack_start (GTK_BOX (choicebox), label, TRUE, TRUE, GNOME_PAD_SMALL); gtk_widget_show (label); } return choicebox; break; case CHOICE_BOX_VH: if(question){ gtk_box_pack_start (GTK_BOX (choicebox), label, TRUE, TRUE, GNOME_PAD_SMALL); gtk_widget_show (label); } hbox=gtk_hbox_new(FALSE,0); gtk_box_pack_start (GTK_BOX (choicebox), hbox, TRUE, TRUE, GNOME_PAD_SMALL); gtk_widget_show (hbox); return hbox; break; case CHOICE_BOX_HV: if(question){ gtk_label_set_line_wrap(GTK_LABEL(label),TRUE); hbox=gtk_hbox_new(FALSE,0); gtk_box_pack_start (GTK_BOX (choicebox), hbox, TRUE, TRUE, 0); gtk_widget_show (hbox); gtk_box_pack_start (GTK_BOX (hbox), label, TRUE, TRUE, GNOME_PAD_SMALL); gtk_widget_show (label); vbox=gtk_vbox_new(FALSE,0); gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, GNOME_PAD_SMALL); gtk_widget_show (vbox); return vbox; } else return choicebox; break; case CHOICE_BOX_HH: hbox=gtk_hbox_new(FALSE,0); gtk_box_pack_start (GTK_BOX (choicebox), hbox, TRUE, TRUE, 0); gtk_widget_show (hbox); if(question){ gtk_box_pack_start (GTK_BOX (hbox), label, TRUE, TRUE, GNOME_PAD_SMALL); gtk_widget_show (label); } return hbox; break; default: if(question){ gtk_box_pack_start (GTK_BOX (choicebox), label, TRUE, TRUE, GNOME_PAD_SMALL); gtk_widget_show (label); } return choicebox; break; } return choicebox; } GtkWidget *gnome_choice_box_new (ChoiceBoxLayout layout, gchar *question,...){ GtkWidget *choicebox; GtkWidget *box; GtkWidget *radio; gchar *s; va_list ap; choicebox = gtk_type_new (gnome_choice_box_get_type ()); box = gnome_choice_box_prep(choicebox,layout,question); va_start(ap,question); while( (s=va_arg(ap,gchar *)) ){ radio = gtk_radio_button_new_with_label(GNOME_CHOICE_BOX(choicebox)->group,s); gtk_box_pack_start (GTK_BOX (box), radio, TRUE, TRUE, GNOME_PAD_SMALL ); gtk_signal_connect(GTK_OBJECT(radio), "clicked", GTK_SIGNAL_FUNC(choice_box_toggled_cb), choicebox); gtk_widget_show (radio); GNOME_CHOICE_BOX(choicebox)->group = gtk_radio_button_group (GTK_RADIO_BUTTON (radio)); GNOME_CHOICE_BOX(choicebox)->choices++; } va_end(ap); return choicebox; } GtkWidget *gnome_choice_box_newv (ChoiceBoxLayout layout, gchar *question, gchar **options){ GtkWidget *choicebox; GtkWidget *box; GtkWidget *radio; gchar **s; choicebox = gtk_type_new (gnome_choice_box_get_type ()); box = gnome_choice_box_prep(choicebox,layout,question); for(s=options;*s;s++){ radio = gtk_radio_button_new_with_label(GNOME_CHOICE_BOX(choicebox)->group,*s); gtk_box_pack_start (GTK_BOX (box), radio, TRUE, TRUE, GNOME_PAD_SMALL ); gtk_signal_connect(GTK_OBJECT(radio), "clicked", GTK_SIGNAL_FUNC(choice_box_toggled_cb), choicebox); gtk_widget_show (radio); GNOME_CHOICE_BOX(choicebox)->group = gtk_radio_button_group (GTK_RADIO_BUTTON (radio)); GNOME_CHOICE_BOX(choicebox)->choices++; } return choicebox; } static void choice_box_toggled_cb (GtkWidget *radio, gpointer choicebox){ if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(radio))) gtk_signal_emit (GTK_OBJECT (choicebox), choice_box_signals[CHOICE_MADE]); } gchar *gnome_choice_box_get_choice(GnomeChoiceBox *choicebox){ GSList *list; GtkWidget *label; char *s; g_return_val_if_fail (choicebox != NULL, NULL); g_return_val_if_fail (GNOME_IS_CHOICE_BOX (choicebox), NULL); list=choicebox->group; while(list){ if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(list->data))){ label = GTK_BIN(list->data)->child; gtk_label_get(GTK_LABEL(label),&s); return s; } list=list->next; } return NULL; } gint gnome_choice_box_get_index(GnomeChoiceBox *choicebox){ gint i; GSList *list; g_return_val_if_fail (choicebox != NULL, -1); g_return_val_if_fail (GNOME_IS_CHOICE_BOX (choicebox), -1); list=choicebox->group; i=choicebox->choices-1; while(list){ if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(list->data))){ return i; } list=list->next; i--; } return -1; } gint gnome_choice_box_set_choice(GnomeChoiceBox *choicebox, gchar *choice){ return -1;} gint gnome_choice_box_set_index(GnomeChoiceBox *choicebox, gint index){ int i; GSList *list; g_return_val_if_fail (choicebox != NULL, -1); g_return_val_if_fail (GNOME_IS_CHOICE_BOX (choicebox), -1); list=choicebox->group; i=(choicebox->choices-1)-index; if(i<0) return -1; for(;list->next && i>0;i--) list=list->next; gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(list->data),TRUE); return index; }