1 /*
2 * This is a plug-in for GIMP.
3 *
4 * Generates clickable image maps.
5 *
6 * Copyright (C) 1998-2005 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 3 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, see <https://www.gnu.org/licenses/>.
20 *
21 */
22
23 #include "config.h"
24
25 #include <stdlib.h>
26 #include <string.h>
27
28 #include <glib/gstdio.h>
29
30 #include "libgimp/gimp.h"
31 #include "libgimp/gimpui.h"
32
33 #include "imap_command.h"
34 #include "imap_file.h"
35 #include "imap_main.h"
36 #include "imap_menu.h"
37 #include "imap_misc.h"
38 #include "imap_mru.h"
39 #include "imap_preferences.h"
40 #include "imap_table.h"
41
42 #include "libgimp/stdplugins-intl.h"
43
44 typedef struct {
45 DefaultDialog_t *dialog;
46 GtkWidget *notebook;
47 GtkWidget *ncsa;
48 GtkWidget *cern;
49 GtkWidget *csim;
50 GtkWidget *prompt_for_area_info;
51 GtkWidget *require_default_url;
52 GtkWidget *show_area_handle;
53 GtkWidget *keep_circles_round;
54 GtkWidget *show_url_tip;
55 GtkWidget *use_doublesized;
56
57 GtkWidget *undo_levels;
58 GtkWidget *mru_size;
59
60 GtkWidget *normal_fg;
61 GtkWidget *normal_bg;
62 GtkWidget *selected_fg;
63 GtkWidget *selected_bg;
64 GtkWidget *interactive_fg;
65 GtkWidget *interactive_bg;
66
67 GtkWidget *threshold;
68 GtkWidget *auto_convert;
69
70 PreferencesData_t *old_data;
71 } PreferencesDialog_t;
72
73 static void get_button_colors (PreferencesDialog_t *dialog,
74 ColorSelData_t *colors);
75
76 static gint
parse_map_type(void)77 parse_map_type(void)
78 {
79 char *token = strtok(NULL, " )");
80 if (!strcmp(token, "ncsa"))
81 return NCSA;
82 else if (!strcmp(token, "cern"))
83 return CERN;
84 return CSIM;
85 }
86
87 static gint
parse_yes_no(void)88 parse_yes_no(void)
89 {
90 char *token = strtok(NULL, " )");
91 return (gint) strcmp(token, "no");
92 }
93
94 static gint
parse_int(void)95 parse_int(void)
96 {
97 char *token = strtok(NULL, " )");
98 return (gint) atoi(token);
99 }
100
101 static void
parse_color(GdkColor * gdk_color)102 parse_color(GdkColor *gdk_color)
103 {
104 gdk_color->red = (guint16) parse_int();
105 gdk_color->green = (guint16) parse_int();
106 gdk_color->blue = (guint16) parse_int();
107 }
108
109 static void
parse_mru_entry(void)110 parse_mru_entry(void)
111 {
112 char *filename = strtok(NULL, " )");
113 mru_add(get_mru(), filename);
114 }
115
116 static void
parse_line(PreferencesData_t * data,char * line)117 parse_line(PreferencesData_t *data, char *line)
118 {
119 char *token;
120 ColorSelData_t *colors = &data->colors;
121
122 line++; /* Skip '(' */
123 token = strtok(line, " ");
124
125 if (!strcmp(token, "default-map-type")) {
126 data->default_map_type = parse_map_type();
127 }else if (!strcmp(token, "prompt-for-area-info")) {
128 data->prompt_for_area_info = parse_yes_no();
129 } else if (!strcmp(token, "require-default-url")) {
130 data->require_default_url = parse_yes_no();
131 } else if (!strcmp(token, "show-area-handle")) {
132 data->show_area_handle = parse_yes_no();
133 } else if (!strcmp(token, "keep-circles-round")) {
134 data->keep_circles_round = parse_yes_no();
135 } else if (!strcmp(token, "show-url-tip")) {
136 data->show_url_tip = parse_yes_no();
137 } else if (!strcmp(token, "use-doublesized")) {
138 data->use_doublesized = parse_yes_no();
139 } else if (!strcmp(token, "mru-size")) {
140 data->mru_size = parse_int();
141 if (data->mru_size < 1)
142 data->mru_size = 1;
143 } else if (!strcmp(token, "undo-levels")) {
144 data->undo_levels = parse_int();
145 if (data->undo_levels < 1)
146 data->undo_levels = 1;
147 } else if (!strcmp(token, "normal-fg-color")) {
148 parse_color(&colors->normal_fg);
149 } else if (!strcmp(token, "normal-bg-color")) {
150 parse_color(&colors->normal_bg);
151 } else if (!strcmp(token, "selected-fg-color")) {
152 parse_color(&colors->selected_fg);
153 } else if (!strcmp(token, "selected-bg-color")) {
154 parse_color(&colors->selected_bg);
155 } else if (!strcmp(token, "interactive-fg-color")) {
156 parse_color(&colors->interactive_fg);
157 } else if (!strcmp(token, "interactive-bg-color")) {
158 parse_color(&colors->interactive_bg);
159 } else if (!strcmp(token, "mru-entry")) {
160 parse_mru_entry();
161 } else {
162 /* Unrecognized, just ignore rest of line */
163 }
164 }
165
166 gboolean
preferences_load(PreferencesData_t * data)167 preferences_load(PreferencesData_t *data)
168 {
169 FILE *in;
170 char buf[256];
171 gchar *filename;
172
173 filename = gimp_personal_rc_file ("imagemaprc");
174
175 in = g_fopen(filename, "rb");
176 g_free(filename);
177 if (in) {
178 while (fgets(buf, sizeof(buf), in)) {
179 if (*buf != '\n' && *buf != '#') {
180 parse_line(data, buf);
181 }
182 }
183 fclose(in);
184 return TRUE;
185 }
186 return FALSE;
187 }
188
189 void
preferences_save(PreferencesData_t * data)190 preferences_save(PreferencesData_t *data)
191 {
192 FILE *out;
193 gchar *filename;
194 ColorSelData_t *colors = &data->colors;
195
196 filename = gimp_personal_rc_file ("imagemaprc");
197
198 out = g_fopen(filename, "wb");
199 if (out) {
200 fprintf(out, "# Image map plug-in resource file\n\n");
201 if (data->default_map_type == NCSA)
202 fprintf(out, "(default-map-type ncsa)\n");
203 else if (data->default_map_type == CERN)
204 fprintf(out, "(default-map-type cern)\n");
205 else
206 fprintf(out, "(default-map-type csim)\n");
207
208 fprintf(out, "(prompt-for-area-info %s)\n",
209 (data->prompt_for_area_info) ? "yes" : "no");
210 fprintf(out, "(require-default-url %s)\n",
211 (data->require_default_url) ? "yes" : "no");
212 fprintf(out, "(show-area-handle %s)\n",
213 (data->show_area_handle) ? "yes" : "no");
214 fprintf(out, "(keep-circles-round %s)\n",
215 (data->keep_circles_round) ? "yes" : "no");
216 fprintf(out, "(show-url-tip %s)\n",
217 (data->show_url_tip) ? "yes" : "no");
218 fprintf(out, "(use-doublesized %s)\n",
219 (data->use_doublesized) ? "yes" : "no");
220
221 fprintf(out, "(undo-levels %d)\n", data->undo_levels);
222 fprintf(out, "(mru-size %d)\n", data->mru_size);
223
224 fprintf(out, "(normal-fg-color %d %d %d)\n",
225 colors->normal_fg.red, colors->normal_fg.green,
226 colors->normal_fg.blue);
227 fprintf(out, "(normal-bg-color %d %d %d)\n",
228 colors->normal_bg.red, colors->normal_bg.green,
229 colors->normal_bg.blue);
230 fprintf(out, "(selected-fg-color %d %d %d)\n",
231 colors->selected_fg.red, colors->selected_fg.green,
232 colors->selected_fg.blue);
233 fprintf(out, "(selected-bg-color %d %d %d)\n",
234 colors->selected_bg.red, colors->selected_bg.green,
235 colors->selected_bg.blue);
236 fprintf(out, "(interactive-fg-color %d %d %d)\n",
237 colors->interactive_fg.red, colors->interactive_fg.green,
238 colors->interactive_fg.blue);
239 fprintf(out, "(interactive-bg-color %d %d %d)\n",
240 colors->interactive_bg.red, colors->interactive_bg.green,
241 colors->interactive_bg.blue);
242
243 mru_write(get_mru(), out);
244
245 fclose(out);
246 } else {
247 do_file_error_dialog( _("Couldn't save resource file:"), filename);
248 }
249 g_free(filename);
250 }
251
252 static void
preferences_ok_cb(gpointer data)253 preferences_ok_cb(gpointer data)
254 {
255 PreferencesDialog_t *param = (PreferencesDialog_t*) data;
256 PreferencesData_t *old_data = param->old_data;
257 ColorSelData_t *colors = &old_data->colors;
258 MRU_t *mru = get_mru();
259
260 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(param->cern)))
261 old_data->default_map_type = CERN;
262 else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(param->ncsa)))
263 old_data->default_map_type = NCSA;
264 else
265 old_data->default_map_type = CSIM;
266
267 old_data->prompt_for_area_info = gtk_toggle_button_get_active(
268 GTK_TOGGLE_BUTTON(param->prompt_for_area_info));
269 old_data->require_default_url = gtk_toggle_button_get_active(
270 GTK_TOGGLE_BUTTON(param->require_default_url));
271 old_data->show_area_handle = gtk_toggle_button_get_active(
272 GTK_TOGGLE_BUTTON(param->show_area_handle));
273 old_data->keep_circles_round = gtk_toggle_button_get_active(
274 GTK_TOGGLE_BUTTON(param->keep_circles_round));
275 old_data->show_url_tip = gtk_toggle_button_get_active(
276 GTK_TOGGLE_BUTTON(param->show_url_tip));
277 old_data->use_doublesized = gtk_toggle_button_get_active(
278 GTK_TOGGLE_BUTTON(param->use_doublesized));
279
280 old_data->mru_size =
281 gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(param->mru_size));
282 old_data->undo_levels =
283 gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(param->undo_levels));
284 mru_set_size(mru, old_data->mru_size);
285 menu_build_mru_items(mru);
286 command_list_set_undo_level(old_data->undo_levels);
287
288 get_button_colors (param, colors);
289
290 set_sash_size(old_data->use_doublesized);
291 preview_redraw();
292 }
293
294 static void
get_button_color(GtkWidget * button,GdkColor * color)295 get_button_color (GtkWidget *button, GdkColor *color)
296 {
297 GimpRGB rgb;
298 gimp_color_button_get_color (GIMP_COLOR_BUTTON (button), &rgb);
299 color->red = rgb.r * 0xffff;
300 color->green = rgb.g * 0xffff;
301 color->blue = rgb.b * 0xffff;
302 }
303
304 static void
get_button_colors(PreferencesDialog_t * dialog,ColorSelData_t * colors)305 get_button_colors(PreferencesDialog_t *dialog, ColorSelData_t *colors)
306 {
307 get_button_color (dialog->normal_fg, &colors->normal_fg);
308 get_button_color (dialog->normal_bg, &colors->normal_bg);
309 get_button_color (dialog->selected_fg, &colors->selected_fg);
310 get_button_color (dialog->selected_bg, &colors->selected_bg);
311 get_button_color (dialog->interactive_fg, &colors->interactive_fg);
312 get_button_color (dialog->interactive_bg, &colors->interactive_bg);
313 }
314
315 static void
set_button_color(GtkWidget * button,GdkColor * color)316 set_button_color (GtkWidget *button, GdkColor *color)
317 {
318 GimpRGB rgb;
319 gimp_rgb_set (&rgb, color->red, color->green, color->blue);
320 gimp_rgb_multiply (&rgb, 1.0 / 0xffff);
321 gimp_color_button_set_color (GIMP_COLOR_BUTTON (button), &rgb);
322 }
323
324 static void
set_button_colors(PreferencesDialog_t * dialog,ColorSelData_t * colors)325 set_button_colors(PreferencesDialog_t *dialog, ColorSelData_t *colors)
326 {
327 set_button_color (dialog->normal_fg, &colors->normal_fg);
328 set_button_color (dialog->normal_bg, &colors->normal_bg);
329 set_button_color (dialog->selected_fg, &colors->selected_fg);
330 set_button_color (dialog->selected_bg, &colors->selected_bg);
331 set_button_color (dialog->interactive_fg, &colors->interactive_fg);
332 set_button_color (dialog->interactive_bg, &colors->interactive_bg);
333 }
334
335 static GtkWidget*
create_tab(GtkWidget * notebook,const gchar * label,gint rows,gint cols)336 create_tab(GtkWidget *notebook, const gchar *label, gint rows, gint cols)
337 {
338 GtkWidget *table;
339 GtkWidget *vbox;
340
341 vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 1);
342 gtk_widget_show(vbox);
343
344 table = gtk_table_new(rows, cols, FALSE);
345 gtk_box_pack_start(GTK_BOX(vbox), table, FALSE, FALSE, 0);
346 gtk_container_set_border_width(GTK_CONTAINER(table), 12);
347 gtk_table_set_row_spacings(GTK_TABLE(table), 6);
348 gtk_table_set_col_spacings(GTK_TABLE(table), 6);
349 gtk_widget_show(table);
350
351 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), vbox,
352 gtk_label_new_with_mnemonic(label));
353
354 return table;
355 }
356
357 static void
create_general_tab(PreferencesDialog_t * data,GtkWidget * notebook)358 create_general_tab(PreferencesDialog_t *data, GtkWidget *notebook)
359 {
360 GtkWidget *table = create_tab(notebook, _("General"), 7, 2);
361 GtkWidget *frame;
362 GtkWidget *hbox;
363
364 frame = gimp_frame_new( _("Default Map Type"));
365 gtk_widget_show(frame);
366 gtk_table_attach_defaults(GTK_TABLE(table), frame, 0, 2, 0, 1);
367 hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 1);
368 gtk_container_add(GTK_CONTAINER(frame), hbox);
369 gtk_widget_show(hbox);
370 data->ncsa = gtk_radio_button_new_with_mnemonic_from_widget(NULL, "_NCSA");
371 gtk_box_pack_start(GTK_BOX(hbox), data->ncsa, TRUE, TRUE, 10);
372 gtk_widget_show(data->ncsa);
373 data->cern = gtk_radio_button_new_with_mnemonic_from_widget(
374 GTK_RADIO_BUTTON(data->ncsa), "C_ERN");
375 gtk_box_pack_start(GTK_BOX(hbox), data->cern, TRUE, TRUE, 10);
376 gtk_widget_show(data->cern);
377 data->csim = gtk_radio_button_new_with_mnemonic_from_widget(
378 GTK_RADIO_BUTTON(data->cern), "C_SIM");
379 gtk_box_pack_start(GTK_BOX(hbox), data->csim, TRUE, TRUE, 10);
380 gtk_widget_show(data->csim);
381
382 data->prompt_for_area_info =
383 create_check_button_in_table(table, 1, 0, _("_Prompt for area info"));
384 data->require_default_url =
385 create_check_button_in_table(table, 2, 0, _("_Require default URL"));
386 data->show_area_handle =
387 create_check_button_in_table(table, 3, 0, _("Show area _handles"));
388 data->keep_circles_round =
389 create_check_button_in_table(table, 4, 0, _("_Keep NCSA circles true"));
390 data->show_url_tip =
391 create_check_button_in_table(table, 5, 0, _("Show area URL _tip"));
392 data->use_doublesized =
393 create_check_button_in_table(table, 6, 0,
394 _("_Use double-sized grab handles"));
395 gtk_widget_show(frame);
396 }
397
398 static void
create_menu_tab(PreferencesDialog_t * data,GtkWidget * notebook)399 create_menu_tab(PreferencesDialog_t *data, GtkWidget *notebook)
400 {
401 GtkWidget *table = create_tab(notebook, _("Menu"), 2, 2);
402 GtkWidget *label;
403
404 label = create_label_in_table(table, 0, 0,
405 _("Number of _undo levels (1 - 99):"));
406 data->undo_levels = create_spin_button_in_table(table, label, 0, 1, 1, 1,
407 99);
408
409 label = create_label_in_table(table, 1, 0,
410 _("Number of M_RU entries (1 - 16):"));
411 data->mru_size = create_spin_button_in_table(table, label, 1, 1, 1, 1, 16);
412 }
413
414 static GtkWidget*
create_color_field(PreferencesDialog_t * data,GtkWidget * table,gint row,gint col)415 create_color_field(PreferencesDialog_t *data, GtkWidget *table, gint row,
416 gint col)
417 {
418 GimpRGB color = {0.0, 0.0, 0.0, 1.0};
419 GtkWidget *area = gimp_color_button_new (_("Select Color"), 16, 8, &color,
420 GIMP_COLOR_AREA_FLAT);
421 gimp_color_button_set_update (GIMP_COLOR_BUTTON (area), TRUE);
422 gtk_table_attach_defaults (GTK_TABLE (table), area, col, col + 1, row,
423 row + 1);
424 gtk_widget_show (area);
425
426 return area;
427 }
428
429 static void
create_colors_tab(PreferencesDialog_t * data,GtkWidget * notebook)430 create_colors_tab(PreferencesDialog_t *data, GtkWidget *notebook)
431 {
432 GtkWidget *table = create_tab(notebook, _("Colors"), 3, 3);
433
434 create_label_in_table(table, 0, 0, _("Normal:"));
435 data->normal_fg = create_color_field(data, table, 0, 1);
436 data->normal_bg = create_color_field(data, table, 0, 2);
437
438 create_label_in_table(table, 1, 0, _("Selected:"));
439 data->selected_fg = create_color_field(data, table, 1, 1);
440 data->selected_bg = create_color_field(data, table, 1, 2);
441
442 create_label_in_table(table, 2, 0, _("Interaction:"));
443 data->interactive_fg = create_color_field(data, table, 2, 1);
444 data->interactive_bg = create_color_field(data, table, 2, 2);
445 }
446
447 #ifdef _NOT_READY_YET_
448 static void
create_contiguous_regions_tab(PreferencesDialog_t * data,GtkWidget * notebook)449 create_contiguous_regions_tab(PreferencesDialog_t *data, GtkWidget *notebook)
450 {
451 GtkWidget *table = create_tab(notebook, _("Co_ntiguous Region"), 2, 2);
452 GtkWidget *label;
453
454 label = create_label_in_table(table, 0, 0,
455 _("_Threshold:"));
456 data->auto_convert =
457 create_check_button_in_table(table, 1, 0, _("_Automatically convert"));
458 }
459 #endif
460
461 static PreferencesDialog_t*
create_preferences_dialog(void)462 create_preferences_dialog(void)
463 {
464 PreferencesDialog_t *data = g_new(PreferencesDialog_t, 1);
465 DefaultDialog_t *dialog;
466 GtkWidget *notebook;
467
468 data->dialog = dialog = make_default_dialog( _("General Preferences"));
469 default_dialog_set_ok_cb(dialog, preferences_ok_cb, (gpointer) data);
470
471 data->notebook = notebook = gtk_notebook_new();
472 gtk_box_pack_start (GTK_BOX (data->dialog->vbox), notebook, TRUE, TRUE, 0);
473 create_general_tab(data, notebook);
474 create_menu_tab(data, notebook);
475 create_colors_tab(data, notebook);
476 #ifdef _NOT_READY_YET_
477 create_contiguous_regions_tab(data, notebook);
478 #endif
479 gtk_widget_show(notebook);
480
481 return data;
482 }
483
484 void
do_preferences_dialog(void)485 do_preferences_dialog(void)
486 {
487 static PreferencesDialog_t *dialog;
488 PreferencesData_t *old_data;
489 GtkWidget *map_type;
490
491 if (!dialog) {
492 dialog = create_preferences_dialog();
493 }
494 gtk_notebook_set_current_page(GTK_NOTEBOOK(dialog->notebook), 0);
495 dialog->old_data = old_data = get_preferences();
496
497 if (old_data->default_map_type == CERN)
498 map_type = dialog->cern;
499 else if (old_data->default_map_type == NCSA)
500 map_type = dialog->ncsa;
501 else
502 map_type = dialog->csim;
503 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(map_type), TRUE);
504
505 gtk_toggle_button_set_active(
506 GTK_TOGGLE_BUTTON(dialog->prompt_for_area_info),
507 old_data->prompt_for_area_info);
508 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog->require_default_url),
509 old_data->require_default_url);
510 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog->show_area_handle),
511 old_data->show_area_handle);
512 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog->keep_circles_round),
513 old_data->keep_circles_round);
514 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog->show_url_tip),
515 old_data->show_url_tip);
516 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog->use_doublesized),
517 old_data->use_doublesized);
518
519 gtk_spin_button_set_value(GTK_SPIN_BUTTON(dialog->undo_levels),
520 old_data->undo_levels);
521 gtk_spin_button_set_value(GTK_SPIN_BUTTON(dialog->mru_size),
522 old_data->mru_size);
523
524 set_button_colors(dialog, &old_data->colors);
525
526 default_dialog_show(dialog->dialog);
527 }
528