
2000-01-13 Michael Natterer <mitch@gimp.org> * app/gimpui.[ch] * app/preferences_dialog.c: removed & renamed some functions from gimpui.[ch] (see below). * libgimp/Makefile.am * libgimp/gimpwidgets.[ch]; new files. Functions moved from app/gimpui.[ch]. Added a constructor for the label + hscale + entry combination used in many plugins (now hscale + spinbutton). * libgimp/gimpui.h: include gimpwidgets.h * plug-ins/megawidget/megawidget.[ch]: removed all functions except the preview stuff (I'm not yet sure how to implement this in libgimp because the libgimp preview should be general enough to replace all the other plugin previews, too). * plug-ins/borderaverage/Makefile.am * plug-ins/borderaverage/borderaverage.c * plug-ins/common/plugin-defs.pl * plug-ins/common/Makefile.am * plug-ins/common/aa.c * plug-ins/common/align_layers.c * plug-ins/common/animationplay.c * plug-ins/common/apply_lens.c * plug-ins/common/blinds.c * plug-ins/common/bumpmap.c * plug-ins/common/checkerboard.c * plug-ins/common/colorify.c * plug-ins/common/convmatrix.c * plug-ins/common/cubism.c * plug-ins/common/curve_bend.c * plug-ins/common/deinterlace.c * plug-ins/common/despeckle.c * plug-ins/common/destripe.c * plug-ins/common/displace.c * plug-ins/common/edge.c * plug-ins/common/emboss.c * plug-ins/common/hot.c * plug-ins/common/nlfilt.c * plug-ins/common/pixelize.c * plug-ins/common/waves.c * plug-ins/sgi/sgi.c * plug-ins/sinus/sinus.c: ui updates like removing megawidget, using the dialog constructor, I18N fixes, indentation, ...
504 lines
13 KiB
C
504 lines
13 KiB
C
/* The GIMP -- an image manipulation program
|
|
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
|
*
|
|
* gimpui.c
|
|
* Copyright (C) 1999 Michael Natterer <mitch@gimp.org>
|
|
*
|
|
* 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 "gimpui.h"
|
|
|
|
#include "libgimp/gimpsizeentry.h"
|
|
#include "libgimp/gimpintl.h"
|
|
|
|
/*
|
|
* 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;
|
|
GtkCallback callback;
|
|
gpointer data;
|
|
};
|
|
|
|
static void gimp_message_box_close_callback (GtkWidget *, gpointer);
|
|
|
|
#define MESSAGE_BOX_MAXIMUM 7 /* the maximum number of concucrrent
|
|
* dialog boxes
|
|
*/
|
|
|
|
static gint message_pool = MESSAGE_BOX_MAXIMUM;
|
|
static gchar *message_box_last = NULL;
|
|
|
|
GtkWidget *
|
|
gimp_message_box (gchar *message,
|
|
GtkCallback callback,
|
|
gpointer data)
|
|
{
|
|
MessageBox *msg_box;
|
|
GtkWidget *mbox;
|
|
GtkWidget *vbox;
|
|
GtkWidget *label;
|
|
|
|
static gint repeat_count;
|
|
|
|
/* arguably, if message_pool <= 0 we could print to stdout */
|
|
if (!message || message_pool <= 0)
|
|
return NULL;
|
|
|
|
if (message_box_last && !strcmp (message_box_last, message))
|
|
{
|
|
repeat_count++;
|
|
if (repeat_count == 3)
|
|
message = "WARNING: message repeated too often, ignoring";
|
|
else if (repeat_count > 3)
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
repeat_count = 0;
|
|
if (message_box_last)
|
|
g_free (message_box_last);
|
|
message_box_last = g_strdup (message);
|
|
}
|
|
|
|
if (message_pool == 1)
|
|
message = "WARNING: too many messages, close some dialog boxes first";
|
|
|
|
msg_box = g_new (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->callback = callback;
|
|
msg_box->data = data;
|
|
|
|
gtk_widget_show (mbox);
|
|
|
|
/* allocate message box */
|
|
message_pool--;
|
|
|
|
return 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_pool++;
|
|
|
|
g_free (msg_box);
|
|
}
|