/* The GIMP -- an image manipulation program * Copyright (C) 1995 Spencer Kimball and Peter Mattis * * gimpui.c * Copyright (C) 1999 Michael Natterer * * 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-1307, USA. */ #include "config.h" #include #include "gimpui.h" #include "libgimp/gimpsizeentry.h" #include "libgimp/gimpintl.h" extern gchar *prog_name; static void gimp_message_box_close_callback (GtkWidget *, gpointer); /* * String, integer, double and size query boxes */ typedef struct _QueryBox QueryBox; struct _QueryBox { GtkWidget *qbox; GtkWidget *vbox; GtkWidget *entry; GtkObject *object; GimpQueryFunc callback; gpointer data; }; static QueryBox * create_query_box (gchar *, GimpHelpFunc, gchar *, GtkSignalFunc, gchar *, GtkObject *, gchar *, GimpQueryFunc, gpointer); static void query_box_cancel_callback (GtkWidget *, gpointer); static void string_query_box_ok_callback (GtkWidget *, gpointer); static void int_query_box_ok_callback (GtkWidget *, gpointer); static void double_query_box_ok_callback (GtkWidget *, gpointer); static void size_query_box_ok_callback (GtkWidget *, gpointer); /* create a generic query box without any entry widget */ static QueryBox * create_query_box (gchar *title, GimpHelpFunc help_func, gchar *help_data, GtkSignalFunc ok_callback, gchar *message, GtkObject *object, gchar *signal, GimpQueryFunc callback, gpointer data) { QueryBox *query_box; GtkWidget *qbox; GtkWidget *vbox; GtkWidget *label; query_box = g_new (QueryBox, 1); qbox = gimp_dialog_new (title, "query_box", help_func, help_data, GTK_WIN_POS_MOUSE, FALSE, TRUE, FALSE, _("OK"), ok_callback, query_box, NULL, NULL, TRUE, FALSE, _("Cancel"), query_box_cancel_callback, query_box, NULL, NULL, FALSE, TRUE, NULL); /* if we are associated with an object, connect to the provided signal */ if (object && GTK_IS_OBJECT (object) && signal) gtk_signal_connect (GTK_OBJECT (object), signal, (GtkSignalFunc) query_box_cancel_callback, query_box); else object = NULL; vbox = gtk_vbox_new (FALSE, 2); gtk_container_set_border_width (GTK_CONTAINER (vbox), 4); gtk_container_add (GTK_CONTAINER (GTK_DIALOG (qbox)->vbox), vbox); gtk_widget_show (vbox); label = gtk_label_new (message); gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0); gtk_widget_show (label); query_box->qbox = qbox; query_box->vbox = vbox; query_box->entry = NULL; query_box->object = object; query_box->callback = callback; query_box->data = data; return query_box; } GtkWidget * gimp_query_string_box (gchar *title, GimpHelpFunc help_func, gchar *help_data, gchar *message, gchar *initial, GtkObject *object, gchar *signal, GimpQueryFunc callback, gpointer data) { QueryBox *query_box; GtkWidget *entry; query_box = create_query_box (title, help_func, help_data, string_query_box_ok_callback, message, object, signal, callback, data); entry = gtk_entry_new (); gtk_box_pack_start (GTK_BOX (query_box->vbox), entry, FALSE, FALSE, 0); if (initial) gtk_entry_set_text (GTK_ENTRY (entry), initial); gtk_widget_grab_focus (entry); gtk_widget_show (entry); query_box->entry = entry; return query_box->qbox; } GtkWidget * gimp_query_int_box (gchar *title, GimpHelpFunc help_func, gchar *help_data, gchar *message, gint initial, gint lower, gint upper, GtkObject *object, gchar *signal, GimpQueryFunc callback, gpointer data) { QueryBox *query_box; GtkAdjustment* adjustment; GtkWidget *spinbutton; query_box = create_query_box (title, help_func, help_data, int_query_box_ok_callback, message, object, signal, callback, data); adjustment = GTK_ADJUSTMENT (gtk_adjustment_new (initial, lower, upper, 1, 10, 0)); spinbutton = gtk_spin_button_new (adjustment, 1.0, 0); gtk_box_pack_start (GTK_BOX (query_box->vbox), spinbutton, FALSE, FALSE, 0); gtk_widget_grab_focus (spinbutton); gtk_widget_show (spinbutton); query_box->entry = spinbutton; return query_box->qbox; } GtkWidget * gimp_query_double_box (gchar *title, GimpHelpFunc help_func, gchar *help_data, gchar *message, gdouble initial, gdouble lower, gdouble upper, gint digits, GtkObject *object, gchar *signal, GimpQueryFunc callback, gpointer data) { QueryBox *query_box; GtkAdjustment* adjustment; GtkWidget *spinbutton; query_box = create_query_box (title, help_func, help_data, double_query_box_ok_callback, message, object, signal, callback, data); adjustment = GTK_ADJUSTMENT (gtk_adjustment_new (initial, lower, upper, 1, 10, 0)); spinbutton = gtk_spin_button_new (adjustment, 1.0, digits); gtk_box_pack_start (GTK_BOX (query_box->vbox), spinbutton, FALSE, FALSE, 0); gtk_widget_grab_focus (spinbutton); gtk_widget_show (spinbutton); query_box->entry = spinbutton; return query_box->qbox; } GtkWidget * gimp_query_size_box (gchar *title, GimpHelpFunc help_func, gchar *help_data, gchar *message, gdouble initial, gdouble lower, gdouble upper, gint digits, GUnit unit, gdouble resolution, gboolean dot_for_dot, GtkObject *object, gchar *signal, GimpQueryFunc callback, gpointer data) { QueryBox *query_box; GtkWidget *sizeentry; query_box = create_query_box (title, help_func, help_data, size_query_box_ok_callback, message, object, signal, callback, data); sizeentry = gimp_size_entry_new (1, unit, "%p", TRUE, FALSE, FALSE, 100, GIMP_SIZE_ENTRY_UPDATE_SIZE); if (dot_for_dot) gimp_size_entry_set_unit (GIMP_SIZE_ENTRY (sizeentry), UNIT_PIXEL); gimp_size_entry_set_resolution (GIMP_SIZE_ENTRY (sizeentry), 0, resolution, FALSE); gimp_size_entry_set_refval_digits (GIMP_SIZE_ENTRY (sizeentry), 0, digits); gimp_size_entry_set_refval_boundaries (GIMP_SIZE_ENTRY (sizeentry), 0, lower, upper); gimp_size_entry_set_refval (GIMP_SIZE_ENTRY (sizeentry), 0, initial); gtk_box_pack_start (GTK_BOX (query_box->vbox), sizeentry, FALSE, FALSE, 0); gimp_size_entry_grab_focus (GIMP_SIZE_ENTRY (sizeentry)); gtk_widget_show (sizeentry); query_box->entry = sizeentry; return query_box->qbox; } static void query_box_cancel_callback (GtkWidget *widget, gpointer data) { QueryBox *query_box; query_box = (QueryBox *) data; /* disconnect, if we are connected to some signal */ if (query_box->object) gtk_signal_disconnect_by_data (query_box->object, query_box); /* Destroy the box */ gtk_widget_destroy (query_box->qbox); g_free (query_box); } static void string_query_box_ok_callback (GtkWidget *widget, gpointer data) { QueryBox *query_box; gchar *string; query_box = (QueryBox *) data; gtk_widget_set_sensitive (query_box->qbox, FALSE); /* disconnect, if we are connected to some signal */ if (query_box->object) gtk_signal_disconnect_by_data (query_box->object, query_box); /* Get the entry data */ string = g_strdup (gtk_entry_get_text (GTK_ENTRY (query_box->entry))); /* Call the user defined callback */ (* query_box->callback) (query_box->qbox, query_box->data, (gpointer) string); /* Destroy the box */ gtk_widget_destroy (query_box->qbox); g_free (query_box); } static void int_query_box_ok_callback (GtkWidget *widget, gpointer data) { QueryBox *query_box; gint *integer_value; query_box = (QueryBox *) data; gtk_widget_set_sensitive (query_box->qbox, FALSE); /* disconnect, if we are connected to some signal */ if (query_box->object) gtk_signal_disconnect_by_data (query_box->object, query_box); /* Get the spinbutton data */ integer_value = g_malloc (sizeof (gint)); *integer_value = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (query_box->entry)); /* Call the user defined callback */ (* query_box->callback) (query_box->qbox, query_box->data, (gpointer) integer_value); /* Destroy the box */ gtk_widget_destroy (query_box->qbox); g_free (query_box); } static void double_query_box_ok_callback (GtkWidget *widget, gpointer data) { QueryBox *query_box; gdouble *double_value; query_box = (QueryBox *) data; gtk_widget_set_sensitive (query_box->qbox, FALSE); /* disconnect, if we are connected to some signal */ if (query_box->object) gtk_signal_disconnect_by_data (query_box->object, query_box); /* Get the spinbutton data */ double_value = g_malloc (sizeof (gdouble)); *double_value = gtk_spin_button_get_value_as_float (GTK_SPIN_BUTTON (query_box->entry)); /* Call the user defined callback */ (* query_box->callback) (query_box->qbox, query_box->data, (gpointer) double_value); /* Destroy the box */ gtk_widget_destroy (query_box->qbox); g_free (query_box); } static void size_query_box_ok_callback (GtkWidget *widget, gpointer data) { QueryBox *query_box; gdouble *double_value; query_box = (QueryBox *) data; gtk_widget_set_sensitive (query_box->qbox, FALSE); /* disconnect, if we are connected to some signal */ if (query_box->object) gtk_signal_disconnect_by_data (query_box->object, query_box); /* Get the sizeentry data */ double_value = g_malloc (sizeof (gdouble)); *double_value = gimp_size_entry_get_refval (GIMP_SIZE_ENTRY (query_box->entry), 0); /* Pass the selected unit to the callback */ gtk_object_set_data (GTK_OBJECT (widget), "size_query_unit", (gpointer) gimp_size_entry_get_unit (GIMP_SIZE_ENTRY (query_box->entry))); /* Call the user defined callback */ (* query_box->callback) (query_box->qbox, query_box->data, (gpointer) double_value); /* Destroy the box */ gtk_widget_destroy (query_box->qbox); g_free (query_box); } /* * Message Boxes... */ typedef struct _MessageBox MessageBox; struct _MessageBox { GtkWidget *mbox; GtkWidget *repeat_label; gchar *message; gint repeat_count; GtkCallback callback; gpointer data; }; /* the maximum number of concucrrent dialog boxes */ #define MESSAGE_BOX_MAXIMUM 4 static GList *message_boxes = NULL; void gimp_message_box (gchar *message, GtkCallback callback, gpointer data) { MessageBox *msg_box; GtkWidget *mbox; GtkWidget *vbox; GtkWidget *label; GList *list; if (!message) return; if (g_list_length (message_boxes) > MESSAGE_BOX_MAXIMUM) { fprintf (stderr, "%s: %s\n", prog_name, message); return; } for (list = message_boxes; list; list = list->next) { msg_box = list->data; if (strcmp (msg_box->message, message) == 0) { msg_box->repeat_count++; if (msg_box->repeat_count > 1) { gchar *text = g_strdup_printf (_("Message repeated %d times"), msg_box->repeat_count); gtk_label_set_text (GTK_LABEL (msg_box->repeat_label), text); g_free (text); gdk_window_raise (msg_box->mbox->window); } else { GtkWidget *hbox; hbox = gtk_hbox_new (FALSE, 0); gtk_box_pack_start (GTK_BOX (GTK_DIALOG (msg_box->mbox)->action_area), hbox, TRUE, FALSE, 4); msg_box->repeat_label = gtk_label_new (_("Message repeated once")); gtk_container_add (GTK_CONTAINER (hbox), msg_box->repeat_label); gtk_widget_show (msg_box->repeat_label); gtk_widget_show (hbox); gdk_window_raise (msg_box->mbox->window); } return; } } if (g_list_length (message_boxes) == MESSAGE_BOX_MAXIMUM) { fprintf (stderr, "%s: %s\n", prog_name, message); message = _("WARNING:\n" "Too many open message dialogs.\n" "Messages are redirected to stderr.\n"); } msg_box = g_new0 (MessageBox, 1); mbox = gimp_dialog_new (_("GIMP Message"), "gimp_message", NULL, NULL, GTK_WIN_POS_MOUSE, FALSE, FALSE, FALSE, _("OK"), gimp_message_box_close_callback, msg_box, NULL, NULL, TRUE, TRUE, NULL); vbox = gtk_vbox_new (FALSE, 0); gtk_container_set_border_width (GTK_CONTAINER (vbox), 6); gtk_container_add (GTK_CONTAINER (GTK_DIALOG (mbox)->vbox), vbox); gtk_widget_show (vbox); label = gtk_label_new (message); gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT); gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, FALSE, 0); gtk_widget_show (label); msg_box->mbox = mbox; msg_box->message = g_strdup (message); msg_box->callback = callback; msg_box->data = data; message_boxes = g_list_append (message_boxes, msg_box); gtk_widget_show (mbox); } static void gimp_message_box_close_callback (GtkWidget *widget, gpointer data) { MessageBox *msg_box; msg_box = (MessageBox *) data; /* If there is a valid callback, invoke it */ if (msg_box->callback) (* msg_box->callback) (widget, msg_box->data); /* Destroy the box */ gtk_widget_destroy (msg_box->mbox); /* make this box available again */ message_boxes = g_list_remove (message_boxes, msg_box); g_free (msg_box->message); g_free (msg_box); }