/*
 *  path.c:		Path selection widget
 *
 *  Written by:		Ullrich Hafner
 *  
 *  Copyright (C) 1998-2000 Ullrich Hafner <hafner@bigfoot.de>
 *
 *  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., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
 */


/*
 *  $Date: 2000/09/03 19:22:04 $
 *  $Author: hafner $
 *  $Revision: 1.19 $
 *  $State: Exp $
 */

#include "config.h"

#include <gtk/gtk.h>
#include "proplist_t.h"

#include "misc.h"
#include "path.h"
#include "themebrowser.h"
#include "menu.h"
#include "error.h"

extern proplist_t windowmaker;
extern proplist_t wmconfig;
extern bool_t	   changed;

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

			       prototypes
  
*****************************************************************************/

static void
remove_dir (GtkWidget *button, gpointer data);
static void
update_proplist (GtkWidget *button, gpointer data);
static void
open_dirbrowser (GtkWidget *button, gpointer data);
static void
insert_dir (GtkWidget *button, gpointer data);
static void
row_moved (GtkWidget *clist, gint source_row, gint dest_row, gpointer data);
static void
update_entry (GtkCList *clist, gint row, gint column,
	      GdkEvent *event, gpointer data);
static void
change_dir (GtkWidget *entry, gpointer data);
static void
update_path (proplist_t key, gpointer ptr, proplist_t value,
	     const char *path);
static void
init_dir_list (GtkCList *clist, proplist_t value);

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

			       public code
  
*****************************************************************************/

void
path_dialog (GtkWidget *page, proplist_t key, proplist_t array,
	     GtkTooltips *tooltips, proplist_t info)
/*
 *  Generate path dialog widget.
 *  Associated wmaker attribute name is given by 'key'.
 *
 *  Return value:
 *	container box
 */ 
{
   GtkWidget *hbox;
   GtkWidget *vbox;
   GtkWidget *entry;
   GtkWidget *clist;
   GtkWidget *frame;
   guint      entry_sig_handler;

   /*
    *  Error handling
    */
   if (array && !WMIsPLArray (array))	/* uups */
   {
      WMReleasePropList (array);
      array = NULL;
   }
   if (!array)
   {
      array = WMCreatePLArray (WMCreatePLString ("/"), NULL);
      WMPutInPLDictionary (windowmaker, key, array);
   }
   
   {
      proplist_t pltitle    = WMCreatePLString ("Title");
      proplist_t keydef     = WMGetFromPLDictionary (wmconfig, key);
      proplist_t title_text = WMGetFromPLDictionary (keydef, pltitle);

      frame = gtk_frame_new (D_(WMGetFromPLString (title_text ? title_text : key)));
      gtk_frame_set_label_align (GTK_FRAME (frame), 0.5, 0.5);
      gtk_container_set_border_width (GTK_CONTAINER (frame), 5);
      
      WMReleasePropList (pltitle);
   }
   
   hbox = gtk_hbox_new (FALSE, 0);
   gtk_container_add (GTK_CONTAINER (frame), hbox);

   vbox = gtk_vbox_new (FALSE, 5);
   gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0);

   clist = gtk_clist_new (1);
   gtk_object_set_user_data (GTK_OBJECT (clist), key);

   gtk_clist_set_reorderable (GTK_CLIST (clist), TRUE);
   gtk_clist_set_use_drag_icons (GTK_CLIST (clist), TRUE);
   gtk_clist_set_column_auto_resize (GTK_CLIST (clist), 0, YES);
   {
      GtkWidget *scrolled = gtk_scrolled_window_new (NULL, NULL);
      gtk_container_set_border_width (GTK_CONTAINER (scrolled), 5);
      gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled),
				      GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
      gtk_widget_set_usize (scrolled, -1, 120);
      gtk_box_pack_start (GTK_BOX (vbox), scrolled, TRUE, TRUE, 0);
      gtk_container_add (GTK_CONTAINER (scrolled), clist);
   }
   gtk_clist_column_titles_passive (GTK_CLIST (clist));
   gtk_clist_set_selection_mode (GTK_CLIST (clist), GTK_SELECTION_BROWSE);

   {
      GtkWidget *button;
      GtkWidget *bbox = gtk_vbutton_box_new ();
      
      gtk_box_pack_start (GTK_BOX (hbox), bbox, FALSE, TRUE, 5);
      gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox),
				 GTK_BUTTONBOX_SPREAD);
      
      button = gtk_button_new_with_label (_("Insert..."));
      gtk_box_pack_start (GTK_BOX (bbox), button, FALSE, TRUE, 5);
      gtk_tooltips_set_tip (tooltips, button,
			    _("Insert new directory."), NULL);
      gtk_object_set_user_data (GTK_OBJECT (button), NULL);
      gtk_signal_connect (GTK_OBJECT (button), "clicked",
			  GTK_SIGNAL_FUNC (open_dirbrowser), clist);
      
      button = gtk_button_new_with_label (_("Remove"));
      gtk_object_set_data (GTK_OBJECT (clist), "remove", button);
      gtk_box_pack_start (GTK_BOX (bbox), button, FALSE, TRUE, 5);
      gtk_tooltips_set_tip (tooltips, button,
			    _("Remove selected directory."), NULL);
      gtk_signal_connect (GTK_OBJECT (button), "clicked",
			  GTK_SIGNAL_FUNC (remove_dir), clist);
   }

   hbox = gtk_hbox_new (FALSE, 5);
   gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
   gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);

   entry = gtk_entry_new ();
   gtk_box_pack_start (GTK_BOX (hbox), entry, TRUE, TRUE, 0);
   if (info)
      gtk_tooltips_set_tip (tooltips, entry, D_(WMGetFromPLString (info)), NULL);
   
   entry_sig_handler = gtk_signal_connect (GTK_OBJECT (entry), "changed",
		                           GTK_SIGNAL_FUNC (change_dir), clist);
   gtk_object_set_user_data (GTK_OBJECT (entry),
		             GINT_TO_POINTER (entry_sig_handler));
   
   gtk_signal_connect (GTK_OBJECT (clist), "select_row",
		       GTK_SIGNAL_FUNC (update_entry), entry);

   gtk_signal_connect_after (GTK_OBJECT (clist), "row_move",
			     GTK_SIGNAL_FUNC (row_moved), clist);

   init_dir_list (GTK_CLIST (clist), WMGetFromPLDictionary (windowmaker, key));
   
   gtk_widget_show_all (frame);
   gtk_box_pack_start (GTK_BOX (page), frame, TRUE, TRUE, 0);

   connect_update_function (key, clist, update_path);
}

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

			       private code
  
*******************************************************************************/

static void
init_dir_list (GtkCList *clist, proplist_t value)
{
   unsigned	i;
      
   gtk_clist_clear (GTK_CLIST (clist));
   for (i = 0; i < WMGetPropListItemCount (value); i++)
   {
      char *text = WMGetFromPLString (WMGetFromPLArray (value, i));
	 
      gtk_clist_insert (GTK_CLIST (clist), i, &text);
   }
   gtk_clist_select_row (GTK_CLIST (clist), 0, 0);
}

static void
remove_dir (GtkWidget *button, gpointer data)
/*
 *  Remove selected directory. 
 */
{
   GtkWidget	*clist = (GtkWidget *) data;
   
   if (GTK_CLIST (clist)->rows > 1)
   {
      gint row = GPOINTER_TO_INT (GTK_CLIST (clist)->selection->data);

      if (row == GTK_CLIST (clist)->rows - 1) /* last row */
	 gtk_clist_select_row (GTK_CLIST (clist), row - 1, 0);
      else
	 gtk_clist_select_row (GTK_CLIST (clist), row + 1, 0);
      gtk_clist_remove (GTK_CLIST (clist), row);
      if (GTK_CLIST (clist)->rows <= 1)
	 gtk_widget_set_sensitive (button, FALSE);
      update_proplist (button, data);
   }
}

static void
open_dirbrowser (GtkWidget *button, gpointer data)
/*
 *  Open pixmap browser to select new directory. 
 */
{
   static GtkWidget	*filesel = NULL;
   GtkWidget		*clist = (GtkWidget *) data;

   if (!filesel)
   {
      GtkFileSelection *fs;

      /*
       *  Fileselection dialog window
       */
      filesel = gtk_file_selection_new (_("Choose directory"));
      fs      = GTK_FILE_SELECTION (filesel);
      gtk_widget_set_sensitive (fs->file_list, FALSE);
      gtk_file_selection_hide_fileop_buttons (fs);
      gtk_window_set_position (GTK_WINDOW (filesel), GTK_WIN_POS_MOUSE);
      gtk_signal_connect (GTK_OBJECT (filesel), "destroy",
                          GTK_SIGNAL_FUNC (gtk_widget_destroyed),
                          &filesel);
      gtk_signal_connect (GTK_OBJECT (fs->ok_button), "clicked",
			  GTK_SIGNAL_FUNC (insert_dir), data);
      gtk_object_set_user_data (GTK_OBJECT (fs->ok_button), filesel);
      
      gtk_signal_connect_object (GTK_OBJECT (fs->cancel_button), "clicked",
				 GTK_SIGNAL_FUNC (gtk_widget_destroy),
				 GTK_OBJECT (filesel));
      gtk_signal_connect_object (GTK_OBJECT (fs->ok_button), "clicked",
				 GTK_SIGNAL_FUNC (gtk_widget_destroy),
				 GTK_OBJECT (filesel));
      {
	 char *filename;
	 
	 if (GTK_CLIST (clist)->rows > 0)
	    gtk_clist_get_text (GTK_CLIST (clist),
				GPOINTER_TO_INT (GTK_CLIST (clist)->selection->data),
				0, &filename);
	 else
	    filename = "";
	 
	 if (streq (filename, ""))
	    gtk_file_selection_set_filename (fs, WMAKERDATADIR "/");
	 else
	    gtk_file_selection_set_filename (fs, filename);
      }
   }

   if (!GTK_WIDGET_VISIBLE (filesel))
      gtk_widget_show (filesel);
   else
      gtk_widget_destroy (filesel);
}

static void
insert_dir (GtkWidget *button, gpointer data)
/*
 *  Insert directory selected with pixmap browser into the directory list. 
 */
{
   GtkWidget		*clist  = (GtkWidget *) data;
   GtkFileSelection	*fs;
   char			*text;

   fs 	= GTK_FILE_SELECTION (gtk_object_get_user_data (GTK_OBJECT (button)));
   text = g_strdup (gtk_file_selection_get_filename (fs));
   
   if (strlen (text) > 1 && text [strlen (text) - 1] == '/')
      text [strlen (text) - 1] = 0;

   if (GTK_CLIST (clist)->rows > 0)
      gtk_clist_insert (GTK_CLIST (clist),
			GPOINTER_TO_INT (GTK_CLIST (clist)->selection->data),
			&text);
   else
      gtk_clist_insert (GTK_CLIST (clist), 0, &text);
      
   Free (text);

   if (GTK_CLIST (clist)->rows > 1)
   {
      GtkWidget *remove = (GtkWidget *) gtk_object_get_data (GTK_OBJECT (clist),
							     "remove");
      gtk_widget_set_sensitive (remove, TRUE);
   }
   update_proplist (button, data);
}

static void
update_proplist (GtkWidget *button, gpointer data)
/*
 *  Update value of WindowMaker array.
 */
{
   GtkWidget	*clist = (GtkWidget *) data;
   proplist_t	key   = gtk_object_get_user_data (GTK_OBJECT (clist));
   proplist_t	array = WMGetFromPLDictionary (windowmaker, key);
   int		n;

   for (n = WMGetPropListItemCount (array); n; n--)
      WMDeleteFromPLArray (array, 0);
   
   for (n = 0; n < GTK_CLIST (clist)->rows; n++)
   {
      char *text;
      
      gtk_clist_get_text (GTK_CLIST (clist), n, 0, &text);
      WMInsertInPLArray (array, n, WMCreatePLString (text));
   }
   toggle_save (changed = YES, key);
}

static void
update_entry (GtkCList *clist, gint row, gint column,
	      GdkEvent *event, gpointer data)
/*
 *  Update entry if new directory has been selected in the dir list.
 */
{
   GtkWidget	*entry = (GtkWidget *) data;
   guint         entry_sig_handler = GPOINTER_TO_INT (gtk_object_get_user_data
						      (GTK_OBJECT (entry)));
   char		*text;
   
   gtk_clist_get_text (GTK_CLIST (clist), row, 0, &text);
   g_signal_handler_block (entry, entry_sig_handler);
   gtk_entry_set_text (GTK_ENTRY (entry), text);
   g_signal_handler_unblock (entry, entry_sig_handler);
}

static void
row_moved (GtkWidget *clist, gint source_row, gint dest_row, gpointer data)
/*
 *  Update directory array if row has been moved with DND.
 */
{
   update_proplist (clist, clist);
}

static void
change_dir (GtkWidget *entry, gpointer data)
/*
 *  Update directory name changed via entry
 */
{
   GtkWidget	*clist = (GtkWidget *) data;
   const char	*new_text;
   char         *text;
   gint		 row = GPOINTER_TO_INT (GTK_CLIST (clist)->selection->data);

   new_text = gtk_entry_get_text (GTK_ENTRY (entry));
   gtk_clist_get_text (GTK_CLIST (clist), row, 0, &text);
   if (strcmp (text, new_text)) {
      gtk_clist_set_text (GTK_CLIST (clist), row, 0, new_text);
      update_proplist (clist, clist);
   }
}

static void
update_path (proplist_t key, gpointer ptr, proplist_t value,
	     const char *path)
{
   if (WMIsPLArray (value))
      init_dir_list (GTK_CLIST (ptr), value);
}
