summaryrefslogtreecommitdiffstats
path: root/plug-ins/imagemap/imap_main.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--plug-ins/imagemap/imap_main.c1306
1 files changed, 1306 insertions, 0 deletions
diff --git a/plug-ins/imagemap/imap_main.c b/plug-ins/imagemap/imap_main.c
new file mode 100644
index 0000000..8254a87
--- /dev/null
+++ b/plug-ins/imagemap/imap_main.c
@@ -0,0 +1,1306 @@
+/*
+ * This is a plug-in for GIMP.
+ *
+ * Generates clickable image maps.
+ *
+ * Copyright (C) 1998-2006 Maurits Rijk m.rijk@chello.nl
+ *
+ * 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 3 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, see <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <glib/gstdio.h>
+
+#include <gtk/gtk.h>
+#include <gdk/gdkkeysyms.h> /* for keyboard values */
+
+#include <libgimp/gimp.h>
+#include <libgimp/gimpui.h>
+
+#include "imap_about.h"
+#include "imap_circle.h"
+#include "imap_commands.h"
+#include "imap_default_dialog.h"
+#include "imap_edit_area_info.h"
+#include "imap_file.h"
+#include "imap_main.h"
+#include "imap_menu.h"
+#include "imap_misc.h"
+#include "imap_object.h"
+#include "imap_polygon.h"
+#include "imap_preview.h"
+#include "imap_rectangle.h"
+#include "imap_selection.h"
+#include "imap_settings.h"
+#include "imap_source.h"
+#include "imap_statusbar.h"
+#include "imap_stock.h"
+#include "imap_string.h"
+
+#include "libgimp/stdplugins-intl.h"
+
+
+#define MAX_ZOOM_FACTOR 8
+#define ZOOMED(x) (_zoom_factor * (x))
+#define GET_REAL_COORD(x) ((x) / _zoom_factor)
+
+static gint zoom_in (void);
+static gint zoom_out (void);
+
+
+/* Global variables */
+static MapInfo_t _map_info;
+static PreferencesData_t _preferences = {CSIM, TRUE, FALSE, TRUE, TRUE, FALSE,
+FALSE, TRUE, DEFAULT_UNDO_LEVELS, DEFAULT_MRU_SIZE};
+static MRU_t *_mru;
+
+static gint32 _drawable_id;
+static GdkCursorType _cursor = GDK_TOP_LEFT_ARROW;
+static gboolean _show_url = TRUE;
+static gchar *_filename = NULL;
+static gchar *_image_name;
+static gint _image_width;
+static gint _image_height;
+static GtkWidget *_dlg;
+static Preview_t *_preview;
+static Selection_t *_selection;
+static StatusBar_t *_statusbar;
+static ObjectList_t *_shapes;
+static gint _zoom_factor = 1;
+static gboolean (*_button_press_func)(GtkWidget*, GdkEventButton*, gpointer);
+static gpointer _button_press_param;
+
+/* Declare local functions. */
+static void query (void);
+static void run (const gchar *name,
+ gint nparams,
+ const GimpParam *param,
+ gint *nreturn_vals,
+ GimpParam **return_vals);
+static gint dialog (gint32 drawable_id);
+
+const GimpPlugInInfo PLUG_IN_INFO = {
+ NULL, /* init_proc */
+ NULL, /* quit_proc */
+ query, /* query_proc */
+ run, /* run_proc */
+};
+
+static int run_flag = 0;
+
+
+MAIN ()
+
+static void query(void)
+{
+ static const GimpParamDef args[] = {
+ {GIMP_PDB_INT32, "run-mode", "The run mode { RUN-INTERACTIVE (0) }"},
+ {GIMP_PDB_IMAGE, "image", "Input image (unused)"},
+ {GIMP_PDB_DRAWABLE, "drawable", "Input drawable"},
+ };
+ static const GimpParamDef *return_vals = NULL;
+ static int nreturn_vals = 0;
+
+ gimp_install_procedure(PLUG_IN_PROC,
+ N_("Create a clickable imagemap"),
+ "",
+ "Maurits Rijk",
+ "Maurits Rijk",
+ "1998-2005",
+ N_("_Image Map..."),
+ "RGB*, GRAY*, INDEXED*",
+ GIMP_PLUGIN,
+ G_N_ELEMENTS (args), nreturn_vals,
+ args, return_vals);
+
+ gimp_plugin_menu_register (PLUG_IN_PROC, "<Image>/Filters/Web");
+}
+
+static void
+run (const gchar *name,
+ gint n_params,
+ const GimpParam *param,
+ gint *nreturn_vals,
+ GimpParam **return_vals)
+{
+ static GimpParam values[1];
+ GimpRunMode run_mode;
+ gint32 drawable_id;
+ GimpPDBStatusType status = GIMP_PDB_SUCCESS;
+
+ INIT_I18N ();
+ gegl_init (NULL, NULL);
+
+ *nreturn_vals = 1;
+ *return_vals = values;
+
+ run_mode = param[0].data.d_int32;
+ drawable_id = param[2].data.d_drawable;
+
+ _drawable_id = drawable_id;
+ _image_name = gimp_image_get_name(param[1].data.d_image);
+ _image_width = gimp_image_width(param[1].data.d_image);
+ _image_height = gimp_image_height(param[1].data.d_image);
+
+ _map_info.color = gimp_drawable_is_rgb(drawable_id);
+
+ if (run_mode == GIMP_RUN_INTERACTIVE) {
+ if (!dialog(drawable_id)) {
+ /* The dialog was closed, or something similarly evil happened. */
+ status = GIMP_PDB_EXECUTION_ERROR;
+ }
+ }
+
+ values[0].type = GIMP_PDB_STATUS;
+ values[0].data.d_status = status;
+}
+
+GtkWidget*
+get_dialog(void)
+{
+ return _dlg;
+}
+
+MRU_t*
+get_mru(void)
+{
+ if (!_mru)
+ _mru = mru_create();
+ return _mru;
+}
+
+MapInfo_t*
+get_map_info(void)
+{
+ return &_map_info;
+}
+
+PreferencesData_t*
+get_preferences(void)
+{
+ return &_preferences;
+}
+
+static void
+init_preferences(void)
+{
+ ColorSelData_t *colors = &_preferences.colors;
+
+ colors->normal_fg.red = 0;
+ colors->normal_fg.green = 0xFFFF;
+ colors->normal_fg.blue = 0;
+
+ colors->normal_bg.red = 0;
+ colors->normal_bg.green = 0;
+ colors->normal_bg.blue = 0xFFFF;
+
+ colors->selected_fg.red = 0xFFFF;
+ colors->selected_fg.green = 0;
+ colors->selected_fg.blue = 0;
+
+ colors->selected_bg.red = 0;
+ colors->selected_bg.green = 0;
+ colors->selected_bg.blue = 0xFFFF;
+
+ colors->interactive_fg.red = 0xFFFF;
+ colors->interactive_fg.green = 0;
+ colors->interactive_fg.blue = 0xFFFF;
+
+ colors->interactive_bg.red = 0xFFFF;
+ colors->interactive_bg.green = 0xFFFF;
+ colors->interactive_bg.blue = 0;
+
+ preferences_load(&_preferences);
+
+ mru_set_size(_mru, _preferences.mru_size);
+ command_list_set_undo_level(_preferences.undo_levels);
+}
+
+gint
+get_image_width(void)
+{
+ return _image_width;
+}
+
+gint
+get_image_height(void)
+{
+ return _image_height;
+}
+
+void
+set_busy_cursor(void)
+{
+ preview_set_cursor(_preview, GDK_WATCH);
+}
+
+void
+remove_busy_cursor(void)
+{
+ gdk_window_set_cursor(gtk_widget_get_window (_dlg), NULL);
+}
+
+static gint
+zoom_in(void)
+{
+ if (_zoom_factor < MAX_ZOOM_FACTOR) {
+ set_zoom(_zoom_factor + 1);
+ menu_set_zoom(_zoom_factor);
+ }
+ return _zoom_factor;
+}
+
+static gint
+zoom_out(void)
+{
+ if (_zoom_factor > 1) {
+ set_zoom(_zoom_factor - 1);
+ menu_set_zoom(_zoom_factor);
+ }
+ return _zoom_factor;
+}
+
+void
+set_zoom(gint zoom_factor)
+{
+ set_busy_cursor();
+ _zoom_factor = zoom_factor;
+ preview_zoom(_preview, zoom_factor);
+ statusbar_set_zoom(_statusbar, zoom_factor);
+ remove_busy_cursor();
+}
+
+gint
+get_real_coord(gint coord)
+{
+ return GET_REAL_COORD(coord);
+}
+
+void
+draw_line(cairo_t *cr, gint x1, gint y1, gint x2, gint y2)
+{
+ cairo_move_to (cr, ZOOMED (x1) + .5, ZOOMED (y1) + .5);
+ cairo_line_to (cr, ZOOMED (x2) + .5, ZOOMED (y2) + .5);
+ cairo_stroke (cr);
+}
+
+void
+draw_rectangle(cairo_t *cr, gboolean filled, gint x, gint y,
+ gint width, gint height)
+{
+ cairo_rectangle (cr, ZOOMED (x) + (filled ? 0. : .5),
+ ZOOMED (y) + (filled ? 0. : .5),
+ ZOOMED (width), ZOOMED (height));
+ if (filled)
+ cairo_fill (cr);
+ else
+ cairo_stroke (cr);
+}
+
+void
+draw_circle(cairo_t *cr, gint x, gint y, gint r)
+{
+ cairo_arc (cr, ZOOMED (x), ZOOMED (y), ZOOMED (r), 0., 2 * G_PI);
+ cairo_stroke (cr);
+}
+
+void
+draw_polygon(cairo_t *cr, GList *list)
+{
+ GList *p;
+
+ for (p = list; p; p = p->next) {
+ GdkPoint *src = (GdkPoint*) p->data;
+ cairo_line_to (cr, ZOOMED (src->x) + .5, ZOOMED (src->y) + .5);
+ }
+ cairo_close_path (cr);
+ cairo_stroke (cr);
+}
+
+void
+set_preview_color (GtkRadioAction *action, GtkRadioAction *current,
+ gpointer user_data)
+{
+ _map_info.show_gray = (gtk_radio_action_get_current_value (current) == 1);
+ set_zoom(_zoom_factor);
+}
+
+void
+preview_redraw(void)
+{
+ gtk_widget_queue_draw(_preview->preview);
+}
+
+void
+set_zoom_factor (GtkRadioAction *action, GtkRadioAction *current,
+ gpointer user_data)
+{
+ gint factor = gtk_radio_action_get_current_value (current);
+ set_zoom (factor + 1);
+}
+
+const gchar *
+get_image_name(void)
+{
+ return _image_name;
+}
+
+const char*
+get_filename(void)
+{
+ return _filename;
+}
+
+static gboolean
+arrow_on_button_press (GtkWidget *widget,
+ GdkEventButton *event,
+ gpointer data)
+{
+ if (gdk_event_triggers_context_menu ((GdkEvent *) event))
+ {
+ do_popup_menu (event);
+ }
+ else if (event->button == 1)
+ {
+ if (event->type == GDK_2BUTTON_PRESS)
+ edit_shape((gint) event->x, (gint) event->y);
+ else
+ select_shape(widget, event);
+ }
+
+ return FALSE;
+}
+
+static void
+set_arrow_func(void)
+{
+ _button_press_func = arrow_on_button_press;
+ _cursor = GDK_TOP_LEFT_ARROW;
+}
+
+static void
+set_object_func(gboolean (*func)(GtkWidget*, GdkEventButton*,
+ gpointer), gpointer param)
+{
+ _button_press_func = func;
+ _button_press_param = param;
+ _cursor = GDK_CROSSHAIR;
+}
+
+void
+set_func(GtkRadioAction *action, GtkRadioAction *current,
+ gpointer user_data)
+{
+ gint value = gtk_radio_action_get_current_value (current);
+ switch (value)
+ {
+ case 0:
+ set_arrow_func();
+ break;
+ case 1:
+ set_object_func(object_on_button_press, get_rectangle_factory);
+ break;
+ case 2:
+ set_object_func(object_on_button_press, get_circle_factory);
+ break;
+ case 3:
+ set_object_func(object_on_button_press, get_polygon_factory);
+ break;
+ default:
+ break;
+ }
+}
+
+void
+add_shape(Object_t *obj)
+{
+ object_list_append(_shapes, obj);
+}
+
+ObjectList_t*
+get_shapes(void)
+{
+ return _shapes;
+}
+
+void
+update_shape(Object_t *obj)
+{
+ object_list_update(_shapes, obj);
+}
+
+void
+do_edit_selected_shape(void)
+{
+ object_list_edit_selected(_shapes);
+}
+
+void
+do_popup_menu(GdkEventButton *event)
+{
+ gint x = GET_REAL_COORD((gint) event->x);
+ gint y = GET_REAL_COORD((gint) event->y);
+ Object_t *obj = object_list_find(_shapes, x, y);
+ if (obj) {
+ obj->class->do_popup(obj, event);
+ } else {
+ do_main_popup_menu(event);
+ }
+}
+
+static void
+set_all_sensitivities(void)
+{
+ gint count = object_list_nr_selected(_shapes);
+ menu_shapes_selected(count);
+}
+
+static void
+main_set_title(const char *filename)
+{
+ char *title, *p;
+
+ g_strreplace(&_filename, filename);
+ p = filename ? g_filename_display_basename (filename) : (gchar *) _("<Untitled>");
+ title = g_strdup_printf("%s - Image Map", p);
+ if (filename)
+ g_free (p);
+ gtk_window_set_title(GTK_WINDOW(_dlg), title);
+ g_free(title);
+}
+
+void
+main_set_dimension(gint width, gint height)
+{
+ statusbar_set_dimension(_statusbar,
+ width / _zoom_factor, height / _zoom_factor);
+}
+
+void
+main_clear_dimension(void)
+{
+ statusbar_clear_dimension(_statusbar);
+}
+
+void
+show_url(void)
+{
+ _show_url = TRUE;
+}
+
+void
+hide_url(void)
+{
+ _show_url = FALSE;
+ statusbar_clear_status(_statusbar);
+}
+
+void
+select_shape(GtkWidget *widget, GdkEventButton *event)
+{
+ Object_t *obj;
+ gint x = GET_REAL_COORD((gint) event->x);
+ gint y = GET_REAL_COORD((gint) event->y);
+ MoveSashFunc_t sash_func;
+
+ obj = object_list_near_sash(_shapes, x, y, &sash_func);
+ if (obj) { /* Start resizing */
+ Command_t *command = move_sash_command_new(widget, obj, x, y, sash_func);
+ command_execute(command);
+ } else {
+ Command_t *command;
+
+ obj = object_list_find(_shapes, x, y);
+ if (obj) {
+ if (event->state & GDK_SHIFT_MASK) {
+ if (obj->selected)
+ command = unselect_command_new(obj);
+ else
+ command = select_command_new(obj);
+ } else { /* No Shift key pressed */
+ if (obj->selected) {
+ command = unselect_all_command_new(_shapes, obj);
+ } else {
+ Command_t *sub_command;
+
+ command = subcommand_start(NULL);
+ sub_command = unselect_all_command_new(_shapes, NULL);
+ command_add_subcommand(command, sub_command);
+ sub_command = select_command_new(obj);
+ command_add_subcommand(command, sub_command);
+ command_set_name(command, sub_command->name);
+ subcommand_end();
+ }
+ }
+ command_execute(command);
+
+ command = move_command_new(_preview, obj, x, y);
+ command_execute(command);
+ } else { /* Start selection rectangle */
+ command = select_region_command_new(widget, _shapes, x, y);
+ command_execute(command);
+ }
+ }
+}
+
+void
+edit_shape(gint x, gint y)
+{
+ Object_t *obj;
+
+ x = GET_REAL_COORD(x);
+ y = GET_REAL_COORD(y);
+
+ obj = object_list_find(_shapes, x, y);
+ if (obj) {
+ object_select(obj);
+ object_edit(obj, TRUE);
+ }
+}
+
+void
+do_zoom_in(void)
+{
+ gint factor = zoom_in();
+ menu_set_zoom_sensitivity(factor);
+}
+
+void
+do_zoom_out(void)
+{
+ gint factor = zoom_out();
+ menu_set_zoom_sensitivity(factor);
+}
+
+void
+draw_shapes(cairo_t *cr)
+{
+ object_list_draw(_shapes, cr);
+}
+
+static void
+clear_map_info(void)
+{
+ const gchar *author = g_get_real_name();
+
+ if (!*author)
+ author = g_get_user_name();
+ g_strreplace(&_map_info.image_name, _image_name);
+ g_strreplace(&_map_info.title, "map");
+ g_strreplace(&_map_info.author, author);
+ g_strreplace(&_map_info.default_url, "");
+ g_strreplace(&_map_info.description, "");
+
+ _map_info.map_format = _preferences.default_map_type;
+ _map_info.show_gray = FALSE;
+}
+
+static void
+do_data_changed_dialog(void (*continue_cb)(gpointer), gpointer param)
+{
+ GtkWidget *dialog = gtk_message_dialog_new
+ (NULL,
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_QUESTION,
+ GTK_BUTTONS_YES_NO,
+ _("Some data has been changed!"));
+ gtk_message_dialog_format_secondary_text
+ (GTK_MESSAGE_DIALOG (dialog),
+ _("Do you really want to discard your changes?"));
+
+ if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_YES)
+ continue_cb (param);
+
+ gtk_widget_destroy (dialog);
+}
+
+static void
+check_if_changed(void (*func)(gpointer), gpointer param)
+{
+ if (object_list_get_changed (_shapes))
+ do_data_changed_dialog (func, param);
+ else
+ func (param);
+}
+
+static void
+close_current(void)
+{
+ selection_freeze(_selection);
+ object_list_remove_all(_shapes);
+ selection_thaw(_selection);
+ clear_map_info();
+ main_set_title(NULL);
+ set_all_sensitivities();
+ preview_redraw();
+ object_list_clear_changed(_shapes);
+ command_list_remove_all();
+}
+
+static void
+really_close(gpointer data)
+{
+ close_current();
+}
+
+void
+do_close(void)
+{
+ check_if_changed(really_close, NULL);
+}
+
+static void
+really_quit(gpointer data)
+{
+ preferences_save(&_preferences);
+ run_flag = 1;
+ gtk_widget_destroy(_dlg);
+}
+
+void
+do_quit(void)
+{
+ check_if_changed(really_quit, NULL);
+}
+
+void
+do_undo(void)
+{
+ selection_freeze(_selection);
+ last_command_undo();
+ selection_thaw(_selection);
+ preview_redraw();
+}
+
+void
+do_redo(void)
+{
+ selection_freeze(_selection);
+ last_command_redo();
+ selection_thaw(_selection);
+ preview_redraw();
+}
+
+void
+save(void)
+{
+ if (_filename)
+ save_as(_filename);
+ else
+ do_file_save_as_dialog();
+}
+
+static void
+write_cern_comment(gpointer param, OutputFunc_t output)
+{
+ output(param, "rect (4096,4096) (4096,4096) imap:#$");
+}
+
+static void
+save_as_cern(gpointer param, OutputFunc_t output)
+{
+ char *p;
+ gchar *description;
+ gchar *next_token;
+
+ write_cern_comment(param, output);
+ output(param, "-:Image map file created by GIMP Image Map plug-in\n");
+ write_cern_comment(param, output);
+ output(param, "-:GIMP Image Map plug-in by Maurits Rijk\n");
+ write_cern_comment(param, output);
+ output(param, "-:Please do not edit lines starting with \"#$\"\n");
+ write_cern_comment(param, output);
+ output(param, "VERSION:2.3\n");
+ write_cern_comment(param, output);
+ output(param, "TITLE:%s\n", _map_info.title);
+ write_cern_comment(param, output);
+ output(param, "AUTHOR:%s\n", _map_info.author);
+ write_cern_comment(param, output);
+ output(param, "FORMAT:cern\n");
+
+ description = g_strdup(_map_info.description);
+ next_token = description;
+ for (p = strtok (next_token, "\n"); p; p = strtok(NULL, "\n")) {
+ write_cern_comment(param, output);
+ output(param, "DESCRIPTION:%s\n", p);
+ }
+ g_free(description);
+
+ if (*_map_info.default_url)
+ output(param, "default %s\n", _map_info.default_url);
+ object_list_write_cern(_shapes, param, output);
+}
+
+static void
+save_as_csim(gpointer param, OutputFunc_t output)
+{
+ char *p;
+ gchar *description;
+
+ output(param, "<img src=\"%s\" width=\"%d\" height=\"%d\" border=\"0\" "
+ "usemap=\"#%s\" />\n\n", _map_info.image_name,
+ _image_width, _image_height, _map_info.title);
+ output(param, "<map name=\"%s\">\n", _map_info.title);
+ output(param,
+ "<!-- #$-:Image map file created by GIMP Image Map plug-in -->\n");
+ output(param, "<!-- #$-:GIMP Image Map plug-in by Maurits Rijk -->\n");
+ output(param,
+ "<!-- #$-:Please do not edit lines starting with \"#$\" -->\n");
+ output(param, "<!-- #$VERSION:2.3 -->\n");
+ output(param, "<!-- #$AUTHOR:%s -->\n", _map_info.author);
+
+ description = g_strdup(_map_info.description);
+ for (p = strtok(description, "\n"); p; p = strtok(NULL, "\n"))
+ output(param, "<!-- #$DESCRIPTION:%s -->\n", p);
+ g_free(description);
+
+ object_list_write_csim(_shapes, param, output);
+ if (*_map_info.default_url)
+ output(param, "<area shape=\"default\" href=\"%s\" />\n",
+ _map_info.default_url);
+ output(param, "</map>\n");
+}
+
+static void
+save_as_ncsa(gpointer param, OutputFunc_t output)
+{
+ char *p;
+ gchar *description;
+
+ output(param, "#$-:Image map file created by GIMP Image Map plug-in\n");
+ output(param, "#$-:GIMP Image Map plug-in by Maurits Rijk\n");
+ output(param, "#$-:Please do not edit lines starting with \"#$\"\n");
+ output(param, "#$VERSION:2.3\n");
+ output(param, "#$TITLE:%s\n", _map_info.title);
+ output(param, "#$AUTHOR:%s\n", _map_info.author);
+ output(param, "#$FORMAT:ncsa\n");
+
+ description = g_strdup(_map_info.description);
+ for (p = strtok(description, "\n"); p; p = strtok(NULL, "\n"))
+ output(param, "#$DESCRIPTION:%s\n", p);
+ g_free(description);
+
+ if (*_map_info.default_url)
+ output(param, "default %s\n", _map_info.default_url);
+ object_list_write_ncsa(_shapes, param, output);
+}
+
+static void save_to_file (gpointer param,
+ const char *format,
+ ...) G_GNUC_PRINTF(2,3);
+
+static void
+save_to_file(gpointer param, const char* format, ...)
+{
+ va_list ap;
+
+ va_start(ap, format);
+ vfprintf((FILE*)param, format, ap);
+ va_end(ap);
+}
+
+void
+dump_output(gpointer param, OutputFunc_t output)
+{
+ if (_map_info.map_format == NCSA)
+ save_as_ncsa(param, output);
+ else if (_map_info.map_format == CERN)
+ save_as_cern(param, output);
+ else if (_map_info.map_format == CSIM)
+ save_as_csim(param, output);
+}
+
+void
+save_as(const gchar *filename)
+{
+ FILE *out = g_fopen(filename, "w");
+ if (out) {
+ dump_output(out, save_to_file);
+ fclose(out);
+
+ statusbar_set_status(_statusbar, _("File \"%s\" saved."), filename);
+ main_set_title(filename);
+ object_list_clear_changed(_shapes);
+ } else {
+ do_file_error_dialog( _("Couldn't save file:"), filename);
+ }
+}
+
+static void
+do_image_size_changed_dialog(void)
+{
+ GtkWidget *dialog = gtk_message_dialog_new_with_markup
+ (NULL,
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_QUESTION,
+ GTK_BUTTONS_YES_NO,
+ "<span weight=\"bold\" size=\"larger\">%s</span>\n\n%s",
+ _("Image size has changed."),
+ _("Resize area's?"));
+
+ if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_YES)
+ {
+ gint per_x = _image_width * 100 / _map_info.old_image_width;
+ gint per_y = _image_height * 100 / _map_info.old_image_height;
+ object_list_resize(_shapes, per_x, per_y);
+ }
+
+ preview_redraw();
+ gtk_widget_destroy (dialog);
+}
+
+static void
+really_load(gpointer data)
+{
+ gchar *filename = (gchar*) data;
+ close_current();
+
+ selection_freeze(_selection);
+ _map_info.old_image_width = _image_width;
+ _map_info.old_image_height = _image_height;
+ if (load_csim(filename)) {
+ _map_info.map_format = CSIM;
+ if (_image_width != _map_info.old_image_width ||
+ _image_height != _map_info.old_image_height) {
+ do_image_size_changed_dialog();
+ }
+ } else if (load_ncsa(filename)) {
+ _map_info.map_format = NCSA;
+ } else if (load_cern(filename)) {
+ _map_info.map_format = CERN;
+ } else {
+ do_file_error_dialog( _("Couldn't read file:"), filename);
+ selection_thaw(_selection);
+ close_current();
+ return;
+ }
+ mru_set_first(_mru, filename);
+ menu_build_mru_items(_mru);
+
+ selection_thaw(_selection);
+ main_set_title(filename);
+ object_list_clear_changed(_shapes);
+ preview_redraw();
+}
+
+void
+load(const gchar *filename)
+{
+ static gchar *tmp_filename;
+ g_strreplace(&tmp_filename, filename);
+ check_if_changed(really_load, (gpointer) tmp_filename);
+}
+
+void
+toggle_area_list(void)
+{
+ selection_toggle_visibility(_selection);
+}
+
+static gboolean
+close_callback(GtkWidget *widget, gpointer data)
+{
+ do_quit();
+ return TRUE;
+}
+
+static gboolean
+preview_move(GtkWidget *widget, GdkEventMotion *event)
+{
+ gint x = GET_REAL_COORD((gint) event->x);
+ gint y = GET_REAL_COORD((gint) event->y);
+ static Object_t *prev_obj = NULL;
+ Object_t *obj = object_list_find(_shapes, x, y);
+
+ statusbar_set_xy(_statusbar, x, y);
+ if (obj != prev_obj) {
+ prev_obj = obj;
+ if (obj && _show_url) {
+ statusbar_set_status(_statusbar, _("URL: %s"), obj->url);
+ } else {
+ statusbar_clear_status(_statusbar);
+ }
+ }
+#ifdef _NOT_READY_YET_
+ if (!obj) {
+ if (grid_near_x(x)) {
+ preview_set_cursor(_preview, GDK_SB_H_DOUBLE_ARROW);
+ } else if (grid_near_y(y)) {
+ preview_set_cursor(_preview, GDK_SB_V_DOUBLE_ARROW);
+ } else {
+ preview_set_cursor(_preview, _cursor);
+ }
+ }
+#endif
+ return FALSE;
+}
+
+static void
+preview_enter(GtkWidget *widget, GdkEventCrossing *event)
+{
+ preview_set_cursor(_preview, _cursor);
+}
+
+static void
+preview_leave(GtkWidget *widget, GdkEventCrossing *event)
+{
+ gdk_window_set_cursor(gtk_widget_get_window (_dlg), NULL);
+ statusbar_clear_xy(_statusbar);
+}
+
+static gboolean
+button_press(GtkWidget* widget, GdkEventButton* event, gpointer data)
+{
+ if (_button_press_func)
+ return _button_press_func(widget, event, _button_press_param);
+
+ return FALSE;
+}
+
+/* A few global vars for key movement */
+
+static guint _timeout;
+static guint _keyval;
+static gint _dx, _dy;
+
+static void
+move_sash_selected_objects(gint dx, gint dy, gboolean fast)
+{
+ if (fast) {
+ dx *= 5;
+ dy *= 5;
+ }
+
+ object_list_move_sash_selected(_shapes, dx, dy);
+
+ preview_redraw ();
+}
+
+static void
+move_selected_objects(gint dx, gint dy, gboolean fast)
+{
+ if (fast) {
+ dx *= 5;
+ dy *= 5;
+ }
+ _dx += dx;
+ _dy += dy;
+
+ object_list_move_selected(_shapes, dx, dy);
+
+ preview_redraw ();
+}
+
+static gboolean
+key_timeout_cb(gpointer data)
+{
+ switch (_keyval) {
+ case GDK_KEY_Left:
+ case GDK_KEY_Right:
+ case GDK_KEY_Up:
+ case GDK_KEY_Down:
+ command_list_add(move_selected_command_new(_shapes, _dx, _dy));
+ _dx = _dy = 0;
+ break;
+ }
+ preview_redraw();
+
+ _timeout = 0;
+ return FALSE;
+}
+
+static gboolean
+key_press_cb(GtkWidget *widget, GdkEventKey *event)
+{
+ gboolean handled = FALSE;
+ gboolean shift = event->state & GDK_SHIFT_MASK;
+ gboolean ctrl = event->state & GDK_CONTROL_MASK;
+ Command_t *command;
+
+ if (_timeout)
+ g_source_remove(_timeout);
+ _timeout = 0;
+
+ switch (event->keyval) {
+ case GDK_KEY_Left:
+ if (ctrl)
+ move_sash_selected_objects(-1, 0, shift);
+ else
+ move_selected_objects(-1, 0, shift);
+ handled = TRUE;
+ break;
+ case GDK_KEY_Right:
+ if (ctrl)
+ move_sash_selected_objects(1, 0, shift);
+ else
+ move_selected_objects(1, 0, shift);
+ handled = TRUE;
+ break;
+ case GDK_KEY_Up:
+ if (ctrl)
+ move_sash_selected_objects(0, -1, shift);
+ else
+ move_selected_objects(0, -1, shift);
+ handled = TRUE;
+ break;
+ case GDK_KEY_Down:
+ if (ctrl)
+ move_sash_selected_objects(0, 1, shift);
+ else
+ move_selected_objects(0, 1, shift);
+ handled = TRUE;
+ break;
+ case GDK_KEY_Tab:
+ if (shift)
+ command = select_prev_command_new(_shapes);
+ else
+ command = select_next_command_new(_shapes);
+ command_execute(command);
+ handled = TRUE;
+ break;
+ }
+ if (handled)
+ g_signal_stop_emission_by_name(widget, "key-press-event");
+
+ return handled;
+}
+
+static gboolean
+key_release_cb(GtkWidget *widget, GdkEventKey *event)
+{
+ _keyval = event->keyval;
+ _timeout = g_timeout_add(250, key_timeout_cb, NULL);
+ return FALSE;
+}
+
+static void
+geometry_changed(Object_t *obj, gpointer data)
+{
+ preview_redraw();
+}
+
+static void
+data_changed(Object_t *obj, gpointer data)
+{
+ preview_redraw();
+ set_all_sensitivities();
+}
+
+static void
+data_selected(Object_t *obj, gpointer data)
+{
+ set_all_sensitivities();
+}
+
+void
+imap_help (void)
+{
+ gimp_standard_help_func ("plug-in-imagemap", NULL);
+}
+
+void
+do_cut (void)
+{
+ command_execute (cut_command_new (_shapes));
+}
+
+void
+do_copy (void)
+{
+ command_execute (copy_command_new (_shapes));
+}
+
+void
+do_paste (void)
+{
+ command_execute (paste_command_new (_shapes));
+}
+
+void
+do_select_all(void)
+{
+ command_execute (select_all_command_new (_shapes));
+}
+
+void
+do_deselect_all(void)
+{
+ command_execute (unselect_all_command_new (_shapes, NULL));
+}
+
+void
+do_clear(void)
+{
+ command_execute (clear_command_new(_shapes));
+}
+
+void
+do_move_up(void)
+{
+ /* Fix me!
+ Command_t *command = object_up_command_new(_current_obj->list,
+ _current_obj);
+ command_execute(command);
+ */
+}
+
+void
+do_move_down(void)
+{
+ /* Fix me!
+ Command_t *command = object_down_command_new(_current_obj->list,
+ _current_obj);
+ command_execute(command);
+ */
+}
+
+void
+do_move_to_front(void)
+{
+ command_execute(move_to_front_command_new(_shapes));
+}
+
+void
+do_send_to_back(void)
+{
+ command_execute(send_to_back_command_new(_shapes));
+}
+
+void
+do_use_gimp_guides_dialog(void)
+{
+ command_execute (gimp_guides_command_new (_shapes, _drawable_id));
+}
+
+void
+do_create_guides_dialog(void)
+{
+ command_execute (guides_command_new (_shapes));
+}
+
+static Command_t*
+factory_move_up(void)
+{
+ return move_up_command_new(_shapes);
+}
+
+static Command_t*
+factory_move_down(void)
+{
+ return move_down_command_new(_shapes);
+}
+
+static gint
+dialog(gint32 drawable_id)
+{
+ GtkWidget *dlg;
+ GtkWidget *hbox;
+ GtkWidget *main_vbox;
+ GtkWidget *tools;
+
+ gimp_ui_init (PLUG_IN_BINARY, TRUE);
+
+ set_arrow_func ();
+
+ _shapes = make_object_list();
+
+ _dlg = dlg = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+ gtk_window_set_resizable(GTK_WINDOW(dlg), TRUE);
+
+ main_set_title(NULL);
+ gimp_help_connect (dlg, gimp_standard_help_func, PLUG_IN_PROC, NULL);
+
+ gtk_window_set_position (GTK_WINDOW (dlg), GTK_WIN_POS_MOUSE);
+
+ gimp_window_set_transient (GTK_WINDOW (dlg));
+
+ g_signal_connect (dlg, "delete-event",
+ G_CALLBACK (close_callback), NULL);
+ g_signal_connect (dlg, "key-press-event",
+ G_CALLBACK (key_press_cb), NULL);
+ g_signal_connect (dlg, "key-release-event",
+ G_CALLBACK (key_release_cb), NULL);
+
+ g_signal_connect (dlg, "destroy",
+ G_CALLBACK (gtk_main_quit),
+ NULL);
+
+ main_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
+ gtk_container_add (GTK_CONTAINER (dlg), main_vbox);
+ gtk_widget_show (main_vbox);
+
+ init_stock_icons();
+
+ /* Create menu */
+ make_menu(main_vbox, dlg);
+
+ /* Create toolbar */
+ make_toolbar(main_vbox, dlg);
+
+ /* Dialog area */
+ hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 1);
+ gtk_box_pack_start (GTK_BOX (main_vbox), hbox, TRUE, TRUE, 0);
+ gtk_widget_show(hbox);
+
+ tools = make_tools(dlg);
+ /* selection_set_edit_command(tools, factory_edit); */
+ gtk_box_pack_start(GTK_BOX(hbox), tools, FALSE, FALSE, 0);
+
+ _preview = make_preview(drawable_id);
+
+ g_signal_connect(_preview->preview, "motion-notify-event",
+ G_CALLBACK(preview_move), NULL);
+ g_signal_connect(_preview->preview, "enter-notify-event",
+ G_CALLBACK(preview_enter), NULL);
+ g_signal_connect(_preview->preview, "leave-notify-event",
+ G_CALLBACK(preview_leave), NULL);
+ g_signal_connect(_preview->preview, "button-press-event",
+ G_CALLBACK(button_press), NULL);
+ gtk_box_pack_start (GTK_BOX (hbox), _preview->window, TRUE, TRUE, 0);
+
+ object_list_add_geometry_cb(_shapes, geometry_changed, NULL);
+ object_list_add_update_cb(_shapes, data_changed, NULL);
+ object_list_add_add_cb(_shapes, data_changed, NULL);
+ object_list_add_remove_cb(_shapes, data_changed, NULL);
+ object_list_add_move_cb(_shapes, data_changed, NULL);
+ object_list_add_select_cb(_shapes, data_selected, NULL);
+
+ /* Selection */
+ _selection = make_selection(_shapes);
+ selection_set_move_up_command(_selection, factory_move_up);
+ selection_set_move_down_command(_selection, factory_move_down);
+ gtk_box_pack_start(GTK_BOX(hbox), _selection->container, FALSE, FALSE, 0);
+
+ _statusbar = make_statusbar(main_vbox, dlg);
+ statusbar_set_zoom(_statusbar, 1);
+
+ gtk_widget_show(dlg);
+
+ _mru = mru_create();
+ init_preferences();
+
+ clear_map_info();
+
+ if (!mru_empty(_mru))
+ menu_build_mru_items(_mru);
+
+ gtk_main();
+
+ return run_flag;
+}