1999-11-20 Michael Natterer <mitch@gimp.org> Reorganized the core menu items (everything except <Image>/Filters). Everything is of course trivial to change again, so please comment on the new "menu feeling" ;-) * app/menus.[ch]: - Applied the suggestions collected by Olof. - Added "..." to all items which open a dialog. - Introduced some additional separators (e.g. in "Dialogs"). - Reorder some plugins and the color correct tools after initialisation. - A menu entry to invoke the tooltips inspector. - A debugging menu entry which dumps the menu paths and their help pages (will of course go away when the help sys is consistent). There are currently two identical "Help" menus because <Toolbox>/Help trashes the menu bar if the toolbox is too narrow (gtk doesn't seem to support multi-line menubars, any idea?) * app/app_procs.c: call menus_reorder_plugins() after loading the plugins to beautify the "Xtns" menu. * app/commands.[ch]: reordered some functions to match the new menu structure (for easier source navigation) and renamed some to be consistent (e.g. all help functions are now called help_*). Show/Hide the rulers with ordinary gtk_widget_[show|hide]() commands. I've tested it several times and it looks exactly the same as the old code which used internal gtk knowledge. * app/gdisplay.c: applied the menu changes to gdisplay_set_menu_sensitivity(). * app/gimphelp.[ch]: new public function gimp_context_help() which invokes the tooltips inspector. Code cleanup. * app/resize.c: changed the dialogs' titles to match the menu entries. * app/session.c: renamed the gradient selection cmd callback to be consistent with brushes/patterns. * app/tools.c: added "..." to the menu paths of the tools which have dialogs. * app/fileops.c * app/channels_dialog.c * app/layers_dialog.c * app/paths_dialog.c: added some "...". * plug-ins/common/align_layers.c * plug-ins/common/autostretch_hsv.c * plug-ins/common/c_astretch.c * plug-ins/common/color_enhance.c * plug-ins/common/compose.c * plug-ins/common/decompose.c * plug-ins/common/mail.c * plug-ins/common/normalize.c * plug-ins/common/threshold_alpha.c * plug-ins/dbbrowser/dbbrowser.c * plug-ins/fp/fp.c * plug-ins/print/print.c * plug-ins/rcm/rcm.c: changed the menu paths and added "...".
1066 lines
28 KiB
C
1066 lines
28 KiB
C
/* align_layers.c -- This is a plug-in for the GIMP (1.0's API)
|
|
* Author: Shuji Narazaki <narazaki@InetQ.or.jp>
|
|
* Time-stamp: <1998/01/17 00:32:23 narazaki@InetQ.or.jp>
|
|
* Version: 0.26
|
|
*
|
|
* Copyright (C) 1997-1998 Shuji Narazaki <narazaki@InetQ.or.jp>
|
|
*
|
|
* 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 "libgimp/gimp.h"
|
|
#include "gtk/gtk.h"
|
|
#include <math.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#define PLUG_IN_NAME "plug_in_align_layers"
|
|
#define SHORT_NAME "align_layers"
|
|
#define PROGRESS_NAME "align_layers"
|
|
#define MENU_POSITION "<Image>/Layers/Align Visible Layers..."
|
|
#define MAIN_FUNCTION main_function
|
|
#define INTERFACE align_layers_interface
|
|
#define DIALOG align_layers_dialog
|
|
#define VALS align_layers_vals
|
|
#define OK_CALLBACK align_layers_ok_callback
|
|
#define PREVIEW_UPDATE _preview_update
|
|
#define PROGRESS_UPDATE_NUM 100
|
|
|
|
/* gtkWrapper functions */
|
|
#define GTKW_ENTRY_WIDTH 40
|
|
#define GTKW_SCALE_WIDTH 100
|
|
#define GTKW_PREVIEW_WIDTH 50
|
|
#define GTKW_PREVIEW_HEIGHT 256
|
|
#define GTKW_BORDER_WIDTH 5
|
|
#define GTKW_FLOAT_MIN_ERROR 0.000001
|
|
static gint **gtkW_gint_wrapper_new (gint index, gint *pointer);
|
|
static void gtkW_close_callback (GtkWidget *widget, gpointer data);
|
|
static void gtkW_toggle_update (GtkWidget *widget, gpointer data);
|
|
static void gtkW_iscale_update (GtkAdjustment *adjustment, gpointer data);
|
|
static void gtkW_ientry_update (GtkWidget *widget, gpointer data);
|
|
static GtkWidget *gtkW_dialog_new (char *name, GtkSignalFunc ok_callback,
|
|
GtkSignalFunc close_callback);
|
|
static void gtkW_message_dialog (gint gtk_was_initialized, gchar *message);
|
|
static GtkWidget *gtkW_message_dialog_new (char * name);
|
|
static void
|
|
gtkW_table_add_toggle (GtkWidget *table,
|
|
gchar *name,
|
|
gint x,
|
|
gint y,
|
|
GtkSignalFunc update,
|
|
gint *value);
|
|
static void
|
|
gtkW_table_add_iscale_entry (GtkWidget *table,
|
|
gchar *name,
|
|
gint x,
|
|
gint y,
|
|
GtkSignalFunc scale_update,
|
|
GtkSignalFunc entry_update,
|
|
gint *value,
|
|
gdouble min,
|
|
gdouble max,
|
|
gdouble step,
|
|
gchar *buffer);
|
|
GtkWidget *gtkW_table_add_button (GtkWidget *table,
|
|
gchar *name,
|
|
gint x0,
|
|
gint x1,
|
|
gint y,
|
|
GtkSignalFunc callback,
|
|
gpointer value);
|
|
typedef struct
|
|
{
|
|
gchar *name;
|
|
gpointer data;
|
|
} gtkW_menu_item;
|
|
GtkWidget *gtkW_table_add_menu (GtkWidget *parent,
|
|
gchar *name,
|
|
int x,
|
|
int y,
|
|
GtkSignalFunc imenu_update,
|
|
int *val,
|
|
gtkW_menu_item *item,
|
|
int item_num);
|
|
static void gtkW_menu_update (GtkWidget *widget, gpointer data);
|
|
GtkWidget *gtkW_check_button_new (GtkWidget *parent,
|
|
gchar *name,
|
|
GtkSignalFunc update,
|
|
gint *value);
|
|
GtkWidget *gtkW_frame_new (GtkWidget *parent, gchar *name);
|
|
GtkWidget *gtkW_table_new (GtkWidget *parent, gint col, gint row);
|
|
GtkWidget *gtkW_hbox_new (GtkWidget *parent);
|
|
GtkWidget *gtkW_vbox_new (GtkWidget *parent);
|
|
/* end of GtkW */
|
|
|
|
static void query (void);
|
|
static void run (char *name,
|
|
int nparams,
|
|
GParam *param,
|
|
int *nreturn_vals,
|
|
GParam **return_vals);
|
|
static GStatusType align_layers (gint32 image_id);
|
|
static void align_layers_get_align_offsets (gint32 drawable_id,
|
|
gint *x,
|
|
gint *y);
|
|
static gint DIALOG ();
|
|
static void OK_CALLBACK (GtkWidget *widget, gpointer data);
|
|
|
|
GPlugInInfo PLUG_IN_INFO =
|
|
{
|
|
NULL, /* init_proc */
|
|
NULL, /* quit_proc */
|
|
query, /* query_proc */
|
|
run, /* run_proc */
|
|
};
|
|
|
|
/* dialog variables */
|
|
gtkW_menu_item h_style_menu [] =
|
|
{
|
|
#define H_NONE 0
|
|
{ "None", NULL },
|
|
#define H_COLLECT 1
|
|
{ "Collect", NULL },
|
|
#define LEFT2RIGHT 2
|
|
{ "Fill (left to right)", NULL },
|
|
#define RIGHT2LEFT 3
|
|
{ "Fill (right to left)", NULL },
|
|
#define SNAP2HGRID 4
|
|
{ "Snap to grid", NULL }
|
|
};
|
|
|
|
gtkW_menu_item h_base_menu [] =
|
|
{
|
|
#define H_BASE_LEFT 0
|
|
{ "Left edge", NULL },
|
|
#define H_BASE_CENTER 1
|
|
{ "Center", NULL },
|
|
#define H_BASE_RIGHT 2
|
|
{ "Right edge", NULL }
|
|
};
|
|
|
|
gtkW_menu_item v_style_menu [] =
|
|
{
|
|
#define V_NONE 0
|
|
{ "None", NULL },
|
|
#define V_COLLECT 1
|
|
{ "Collect", NULL },
|
|
#define TOP2BOTTOM 2
|
|
{ "Fill (top to bottom)", NULL },
|
|
#define BOTTOM2TOP 3
|
|
{ "Fill (bottom to top)", NULL },
|
|
#define SNAP2VGRID 4
|
|
{ "Snap to grid", NULL }
|
|
};
|
|
|
|
gtkW_menu_item v_base_menu [] =
|
|
{
|
|
#define V_BASE_TOP 0
|
|
{ "Top edge", NULL },
|
|
#define V_BASE_CENTER 1
|
|
{ "Center", NULL },
|
|
#define V_BASE_BOTTOM 2
|
|
{ "Bottom edge", NULL }
|
|
};
|
|
|
|
typedef struct
|
|
{
|
|
gint h_style;
|
|
gint h_base;
|
|
gint v_style;
|
|
gint v_base;
|
|
gint ignore_bottom;
|
|
gint base_is_bottom_layer;
|
|
gint grid_size;
|
|
} ValueType;
|
|
|
|
static ValueType VALS =
|
|
{
|
|
H_NONE, H_BASE_LEFT, V_NONE, V_BASE_TOP, 1, 0, 10
|
|
};
|
|
|
|
typedef struct
|
|
{
|
|
gint run;
|
|
} Interface;
|
|
|
|
static Interface INTERFACE = { FALSE };
|
|
|
|
/* gint link_after_alignment = 0;*/
|
|
|
|
MAIN ()
|
|
|
|
static void
|
|
query ()
|
|
{
|
|
static GParamDef args [] =
|
|
{
|
|
{ PARAM_INT32, "run_mode", "Interactive, non-interactive"},
|
|
{ PARAM_IMAGE, "image", "Input image"},
|
|
{ PARAM_DRAWABLE, "drawable", "Input drawable (not used)"},
|
|
{ PARAM_INT32, "link-afteer-alignment", "Link the visible layers after alignment"},
|
|
{ PARAM_INT32, "use-bottom", "use the bottom layer as the base of alignment"},
|
|
};
|
|
static GParamDef *return_vals = NULL;
|
|
static int nargs = sizeof (args) / sizeof (args[0]);
|
|
static int nreturn_vals = 0;
|
|
|
|
gimp_install_procedure (PLUG_IN_NAME,
|
|
"Align visible layers",
|
|
"align visible layers",
|
|
"Shuji Narazaki <narazaki@InetQ.or.jp>",
|
|
"Shuji Narazaki",
|
|
"1997",
|
|
MENU_POSITION,
|
|
"RGB*,GRAY*",
|
|
PROC_PLUG_IN,
|
|
nargs, nreturn_vals,
|
|
args, return_vals);
|
|
}
|
|
|
|
static void
|
|
run (char *name,
|
|
int nparams,
|
|
GParam *param,
|
|
int *nreturn_vals,
|
|
GParam **return_vals)
|
|
{
|
|
static GParam values[1];
|
|
GStatusType status = STATUS_EXECUTION_ERROR;
|
|
GRunModeType run_mode;
|
|
gint image_id, layer_num;
|
|
|
|
run_mode = param[0].data.d_int32;
|
|
image_id = param[1].data.d_int32;
|
|
|
|
*nreturn_vals = 1;
|
|
*return_vals = values;
|
|
|
|
values[0].type = PARAM_STATUS;
|
|
values[0].data.d_status = status;
|
|
|
|
switch ( run_mode )
|
|
{
|
|
case RUN_INTERACTIVE:
|
|
gimp_image_get_layers (image_id, &layer_num);
|
|
if (layer_num < 2)
|
|
{
|
|
gtkW_message_dialog (0, "Error: there are too few layers.");
|
|
return;
|
|
}
|
|
gimp_get_data (PLUG_IN_NAME, &VALS);
|
|
if (! DIALOG ())
|
|
return;
|
|
break;
|
|
case RUN_NONINTERACTIVE:
|
|
break;
|
|
case RUN_WITH_LAST_VALS:
|
|
gimp_get_data (PLUG_IN_NAME, &VALS);
|
|
break;
|
|
}
|
|
|
|
status = align_layers (image_id);
|
|
|
|
if (run_mode != RUN_NONINTERACTIVE)
|
|
gimp_displays_flush();
|
|
if (run_mode == RUN_INTERACTIVE && status == STATUS_SUCCESS )
|
|
gimp_set_data (PLUG_IN_NAME, &VALS, sizeof (ValueType));
|
|
|
|
values[0].type = PARAM_STATUS;
|
|
values[0].data.d_status = status;
|
|
}
|
|
|
|
static GStatusType
|
|
align_layers (gint32 image_id)
|
|
{
|
|
GParam* return_vals;
|
|
gint retvals;
|
|
gint layer_num = 0;
|
|
gint visible_layer_num = 1;
|
|
gint *layers = NULL;
|
|
gint index, vindex;
|
|
gint step_x = 0;
|
|
gint step_y = 0;
|
|
gint x = 0;
|
|
gint y = 0;
|
|
gint orig_x = 0;
|
|
gint orig_y = 0;
|
|
gint offset_x = 0;
|
|
gint offset_y = 0;
|
|
gint base_x = 0;
|
|
gint base_y =0;
|
|
|
|
layers = gimp_image_get_layers (image_id, &layer_num);
|
|
for (index = 0; index < layer_num; index++)
|
|
if (gimp_layer_get_visible (layers[index])) visible_layer_num++;
|
|
|
|
if (VALS.ignore_bottom)
|
|
{
|
|
layer_num--;
|
|
visible_layer_num--;
|
|
}
|
|
|
|
if (0 < visible_layer_num)
|
|
{
|
|
gint unintialzied = 1;
|
|
gint min_x = 0;
|
|
gint min_y = 0;
|
|
gint max_x = 0;
|
|
gint max_y = 0;
|
|
|
|
/* 0 is the top layer */
|
|
for (index = 0; index < layer_num; index++)
|
|
if (gimp_layer_get_visible (layers[index]))
|
|
{
|
|
gimp_drawable_offsets (layers[index], &orig_x, &orig_y);
|
|
align_layers_get_align_offsets (layers[index], &offset_x, &offset_y);
|
|
orig_x += offset_x;
|
|
orig_y += offset_y;
|
|
|
|
if (unintialzied)
|
|
{
|
|
base_x = min_x = max_y = orig_x;
|
|
base_y = min_y = max_y = orig_y;
|
|
unintialzied = 0;
|
|
}
|
|
else
|
|
{
|
|
if ( orig_x < min_x ) min_x = orig_x;
|
|
if ( max_x < orig_x ) max_x = orig_x;
|
|
if ( orig_y < min_y ) min_y = orig_y;
|
|
if ( max_y < orig_y ) max_y = orig_y;
|
|
}
|
|
}
|
|
if (VALS.base_is_bottom_layer)
|
|
{
|
|
gimp_drawable_offsets (layers[layer_num], &orig_x, &orig_y);
|
|
align_layers_get_align_offsets (layers[layer_num], &offset_x, &offset_y);
|
|
orig_x += offset_x;
|
|
orig_y += offset_y;
|
|
base_x = min_x = max_y = orig_x;
|
|
base_y = min_y = max_y = orig_y;
|
|
}
|
|
if (1 < visible_layer_num)
|
|
{
|
|
step_x = (max_x - min_x) / (visible_layer_num - 1);
|
|
step_y = (max_y - min_y) / (visible_layer_num - 1);
|
|
}
|
|
if ( (VALS.h_style == LEFT2RIGHT) || (VALS.h_style == RIGHT2LEFT))
|
|
base_x = min_x;
|
|
if ( (VALS.v_style == TOP2BOTTOM) || (VALS.v_style == BOTTOM2TOP))
|
|
base_y = min_y;
|
|
}
|
|
|
|
return_vals = gimp_run_procedure ("gimp_undo_push_group_start",
|
|
&retvals,
|
|
PARAM_IMAGE, image_id,
|
|
PARAM_END);
|
|
gimp_destroy_params (return_vals, retvals);
|
|
|
|
for (vindex = -1, index = 0; index < layer_num; index++)
|
|
{
|
|
if (gimp_layer_get_visible (layers[index]))
|
|
vindex++;
|
|
else
|
|
continue;
|
|
|
|
gimp_drawable_offsets (layers[index], &orig_x, &orig_y);
|
|
align_layers_get_align_offsets (layers[index], &offset_x, &offset_y);
|
|
|
|
switch (VALS.h_style)
|
|
{
|
|
case H_NONE:
|
|
x = orig_x;
|
|
break;
|
|
case H_COLLECT:
|
|
x = base_x - offset_x;
|
|
break;
|
|
case LEFT2RIGHT:
|
|
x = (base_x + vindex * step_x) - offset_x;
|
|
break;
|
|
case RIGHT2LEFT:
|
|
x = (base_x + (visible_layer_num - vindex) * step_x) - offset_x;
|
|
break;
|
|
case SNAP2HGRID:
|
|
x = VALS.grid_size
|
|
* (int) ((orig_x + offset_x + VALS.grid_size /2) / VALS.grid_size)
|
|
- offset_x;
|
|
break;
|
|
}
|
|
switch (VALS.v_style)
|
|
{
|
|
case V_NONE:
|
|
y = orig_y;
|
|
break;
|
|
case V_COLLECT:
|
|
y = base_y - offset_y;
|
|
break;
|
|
case TOP2BOTTOM:
|
|
y = (base_y + vindex * step_y) - offset_y;
|
|
break;
|
|
case BOTTOM2TOP:
|
|
y = (base_y + (visible_layer_num - vindex) * step_y) - offset_y;
|
|
break;
|
|
case SNAP2VGRID:
|
|
y = VALS.grid_size
|
|
* (int) ((orig_y + offset_y + VALS.grid_size / 2) / VALS.grid_size)
|
|
- offset_y;
|
|
break;
|
|
}
|
|
gimp_layer_set_offsets (layers[index], x, y);
|
|
}
|
|
return_vals = gimp_run_procedure ("gimp_undo_push_group_end",
|
|
&retvals,
|
|
PARAM_IMAGE, image_id,
|
|
PARAM_END);
|
|
gimp_destroy_params (return_vals, retvals);
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
static void
|
|
align_layers_get_align_offsets (gint32 drawable_id,
|
|
gint *x,
|
|
gint *y)
|
|
{
|
|
GDrawable *layer = gimp_drawable_get (drawable_id);
|
|
|
|
switch (VALS.h_base)
|
|
{
|
|
case H_BASE_LEFT:
|
|
*x = 0;
|
|
break;
|
|
case H_BASE_CENTER:
|
|
*x = (gint) (layer->width / 2);
|
|
break;
|
|
case H_BASE_RIGHT:
|
|
*x = layer->width;
|
|
break;
|
|
default:
|
|
*x = 0;
|
|
break;
|
|
}
|
|
switch (VALS.v_base)
|
|
{
|
|
case V_BASE_TOP:
|
|
*y = 0;
|
|
break;
|
|
case V_BASE_CENTER:
|
|
*y = (gint) (layer->height / 2);
|
|
break;
|
|
case V_BASE_BOTTOM:
|
|
*y = layer->height;
|
|
break;
|
|
default:
|
|
*y = 0;
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* dialog stuff */
|
|
static int
|
|
DIALOG ()
|
|
{
|
|
GtkWidget *dlg;
|
|
GtkWidget *frame;
|
|
GtkWidget *table;
|
|
#ifdef OLD
|
|
GtkWidget *hbox, *vbox;
|
|
GtkWidget *sep;
|
|
GtkWidget *toggle_vbox;
|
|
GSList *group = NULL;
|
|
#endif
|
|
int index = 0;
|
|
gchar buffer[10];
|
|
gchar **argv;
|
|
gint argc;
|
|
|
|
argc = 1;
|
|
argv = g_new (gchar *, 1);
|
|
argv[0] = g_strdup (PLUG_IN_NAME);
|
|
gtk_init (&argc, &argv);
|
|
gtk_rc_parse (gimp_gtkrc ());
|
|
|
|
dlg = gtkW_dialog_new (PLUG_IN_NAME,
|
|
(GtkSignalFunc) OK_CALLBACK,
|
|
(GtkSignalFunc) gtkW_close_callback);
|
|
|
|
#ifdef OLD
|
|
hbox = gtkW_hbox_new ((GTK_DIALOG (dlg)->vbox));
|
|
frame = gtkW_frame_new (hbox, "Horizontal Settings");
|
|
|
|
toggle_vbox = gtkW_vbox_new (frame);
|
|
|
|
group = gtkW_vbox_add_radio_button (toggle_vbox, "None", group,
|
|
(GtkSignalFunc) gtkW_toggle_update,
|
|
&d_var[H_NONE]);
|
|
group = gtkW_vbox_add_radio_button (toggle_vbox, "Collect", group,
|
|
(GtkSignalFunc) gtkW_toggle_update,
|
|
&d_var[H_COLLECT]);
|
|
group = gtkW_vbox_add_radio_button (toggle_vbox, "Fill (left to right)", group,
|
|
(GtkSignalFunc) gtkW_toggle_update,
|
|
&d_var[LEFT2RIGHT]);
|
|
group = gtkW_vbox_add_radio_button (toggle_vbox, "Fill (right to left)", group,
|
|
(GtkSignalFunc) gtkW_toggle_update,
|
|
&d_var[RIGHT2LEFT]);
|
|
group = gtkW_vbox_add_radio_button (toggle_vbox, "Snap to grid", group,
|
|
(GtkSignalFunc) gtkW_toggle_update,
|
|
&d_var[SNAP2HGRID]);
|
|
/* h base */
|
|
sep = gtk_hseparator_new ();
|
|
gtk_container_add (GTK_CONTAINER (toggle_vbox), sep);
|
|
gtk_widget_show (sep);
|
|
group = NULL;
|
|
group = gtkW_vbox_add_radio_button (toggle_vbox, "Left edge", group,
|
|
(GtkSignalFunc) gtkW_toggle_update,
|
|
&d_var[H_BASE_LEFT]);
|
|
group = gtkW_vbox_add_radio_button (toggle_vbox, "Center", group,
|
|
(GtkSignalFunc) gtkW_toggle_update,
|
|
&d_var[H_BASE_CENTER]);
|
|
group = gtkW_vbox_add_radio_button (toggle_vbox, "Right edge", group,
|
|
(GtkSignalFunc) gtkW_toggle_update,
|
|
&d_var[H_BASE_RIGHT]);
|
|
|
|
gtk_widget_show (toggle_vbox);
|
|
gtk_widget_show (frame);
|
|
frame = gtkW_frame_new (hbox, "Vetical Settings");
|
|
toggle_vbox = gtkW_vbox_new (frame);
|
|
|
|
/* v style */
|
|
group = NULL;
|
|
group = gtkW_vbox_add_radio_button (toggle_vbox, "None", group,
|
|
(GtkSignalFunc) gtkW_toggle_update,
|
|
&d_var[V_NONE]);
|
|
group = gtkW_vbox_add_radio_button (toggle_vbox, "Collect", group,
|
|
(GtkSignalFunc) gtkW_toggle_update,
|
|
&d_var[V_COLLECT]);
|
|
group = gtkW_vbox_add_radio_button (toggle_vbox, "Fill (top to bottom)", group,
|
|
(GtkSignalFunc) gtkW_toggle_update,
|
|
&d_var[TOP2BOTTOM]);
|
|
group = gtkW_vbox_add_radio_button (toggle_vbox, "Fill (bottom to top)", group,
|
|
(GtkSignalFunc) gtkW_toggle_update,
|
|
&d_var[BOTTOM2TOP]);
|
|
group = gtkW_vbox_add_radio_button (toggle_vbox, "Snap to grid", group,
|
|
(GtkSignalFunc) gtkW_toggle_update,
|
|
&d_var[SNAP2VGRID]);
|
|
/* v base */
|
|
sep = gtk_hseparator_new ();
|
|
gtk_container_add (GTK_CONTAINER (toggle_vbox), sep);
|
|
gtk_widget_show (sep);
|
|
group = NULL;
|
|
group = gtkW_vbox_add_radio_button (toggle_vbox, "Top edge", group,
|
|
(GtkSignalFunc) gtkW_toggle_update,
|
|
&d_var[V_BASE_TOP]);
|
|
group = gtkW_vbox_add_radio_button (toggle_vbox, "Center", group,
|
|
(GtkSignalFunc) gtkW_toggle_update,
|
|
&d_var[V_BASE_CENTER]);
|
|
group = gtkW_vbox_add_radio_button (toggle_vbox, "Bottom edge", group,
|
|
(GtkSignalFunc) gtkW_toggle_update,
|
|
&d_var[V_BASE_BOTTOM]);
|
|
|
|
gtk_widget_show (toggle_vbox);
|
|
gtk_widget_show (frame);
|
|
gtk_widget_show (hbox);
|
|
#else
|
|
frame = gtkW_frame_new (GTK_DIALOG (dlg)->vbox, "Parameter settings");
|
|
table = gtkW_table_new (frame, 7, 2);
|
|
gtkW_table_add_menu (table, "Horizontal style", 0, index++,
|
|
(GtkSignalFunc) gtkW_menu_update,
|
|
&VALS.h_style,
|
|
h_style_menu,
|
|
sizeof (h_style_menu) / sizeof (h_style_menu[0]));
|
|
gtkW_table_add_menu (table, "Horizontal base", 0, index++,
|
|
(GtkSignalFunc) gtkW_menu_update,
|
|
&VALS.h_base,
|
|
h_base_menu,
|
|
sizeof (h_base_menu) / sizeof (h_base_menu[0]));
|
|
gtkW_table_add_menu (table, "Vertical style", 0, index++,
|
|
(GtkSignalFunc) gtkW_menu_update,
|
|
&VALS.v_style,
|
|
v_style_menu,
|
|
sizeof (v_style_menu) / sizeof (v_style_menu[0]));
|
|
gtkW_table_add_menu (table, "Vertical base", 0, index++,
|
|
(GtkSignalFunc) gtkW_menu_update,
|
|
&VALS.v_base,
|
|
v_base_menu,
|
|
sizeof (v_base_menu) / sizeof (v_base_menu[0]));
|
|
#endif
|
|
|
|
gtkW_table_add_toggle (table, "Ignore the bottom layer even if visible",
|
|
0, index++,
|
|
(GtkSignalFunc) gtkW_toggle_update,
|
|
&VALS.ignore_bottom);
|
|
gtkW_table_add_toggle (table, "Use the (invisible) bottom layer as the base",
|
|
0, index++,
|
|
(GtkSignalFunc) gtkW_toggle_update,
|
|
&VALS.base_is_bottom_layer);
|
|
gtkW_table_add_iscale_entry (table, "Grid size",
|
|
0, index++,
|
|
(GtkSignalFunc) gtkW_iscale_update,
|
|
(GtkSignalFunc) gtkW_ientry_update,
|
|
&VALS.grid_size, 0, 200, 1, buffer);
|
|
|
|
gtk_widget_show (table);
|
|
gtk_widget_show (frame);
|
|
gtk_widget_show (dlg);
|
|
|
|
gtk_main ();
|
|
gdk_flush ();
|
|
|
|
return INTERFACE.run;
|
|
}
|
|
|
|
static void
|
|
OK_CALLBACK (GtkWidget *widget,
|
|
gpointer data)
|
|
{
|
|
#ifdef OLD
|
|
int index;
|
|
|
|
for (index = H_NONE; index <= SNAP2HGRID; index++)
|
|
if (d_var[index])
|
|
{
|
|
VALS.h_style = index;
|
|
break;
|
|
}
|
|
for (index = H_BASE_LEFT; index <= H_BASE_RIGHT; index++)
|
|
if (d_var[index])
|
|
{
|
|
VALS.h_base = index;
|
|
break;
|
|
}
|
|
for (index = V_NONE; index <= SNAP2VGRID; index++)
|
|
if (d_var[index])
|
|
{
|
|
VALS.v_style = index;
|
|
break;
|
|
}
|
|
for (index = V_BASE_TOP; index <= V_BASE_BOTTOM; index++)
|
|
if (d_var[index])
|
|
{
|
|
VALS.v_base = index;
|
|
break;
|
|
}
|
|
#endif
|
|
INTERFACE.run = TRUE;
|
|
gtk_widget_destroy (GTK_WIDGET (data));
|
|
}
|
|
|
|
static void
|
|
PREVIEW_UPDATE ()
|
|
{
|
|
}
|
|
|
|
/* gtkW functions: gtkW is the abbreviation of gtk Wrapper */
|
|
static gint **
|
|
gtkW_gint_wrapper_new (gint index, gint *pointer)
|
|
{
|
|
gint **tmp;
|
|
|
|
tmp = (gint **)malloc(3 * sizeof (gint *));
|
|
tmp[0] = (gint *) ((*pointer == index) ? TRUE : FALSE);
|
|
tmp[1] = pointer;
|
|
tmp[2] = (gint *) index;
|
|
return tmp;
|
|
}
|
|
|
|
static void
|
|
gtkW_close_callback (GtkWidget *widget,
|
|
gpointer data)
|
|
{
|
|
gtk_main_quit ();
|
|
}
|
|
|
|
static void
|
|
gtkW_toggle_update (GtkWidget *widget,
|
|
gpointer data)
|
|
{
|
|
int *toggle_val;
|
|
|
|
toggle_val = (int *) data;
|
|
|
|
if (GTK_TOGGLE_BUTTON (widget)->active)
|
|
*toggle_val = TRUE;
|
|
else
|
|
*toggle_val = FALSE;
|
|
PREVIEW_UPDATE ();
|
|
}
|
|
|
|
static GtkWidget *
|
|
gtkW_dialog_new (char * name,
|
|
GtkSignalFunc ok_callback,
|
|
GtkSignalFunc close_callback)
|
|
{
|
|
GtkWidget *dlg, *button;
|
|
|
|
dlg = gtk_dialog_new ();
|
|
gtk_window_set_title (GTK_WINDOW (dlg), name);
|
|
gtk_window_position (GTK_WINDOW (dlg), GTK_WIN_POS_MOUSE);
|
|
gtk_signal_connect (GTK_OBJECT (dlg), "destroy",
|
|
(GtkSignalFunc) close_callback, NULL);
|
|
|
|
/* Action Area */
|
|
button = gtk_button_new_with_label ("OK");
|
|
GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
|
|
gtk_signal_connect (GTK_OBJECT (button), "clicked",
|
|
(GtkSignalFunc) ok_callback, dlg);
|
|
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dlg)->action_area), button,
|
|
TRUE, TRUE, 0);
|
|
gtk_widget_grab_default (button);
|
|
gtk_widget_show (button);
|
|
|
|
button = gtk_button_new_with_label ("Cancel");
|
|
GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
|
|
gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
|
|
(GtkSignalFunc) gtk_widget_destroy,
|
|
GTK_OBJECT(dlg));
|
|
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dlg)->action_area), button,
|
|
TRUE, TRUE, 0);
|
|
gtk_widget_show (button);
|
|
|
|
return dlg;
|
|
}
|
|
|
|
static void
|
|
gtkW_message_dialog (gint gtk_was_initialized, gchar *message)
|
|
{
|
|
GtkWidget *dlg;
|
|
GtkWidget *table;
|
|
GtkWidget *label;
|
|
gchar **argv;
|
|
gint argc;
|
|
|
|
if (! gtk_was_initialized)
|
|
{
|
|
argc = 1;
|
|
argv = g_new (gchar *, 1);
|
|
argv[0] = g_strdup (PLUG_IN_NAME);
|
|
gtk_init (&argc, &argv);
|
|
gtk_rc_parse (gimp_gtkrc ());
|
|
}
|
|
|
|
dlg = gtkW_message_dialog_new (PLUG_IN_NAME);
|
|
|
|
table = gtk_table_new (1,1, FALSE);
|
|
gtk_container_border_width (GTK_CONTAINER (table), GTKW_BORDER_WIDTH);
|
|
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dlg)->vbox), table, TRUE, TRUE, 0);
|
|
|
|
label = gtk_label_new (message);
|
|
gtk_table_attach (GTK_TABLE (table), label, 0, 1, 0, 1, GTK_FILL|GTK_EXPAND,
|
|
0, 0, 0);
|
|
gtk_widget_show (label);
|
|
gtk_widget_show (table);
|
|
gtk_widget_show (dlg);
|
|
|
|
gtk_main ();
|
|
gdk_flush ();
|
|
}
|
|
|
|
static GtkWidget *
|
|
gtkW_message_dialog_new (char * name)
|
|
{
|
|
GtkWidget *dlg, *button;
|
|
|
|
dlg = gtk_dialog_new ();
|
|
gtk_window_set_title (GTK_WINDOW (dlg), name);
|
|
gtk_window_position (GTK_WINDOW (dlg), GTK_WIN_POS_MOUSE);
|
|
gtk_signal_connect (GTK_OBJECT (dlg), "destroy",
|
|
(GtkSignalFunc) gtkW_close_callback, NULL);
|
|
|
|
/* Action Area */
|
|
button = gtk_button_new_with_label ("OK");
|
|
GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
|
|
gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
|
|
(GtkSignalFunc) gtk_widget_destroy,
|
|
GTK_OBJECT (dlg));
|
|
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dlg)->action_area), button,
|
|
TRUE, TRUE, 0);
|
|
gtk_widget_grab_default (button);
|
|
gtk_widget_show (button);
|
|
|
|
return dlg;
|
|
}
|
|
|
|
GtkWidget *
|
|
gtkW_table_new (GtkWidget *parent, gint col, gint row)
|
|
{
|
|
GtkWidget *table;
|
|
|
|
table = gtk_table_new (col,row, FALSE);
|
|
gtk_container_border_width (GTK_CONTAINER (table), GTKW_BORDER_WIDTH);
|
|
gtk_container_add (GTK_CONTAINER (parent), table);
|
|
gtk_widget_show (table);
|
|
|
|
return table;
|
|
}
|
|
|
|
GtkWidget *
|
|
gtkW_hbox_new (GtkWidget *parent)
|
|
{
|
|
GtkWidget *hbox;
|
|
|
|
hbox = gtk_hbox_new (FALSE, 2);
|
|
gtk_container_border_width (GTK_CONTAINER (hbox), GTKW_BORDER_WIDTH);
|
|
/* gtk_box_pack_start (GTK_BOX (parent), hbox, FALSE, TRUE, 0); */
|
|
gtk_container_add (GTK_CONTAINER (parent), hbox);
|
|
gtk_widget_show (hbox);
|
|
|
|
return hbox;
|
|
}
|
|
|
|
GtkWidget *
|
|
gtkW_vbox_new (GtkWidget *parent)
|
|
{
|
|
GtkWidget *vbox;
|
|
|
|
vbox = gtk_vbox_new (FALSE, 2);
|
|
gtk_container_border_width (GTK_CONTAINER (vbox), GTKW_BORDER_WIDTH);
|
|
/* gtk_box_pack_start (GTK_BOX (parent), vbox, TRUE, TRUE, 0); */
|
|
gtk_container_add (GTK_CONTAINER (parent), vbox);
|
|
gtk_widget_show (vbox);
|
|
|
|
return vbox;
|
|
}
|
|
|
|
GtkWidget *
|
|
gtkW_check_button_new (GtkWidget *parent,
|
|
gchar *name,
|
|
GtkSignalFunc update,
|
|
gint *value)
|
|
{
|
|
GtkWidget *toggle;
|
|
|
|
toggle = gtk_check_button_new_with_label (name);
|
|
gtk_signal_connect (GTK_OBJECT (toggle), "toggled",
|
|
(GtkSignalFunc) update,
|
|
value);
|
|
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), *value);
|
|
gtk_container_add (GTK_CONTAINER (parent), toggle);
|
|
gtk_widget_show (toggle);
|
|
return toggle;
|
|
}
|
|
|
|
GtkWidget *
|
|
gtkW_frame_new (GtkWidget *parent,
|
|
gchar *name)
|
|
{
|
|
GtkWidget *frame;
|
|
|
|
frame = gtk_frame_new (name);
|
|
gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN);
|
|
gtk_container_border_width (GTK_CONTAINER (frame), GTKW_BORDER_WIDTH);
|
|
if (parent != NULL)
|
|
gtk_box_pack_start (GTK_BOX(parent), frame, FALSE, FALSE, 0);
|
|
gtk_widget_show (frame);
|
|
|
|
return frame;
|
|
}
|
|
|
|
static void
|
|
gtkW_table_add_toggle (GtkWidget *table,
|
|
gchar *name,
|
|
gint x,
|
|
gint y,
|
|
GtkSignalFunc update,
|
|
gint *value)
|
|
{
|
|
GtkWidget *toggle;
|
|
|
|
toggle = gtk_check_button_new_with_label(name);
|
|
gtk_table_attach (GTK_TABLE (table), toggle, x, x + 2, y, y+1,
|
|
GTK_FILL|GTK_EXPAND, 0 & GTK_FILL, 0, 0);
|
|
gtk_signal_connect (GTK_OBJECT (toggle), "toggled",
|
|
(GtkSignalFunc) update,
|
|
value);
|
|
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), *value);
|
|
gtk_widget_show (toggle);
|
|
}
|
|
|
|
static void
|
|
gtkW_table_add_iscale_entry (GtkWidget *table,
|
|
gchar *name,
|
|
gint x,
|
|
gint y,
|
|
GtkSignalFunc scale_update,
|
|
GtkSignalFunc entry_update,
|
|
gint *value,
|
|
gdouble min,
|
|
gdouble max,
|
|
gdouble step,
|
|
gchar *buffer)
|
|
{
|
|
GtkObject *adjustment;
|
|
GtkWidget *label, *hbox, *scale, *entry;
|
|
|
|
label = gtk_label_new (name);
|
|
gtk_misc_set_alignment (GTK_MISC(label), 0.0, 0.5);
|
|
gtk_table_attach (GTK_TABLE(table), label, x, x+1, y, y+1,
|
|
GTK_FILL|GTK_EXPAND, 0 & GTK_FILL, 5, 0);
|
|
gtk_widget_show (label);
|
|
|
|
hbox = gtk_hbox_new (FALSE, 5);
|
|
gtk_table_attach (GTK_TABLE (table), hbox, x+1, x+2, y, y+1,
|
|
GTK_EXPAND | GTK_FILL, 0 & GTK_FILL, 0, 0);
|
|
|
|
adjustment = gtk_adjustment_new (*value, min, max, step, step, 0.0);
|
|
gtk_widget_show (hbox);
|
|
|
|
scale = gtk_hscale_new (GTK_ADJUSTMENT (adjustment));
|
|
gtk_widget_set_usize (scale, GTKW_SCALE_WIDTH, 0);
|
|
gtk_box_pack_start (GTK_BOX (hbox), scale, TRUE, TRUE, 0);
|
|
gtk_scale_set_value_pos (GTK_SCALE (scale), GTK_POS_TOP);
|
|
gtk_scale_set_digits (GTK_SCALE (scale), 0);
|
|
gtk_range_set_update_policy (GTK_RANGE (scale), GTK_UPDATE_DELAYED);
|
|
gtk_signal_connect (GTK_OBJECT (adjustment), "value_changed",
|
|
(GtkSignalFunc) scale_update, value);
|
|
|
|
entry = gtk_entry_new ();
|
|
gtk_object_set_user_data (GTK_OBJECT (entry), adjustment);
|
|
gtk_object_set_user_data (adjustment, entry);
|
|
gtk_box_pack_start (GTK_BOX (hbox), entry, TRUE, TRUE, 0);
|
|
gtk_widget_set_usize (entry, GTKW_ENTRY_WIDTH, 0);
|
|
sprintf (buffer, "%d", *value);
|
|
gtk_entry_set_text (GTK_ENTRY (entry), buffer);
|
|
gtk_signal_connect (GTK_OBJECT (entry), "changed",
|
|
(GtkSignalFunc) entry_update, value);
|
|
|
|
gtk_widget_show (label);
|
|
gtk_widget_show (scale);
|
|
gtk_widget_show (entry);
|
|
}
|
|
|
|
static void
|
|
gtkW_iscale_update (GtkAdjustment *adjustment,
|
|
gpointer data)
|
|
{
|
|
GtkWidget *entry;
|
|
gchar buffer[32];
|
|
int *val;
|
|
|
|
val = data;
|
|
if (*val != (int) adjustment->value)
|
|
{
|
|
*val = adjustment->value;
|
|
entry = gtk_object_get_user_data (GTK_OBJECT (adjustment));
|
|
sprintf (buffer, "%d", (int) adjustment->value);
|
|
gtk_entry_set_text (GTK_ENTRY (entry), buffer);
|
|
PREVIEW_UPDATE ();
|
|
}
|
|
}
|
|
|
|
static void
|
|
gtkW_ientry_update (GtkWidget *widget,
|
|
gpointer data)
|
|
{
|
|
GtkAdjustment *adjustment;
|
|
int new_val;
|
|
int *val;
|
|
|
|
val = data;
|
|
new_val = atoi (gtk_entry_get_text (GTK_ENTRY (widget)));
|
|
|
|
if (*val != new_val)
|
|
{
|
|
adjustment = gtk_object_get_user_data (GTK_OBJECT (widget));
|
|
|
|
if ((new_val >= adjustment->lower) &&
|
|
(new_val <= adjustment->upper))
|
|
{
|
|
*val = new_val;
|
|
adjustment->value = new_val;
|
|
gtk_signal_emit_by_name (GTK_OBJECT (adjustment), "value_changed");
|
|
PREVIEW_UPDATE ();
|
|
}
|
|
}
|
|
}
|
|
|
|
GtkWidget *
|
|
gtkW_table_add_button (GtkWidget *table,
|
|
gchar *name,
|
|
gint x0,
|
|
gint x1,
|
|
gint y,
|
|
GtkSignalFunc callback,
|
|
gpointer value)
|
|
{
|
|
GtkWidget *button;
|
|
|
|
button = gtk_button_new_with_label (name);
|
|
gtk_table_attach (GTK_TABLE(table), button, x0, x1, y, y+1,
|
|
GTK_FILL|GTK_EXPAND, GTK_FILL, 0, 0);
|
|
gtk_signal_connect (GTK_OBJECT (button), "clicked",
|
|
(GtkSignalFunc) callback, value);
|
|
gtk_widget_show(button);
|
|
|
|
return button;
|
|
}
|
|
|
|
GtkWidget *
|
|
gtkW_table_add_menu (GtkWidget *table,
|
|
gchar *name,
|
|
int x,
|
|
int y,
|
|
GtkSignalFunc menu_update,
|
|
int *val,
|
|
gtkW_menu_item *item,
|
|
int item_num)
|
|
{
|
|
GtkWidget *label;
|
|
GtkWidget *menu, *menuitem, *option_menu;
|
|
gchar buf[64];
|
|
gint i;
|
|
|
|
label = gtk_label_new (name);
|
|
gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
|
|
gtk_table_attach (GTK_TABLE (table), label, x, x + 1, y, y + 1,
|
|
GTK_FILL|GTK_EXPAND, 0 & GTK_FILL, GTKW_BORDER_WIDTH, 0);
|
|
gtk_widget_show (label);
|
|
|
|
menu = gtk_menu_new ();
|
|
|
|
for (i = 0; i < item_num; i++)
|
|
{
|
|
sprintf (buf, item[i].name);
|
|
menuitem = gtk_menu_item_new_with_label (buf);
|
|
gtk_menu_append (GTK_MENU (menu), menuitem);
|
|
gtk_signal_connect (GTK_OBJECT (menuitem), "activate",
|
|
(GtkSignalFunc) menu_update,
|
|
gtkW_gint_wrapper_new (i, val));
|
|
gtk_widget_show (menuitem);
|
|
}
|
|
|
|
option_menu = gtk_option_menu_new ();
|
|
gtk_option_menu_set_menu (GTK_OPTION_MENU (option_menu), menu);
|
|
gtk_option_menu_set_history (GTK_OPTION_MENU (option_menu), *val);
|
|
gtk_table_attach (GTK_TABLE (table), option_menu, x + 1, x + 2, y, y + 1,
|
|
GTK_FILL|GTK_EXPAND, 0, 0, 0);
|
|
gtk_widget_show (option_menu);
|
|
|
|
return option_menu;
|
|
}
|
|
|
|
static void
|
|
gtkW_menu_update (GtkWidget *widget,
|
|
gpointer data)
|
|
{
|
|
gint **buffer = (gint **) data;
|
|
|
|
if (*buffer[1] != (gint) buffer[2])
|
|
{
|
|
*buffer[1] = (gint) buffer[2];
|
|
PREVIEW_UPDATE ();
|
|
}
|
|
}
|
|
/* end of gtkW functions */
|
|
/* end of align_layers.c */
|