/* * 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 . */ #include "config.h" #include #include #include #include #include #include /* for keyboard values */ #include #include #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 GimpDrawable *_drawable; 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 (GimpDrawable *drawable); 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, "/Filters/Web"); } static void run (const gchar *name, gint n_params, const GimpParam *param, gint *nreturn_vals, GimpParam **return_vals) { static GimpParam values[1]; GimpDrawable *drawable; GimpRunMode run_mode; GimpPDBStatusType status = GIMP_PDB_SUCCESS; INIT_I18N (); *nreturn_vals = 1; *return_vals = values; /* Get the specified drawable */ drawable = gimp_drawable_get(param[2].data.d_drawable); _drawable = drawable; _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->drawable_id); run_mode = (GimpRunMode) param[0].data.d_int32; if (run_mode == GIMP_RUN_INTERACTIVE) { if (!dialog(drawable)) { /* The dialog was closed, or something similarly evil happened. */ status = GIMP_PDB_EXECUTION_ERROR; } } if (status == GIMP_PDB_SUCCESS) { gimp_drawable_detach(drawable); } 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 *) _(""); 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, "\n\n", _map_info.image_name, _image_width, _image_height, _map_info.title); output(param, "\n", _map_info.title); output(param, "\n"); output(param, "\n"); output(param, "\n"); output(param, "\n"); output(param, "\n", _map_info.author); description = g_strdup(_map_info.description); for (p = strtok(description, "\n"); p; p = strtok(NULL, "\n")) output(param, "\n", p); g_free(description); object_list_write_csim(_shapes, param, output); if (*_map_info.default_url) output(param, "\n", _map_info.default_url); output(param, "\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, "%s\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(); 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)); } 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(GimpDrawable *drawable) { 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); 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; }