/*
** 1998-08-14 -	Configure styles, e.g. things such as back- & foreground colors, icons, and
**		actions. This might become involved.
** 1998-08-23 -	Did lots of work. Now you can actually add and delete styles. Got involved.
** 1998-08-24 -	Completed a first version, fixed plenty of bugs too...
** 1998-08-26 -	Added fun "Copy" button group for visual properties. Also added a deselect
**		signal handler for root style. Oops.
** 1998-08-30 -	Now uses the ico_get_all() function to retrieve a list of all icon file names.
**		Added three (!) forgotten modified-sets. Damn.
** 1998-09-02 -	Added action property configuration, and cleaned up their save/load handling.
** 1998-09-16 -	Made some optimizations, mainly in set_preview() (one more signal blocker).
** 1998-09-27 -	Now uses the brand new cmdseq_dialog for choosing actions. Works fine.
** 1999-03-05 -	Due to new selection handling, we no longer have control over how selected items
**		look. That got rid of some code.
** 1999-03-13 -	Rewrote the dialog module (from scratch), which lead to some changes here too.
** 1999-05-07 -	Now uses the (new) color dialog module. Got rid of lots of crufty code.
*/

#include "gentoo.h"

#include "styles.h"
#include "types.h"
#include "dirpane.h"
#include "dialog.h"
#include "iconutil.h"
#include "strutil.h"
#include "fileutil.h"
#include "xmlutil.h"
#include "guiutil.h"
#include "style_dialog.h"
#include "cmdseq_dialog.h"
#include "color_dialog.h"
#include "icon_dialog.h"

#include "cfg_gui.h"
#include "cfg_module.h"
#include "cfg_paths.h"		/* For cpt_get_path(). */
#include "cfg_types.h"		/* For ctp_get_types(). */
#include "cfg_cmdseq.h"		/* For ccs_get_current(). */

#include "cfg_styles.h"

#define	NODE	"FileStyles"

/* ----------------------------------------------------------------------------------------- */

typedef struct {			/* Visual properties notebook page. */
	GtkWidget	*vbox;
	GtkWidget	*preview;	/* CList showing preview of style (old-school!). */
	GtkWidget	*override[3];	/* Override check buttons for back- & foreground colors, plus icon. */
	GtkWidget	*edit[3];	/* The "edit" (or "pick") command buttons. */
} PVisual;

typedef struct {			/* Action properties notebook page. */
	GtkWidget	*vbox;
	GtkWidget	*actions;	/* List of properties in current style (both local and inherited). */
	GtkWidget	*aname;		/* Entry widget for editing name of an action. */
	GtkWidget	*acmdseq;	/* Entry for command sequence name. */
	GtkWidget	*acmdpick;	/* Pick button for cmdseq. */
	GtkWidget	*adel;		/* Delete (or override) command button. */
} PAction;

typedef struct {
	GtkWidget	*vbox;
	GtkWidget	*scwin;
	GtkWidget	*tree;		/* Main style tree widget. */

	GtkWidget	*dvbox;		/* Vbox holding definition widgets. */
	GtkWidget	*dname;		/* Name of selected style. */
	GtkWidget	*dparent;	/* Parent of selected style. */
	GtkWidget	*dreparent;	/* Button for reparenting dialog. */

	GtkWidget	*dpnbook;	/* Property notebook. */
	PVisual		dpvisual;
	PAction		dpaction;

	GtkWidget	*del;		/* The style "Delete" button. */

	MainInfo	*min;
	StyleInfo	*si;
	Style		*curr_style;
	GtkWidget	*curr_style_widget;
	const gchar	*curr_prop;	/* Current property, when editing one. */
	gint		curr_arow;	/* Action property clist row. */
	gboolean	modified;
} P_Styles;

static P_Styles	the_page;

/* ----------------------------------------------------------------------------------------- */

static void	cst_update(MainInfo *min);

/* ----------------------------------------------------------------------------------------- */

/* 1999-05-24 -	Set the preview widget(s). */
static void set_widgets_preview(P_Styles *page, Style *stl)
{
	const gchar	*iname;
	const GdkColor	*col;

	if((iname = stl_style_property_get_icon(stl, SPN_ICON_UNSEL)) != NULL)
	{
		GdkPixmap	*ipix;
		GdkBitmap	*imsk;

		if((ipix = ico_icon_get(page->min, page->vbox->window, iname, &imsk)) != NULL)
			gtk_clist_set_pixmap(GTK_CLIST(page->dpvisual.preview), 0, 0, ipix, imsk);
	}
	if((col = stl_style_property_get_color(stl, SPN_COL_UNSEL_BG)) != NULL)
		gtk_clist_set_background(GTK_CLIST(page->dpvisual.preview), 0, (GdkColor *) col);
	if((col = stl_style_property_get_color(stl, SPN_COL_UNSEL_FG)) != NULL)
		gtk_clist_set_foreground(GTK_CLIST(page->dpvisual.preview), 0, (GdkColor *) col);
}

/* 1999-05-24 -	Set action list. */
static void set_widgets_action(P_Styles *page, Style *stl)
{
	GList	*alist;

	gtk_clist_freeze(GTK_CLIST(page->dpaction.actions));
	gtk_clist_clear(GTK_CLIST(page->dpaction.actions));
	if((alist = stl_style_property_get_actions(stl)) != NULL)
	{
		gchar	*rd[2];
		gint	row;
		GList	*iter;

		for(iter = alist; iter != NULL; iter = g_list_next(iter))
		{
			rd[0] = iter->data;
			rd[1] = (gchar *) stl_style_property_get_action(stl, iter->data);
			row = gtk_clist_append(GTK_CLIST(page->dpaction.actions), rd);
		}
		g_list_free(alist);
	}
	gtk_clist_thaw(GTK_CLIST(page->dpaction.actions));
}

/* 1999-05-24 -	Set various editing widgets to display <stl>'s details. */
static void set_widgets(P_Styles *page, Style *stl)
{
	const gchar	*pname, *vpname[] = { SPN_COL_UNSEL_BG, SPN_COL_UNSEL_FG, SPN_ICON_UNSEL };
	gboolean	or;
	guint		i;

	if((page == NULL) || (stl == NULL))
		return;

	gtk_entry_set_text(GTK_ENTRY(page->dname), stl_style_get_name(stl));
	if((pname = stl_style_get_name(stl_styleinfo_style_get_parent(page->si, stl))) != NULL)
		gtk_entry_set_text(GTK_ENTRY(page->dparent), pname);
	else
		gtk_entry_set_text(GTK_ENTRY(page->dparent), "(None)");
	gtk_widget_set_sensitive(page->dreparent, pname != NULL);

	set_widgets_preview(page, stl);
	for(i = 0; i < 3; i++)
	{
		or = stl_style_property_get_override(stl, vpname[i]);
		gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(page->dpvisual.override[i]), or);
		gtk_widget_set_sensitive(page->dpvisual.override[i], pname != NULL);
		gtk_widget_set_sensitive(page->dpvisual.edit[i], or);
	}
	set_widgets_action(page, stl);
	gtk_widget_set_sensitive(page->dvbox, TRUE);
	gtk_widget_set_sensitive(page->del, stl_styleinfo_style_root(page->si) != stl);
}

/* 1999-05-25 -	Reset action editing widgets. */
static void reset_widgets_action(P_Styles *page)
{
	gtk_clist_unselect_all(GTK_CLIST(page->dpaction.actions));
	gtk_entry_set_text(GTK_ENTRY(page->dpaction.aname), "");
	gtk_widget_set_sensitive(page->dpaction.aname, FALSE);
	gtk_entry_set_text(GTK_ENTRY(page->dpaction.acmdseq), "");
	gtk_widget_set_sensitive(page->dpaction.acmdseq, FALSE);
	gtk_widget_set_sensitive(page->dpaction.acmdpick, FALSE);
	gtk_label_set_text(GTK_LABEL(GTK_BIN(page->dpaction.adel)->child), "Delete Action");
	gtk_widget_set_sensitive(page->dpaction.adel, FALSE);
}

/* 1999-05-24 -	Reset widgets. Handy when there is no longer a selection. */
static void reset_widgets(P_Styles *page)
{
	page->curr_style = NULL;
	page->curr_prop  = NULL;
	page->curr_arow  = -1;
	gtk_entry_set_text(GTK_ENTRY(page->dname), "");
	gtk_entry_set_text(GTK_ENTRY(page->dparent), "");
	reset_widgets_action(page);
	gtk_widget_set_sensitive(page->dvbox, FALSE);
	gtk_widget_set_sensitive(page->del, FALSE);
}

/* ----------------------------------------------------------------------------------------- */

/* 1999-05-27 -	This gets called when the user changes the style selection. Nice. */
static void evt_style_selection_changed(GtkWidget *wid, gpointer user)
{
	P_Styles	*page = user;
	GList		*sel;

	if(page != NULL)
	{
		page->curr_style = NULL;
		page->curr_style_widget = NULL;
		if((sel = GTK_TREE_SELECTION(GTK_TREE(wid))) != NULL)
		{
			GtkWidget	*child = sel->data;
			Style		*nc;

			nc = stl_style_get(child);
			set_widgets(page, nc);
			reset_widgets_action(page);
			page->curr_style = nc;
			page->curr_style_widget = child;
		}
		else
			reset_widgets(page);
	}
}

/* 1999-05-24 -	Repopulate the tree. */
static void populate_tree(P_Styles *page)
{
	if(page->tree != NULL)
	{
		GList	*chlist, *iter;

		chlist = gtk_container_children(GTK_CONTAINER(page->scwin));
		for(iter = chlist; iter != NULL; iter = g_list_next(iter))
		{
			gtk_container_remove(GTK_CONTAINER(page->scwin), iter->data);
			gtk_widget_destroy(iter->data);
		}
		g_list_free(chlist);
		page->tree = NULL;
	}
	if(page->si != NULL)
	{
		page->tree = GTK_WIDGET(stl_styleinfo_build(page->si));
		gtk_signal_connect(GTK_OBJECT(page->tree), "selection_changed", evt_style_selection_changed, page);
		gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(page->scwin), page->tree);
		gtk_widget_show(page->tree);
	}
}

/* ----------------------------------------------------------------------------------------- */

/* 1999-05-24 -	Set a new name for the current style. */
static void evt_style_name_changed(GtkWidget *wid, gpointer user)
{
	P_Styles	*page = user;
	const gchar	*name;

	if((page != NULL) && (page->curr_style != NULL) && (name = gtk_entry_get_text(GTK_ENTRY(wid))) != NULL)
	{
		ctp_replace_style(stl_style_get_name(page->curr_style), page->curr_style);
		stl_style_set_name(page->curr_style, name);
		stl_style_set_name_widget(page->curr_style_widget, name);
		page->modified = TRUE;
	}
}

/* 1999-05-24 -	User clicked the details (magnifying glass) button to set new parent for current style. */
static void evt_style_parent_clicked(GtkWidget *wid, gpointer user)
{
	P_Styles	*page = user;
	Style		*np;

	if((np = sdl_dialog(page->si, page->curr_style)) != NULL)	
	{
		stl_styleinfo_style_set_parent(page->si, page->curr_style, np);
		populate_tree(page);
		page->modified = TRUE;
	}
}

/* ----------------------------------------------------------------------------------------- */

/* 1999-05-24 -	User toggled one of the visual property override checkbuttons. Update
**		the current style accordingly.
*/
static void evt_vprop_override_toggled(GtkWidget *wid, gpointer user)
{
	P_Styles	*page = user;

	if((page != NULL) && (page->curr_style != NULL))
	{
		const gchar	*pname;
		gboolean	or;

		pname = gtk_object_get_user_data(GTK_OBJECT(wid));
		or = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(wid));
		if(or)
		{
			if(strcmp(pname, SPN_ICON_UNSEL) == 0)
				stl_style_property_set_icon(page->curr_style, pname, stl_style_property_get_icon(page->curr_style, pname));
			else
				stl_style_property_set_color(page->curr_style, pname, stl_style_property_get_color(page->curr_style, pname));
		}
		else
			stl_style_property_remove(page->curr_style, pname);
		set_widgets(page, page->curr_style);
		page->modified = TRUE;
	}
}

/* 1999-05-24 -	A color property has changed. Update previews and stuff. */
static void evt_vprop_color_changed(GdkColor *color, gpointer user)
{
	P_Styles	*page = user;

	stl_style_property_set_color(page->curr_style, page->curr_prop, color);
	set_widgets(page, page->curr_style);
}

/* 1999-05-24 -	User hit the "Edit..." (or, for the icon, "Pick...") button below override toggle. */
static void evt_vprop_edit_clicked(GtkWidget *wid, gpointer user)
{
	P_Styles	*page = user;

	if((page != NULL) && (page->curr_style != NULL))
	{
		page->curr_prop = gtk_object_get_user_data(GTK_OBJECT(wid));

		if(strcmp(page->curr_prop, SPN_ICON_UNSEL) == 0)
		{
			const gchar	*icon;

			if((icon = idl_dialog(page->min, cpt_get_path(PTID_ICON), NULL,
					  stl_style_property_get_icon(page->curr_style, page->curr_prop), TRUE)) != NULL)
			{
				stl_style_property_set_icon(page->curr_style, page->curr_prop, icon);
				page->modified = TRUE;
				set_widgets(page, page->curr_style);
			}
		}
		else
		{
			const GdkColor	*col;
			GdkColor	initial;

			if((col = stl_style_property_get_color(page->curr_style, page->curr_prop)) != NULL)
				initial = *col;
			if(cdl_dialog("Edit Color", evt_vprop_color_changed, &initial, page) == 1)
				stl_style_property_set_color(page->curr_style, page->curr_prop, &initial);
			else
				page->modified = TRUE;
			set_widgets(page, page->curr_style);
		}
	}
}

/* ----------------------------------------------------------------------------------------- */

/* 1999-05-25 -	Set the label of the action "Delete" button. */
static void action_set_delete_button(P_Styles *page)
{
	gboolean	unique, or;

	unique = stl_style_property_is_unique(page->curr_style, page->curr_prop);
	gtk_label_set_text(GTK_LABEL(GTK_BIN(page->dpaction.adel)->child), unique ? "Delete Action" : "Revert to Inherited Command");
	or = stl_style_property_get_override(page->curr_style, page->curr_prop);
	gtk_entry_set_editable(GTK_ENTRY(page->dpaction.aname), or);
	gtk_widget_set_sensitive(page->dpaction.adel, or);
}

/* 1999-05-25 -	An action property has been selected. Update label on "delete/override" button. */
static void evt_aprop_selected(GtkWidget *wid, gint row, gint column, GdkEventButton *evt, gpointer user)
{
	P_Styles	*page = user;

	if((page != NULL) && (page->curr_style != NULL))
	{
		gchar	*prop;

		page->curr_prop = NULL;
		page->curr_arow = -1;
		gtk_clist_get_text(GTK_CLIST(page->dpaction.actions), row, 0, (gchar **) &prop);
		gtk_entry_set_text(GTK_ENTRY(page->dpaction.aname), prop);
		gtk_widget_set_sensitive(page->dpaction.aname, TRUE);
		gtk_entry_set_text(GTK_ENTRY(page->dpaction.acmdseq), stl_style_property_get_action(page->curr_style, prop));
		/* Force execution of cmdseq_changed() before we set curr_prop & curr_arow. */
		while(gtk_events_pending())
			gtk_main_iteration();
		gtk_widget_set_sensitive(page->dpaction.acmdseq, TRUE);
		gtk_widget_set_sensitive(page->dpaction.acmdpick, TRUE);
		page->curr_prop = prop;
		page->curr_arow = row;
		action_set_delete_button(page);
	}
}

/* 1999-05-25 -	An action was just deselected. Update widgetry. */
static void evt_aprop_unselected(GtkWidget *wid, gint row, gint column, GdkEventButton *evt, gpointer user)
{
	P_Styles	*page = user;

	if((page != NULL) && (page->curr_style != NULL))
	{
		page->curr_prop = NULL;
		page->curr_arow = -1;
		reset_widgets_action(page);
	}
}

/* 1999-05-25 -	Command sequence of current action property changed. Register that. */
static void evt_aprop_cmdseq_changed(GtkWidget *wid, gpointer user)
{
	P_Styles	*page = user;

	if((page != NULL) && (page->curr_style != NULL) && (page->curr_prop != NULL) && (page->curr_arow >= 0))
	{
		const gchar	*text;

		if((text = gtk_entry_get_text(GTK_ENTRY(wid))) != NULL)
		{
			gtk_clist_set_text(GTK_CLIST(page->dpaction.actions), page->curr_arow, 1, text);
			stl_style_property_set_action(page->curr_style, page->curr_prop, text);
			action_set_delete_button(page);
			page->modified = TRUE;
		}
	}
}

/* 1999-05-25 -	User hit the details (mag. glass) button to the right of the Command field. Dialog-time. */
static void evt_aprop_cmdpick_clicked(GtkWidget *wid, gpointer user)
{
	P_Styles	*page = user;

	if((page != NULL) && (page->curr_style != NULL) && (page->curr_prop != NULL) && (page->curr_arow >= 0))
	{
		const gchar	*cmd;

		if((cmd = csq_dialog(page->min, ccs_get_current())) != NULL)
			gtk_entry_set_text(GTK_ENTRY(page->dpaction.acmdseq), cmd);
	}
}

/* 1999-05-25 -	Add a new action property. Pops up a dialog asking for the name. */
static void evt_aprop_add_clicked(GtkWidget *wid, gpointer user)
{
	P_Styles	*page = user;

	if((page != NULL) && (page->curr_style != NULL))
	{
		Dialog		*dlg;
		GtkWidget	*hbox, *label, *entry;

		hbox = gtk_hbox_new(FALSE, 0);
		label = gtk_label_new("Name");
		gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
		gtk_widget_show(label);
		entry = gtk_entry_new_with_max_length(STL_PROPERTY_NAME_MAX - 1);
		gtk_box_pack_start(GTK_BOX(hbox), entry, TRUE, TRUE, 0);
		gtk_widget_show(entry);
		gtk_widget_show(hbox);
		dlg = dlg_dialog(hbox, "New Action Property", "OK|Cancel", NULL, NULL);
		dlg_dialog_set_keep(dlg, TRUE);
		gtk_widget_grab_focus(entry);
		if(dlg_dialog_wait(dlg) == 0)
		{
			const gchar	*name;

			if((name = gtk_entry_get_text(GTK_ENTRY(entry))) != NULL)
			{
				stl_style_property_set_action(page->curr_style, name, "something");
				set_widgets_action(page, page->curr_style);
				reset_widgets_action(page);
				page->modified = TRUE;
			}
		}
		dlg_dialog_destroy(dlg);
	}
}

/* 1999-05-25 -	User clicked the "Delete" (or "Revert...") button. Do it. */
static void evt_aprop_delete_clicked(GtkWidget *wid, gpointer user)
{
	P_Styles	*page = user;

	if((page != NULL) && (page->curr_style != NULL) && (page->curr_prop != NULL) && (page->curr_arow >= 0))
	{
		stl_style_property_remove(page->curr_style, page->curr_prop);
		gtk_clist_unselect_all(GTK_CLIST(page->dpaction.actions));
		set_widgets_action(page, page->curr_style);
		reset_widgets_action(page);
		page->modified = TRUE;
	}
}

/* ----------------------------------------------------------------------------------------- */

/* 1999-05-26 -	Add a new style. Use the currently selected style, if one exists, as parent.
**		If there is no selection, add style with Root as parent.
*/
static void evt_style_add_clicked(GtkWidget *wid, gpointer user)
{
	P_Styles	*page = user;

	if(page != NULL)
	{
		Style		*stl, *pstl;
		GtkWidget	*child;

		stl = stl_style_new_unique_name(page->si);
		if((pstl = page->curr_style) == NULL)
			pstl = stl_styleinfo_style_root(page->si);
		stl_styleinfo_style_add(page->si, pstl, stl);
		populate_tree(page);
		if((child = stl_styleinfo_widget_find(page->si, GTK_TREE(page->tree), stl)) != NULL)
			gtk_tree_select_child(GTK_TREE(page->tree), child);
		gtk_entry_select_region(GTK_ENTRY(page->dname), 0, -1);
		gtk_widget_grab_focus(page->dname);
	}
}

/* 1999-05-27 -	Delete the currently selected style. If the style has children, the user must
**		confirm the operation, since all children will be deleted, too.
*/
static void evt_style_del_clicked(GtkWidget *wid, gpointer user)
{
	P_Styles	*page = user;

	if((page != NULL) && (page->curr_style != NULL))
	{
		gint	ok = 0;

		if(stl_styleinfo_style_has_children(page->si, page->curr_style))
			ok = dlg_dialog_simple_wait("Deleting this style will also delete\nall its children. Are you sure?", "Confirm Delete", "Delete|Cancel");
		if(ok == 0)
		{
			GList	*chlist, *iter;
			Style	*stl;

			stl = stl_styleinfo_style_root(page->si);
			chlist = stl_styleinfo_style_get_children(page->si, page->curr_style, TRUE);
			for(iter = chlist; iter != NULL; iter = g_list_next(iter))
				ctp_replace_style(stl_style_get_name(iter->data), stl);
			g_list_free(chlist);
			stl_styleinfo_style_remove(page->si, page->curr_style);
			populate_tree(page);
			reset_widgets(page);
		}
	}
}

/* ----------------------------------------------------------------------------------------- */

/* 1999-05-22 -	Build the visual property editing widgets. */
static void build_pvisual(P_Styles *page)
{
	PVisual		*pv = &page->dpvisual;
	const gchar	*vplab[] = { "Background Color", "Foreground Color", "Icon" },
			*vpname[] = { SPN_COL_UNSEL_BG, SPN_COL_UNSEL_FG, SPN_ICON_UNSEL };
	gchar		*ctxt[] = { "", "Unselected Style Preview" };
	GtkWidget	*hbox, *frame, *vbox, *label;
	guint		i;

	pv->vbox = gtk_vbox_new(FALSE, 0);
	hbox = gtk_hbox_new(FALSE, 0);
	label = gtk_label_new("Preview");
	gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
	gtk_widget_show(label);
	pv->preview = gtk_clist_new(2);
	gtk_widget_set_name(pv->preview, "cstPreview");
	gtk_clist_set_column_width(GTK_CLIST(pv->preview), 0, 16);
	gtk_clist_append(GTK_CLIST(pv->preview), ctxt);
	gtk_clist_set_selectable(GTK_CLIST(pv->preview), 0, FALSE);
	gtk_box_pack_start(GTK_BOX(hbox), pv->preview, TRUE, TRUE, 0);
	gtk_widget_show(pv->preview);
	gtk_box_pack_start(GTK_BOX(pv->vbox), hbox, FALSE, FALSE, 2);
	gtk_widget_show(hbox);

	hbox = gtk_hbox_new(FALSE, 0);
	for(i = 0; i < 3; i++)
	{
		frame = gtk_frame_new(vplab[i]);
		vbox = gtk_vbox_new(FALSE, 0);
		gtk_container_set_border_width(GTK_CONTAINER(vbox), 5);
		pv->override[i] = gtk_check_button_new_with_label("Override Parent's?");
		gtk_object_set_user_data(GTK_OBJECT(pv->override[i]), (gpointer) vpname[i]);
		gtk_signal_connect(GTK_OBJECT(pv->override[i]), "toggled", GTK_SIGNAL_FUNC(evt_vprop_override_toggled), page);
		gtk_box_pack_start(GTK_BOX(vbox), pv->override[i], FALSE, FALSE, 0);
		gtk_widget_show(pv->override[i]);
		pv->edit[i] = gtk_button_new_with_label(i < 2 ? "Edit..." : "Pick...");
		gtk_object_set_user_data(GTK_OBJECT(pv->edit[i]), (gpointer) vpname[i]);
		gtk_signal_connect(GTK_OBJECT(pv->edit[i]), "clicked", GTK_SIGNAL_FUNC(evt_vprop_edit_clicked), page);
		gtk_box_pack_start(GTK_BOX(vbox), pv->edit[i], FALSE, FALSE, 0);
		gtk_widget_show(pv->edit[i]);
		gtk_container_add(GTK_CONTAINER(frame), vbox);
		gtk_widget_show(vbox);
		gtk_box_pack_start(GTK_BOX(hbox), frame, TRUE, TRUE, 5);
		gtk_widget_show(frame);
	}
	gtk_box_pack_start(GTK_BOX(pv->vbox), hbox, FALSE, FALSE, 0);
	gtk_widget_show(hbox);
}

/* 1999-05-22 -	Build action property editing widgetry. */
static void build_paction(P_Styles *page)
{
	gchar		*at[] = { "Name", "Command" };
	PAction		*pa = &page->dpaction;
	GtkWidget	*hbox, *btn, *table, *label, *scwin;

	pa->vbox = gtk_vbox_new(FALSE, 0);
	scwin = gtk_scrolled_window_new(NULL, NULL);
	gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scwin), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
	pa->actions = gtk_clist_new(2);
	gtk_widget_set_usize(pa->actions, -1, 48);
	gtk_clist_set_column_justification(GTK_CLIST(pa->actions), 0, GTK_JUSTIFY_LEFT);
	gtk_clist_set_column_justification(GTK_CLIST(pa->actions), 1, GTK_JUSTIFY_LEFT);
	gtk_clist_set_column_auto_resize(GTK_CLIST(pa->actions), 0, TRUE);
	gtk_clist_set_column_min_width(GTK_CLIST(pa->actions), 0, 128);
	gtk_clist_set_column_resizeable(GTK_CLIST(pa->actions), 1, FALSE);
	gtk_clist_append(GTK_CLIST(pa->actions), at);
	gtk_clist_append(GTK_CLIST(pa->actions), at);
	gtk_clist_append(GTK_CLIST(pa->actions), at);
	gtk_clist_append(GTK_CLIST(pa->actions), at);
	gtk_clist_append(GTK_CLIST(pa->actions), at);
	gtk_clist_append(GTK_CLIST(pa->actions), at);
	gtk_clist_append(GTK_CLIST(pa->actions), at);
	gtk_clist_append(GTK_CLIST(pa->actions), at);
	gtk_signal_connect(GTK_OBJECT(pa->actions), "select_row", GTK_SIGNAL_FUNC(evt_aprop_selected), page);
	gtk_signal_connect(GTK_OBJECT(pa->actions), "unselect_row", GTK_SIGNAL_FUNC(evt_aprop_unselected), page);
	gtk_container_add(GTK_CONTAINER(scwin), pa->actions);
	gtk_widget_show(pa->actions);
	gtk_box_pack_start(GTK_BOX(pa->vbox), scwin, TRUE, TRUE, 0);
	gtk_widget_show(scwin);

	table = gtk_table_new(2, 3, FALSE);
	label = gtk_label_new("Name");
	gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1,  0,0,0,0);
/*	gtk_widget_show(label);*/
	pa->aname = gtk_entry_new_with_max_length(STL_PROPERTY_NAME_MAX - 1);
	gtk_entry_set_editable(GTK_ENTRY(pa->aname), FALSE);
	gtk_table_attach(GTK_TABLE(table), pa->aname, 1, 3, 0, 1,  GTK_EXPAND|GTK_FILL,0,0,0);
/*	gtk_widget_show(pa->aname);*/
	label = gtk_label_new("Command");
	gtk_table_attach(GTK_TABLE(table), label, 0, 1, 1, 2,  0,0,0,0);
	gtk_widget_show(label);
	pa->acmdseq = gtk_entry_new();
	gtk_signal_connect(GTK_OBJECT(pa->acmdseq), "changed", GTK_SIGNAL_FUNC(evt_aprop_cmdseq_changed), page);
	gtk_table_attach(GTK_TABLE(table), pa->acmdseq, 1, 2, 1, 2,  GTK_EXPAND|GTK_FILL,0,0,0);
	pa->acmdpick = gui_details_button_new(page->min->gui->window->window);
	gtk_signal_connect(GTK_OBJECT(pa->acmdpick), "clicked", GTK_SIGNAL_FUNC(evt_aprop_cmdpick_clicked), page);
	gtk_table_attach(GTK_TABLE(table), pa->acmdpick, 2, 3, 1, 2,  0,0,0,0);
	gtk_widget_show(pa->acmdpick);
	gtk_widget_show(pa->acmdseq);
	gtk_box_pack_start(GTK_BOX(pa->vbox), table, FALSE, FALSE, 0);
	gtk_widget_show(table);

	hbox = gtk_hbox_new(FALSE, 0);
	btn = gtk_button_new_with_label("Add Action...");
	gtk_signal_connect(GTK_OBJECT(btn), "clicked", GTK_SIGNAL_FUNC(evt_aprop_add_clicked), page);
	gtk_box_pack_start(GTK_BOX(hbox), btn, TRUE, TRUE, 5);
	gtk_widget_show(btn);
	pa->adel = gtk_button_new_with_label("Delete Action");
	gtk_signal_connect(GTK_OBJECT(pa->adel), "clicked", GTK_SIGNAL_FUNC(evt_aprop_delete_clicked), page);
	gtk_box_pack_start(GTK_BOX(hbox), pa->adel, TRUE, TRUE, 5);
	gtk_widget_show(pa->adel);
	gtk_box_pack_start(GTK_BOX(pa->vbox), hbox, FALSE, FALSE, 5);
	gtk_widget_show(hbox);
}

/* 1999-05-22 -	Build style configuration GUI page. */
static GtkWidget * cst_init(MainInfo *min, gchar **name)
{
	P_Styles	*page = &the_page;
	GtkWidget	*table, *label, *frame, *hbox, *btn;

	if(name == NULL)
		return NULL;

	*name = "File Styles";

	page->min = min;
	page->si  = NULL;
	page->curr_style = NULL;
	page->modified = FALSE;
	page->tree = NULL;

	page->vbox = gtk_vbox_new(FALSE, 0);
	page->scwin = gtk_scrolled_window_new(FALSE, FALSE);
	gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(page->scwin), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
	gtk_box_pack_start(GTK_BOX(page->vbox), page->scwin, TRUE, TRUE, 0);
	gtk_widget_show(page->scwin);

	page->dvbox = gtk_vbox_new(FALSE, 0);

	table = gtk_table_new(2, 3, FALSE);
	label = gtk_label_new("Name");
	gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1,  0,0,0,0);
	gtk_widget_show(label);
	page->dname = gtk_entry_new_with_max_length(STL_STYLE_NAME_MAX - 1);
	gtk_signal_connect(GTK_OBJECT(page->dname), "changed", GTK_SIGNAL_FUNC(evt_style_name_changed), page);
	gtk_table_attach(GTK_TABLE(table), page->dname, 1, 3, 0, 1,  GTK_EXPAND|GTK_FILL,0,0,0);
	gtk_widget_show(page->dname);
	label = gtk_label_new("Parent");
	gtk_table_attach(GTK_TABLE(table), label, 0, 1, 1, 2,  0,0,0,0);
	gtk_widget_show(label);
	page->dparent = gtk_entry_new_with_max_length(STL_STYLE_NAME_MAX - 1);
	gtk_entry_set_editable(GTK_ENTRY(page->dparent), FALSE);
	gtk_table_attach(GTK_TABLE(table), page->dparent, 1, 2, 1, 2,  GTK_EXPAND|GTK_FILL,0,0,0);
	gtk_widget_show(page->dparent);
	page->dreparent = gui_details_button_new(min->gui->window->window);
	gtk_signal_connect(GTK_OBJECT(page->dreparent), "clicked", GTK_SIGNAL_FUNC(evt_style_parent_clicked), page);
	gtk_table_attach(GTK_TABLE(table), page->dreparent, 2, 3, 1, 2,  0,0,0,0);
	gtk_widget_show(page->dreparent);
	gtk_box_pack_start(GTK_BOX(page->dvbox), table, FALSE, FALSE, 0);
	gtk_widget_show(table);

	frame = gtk_frame_new("Inherited Properties");
	page->dpnbook = gtk_notebook_new();
	gtk_notebook_set_tab_pos(GTK_NOTEBOOK(page->dpnbook), GTK_POS_LEFT);
	build_pvisual(page);
	gtk_notebook_append_page(GTK_NOTEBOOK(page->dpnbook), page->dpvisual.vbox, gtk_label_new("Visual"));
	gtk_widget_show(page->dpvisual.vbox);
	build_paction(page);
	gtk_notebook_append_page(GTK_NOTEBOOK(page->dpnbook), page->dpaction.vbox, gtk_label_new("Actions"));
	gtk_widget_show(page->dpaction.vbox);
	gtk_container_add(GTK_CONTAINER(frame), page->dpnbook);
	gtk_widget_show(page->dpnbook);

	gtk_box_pack_start(GTK_BOX(page->dvbox), frame, FALSE, FALSE, 5);
	gtk_widget_show(frame);

	gtk_box_pack_start(GTK_BOX(page->vbox), page->dvbox, FALSE, FALSE, 0);
	gtk_widget_show(page->dvbox);

	hbox = gtk_hbox_new(FALSE, 0);
	btn = gtk_button_new_with_label("Add");
	gtk_signal_connect(GTK_OBJECT(btn), "clicked", GTK_SIGNAL_FUNC(evt_style_add_clicked), page);
	gtk_box_pack_start(GTK_BOX(hbox), btn, TRUE, TRUE, 5);
	gtk_widget_show(btn);
	page->del = gtk_button_new_with_label("Delete");
	gtk_signal_connect(GTK_OBJECT(page->del), "clicked", GTK_SIGNAL_FUNC(evt_style_del_clicked), page);
	gtk_box_pack_start(GTK_BOX(hbox), page->del, TRUE, TRUE, 5);
	gtk_widget_show(page->del);
	gtk_box_pack_start(GTK_BOX(page->vbox), hbox, FALSE, FALSE, 5);
	gtk_widget_show(hbox);

	gtk_widget_show(page->vbox);

	return page->vbox;
}


/* ----------------------------------------------------------------------------------------- */

/* 1999-05-12 -	Update style display. */
static void cst_update(MainInfo *min)
{
	P_Styles	*page = &the_page;

	page->si = stl_styleinfo_copy(min->cfg.style);
	populate_tree(page);
	reset_widgets(page);
}

/* ----------------------------------------------------------------------------------------- */

/* 1999-05-27 -	Accept changes, if any. Causes a call to the relink function in types config. */
static void cst_accept(MainInfo *min)
{
	P_Styles	*page = &the_page;

	if(page->modified)
	{
		ctp_relink_styles(min->cfg.style, page->si);
		stl_styleinfo_destroy(min->cfg.style);
		min->cfg.style = page->si;
		page->si = NULL;
		page->modified = FALSE;
		cfg_set_flags(CFLG_RESCAN_LEFT | CFLG_RESCAN_RIGHT);
	}
}

/* ----------------------------------------------------------------------------------------- */

/* 1998-08-24 -	Load style configuration info from given XML tree. */
static void cst_load(MainInfo *min, XmlNode *node)
{
	/* Free the built-in first. */
	stl_styleinfo_destroy(min->cfg.style);
	min->cfg.style = stl_styleinfo_load(node);
}

/* 1999-05-27 -	Save the current style configuration. Thanks to the styles module, this
**		is really not complicated. :)
*/
static int cst_save(MainInfo *min, FILE *out)
{
	stl_styleinfo_save(min, min->cfg.style, out, NODE);

	return TRUE;
}

/* ----------------------------------------------------------------------------------------- */

/* 1999-05-27 -	When the config window closes, free the editing copies since they're bulky. */
static void cst_hide(MainInfo *min)
{
	P_Styles	*page = &the_page;

	stl_styleinfo_destroy(page->si);
	page->si = NULL;
	populate_tree(page);	/* This will destroy the tree widget and *not* create a new one, since there's no si. */
	reset_widgets(page);
}

/* ----------------------------------------------------------------------------------------- */

CfgPage * cst_describe(MainInfo *min)
{
	static CfgPage	desc = { NODE, cst_init, cst_update, cst_accept, cst_save, cst_load, cst_hide };

	return &desc;
}

/* ----------------------------------------------------------------------------------------- */

/* 1999-05-27 -	Get the most current style info, namely the editing version. */
StyleInfo * cst_get_styleinfo(void)
{
	return the_page.si;
}
