/******************************************************************************
*		       							      *
* gnome/prefs.c (part of rcalc)					       	      *
* Copyright (C) 2000, 2001 Free Software Foundation, Inc.		      *
*								       	      *
* This program is free software; you can redistribute it and/or modify 	      *
* it under the terms of the GNU General Public License as published by 	      *
* the Free Software Foundation; either version 2 of the License, 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 General Public License for more details.			       	      *
*								       	      *
* You should have received a copy of the GNU General Public License    	      *
* along with this program; if not, write to the Free Software	       	      *
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.	       	      *
*								       	      *
******************************************************************************/

#ifdef HAVE_CONFIG_H
#  include <config.h>
#endif

#include "prefs.h"		/* This file's header	     		*/
#include <engine/debug.h>	/* Debugging functions			*/

/*****************************************************************************/

/* Structure to hold pointers to all important widgets in a prefs window.
*/
typedef struct _RcPrefsBox RcPrefsBox;

struct _RcPrefsBox
{
	GtkWidget *scrollbar_pos;	/*  Scrollbar position		*/
	GtkWidget *scrollback_spin;	/*  Scrollback lines		*/
	GtkWidget *scroll_on_key_check;	/*  Scroll on keystroke		*/
	GtkWidget *scroll_on_out_check;	/*  Scroll on output		*/
	GtkWidget *blink_check;		/*  Blinking cursor		*/
	GtkWidget *silence_bell_check;	/*  Silence bell		*/
	GtkWidget *font_picker;		/*  Font			*/

	GtkWidget *colour[_RC_NUMBER_OF_COLOURS];
					/*  Colour selectors.		*/
};

/* Names for the entries in RcScrollbarPos and RcColour.
*/
static gchar *scrollbar_positions[_RC_NUMBER_OF_SCROLLBAR_POSES] =
{
	/* Preferences | Behaviour | Scrollbar on left */
	N_("Left"),
	/* Preferences | Behaviour | Scrollbar on right */
	N_("Right"),
	/* Preferences | Behaviour | Scrollbar hidden */
	N_("Hidden"),
};
static gchar *colour_names[_RC_NUMBER_OF_COLOURS] =
{
	/* Preferences | Appearance | Foreground colour selector */
	N_("Foreground color"),
	/* Preferences | Appearance | Background colour selector */
	N_("Background color"),
	/* Preferences | Appearance | Prompt colour selector */
	N_("Prompt color"),
	/* Preferences | Appearance | Error colour selector */
	N_("Error color"),
};

/*****************************************************************************/

/* Apply the settings from the preferences box to the RcGnomeUiConfig,
** and then apply the changes to the item they refer to.
*/
static void apply_changes( GtkWidget *caller, gint page, GtkWidget *dialog )
{
	RcGnomeUiCfg	 *config;
	RcPrefsBox	 *prefs;
	RcApplyConfigFunc apply;
	gpointer	  apply_to;

	GtkWidget *menu,*item;
	RcColour colour;

	rc_debug( RC_DBG_GNOMEUI, "%s(%d)", __FUNCTION__, page );
	g_assert( dialog );
	if( page == -1 ) return;

	config	 = gtk_object_get_data( GTK_OBJECT(dialog), "config" );
	prefs	 = gtk_object_get_data( GTK_OBJECT(dialog), "prefs" );
	apply    = gtk_object_get_data( GTK_OBJECT(dialog), "apply_func" );
	apply_to = gtk_object_get_data( GTK_OBJECT(dialog), "apply_to" );

	g_assert( config );
	g_assert( prefs );
	g_assert( apply );
	g_assert( apply_to );
	
	
	/* Gather the Behaviour preferences.
	*/
	menu = GTK_OPTION_MENU(prefs->scrollbar_pos)->menu;
	item = gtk_menu_get_active( GTK_MENU(menu) );

	rcg_conf_set_scrollbar_pos(
		config, g_list_index( GTK_MENU_SHELL(menu)->children, item ) );
	rcg_conf_set_scrollback(
		config,	gtk_spin_button_get_value_as_int(
				GTK_SPIN_BUTTON(prefs->scrollback_spin) ) );
	rcg_conf_set_scroll_on_key(
		config, GTK_TOGGLE_BUTTON(prefs->scroll_on_key_check)->active );
	rcg_conf_set_scroll_on_out(
		config, GTK_TOGGLE_BUTTON(prefs->scroll_on_out_check)->active );
	rcg_conf_set_blink(
		config, GTK_TOGGLE_BUTTON(prefs->blink_check)->active );
	rcg_conf_set_bell(
		config, !GTK_TOGGLE_BUTTON(prefs->silence_bell_check)->active );

	/* Gather the Appearance preferences.
	*/
	rcg_conf_set_font_name(
		config, gnome_font_picker_get_font_name(
				GNOME_FONT_PICKER(prefs->font_picker) ) );
				
	for( colour=0; colour<_RC_NUMBER_OF_COLOURS; colour++ )
	{
		gushort regs[3];

		gnome_color_picker_get_i16(
			GNOME_COLOR_PICKER(prefs->colour[colour]),
			&regs[0], &regs[1], &regs[2], NULL );

		rcg_conf_set_colour( config, colour, regs );
	}

	/* Apply the preferences to whatever they refer to.
	*/
	apply( dialog, apply_to );
}

/* Display help for the preferences box.
*/
static void display_help( GtkWidget *caller, gint page, GtkWidget *dialog )
{
   gnome_help_display( "index.html", "#use_config", NULL );
	rc_debug( RC_DBG_GNOMEUI, "%s()", __FUNCTION__ );
}

/* The user has changed some property.
*/
static void property_changed( GtkWidget *caller, GtkWidget *dialog )
{
	rc_debug( RC_DBG_GNOMEUI, "%s()", __FUNCTION__ );

	gnome_property_box_changed( GNOME_PROPERTY_BOX(dialog) );
}

/* The user has changed a font property.
*/
static void font_property_changed( GtkWidget *caller,
				   guchar *name,
				   GtkWidget *dialog )
{
	rc_debug( RC_DBG_GNOMEUI, "%s()", __FUNCTION__ );

	property_changed( caller, dialog );
}

/* The user has changed a colour property.
*/
static void colour_property_changed( GtkWidget *caller,
				     guint r, guint g, guint b, guint a,
				     GtkWidget *dialog )
{
	rc_debug( RC_DBG_GNOMEUI, "%s()", __FUNCTION__ );

	property_changed( caller, dialog );
}

/*****************************************************************************/

/* Build and run the preferences window.
*/
GtkWidget* rcg_prefs( RcGnomeUiCfg	*config,
			     RcApplyConfigFunc	 apply_func,
			     gpointer		 apply_func_data )
{
	RcPrefsBox	*prefs;
	GtkWidget	*dialog;
	GtkWidget	*table,*label,*menu;
	GtkObject	*adj;
	RcScrollbarPos	 scroll_pos;
	RcColour	 colour;
	
	GtkWidget	*fontsel;

	g_assert( config );
	g_assert( apply_func );
	g_assert( apply_func_data );

	prefs = g_new0( RcPrefsBox, 1 );
	
	dialog = gnome_property_box_new();
	gtk_window_set_title(
		GTK_WINDOW(dialog), PACKAGE );
	gtk_signal_connect(
		GTK_OBJECT(dialog), "apply",
		GTK_SIGNAL_FUNC(apply_changes), dialog );
	/* The destroy event is handled by the caller */
	gtk_signal_connect(
		GTK_OBJECT(dialog), "help",
		GTK_SIGNAL_FUNC(display_help), dialog );

	gtk_object_set_data( GTK_OBJECT(dialog), "config", config );
	gtk_object_set_data( GTK_OBJECT(dialog), "prefs", prefs );
	gtk_object_set_data( GTK_OBJECT(dialog), "apply_func", apply_func );
	gtk_object_set_data( GTK_OBJECT(dialog), "apply_to", apply_func_data );
	
	/* BEHAVIOUR PAGE */
	table = gtk_table_new( 6, 2, FALSE );
	gnome_property_box_append_page(
		GNOME_PROPERTY_BOX(dialog), table,
		/* Preferences | Behaviour */
		gtk_label_new (_("Behavior")));

	/* Preferences | Behaviour | Scrollbar position selector */
	label = gtk_label_new( _("Scrollbar position") );
	gtk_misc_set_alignment( GTK_MISC(label), 1.0, 0.5 );
	gtk_table_attach(
		GTK_TABLE(table), label, 1, 2, 1, 2,
		GTK_FILL, 0, GNOME_PAD, GNOME_PAD );

	prefs->scrollbar_pos = gtk_option_menu_new ();
	menu = gtk_menu_new ();
	for( scroll_pos=0;scroll_pos<_RC_NUMBER_OF_SCROLLBAR_POSES;scroll_pos++ )
	{
		GtkWidget *entry;
		entry = gtk_menu_item_new_with_label(
			_(scrollbar_positions[scroll_pos]) );
		gtk_widget_show( entry );
		gtk_menu_append( GTK_MENU(menu), entry );
	}
	gtk_option_menu_set_menu( GTK_OPTION_MENU(prefs->scrollbar_pos), menu );
	gtk_option_menu_set_history(
		GTK_OPTION_MENU(prefs->scrollbar_pos),
		rcg_conf_get_scrollbar_pos(config) );
	gtk_signal_connect(
		GTK_OBJECT(menu), "deactivate",
		GTK_SIGNAL_FUNC(property_changed), dialog );
	gtk_table_attach(
		GTK_TABLE(table), prefs->scrollbar_pos, 2, 3, 1, 2,
		GTK_FILL, 0, GNOME_PAD, GNOME_PAD );
	
	/* Preferences | Behaviour | Number of scrollback lines */
	label = gtk_label_new( _("Scrollback lines") );
	gtk_misc_set_alignment( GTK_MISC(label), 1.0, 0.5 );
	gtk_table_attach(
		GTK_TABLE(table), label, 1, 2, 2, 3,
		GTK_FILL, 0, GNOME_PAD, GNOME_PAD );

	adj = gtk_adjustment_new(
		(gfloat)rcg_conf_get_scrollback(config),
		1.0, 100000.0, 1.0, 5.0, 0.0 );
	prefs->scrollback_spin = gtk_spin_button_new(
		GTK_ADJUSTMENT(adj), 0, 0 );
	gtk_signal_connect(
		GTK_OBJECT(prefs->scrollback_spin), "changed",
		GTK_SIGNAL_FUNC(property_changed), dialog );
	gnome_dialog_editable_enters(
		GNOME_DIALOG(dialog),
		GTK_EDITABLE(prefs->scrollback_spin) );
	gtk_table_attach(
		GTK_TABLE(table), prefs->scrollback_spin, 2, 3, 2, 3,
		GTK_FILL, 0, GNOME_PAD, GNOME_PAD );

	/* Scroll on keystroke? */
	prefs->scroll_on_key_check = gtk_check_button_new_with_label(
		/* Preferences | Behaviour | Scroll on keystroke checkbox */
		_("Scroll on keystroke"));
	gtk_toggle_button_set_active(
		GTK_TOGGLE_BUTTON(prefs->scroll_on_key_check),
		rcg_conf_get_scroll_on_key(config) );
	gtk_signal_connect(
		GTK_OBJECT(prefs->scroll_on_key_check), "toggled",
		GTK_SIGNAL_FUNC(property_changed), dialog );
	gtk_table_attach(
		GTK_TABLE(table), prefs->scroll_on_key_check, 2, 3, 3, 4, 
		GTK_FILL, 0, GNOME_PAD, GNOME_PAD );

	/* Scroll on output? */
	prefs->scroll_on_out_check = gtk_check_button_new_with_label(
		/* Preferences | Behaviour | Scroll on output checkbox */
		_("Scroll on output"));
	gtk_toggle_button_set_active(
		GTK_TOGGLE_BUTTON(prefs->scroll_on_out_check),
		rcg_conf_get_scroll_on_out(config) );
	gtk_signal_connect(
		GTK_OBJECT(prefs->scroll_on_out_check), "toggled",
		GTK_SIGNAL_FUNC(property_changed), dialog );
	gtk_table_attach(
		GTK_TABLE(table), prefs->scroll_on_out_check, 2, 3, 4, 5, 
		GTK_FILL, 0, GNOME_PAD, GNOME_PAD );

	/* Blinking cursor? */
	prefs->blink_check = gtk_check_button_new_with_label(
		/* Preferences | Behaviour | Blinking cursor checkbox */
		_("Blinking cursor"));
	gtk_toggle_button_set_active(
		GTK_TOGGLE_BUTTON(prefs->blink_check),
		rcg_conf_get_blink(config) );
	gtk_signal_connect(
		GTK_OBJECT(prefs->blink_check), "toggled",
		GTK_SIGNAL_FUNC(property_changed), dialog );
	gtk_table_attach(
		GTK_TABLE(table), prefs->blink_check, 2, 3, 5, 6, 
		GTK_FILL, 0, GNOME_PAD, GNOME_PAD );

	/* Silence bell? */
	prefs->silence_bell_check = gtk_check_button_new_with_label(
		/* Preferences | Behaviour | Silence bell checkbox */
		_("Silence bell"));
	gtk_toggle_button_set_active(
		GTK_TOGGLE_BUTTON(prefs->silence_bell_check),
		!rcg_conf_get_bell(config) );
	gtk_signal_connect(
		GTK_OBJECT(prefs->silence_bell_check), "toggled",
		GTK_SIGNAL_FUNC(property_changed), dialog );
	gtk_table_attach(
		GTK_TABLE(table), prefs->silence_bell_check, 2, 3, 6, 7, 
		GTK_FILL, 0, GNOME_PAD, GNOME_PAD );

	/* APPEARANCE PAGE
	*/
	table = gtk_table_new( 5, 2, FALSE );
	gnome_property_box_append_page(
		GNOME_PROPERTY_BOX(dialog), table,
		/* Preferences | Appearance */
		gtk_label_new (_("Appearance")));

	/* Preferences | Appearance | Font selector */
	label = gtk_label_new( _("Font") );
	gtk_misc_set_alignment( GTK_MISC(label), 1.0, 0.5 );
	gtk_table_attach(
		GTK_TABLE(table), label, 1, 2, 1, 2,
		GTK_FILL, 0, GNOME_PAD, GNOME_PAD );

	prefs->font_picker = gnome_font_picker_new();
	gnome_font_picker_set_mode(
		GNOME_FONT_PICKER(prefs->font_picker),
		GNOME_FONT_PICKER_MODE_FONT_INFO );
	gnome_font_picker_fi_set_show_size(
		GNOME_FONT_PICKER(prefs->font_picker), TRUE );
	gnome_font_picker_set_font_name(
		GNOME_FONT_PICKER(prefs->font_picker),
		rcg_conf_get_font_name( config ) );
	gtk_signal_connect(
		GTK_OBJECT(prefs->font_picker), "font_set",
		GTK_SIGNAL_FUNC(font_property_changed), dialog );
	gtk_table_attach(
		GTK_TABLE(table), prefs->font_picker, 2, 3, 1, 2,
		GTK_FILL, 0, GNOME_PAD, GNOME_PAD );

	/* Colour selectors
	*/
	for( colour=0; colour<_RC_NUMBER_OF_COLOURS; colour++ )
	{
		const gushort *regs;
		
		label = gtk_label_new( _(colour_names[colour]) );
		gtk_misc_set_alignment( GTK_MISC(label), 1.0, 0.5 );
		gtk_table_attach(
			GTK_TABLE(table), label,
			1, 2, 2+colour, 3+colour,
			GTK_FILL, 0, GNOME_PAD, GNOME_PAD );

		prefs->colour[colour] = gnome_color_picker_new();
		regs = rcg_conf_get_colour( config, colour );
		gnome_color_picker_set_i16(
			GNOME_COLOR_PICKER(prefs->colour[colour]),
			regs[0], regs[1], regs[2], 0 );
		gtk_signal_connect(
			GTK_OBJECT(prefs->colour[colour]), "color_set",
			GTK_SIGNAL_FUNC(colour_property_changed), dialog );
		gtk_table_attach(
			GTK_TABLE(table), prefs->colour[colour],
			2, 3, 2+colour, 3+colour,
			0, 0, GNOME_PAD, GNOME_PAD );
	}

	return dialog;
}

/*** end of gnome/prefs.c ****************************************************/
