1 /*
2  * This is a plug-in for 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 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 <stdio.h>
26 
27 #include <gtk/gtk.h>
28 
29 #include "libgimp/gimp.h"
30 #include "libgimpwidgets/gimpwidgets.h"
31 
32 #include "imap_commands.h"
33 #include "imap_default_dialog.h"
34 #include "imap_main.h"
35 #include "imap_rectangle.h"
36 #include "imap_table.h"
37 
38 #include "libgimp/stdplugins-intl.h"
39 
40 typedef struct {
41    DefaultDialog_t      *dialog;
42 
43    ObjectList_t         *list;
44    gint32                drawable_id;
45 
46    GtkWidget            *alternate;
47    GtkWidget            *all;
48    GtkWidget            *left_border;
49    GtkWidget            *right_border;
50    GtkWidget            *upper_border;
51    GtkWidget            *lower_border;
52    GtkWidget            *url;
53 } GimpGuidesDialog_t;
54 
55 static gint
guide_sort_func(gconstpointer a,gconstpointer b)56 guide_sort_func(gconstpointer a, gconstpointer b)
57 {
58    return GPOINTER_TO_INT(a) - GPOINTER_TO_INT(b);
59 }
60 
61 static void
gimp_guides_ok_cb(gpointer data)62 gimp_guides_ok_cb(gpointer data)
63 {
64    GimpGuidesDialog_t *param = (GimpGuidesDialog_t*) data;
65    gint  guide_num;
66    GSList *hguides, *hg;
67    GSList *vguides, *vg;
68    gboolean all;
69    const gchar *url;
70    gint32 image_ID = gimp_item_get_image (param->drawable_id);
71 
72    /* First get some dialog values */
73 
74    all = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(param->all));
75 
76    if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(param->left_border)))
77       vguides = g_slist_append(NULL, GINT_TO_POINTER(0));
78    else
79       vguides = NULL;
80 
81    if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(param->right_border)))
82       vguides = g_slist_append(vguides,
83                                GINT_TO_POINTER(gimp_image_width(image_ID)));
84 
85    if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(param->upper_border)))
86       hguides = g_slist_append(NULL, GINT_TO_POINTER(0));
87    else
88       hguides = NULL;
89 
90    if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(param->lower_border)))
91       hguides = g_slist_append(hguides,
92                                GINT_TO_POINTER(gimp_image_height(image_ID)));
93 
94    url = gtk_entry_get_text(GTK_ENTRY(param->url));
95 
96    /* Next get all the GIMP guides */
97 
98    guide_num = gimp_image_find_next_guide(image_ID, 0);
99 
100    while (guide_num > 0) {
101       gint position = gimp_image_get_guide_position(image_ID, guide_num);
102 
103       if (gimp_image_get_guide_orientation(image_ID, guide_num)
104           == GIMP_ORIENTATION_HORIZONTAL) {
105          hguides = g_slist_insert_sorted(hguides, GINT_TO_POINTER(position),
106                                          guide_sort_func);
107       } else {                  /* GIMP_ORIENTATION_VERTICAL */
108          vguides = g_slist_insert_sorted(vguides, GINT_TO_POINTER(position),
109                                          guide_sort_func);
110       }
111       guide_num = gimp_image_find_next_guide(image_ID, guide_num);
112    }
113 
114    /* Create the areas */
115 
116    subcommand_start(_("Use Gimp Guides"));
117 
118    for (hg = hguides; hg && hg->next;
119         hg = (all) ? hg->next : hg->next->next) {
120       gint y = GPOINTER_TO_INT(hg->data);
121       gint height = GPOINTER_TO_INT(hg->next->data) - y;
122       for (vg = vguides; vg && vg->next;
123            vg = (all) ? vg->next : vg->next->next) {
124          gint x = GPOINTER_TO_INT(vg->data);
125          gint width = GPOINTER_TO_INT(vg->next->data) - x;
126          Object_t *obj = create_rectangle(x, y, width, height);
127          Command_t *command = create_command_new(param->list, obj);
128 
129          object_set_url(obj, url);
130          command_execute(command);
131       }
132    }
133 
134    subcommand_end();
135    preview_redraw();
136 }
137 
138 static GimpGuidesDialog_t*
make_gimp_guides_dialog(void)139 make_gimp_guides_dialog(void)
140 {
141    GimpGuidesDialog_t *data = g_new(GimpGuidesDialog_t, 1);
142    DefaultDialog_t *dialog;
143    GtkWidget *table, *frame, *hbox, *vbox;
144    GtkWidget *label;
145 
146    dialog = data->dialog = make_default_dialog(_("Use Gimp Guides"));
147    default_dialog_set_ok_cb(dialog, gimp_guides_ok_cb, data);
148    table = default_dialog_add_table(dialog, 3, 2);
149 
150    frame = gimp_frame_new(_("Create"));
151    gtk_widget_show(frame);
152    gtk_table_attach_defaults(GTK_TABLE(table), frame, 0, 1, 0, 1);
153 
154    hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
155    gtk_container_add(GTK_CONTAINER(frame), hbox);
156    gtk_widget_show(hbox);
157 
158    data->alternate =
159       gtk_radio_button_new_with_mnemonic_from_widget(NULL, _("Al_ternate"));
160    gtk_box_pack_start(GTK_BOX(hbox), data->alternate, FALSE, FALSE, 0);
161    gtk_widget_show(data->alternate);
162 
163    data->all = gtk_radio_button_new_with_mnemonic_from_widget(
164       GTK_RADIO_BUTTON(data->alternate), _("A_ll"));
165    gtk_box_pack_start(GTK_BOX(hbox), data->all, FALSE, FALSE, 0);
166    gtk_widget_show(data->all);
167 
168    frame = gimp_frame_new(_("Add Additional Guides"));
169    gtk_widget_show(frame);
170    gtk_table_attach_defaults(GTK_TABLE(table), frame, 0, 1, 1, 2);
171 
172    vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 2);
173    gtk_container_add(GTK_CONTAINER(frame), vbox);
174    gtk_widget_show(vbox);
175 
176    data->left_border = gtk_check_button_new_with_mnemonic(_("L_eft border"));
177    gtk_container_add(GTK_CONTAINER(vbox), data->left_border);
178    gtk_widget_show(data->left_border);
179 
180    data->right_border = gtk_check_button_new_with_mnemonic(_("_Right border"));
181    gtk_container_add(GTK_CONTAINER(vbox), data->right_border);
182    gtk_widget_show(data->right_border);
183 
184    data->upper_border = gtk_check_button_new_with_mnemonic(_("_Upper border"));
185    gtk_container_add(GTK_CONTAINER(vbox), data->upper_border);
186    gtk_widget_show(data->upper_border);
187 
188    data->lower_border = gtk_check_button_new_with_mnemonic(_("Lo_wer border"));
189    gtk_container_add(GTK_CONTAINER(vbox), data->lower_border);
190    gtk_widget_show(data->lower_border);
191 
192    hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
193    gtk_table_attach_defaults(GTK_TABLE(table), hbox, 0, 2, 2, 3);
194    gtk_widget_show(hbox);
195 
196    label = gtk_label_new_with_mnemonic(_("_Base URL:"));
197    gtk_widget_show(label);
198    gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
199 
200    data->url = gtk_entry_new();
201    gtk_container_add(GTK_CONTAINER(hbox), data->url);
202    gtk_widget_show(data->url);
203 
204    gtk_label_set_mnemonic_widget (GTK_LABEL (label), data->url);
205 
206    return data;
207 }
208 
209 static void
init_gimp_guides_dialog(GimpGuidesDialog_t * dialog,ObjectList_t * list,gint32 drawable_id)210 init_gimp_guides_dialog(GimpGuidesDialog_t *dialog, ObjectList_t *list,
211                         gint32 drawable_id)
212 {
213    dialog->list = list;
214    dialog->drawable_id = drawable_id;
215 }
216 
217 static void
do_create_gimp_guides_dialog(ObjectList_t * list,gint32 drawable_id)218 do_create_gimp_guides_dialog(ObjectList_t *list, gint32 drawable_id)
219 {
220    static GimpGuidesDialog_t *dialog;
221 
222    if (!dialog)
223       dialog = make_gimp_guides_dialog();
224 
225    init_gimp_guides_dialog(dialog, list, drawable_id);
226    default_dialog_show(dialog->dialog);
227 }
228 
229 static CmdExecuteValue_t gimp_guides_command_execute(Command_t *parent);
230 
231 static CommandClass_t gimp_guides_command_class = {
232    NULL,                        /* guides_command_destruct */
233    gimp_guides_command_execute,
234    NULL,                        /* guides_command_undo */
235    NULL                         /* guides_command_redo */
236 };
237 
238 typedef struct {
239   Command_t parent;
240   ObjectList_t *list;
241   gint32 drawable_id;
242 } GimpGuidesCommand_t;
243 
244 Command_t*
gimp_guides_command_new(ObjectList_t * list,gint32 drawable_id)245 gimp_guides_command_new(ObjectList_t *list, gint32 drawable_id)
246 {
247    GimpGuidesCommand_t *command = g_new(GimpGuidesCommand_t, 1);
248    command->list = list;
249    command->drawable_id = drawable_id;
250    return command_init(&command->parent, _("Use Gimp Guides"),
251                        &gimp_guides_command_class);
252 }
253 
254 static CmdExecuteValue_t
gimp_guides_command_execute(Command_t * parent)255 gimp_guides_command_execute(Command_t *parent)
256 {
257    GimpGuidesCommand_t *command = (GimpGuidesCommand_t*) parent;
258    do_create_gimp_guides_dialog(command->list, command->drawable_id);
259    return CMD_DESTRUCT;
260 }
261