2
* This is a plug-in for the GIMP.
4
* Generates clickable image maps.
6
* Copyright (C) 1998-2004 Maurits Rijk m.rijk@chello.nl
8
* This program is free software; you can redistribute it and/or modify
9
* it under the terms of the GNU General Public License as published by
10
* the Free Software Foundation; either version 2 of the License, or
11
* (at your option) any later version.
13
* This program is distributed in the hope that it will be useful,
14
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
* GNU General Public License for more details.
18
* You should have received a copy of the GNU General Public License
19
* along with this program; if not, write to the Free Software
20
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
30
#include <libgimp/gimp.h>
31
#include <libgimp/gimpui.h>
33
#include "imap_grid.h"
34
#include "imap_main.h"
35
#include "imap_menu.h"
36
#include "imap_popup.h"
37
#include "imap_preview.h"
38
#include "imap_table.h"
39
#include "imap_toolbar.h"
41
#include "libgimp/stdplugins-intl.h"
43
typedef enum {GRID_HIDDEN, GRID_LINES, GRID_CROSSES} GridType_t;
46
DefaultDialog_t *dialog;
47
GtkWidget *type_frame;
48
GtkWidget *granularity_frame;
49
GtkWidget *offset_frame;
53
GtkWidget *chain_width_height;
56
GtkWidget *chain_left_top;
62
gboolean enable_preview;
66
static GdkGC *grid_gc;
67
static gboolean grid_snap = FALSE;
68
static gint grid_width = 15;
69
static gint grid_height = 15;
70
static gint grid_left = 0;
71
static gint grid_top = 0;
72
static GridType_t grid_type = GRID_LINES;
75
grid_settings_ok_cb(gpointer data)
77
GridDialog_t *param = (GridDialog_t*) data;
80
new_snap = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(param->snap));
81
grid_width = gtk_spin_button_get_value_as_int(
82
GTK_SPIN_BUTTON(param->width));
83
grid_height = gtk_spin_button_get_value_as_int(
84
GTK_SPIN_BUTTON(param->height));
85
grid_left = gtk_spin_button_get_value_as_int(
86
GTK_SPIN_BUTTON(param->left));
87
grid_top = gtk_spin_button_get_value_as_int(
88
GTK_SPIN_BUTTON(param->top));
90
if (grid_snap != new_snap) {
92
main_toolbar_set_grid(grid_snap);
93
popup_check_grid(grid_snap);
94
menu_check_grid(grid_snap);
100
snap_toggled_cb(GtkWidget *widget, gpointer data)
102
GridDialog_t *param = (GridDialog_t*) data;
103
gint sensitive = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
105
gtk_widget_set_sensitive(param->type_frame, sensitive);
106
gtk_widget_set_sensitive(param->granularity_frame, sensitive);
107
gtk_widget_set_sensitive(param->offset_frame, sensitive);
108
gtk_widget_set_sensitive(param->preview, sensitive);
112
type_toggled_cb(GtkWidget *widget, gpointer data)
114
if (GTK_WIDGET_STATE(widget) & GTK_STATE_SELECTED) {
115
grid_type = GPOINTER_TO_INT (data);
121
toggle_preview_cb(GtkWidget *widget, GridDialog_t *param)
123
param->enable_preview =
124
gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
129
grid_assign_value(GtkWidget *widget, gpointer data, gint *value)
131
GridDialog_t *dialog = (GridDialog_t*) data;
132
if (dialog->enable_preview) {
133
*value = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget));
134
redraw_preview(); /* Fix me! */
139
width_changed_cb(GtkWidget *widget, gpointer data)
141
GridDialog_t *dialog = (GridDialog_t*) data;
143
grid_assign_value(widget, data, &grid_width);
144
if (gimp_chain_button_get_active(
145
GIMP_CHAIN_BUTTON(dialog->chain_width_height))) {
146
gint value = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget));
147
gtk_spin_button_set_value(GTK_SPIN_BUTTON(dialog->height), value);
152
height_changed_cb(GtkWidget *widget, gpointer data)
154
GridDialog_t *dialog = (GridDialog_t*) data;
156
grid_assign_value(widget, data, &grid_height);
157
if (gimp_chain_button_get_active(
158
GIMP_CHAIN_BUTTON(dialog->chain_width_height))) {
159
gint value = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget));
160
gtk_spin_button_set_value(GTK_SPIN_BUTTON(dialog->width), value);
165
left_changed_cb(GtkWidget *widget, gpointer data)
167
GridDialog_t *dialog = (GridDialog_t*) data;
169
grid_assign_value(widget, data, &grid_left);
170
if (gimp_chain_button_get_active(
171
GIMP_CHAIN_BUTTON(dialog->chain_left_top))) {
172
gint value = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget));
173
gtk_spin_button_set_value(GTK_SPIN_BUTTON(dialog->top), value);
178
top_changed_cb(GtkWidget *widget, gpointer data)
180
GridDialog_t *dialog = (GridDialog_t*) data;
182
grid_assign_value(widget, data, &grid_top);
183
if (gimp_chain_button_get_active(
184
GIMP_CHAIN_BUTTON(dialog->chain_left_top))) {
185
gint value = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget));
186
gtk_spin_button_set_value(GTK_SPIN_BUTTON(dialog->left), value);
191
create_grid_settings_dialog(void)
193
GridDialog_t *data = g_new(GridDialog_t, 1);
194
DefaultDialog_t *dialog;
195
GtkWidget *main_table, *table, *label;
199
GtkWidget *chain_button;
201
data->dialog = dialog = make_default_dialog(_("Grid Settings"));
202
default_dialog_set_ok_cb(dialog, grid_settings_ok_cb, (gpointer) data);
203
main_table = default_dialog_add_table(dialog, 4, 2);
205
data->snap = gtk_check_button_new_with_mnemonic(_("_Snap-To Grid Enabled"));
206
g_signal_connect(data->snap, "toggled",
207
G_CALLBACK (snap_toggled_cb), data);
208
gtk_table_attach_defaults(GTK_TABLE(main_table), data->snap, 0, 1, 0, 1);
209
gtk_widget_show(data->snap);
211
data->type_frame = frame = gimp_frame_new(_("Grid Visibility and Type"));
212
gtk_widget_show(frame);
213
gtk_table_attach_defaults(GTK_TABLE(main_table), frame, 0, 2, 1, 2);
214
hbox = gtk_hbox_new(FALSE, 6);
215
gtk_container_add(GTK_CONTAINER(frame), hbox);
216
gtk_widget_show(hbox);
218
button = gtk_radio_button_new_with_mnemonic_from_widget(NULL, _("_Hidden"));
219
data->hidden = button;
220
g_signal_connect(button, "toggled",
221
G_CALLBACK (type_toggled_cb), (gpointer) GRID_HIDDEN);
222
gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
223
gtk_widget_show(button);
225
button = gtk_radio_button_new_with_mnemonic_from_widget(
226
GTK_RADIO_BUTTON(button), _("_Lines"));
227
data->lines = button;
228
g_signal_connect(button, "toggled",
229
G_CALLBACK (type_toggled_cb), (gpointer) GRID_LINES);
230
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), TRUE);
231
gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
232
gtk_widget_show(button);
234
button = gtk_radio_button_new_with_mnemonic_from_widget(
235
GTK_RADIO_BUTTON(button), _("C_rosses"));
236
data->crosses = button;
237
g_signal_connect(button, "toggled",
238
G_CALLBACK (type_toggled_cb),
239
(gpointer) GRID_CROSSES);
240
gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
241
gtk_widget_show(button);
243
data->granularity_frame = frame = gimp_frame_new(_("Grid Granularity"));
244
gtk_table_attach_defaults(GTK_TABLE(main_table), frame, 0, 1, 2, 3);
245
table = gtk_table_new(2, 4, FALSE);
246
gtk_table_set_row_spacings(GTK_TABLE(table), 6);
247
gtk_table_set_col_spacings(GTK_TABLE(table), 6);
248
gtk_container_add(GTK_CONTAINER(frame), table);
250
label = create_label_in_table(table, 0, 0, _("_Width"));
251
data->width = create_spin_button_in_table(table, label, 0, 1, 15, 1, 100);
252
g_signal_connect(data->width, "value_changed",
253
G_CALLBACK (width_changed_cb), (gpointer) data);
254
create_label_in_table(table, 0, 3, _("pixels"));
256
label = create_label_in_table(table, 1, 0, _("_Height"));
257
data->height = create_spin_button_in_table(table, label, 1, 1, 15, 1, 100);
258
g_signal_connect(data->height, "value_changed",
259
G_CALLBACK (height_changed_cb), (gpointer) data);
260
create_label_in_table(table, 1, 3, _("pixels"));
262
chain_button = gimp_chain_button_new(GIMP_CHAIN_RIGHT);
263
data->chain_width_height = chain_button;
264
gtk_table_attach_defaults(GTK_TABLE(table), chain_button, 2, 3, 0, 2);
265
gtk_widget_show(chain_button);
267
gtk_widget_show(table);
268
gtk_widget_show(frame);
270
data->offset_frame = frame = gimp_frame_new(_("Grid Offset"));
271
gtk_table_attach_defaults(GTK_TABLE(main_table), frame, 1, 2, 2, 3);
272
table = gtk_table_new(2, 3, FALSE);
273
gtk_table_set_row_spacings(GTK_TABLE(table), 6);
274
gtk_table_set_col_spacings(GTK_TABLE(table), 6);
275
gtk_container_add(GTK_CONTAINER(frame), table);
277
label = create_label_in_table(table, 0, 2, _("pixels from l_eft"));
278
data->left = create_spin_button_in_table(table, label, 0, 0, 0, 0, 100);
279
g_signal_connect(data->left, "value_changed",
280
G_CALLBACK (left_changed_cb), (gpointer) data);
282
label = create_label_in_table(table, 1, 2, _("pixels from _top"));
283
data->top = create_spin_button_in_table(table, label, 1, 0, 0, 0, 100);
284
g_signal_connect(data->top, "value_changed",
285
G_CALLBACK (top_changed_cb), (gpointer) data);
287
chain_button = gimp_chain_button_new(GIMP_CHAIN_RIGHT);
288
data->chain_left_top = chain_button;
289
gtk_table_attach_defaults(GTK_TABLE(table), chain_button, 1, 2, 0, 2);
290
gtk_widget_show(chain_button);
292
data->preview = create_check_button_in_table(main_table, 3, 0,
294
g_signal_connect(data->preview, "toggled",
295
G_CALLBACK (toggle_preview_cb), (gpointer) data);
296
gtk_widget_show(data->preview);
298
snap_toggled_cb(data->snap, data);
300
gtk_widget_show(table);
301
gtk_widget_show(frame);
307
do_grid_settings_dialog(void)
309
static GridDialog_t* dialog;
313
dialog = create_grid_settings_dialog();
315
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog->snap), grid_snap);
316
gtk_spin_button_set_value(GTK_SPIN_BUTTON(dialog->width), grid_width);
317
gtk_spin_button_set_value(GTK_SPIN_BUTTON(dialog->height), grid_height);
318
gtk_spin_button_set_value(GTK_SPIN_BUTTON(dialog->left), grid_left);
319
gtk_spin_button_set_value(GTK_SPIN_BUTTON(dialog->top), grid_top);
321
if (grid_type == GRID_HIDDEN)
322
type = dialog->hidden;
323
else if (grid_type == GRID_LINES)
324
type = dialog->lines;
326
type = dialog->crosses;
327
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(type), TRUE);
329
default_dialog_show(dialog->dialog);
333
draw_lines(GdkWindow *window, GdkGC* gc, gint width, gint height)
337
for (x = grid_left; x < width; x += grid_width)
338
draw_line(window, grid_gc, x, 1, x, height);
339
for (y = grid_top; y < height; y += grid_height)
340
draw_line(window, grid_gc, 1, y, width, y);
344
draw_crosses(GdkWindow *window, GdkGC* gc, gint width, gint height)
348
for (x = grid_left; x < width; x += grid_width) {
349
for (y = grid_top; y < height; y += grid_height) {
350
draw_line(window, gc, x - 3, y, x + 3, y);
351
draw_line(window, gc, x, y - 3, x, y + 3);
357
draw_grid(GtkWidget *preview)
359
if (grid_snap && grid_type != GRID_HIDDEN) {
360
gint width = preview_get_width(preview);
361
gint height = preview_get_height(preview);
364
grid_gc = gdk_gc_new(preview->window);
366
gdk_gc_set_line_attributes(grid_gc, 1, GDK_LINE_ON_OFF_DASH,
367
GDK_CAP_BUTT, GDK_JOIN_BEVEL);
369
if (grid_type == GRID_LINES)
370
draw_lines(preview->window, grid_gc, width, height);
372
draw_crosses(preview->window, preview->style->black_gc, width,
380
grid_snap = !grid_snap;
386
grid_nearest_x(gint x)
388
return grid_left + (x - grid_left + grid_width / 2) / grid_width
393
grid_nearest_y(gint y)
395
return grid_top + (y - grid_top + grid_height / 2) / grid_height
400
round_to_grid(gint *x, gint *y)
403
*x = grid_nearest_x(*x);
404
*y = grid_nearest_y(*y);
411
return grid_snap && grid_type != GRID_HIDDEN
412
&& abs(grid_nearest_x(x) - x) <= 1;
418
return grid_snap && grid_type != GRID_HIDDEN
419
&& abs(grid_nearest_x(y) - y) <= 1;