/* The GIMP -- an image manipulation program * Copyright (C) 1995 Spencer Kimball and Peter Mattis * Copyright (C) 1998 Andy Thomas. * * Gradient editor module copyight (C) 1996-1997 Federico Mena Quintero * federico@nuclecu.unam.mx * * 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 PURIGHTE. 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-1307, USA. */ /* This is the popup for the gradient selection stuff.. * idea is a cut down version of the gradient selection widget * just a clist on which each gradient can be selected. * Of course all the support functions for getting the slected gradient and * setting the slection all need to be done as well. */ /* Main structure for the dialog. There can be multiple of these * so every thing has to go into the strcuture and we have to have a list * the structures so we can find which one we are taking about. */ #include "config.h" #include #include #include #include #ifdef HAVE_UNISTD_H #include #endif #include "appenv.h" #include "colormaps.h" #include "cursorutil.h" #include "datafiles.h" #include "errors.h" #include "general.h" #include "gimprc.h" #include "gradient.h" #include "gradient_header.h" #include "interface.h" #include "palette.h" #include "session.h" #include "actionarea.h" #include "dialog_handler.h" #include "libgimp/gimpintl.h" GSList *grad_active_dialogs = NULL; /* List of active dialogs */ GradSelectP gradient_select_dialog = NULL; /* The main selection dialog */ static void grad_select_close_callback (GtkWidget *, gpointer); static void grad_select_edit_callback (GtkWidget *, gpointer); static void grad_change_callbacks(GradSelectP gsp, gint closing); extern void import_palette_grad_update(gradient_t *); /* ALT Hmm... */ static ActionAreaItem action_items[2] = { { N_("Edit"), grad_select_edit_callback, NULL, NULL }, { N_("Close"), grad_select_close_callback, NULL, NULL } }; void grad_free_gradient_editor(void) { if (gradient_select_dialog) session_get_window_info (gradient_select_dialog->shell, &gradient_select_session_info); } /* grad_free_gradient_editor */ void grad_sel_rename_all(gint n, gradient_t *grad) { GSList *list = grad_active_dialogs; GradSelectP gsp; while(list) { gsp = (GradSelectP)list->data; gtk_clist_set_text(GTK_CLIST(gsp->clist),n,1,grad->name); list = g_slist_next(list); } if(gradient_select_dialog) { gtk_clist_set_text(GTK_CLIST(gradient_select_dialog->clist),n,1,grad->name); } } void grad_sel_new_all(gint pos, gradient_t *grad) { GSList *list = grad_active_dialogs; GradSelectP gsp; while(list) { gsp = (GradSelectP)list->data; gtk_clist_freeze(GTK_CLIST(gsp->clist)); ed_insert_in_gradients_listbox(gsp->gc,gsp->clist,grad, pos, 1); gtk_clist_thaw(GTK_CLIST(gsp->clist)); list = g_slist_next(list); } if(gradient_select_dialog) { gtk_clist_freeze(GTK_CLIST(gradient_select_dialog->clist)); ed_insert_in_gradients_listbox(gradient_select_dialog->gc,gradient_select_dialog->clist,grad, pos, 1); gtk_clist_thaw(GTK_CLIST(gradient_select_dialog->clist)); } } void grad_sel_copy_all(gint pos, gradient_t *grad) { GSList *list = grad_active_dialogs; GradSelectP gsp; while(list) { gsp = (GradSelectP)list->data; gtk_clist_freeze(GTK_CLIST(gsp->clist)); ed_insert_in_gradients_listbox(gsp->gc,gsp->clist,grad, pos, 1); gtk_clist_thaw(GTK_CLIST(gsp->clist)); list = g_slist_next(list); } if(gradient_select_dialog) { gtk_clist_freeze(GTK_CLIST(gradient_select_dialog->clist)); ed_insert_in_gradients_listbox(gradient_select_dialog->gc,gradient_select_dialog->clist,grad, pos, 1); gtk_clist_thaw(GTK_CLIST(gradient_select_dialog->clist)); } } void grad_sel_delete_all(gint n) { GSList *list = grad_active_dialogs; GradSelectP gsp; while(list) { gsp = (GradSelectP)list->data; gtk_clist_remove(GTK_CLIST(gsp->clist), n); list = g_slist_next(list); } if(gradient_select_dialog) { gtk_clist_remove(GTK_CLIST(gradient_select_dialog->clist), n); } } void grad_sel_free_all() { GSList *list = grad_active_dialogs; GradSelectP gsp; while(list) { gsp = (GradSelectP)list->data; gtk_clist_freeze(GTK_CLIST(gsp->clist)); gtk_clist_clear(GTK_CLIST(gsp->clist)); gtk_clist_thaw(GTK_CLIST(gsp->clist)); list = g_slist_next(list); } if(gradient_select_dialog) { gtk_clist_freeze(GTK_CLIST(gradient_select_dialog->clist)); gtk_clist_clear(GTK_CLIST(gradient_select_dialog->clist)); gtk_clist_thaw(GTK_CLIST(gradient_select_dialog->clist)); } } void grad_sel_refill_all() { GSList *list = grad_active_dialogs; GradSelectP gsp; int select_pos = -1; while(list) { gsp = (GradSelectP)list->data; gsp->grad = curr_gradient; select_pos = ed_set_list_of_gradients(gsp->gc, gsp->clist, curr_gradient); if(select_pos != -1) gtk_clist_moveto(GTK_CLIST(gsp->clist),select_pos,0,0.0,0.0); list = g_slist_next(list); } if(gradient_select_dialog) { gradient_select_dialog->grad = curr_gradient; select_pos = ed_set_list_of_gradients(gradient_select_dialog->gc, gradient_select_dialog->clist, curr_gradient); if(select_pos != -1) gtk_clist_moveto(GTK_CLIST(gradient_select_dialog->clist),select_pos,0,0.0,0.0); } } void sel_update_dialogs(gint row, gradient_t *grad) { /* Go around each updating the names and hopefully the previews */ GSList *list = grad_active_dialogs; GradSelectP gsp; while(list) { gsp = (GradSelectP)list->data; gtk_clist_set_text(GTK_CLIST(gsp->clist),row,1,grad->name); /* Are we updating one that is selected in a popup dialog? */ if(grad == gsp->grad) grad_change_callbacks(gsp, 0); list = g_slist_next(list); } if(gradient_select_dialog) gtk_clist_set_text(GTK_CLIST(gradient_select_dialog->clist),row,1,grad->name); import_palette_grad_update(grad); } static void sel_list_item_update(GtkWidget *widget, gint row, gint column, GdkEventButton *event, gpointer data) { GradSelectP gsp = (GradSelectP)data; GSList* tmp = g_slist_nth(gradients_list,row); gsp->grad = (gradient_t *)(tmp->data); /* If main one then make it the current selection */ if(gsp == gradient_select_dialog) { grad_set_grad_to_name(gsp->grad->name); import_palette_grad_update(gsp->grad); } else { grad_change_callbacks(gsp, 0); } } static void grad_select_edit_callback (GtkWidget *w, gpointer client_data) { GradSelectP gsp; gsp = (GradSelectP) client_data; grad_create_gradient_editor_init(TRUE); /* Set the current gradient in this dailog to the "real current"*/ if(gsp && gsp->grad) grad_set_grad_to_name(gsp->grad->name); } void grad_select_free (GradSelectP gsp) { if (gsp) { if(gsp->callback_name) g_free(gsp->callback_name); /* remove from active list */ grad_active_dialogs = g_slist_remove(grad_active_dialogs,gsp); g_free (gsp); } } /* Close active dialogs that no longer have PDB registered for them */ void gradients_check_dialogs(void) { GSList *list; GradSelectP gsp; gchar * name; ProcRecord *prec = NULL; list = grad_active_dialogs; while (list) { gsp = (GradSelectP) list->data; list = list->next; name = gsp->callback_name; prec = procedural_db_lookup(name); if(!prec) { grad_active_dialogs = g_slist_remove(grad_active_dialogs,gsp); /* Can alter grad_active_dialogs list*/ grad_select_close_callback(NULL,gsp); } } } static void grad_change_callbacks(GradSelectP gsp, gint closing) { gchar * name; ProcRecord *prec = NULL; gradient_t *grad; int nreturn_vals; static int busy = 0; gradient_t *oldgrad = curr_gradient; /* Any procs registered to callback? */ Argument *return_vals; if(!gsp || !gsp->callback_name || busy != 0) return; busy = 1; name = gsp->callback_name; grad = gsp->grad; /* If its still registered run it */ prec = procedural_db_lookup(name); if(prec && grad) { gdouble *values, *pv; double pos, delta; double r, g, b, a; int i = gsp->sample_size; pos = 0.0; delta = 1.0 / (i - 1); values = g_malloc(i * 4 * sizeof(gdouble)); pv = values; curr_gradient = grad; while (i--) { grad_get_color_at(pos, &r, &g, &b, &a); *pv++ = r; *pv++ = g; *pv++ = b; *pv++ = a; pos += delta; } /* while */ curr_gradient = oldgrad; return_vals = procedural_db_run_proc (name, &nreturn_vals, PDB_STRING,grad->name, PDB_INT32,gsp->sample_size*4, PDB_FLOATARRAY,values, PDB_INT32,closing, PDB_END); if (!return_vals || return_vals[0].value.pdb_int != PDB_SUCCESS) g_message ("failed to run gradient callback function"); else procedural_db_destroy_args (return_vals, nreturn_vals); } busy = 0; } static void grad_select_close_callback (GtkWidget *w, gpointer client_data) { GradSelectP gsp; gsp = (GradSelectP) client_data; if (GTK_WIDGET_VISIBLE (gsp->shell)) gtk_widget_hide (gsp->shell); /* Free memory if poping down dialog which is not the main one */ if(gsp != gradient_select_dialog) { grad_change_callbacks(gsp,1); gtk_widget_destroy(gsp->shell); grad_select_free(gsp); } } static gint grad_select_delete_callback (GtkWidget *w, GdkEvent *e, gpointer client_data) { grad_select_close_callback (w, client_data); return TRUE; } GradSelectP gsel_new_selection (gchar * title, gchar * initial_gradient) { GradSelectP gsp; gradient_t *grad = NULL; GSList *list; GtkWidget *vbox; GtkWidget *hbox; GtkWidget *scrolled_win; GdkColormap *colormap; gint select_pos; /* Load them if they are not already loaded */ if (g_editor == NULL) { grad_create_gradient_editor_init(FALSE); } gsp = g_malloc (sizeof (_GradSelect)); gsp->callback_name = NULL; /* The shell and main vbox */ gsp->shell = gtk_dialog_new (); gtk_window_set_wmclass (GTK_WINDOW (gsp->shell), "gradselection", "Gimp"); gtk_window_set_policy (GTK_WINDOW (gsp->shell), FALSE, TRUE, FALSE); vbox = gtk_vbox_new (FALSE, 1); gtk_container_set_border_width (GTK_CONTAINER (vbox), 1); gtk_box_pack_start (GTK_BOX (GTK_DIALOG (gsp->shell)->vbox), vbox, TRUE, TRUE, 0); /* handle the wm close event */ gtk_signal_connect (GTK_OBJECT (gsp->shell), "delete_event", GTK_SIGNAL_FUNC (grad_select_delete_callback), gsp); /* clist preview of gradients */ scrolled_win = gtk_scrolled_window_new (NULL, NULL); gsp->clist = gtk_clist_new (2); gtk_clist_set_shadow_type (GTK_CLIST (gsp->clist), GTK_SHADOW_IN); gtk_clist_set_row_height (GTK_CLIST (gsp->clist), 18); gtk_clist_set_column_width (GTK_CLIST (gsp->clist), 0, 52); gtk_clist_set_column_title (GTK_CLIST (gsp->clist), 0, _("Gradient")); gtk_clist_set_column_title (GTK_CLIST (gsp->clist), 1, _("Name")); gtk_clist_column_titles_show (GTK_CLIST (gsp->clist)); hbox = gtk_hbox_new (FALSE, 8); gtk_container_set_border_width (GTK_CONTAINER (hbox), 0); gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 0); gtk_widget_show (hbox); gtk_box_pack_start (GTK_BOX (hbox), scrolled_win, TRUE, TRUE, 0); gtk_container_add (GTK_CONTAINER (scrolled_win), gsp->clist); gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS); gtk_widget_show (scrolled_win); gtk_widget_show (gsp->clist); gtk_widget_set_usize (gsp->clist, 200, 250); colormap = gtk_widget_get_colormap (gsp->clist); gdk_color_parse ("black", &gsp->black); gdk_color_alloc (colormap, &gsp->black); gtk_signal_connect (GTK_OBJECT(gsp->clist), "select_row", GTK_SIGNAL_FUNC(sel_list_item_update), (gpointer) gsp); action_items[0].user_data = gsp; action_items[1].user_data = gsp; build_action_area (GTK_DIALOG (gsp->shell), action_items, 2, 1); if(!title) { gtk_window_set_title (GTK_WINDOW (gsp->shell), _("Gradient Selection")); } else { gtk_window_set_title (GTK_WINDOW (gsp->shell), title); } if (initial_gradient && strlen (initial_gradient)) { list = gradients_list; while (list) { grad = list->data; if (strcmp (grad->name, initial_gradient) == 0) { /* We found it! */ break; } list = g_slist_next (list); } } if (grad == NULL) grad = curr_gradient; gsp->grad = grad; gtk_widget_realize (gsp->shell); gsp->gc = gdk_gc_new (gsp->shell->window); select_pos = ed_set_list_of_gradients (gsp->gc, gsp->clist, grad); /* Now show the dialog */ gtk_widget_show (vbox); gtk_widget_show (gsp->shell); if (select_pos != -1) gtk_clist_moveto (GTK_CLIST(gsp->clist),select_pos,0,0.0,0.0); return gsp; } void grad_create_gradient_editor(void) { if(gradient_select_dialog == NULL) { gradient_select_dialog = gsel_new_selection(_("Gradients"),NULL); /* register this one only */ dialog_register(gradient_select_dialog->shell); session_set_window_geometry (gradient_select_dialog->shell, &gradient_select_session_info, TRUE); } else { if (!GTK_WIDGET_VISIBLE(gradient_select_dialog->shell)) { gtk_widget_show(gradient_select_dialog->shell); } else gdk_window_raise(gradient_select_dialog->shell->window); return; } }