/* * path.c: Path selection widget * * Written by: Ullrich Hafner * * Copyright (C) 1998-2000 Ullrich Hafner * * 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 #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); }