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

}

    
  


syntax highlighted by Code2HTML, v. 0.9.1