~ubuntu-branches/ubuntu/maverick/gimp/maverick-updates

« back to all changes in this revision

Viewing changes to plug-ins/imagemap/imap_grid.c

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Holbach
  • Date: 2005-12-09 19:44:52 UTC
  • Revision ID: james.westby@ubuntu.com-20051209194452-yggpemjlofpjqyf4
Tags: upstream-2.2.9
ImportĀ upstreamĀ versionĀ 2.2.9

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * This is a plug-in for the GIMP.
 
3
 *
 
4
 * Generates clickable image maps.
 
5
 *
 
6
 * Copyright (C) 1998-2004 Maurits Rijk  m.rijk@chello.nl
 
7
 *
 
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.
 
12
 *
 
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.
 
17
 *
 
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.
 
21
 *
 
22
 */
 
23
 
 
24
#include "config.h"
 
25
 
 
26
#include <stdlib.h>
 
27
 
 
28
#include <gtk/gtk.h>
 
29
 
 
30
#include <libgimp/gimp.h>
 
31
#include <libgimp/gimpui.h>
 
32
 
 
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"
 
40
 
 
41
#include "libgimp/stdplugins-intl.h"
 
42
 
 
43
typedef enum {GRID_HIDDEN, GRID_LINES, GRID_CROSSES} GridType_t;
 
44
 
 
45
typedef struct {
 
46
   DefaultDialog_t *dialog;
 
47
   GtkWidget *type_frame;
 
48
   GtkWidget *granularity_frame;
 
49
   GtkWidget *offset_frame;
 
50
   GtkWidget *snap;
 
51
   GtkWidget *width;
 
52
   GtkWidget *height;
 
53
   GtkWidget *chain_width_height;
 
54
   GtkWidget *left;
 
55
   GtkWidget *top;
 
56
   GtkWidget *chain_left_top;
 
57
   GtkWidget *hidden;
 
58
   GtkWidget *lines;
 
59
   GtkWidget *crosses;
 
60
   GtkWidget *preview;
 
61
 
 
62
   gboolean   enable_preview;
 
63
} GridDialog_t;
 
64
 
 
65
 
 
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;
 
73
 
 
74
static void
 
75
grid_settings_ok_cb(gpointer data)
 
76
{
 
77
   GridDialog_t *param = (GridDialog_t*) data;
 
78
   gboolean new_snap;
 
79
 
 
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));
 
89
 
 
90
   if (grid_snap != new_snap) {
 
91
      grid_snap = new_snap;
 
92
      main_toolbar_set_grid(grid_snap);
 
93
      popup_check_grid(grid_snap);
 
94
      menu_check_grid(grid_snap);
 
95
   }
 
96
   redraw_preview();
 
97
}
 
98
 
 
99
static void
 
100
snap_toggled_cb(GtkWidget *widget, gpointer data)
 
101
{
 
102
   GridDialog_t *param = (GridDialog_t*) data;
 
103
   gint sensitive = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
 
104
 
 
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);
 
109
}
 
110
 
 
111
static void
 
112
type_toggled_cb(GtkWidget *widget, gpointer data)
 
113
{
 
114
   if (GTK_WIDGET_STATE(widget) & GTK_STATE_SELECTED) {
 
115
      grid_type = GPOINTER_TO_INT (data);
 
116
      redraw_preview();
 
117
   }
 
118
}
 
119
 
 
120
static void
 
121
toggle_preview_cb(GtkWidget *widget, GridDialog_t *param)
 
122
{
 
123
   param->enable_preview =
 
124
      gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
 
125
   redraw_preview();
 
126
}
 
127
 
 
128
static void
 
129
grid_assign_value(GtkWidget *widget, gpointer data, gint *value)
 
130
{
 
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! */
 
135
   }
 
136
}
 
137
 
 
138
static void
 
139
width_changed_cb(GtkWidget *widget, gpointer data)
 
140
{
 
141
   GridDialog_t *dialog = (GridDialog_t*) data;
 
142
 
 
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);
 
148
   }
 
149
}
 
150
 
 
151
static void
 
152
height_changed_cb(GtkWidget *widget, gpointer data)
 
153
{
 
154
   GridDialog_t *dialog = (GridDialog_t*) data;
 
155
 
 
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);
 
161
   }
 
162
}
 
163
 
 
164
static void
 
165
left_changed_cb(GtkWidget *widget, gpointer data)
 
166
{
 
167
   GridDialog_t *dialog = (GridDialog_t*) data;
 
168
 
 
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);
 
174
   }
 
175
}
 
176
 
 
177
static void
 
178
top_changed_cb(GtkWidget *widget, gpointer data)
 
179
{
 
180
   GridDialog_t *dialog = (GridDialog_t*) data;
 
181
 
 
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);
 
187
   }
 
188
}
 
189
 
 
190
static GridDialog_t*
 
191
create_grid_settings_dialog(void)
 
192
{
 
193
   GridDialog_t *data = g_new(GridDialog_t, 1);
 
194
   DefaultDialog_t *dialog;
 
195
   GtkWidget *main_table, *table, *label;
 
196
   GtkWidget *frame;
 
197
   GtkWidget *hbox;
 
198
   GtkWidget *button;
 
199
   GtkWidget *chain_button;
 
200
 
 
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);
 
204
 
 
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);
 
210
 
 
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);
 
217
 
 
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);
 
224
 
 
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);
 
233
 
 
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);
 
242
 
 
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);
 
249
 
 
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"));
 
255
 
 
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"));
 
261
 
 
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);
 
266
 
 
267
   gtk_widget_show(table);
 
268
   gtk_widget_show(frame);
 
269
 
 
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);
 
276
 
 
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);
 
281
 
 
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);
 
286
 
 
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);
 
291
 
 
292
   data->preview = create_check_button_in_table(main_table, 3, 0,
 
293
                                                _("_Preview"));
 
294
   g_signal_connect(data->preview, "toggled",
 
295
                    G_CALLBACK (toggle_preview_cb), (gpointer) data);
 
296
   gtk_widget_show(data->preview);
 
297
 
 
298
   snap_toggled_cb(data->snap, data);
 
299
 
 
300
   gtk_widget_show(table);
 
301
   gtk_widget_show(frame);
 
302
 
 
303
   return data;
 
304
}
 
305
 
 
306
void
 
307
do_grid_settings_dialog(void)
 
308
{
 
309
   static GridDialog_t* dialog;
 
310
   GtkWidget *type;
 
311
 
 
312
   if (!dialog)
 
313
      dialog = create_grid_settings_dialog();
 
314
 
 
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);
 
320
 
 
321
   if (grid_type == GRID_HIDDEN)
 
322
      type = dialog->hidden;
 
323
   else if (grid_type == GRID_LINES)
 
324
      type = dialog->lines;
 
325
   else
 
326
      type = dialog->crosses;
 
327
   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(type), TRUE);
 
328
 
 
329
   default_dialog_show(dialog->dialog);
 
330
}
 
331
 
 
332
static void
 
333
draw_lines(GdkWindow *window, GdkGC* gc, gint width, gint height)
 
334
{
 
335
   gint x, y;
 
336
 
 
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);
 
341
}
 
342
 
 
343
static void
 
344
draw_crosses(GdkWindow *window, GdkGC* gc, gint width, gint height)
 
345
{
 
346
   gint x, y;
 
347
 
 
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);
 
352
      }
 
353
   }
 
354
}
 
355
 
 
356
void
 
357
draw_grid(GtkWidget *preview)
 
358
{
 
359
   if (grid_snap && grid_type != GRID_HIDDEN) {
 
360
      gint width = preview_get_width(preview);
 
361
      gint height = preview_get_height(preview);
 
362
 
 
363
      if (!grid_gc) {
 
364
         grid_gc = gdk_gc_new(preview->window);
 
365
 
 
366
         gdk_gc_set_line_attributes(grid_gc, 1, GDK_LINE_ON_OFF_DASH,
 
367
                                    GDK_CAP_BUTT, GDK_JOIN_BEVEL);
 
368
      }
 
369
      if (grid_type == GRID_LINES)
 
370
         draw_lines(preview->window, grid_gc, width, height);
 
371
      else
 
372
         draw_crosses(preview->window, preview->style->black_gc, width,
 
373
                      height);
 
374
   }
 
375
}
 
376
 
 
377
gboolean
 
378
toggle_grid(void)
 
379
{
 
380
   grid_snap = !grid_snap;
 
381
   redraw_preview();
 
382
   return grid_snap;
 
383
}
 
384
 
 
385
static gint
 
386
grid_nearest_x(gint x)
 
387
{
 
388
   return grid_left + (x - grid_left + grid_width / 2) / grid_width
 
389
      * grid_width;
 
390
}
 
391
 
 
392
static gint
 
393
grid_nearest_y(gint y)
 
394
{
 
395
   return grid_top + (y - grid_top + grid_height / 2) / grid_height
 
396
      * grid_height;
 
397
}
 
398
 
 
399
void
 
400
round_to_grid(gint *x, gint *y)
 
401
{
 
402
   if (grid_snap) {
 
403
      *x = grid_nearest_x(*x);
 
404
      *y = grid_nearest_y(*y);
 
405
   }
 
406
}
 
407
 
 
408
gboolean
 
409
grid_near_x(gint x)
 
410
{
 
411
   return grid_snap && grid_type != GRID_HIDDEN
 
412
      && abs(grid_nearest_x(x) - x) <= 1;
 
413
}
 
414
 
 
415
gboolean
 
416
grid_near_y(gint y)
 
417
{
 
418
   return grid_snap && grid_type != GRID_HIDDEN
 
419
      && abs(grid_nearest_x(y) - y) <= 1;
 
420
}