summaryrefslogtreecommitdiffstats
path: root/plug-ins/gfig/gfig-dialog.c
diff options
context:
space:
mode:
Diffstat (limited to 'plug-ins/gfig/gfig-dialog.c')
-rw-r--r--plug-ins/gfig/gfig-dialog.c2193
1 files changed, 2193 insertions, 0 deletions
diff --git a/plug-ins/gfig/gfig-dialog.c b/plug-ins/gfig/gfig-dialog.c
new file mode 100644
index 0000000..9f72b97
--- /dev/null
+++ b/plug-ins/gfig/gfig-dialog.c
@@ -0,0 +1,2193 @@
+/*
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * This is a plug-in for GIMP.
+ *
+ * Generates images containing vector type drawings.
+ *
+ * Copyright (C) 1997 Andy Thomas alt@picnic.demon.co.uk
+ *
+ * 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 <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include <glib.h>
+
+#ifdef G_OS_WIN32
+#include <libgimpbase/gimpwin32-io.h>
+#endif
+
+#include <libgimp/gimp.h>
+#include <libgimp/gimpui.h>
+
+#include "libgimp/stdplugins-intl.h"
+
+#include "gfig.h"
+#include "gfig-style.h"
+#include "gfig-dialog.h"
+#include "gfig-arc.h"
+#include "gfig-bezier.h"
+#include "gfig-circle.h"
+#include "gfig-dobject.h"
+#include "gfig-ellipse.h"
+#include "gfig-grid.h"
+#include "gfig-line.h"
+#include "gfig-poly.h"
+#include "gfig-preview.h"
+#include "gfig-rectangle.h"
+#include "gfig-spiral.h"
+#include "gfig-star.h"
+#include "gfig-stock.h"
+
+#define SEL_BUTTON_WIDTH 100
+#define SEL_BUTTON_HEIGHT 20
+
+#define GRID_TYPE_MENU 1
+#define GRID_RENDER_MENU 2
+
+#define PAINT_BGS_MENU 2
+#define PAINT_TYPE_MENU 3
+
+#define OBJ_SELECT_GT 1
+#define OBJ_SELECT_LT 2
+#define OBJ_SELECT_EQ 4
+
+#define UPDATE_DELAY 300 /* From GtkRange in GTK+ 2.22 */
+
+/* Globals */
+gint undo_level; /* Last slot filled in -1 = no undo */
+GList *undo_table[MAX_UNDO];
+
+/* Values when first invoked */
+SelectItVals selvals =
+{
+ {
+ MIN_GRID + (MAX_GRID - MIN_GRID)/2, /* Gridspacing */
+ RECT_GRID, /* Default to rectangle type */
+ FALSE, /* drawgrid */
+ FALSE, /* snap2grid */
+ FALSE, /* lockongrid */
+ TRUE, /* show control points */
+ 0.0, /* grid_radius_min */
+ 10.0, /* grid_radius_interval */
+ 0.0, /* grid_rotation */
+ 5.0, /* grid_granularity */
+ 120 /* grid_sectors_desired */
+ },
+ FALSE, /* show image */
+ MIN_UNDO + (MAX_UNDO - MIN_UNDO)/2, /* Max level of undos */
+ TRUE, /* Show pos updates */
+ 0.0, /* Brush fade */
+ 0.0, /* Brush gradient */
+ 20.0, /* Air brush pressure */
+ ORIGINAL_LAYER, /* Draw all objects on one layer */
+ LAYER_TRANS_BG, /* New layers background */
+ PAINT_BRUSH_TYPE, /* Default to use brushes */
+ FALSE, /* reverse lines */
+ TRUE, /* Scale to image when painting */
+ 1.0, /* Scale to image fp */
+ BRUSH_BRUSH_TYPE, /* Default to use a brush */
+ LINE /* Initial object type */
+};
+
+selection_option selopt =
+{
+ ADD, /* type */
+ FALSE, /* Antia */
+ FALSE, /* Feather */
+ 10.0, /* feather radius */
+ ARC_SEGMENT, /* Arc as a segment */
+ FILL_PATTERN, /* Fill as pattern */
+ 100.0, /* Max opacity */
+};
+
+/* Should be kept in sync with GfigOpts */
+typedef struct
+{
+ GtkAdjustment *gridspacing;
+ GtkAdjustment *grid_sectors_desired;
+ GtkAdjustment *grid_radius_interval;
+ GtkWidget *gridtypemenu;
+ GtkWidget *drawgrid;
+ GtkWidget *snap2grid;
+ GtkWidget *lockongrid;
+ GtkWidget *showcontrol;
+} GfigOptWidgets;
+
+static GfigOptWidgets gfig_opt_widget = { NULL, NULL, NULL, NULL, NULL, NULL };
+static gchar *gfig_path = NULL;
+static GtkWidget *page_menu_bg;
+static GtkWidget *tool_options_notebook;
+static GtkWidget *fill_type_notebook;
+static guint paint_timeout = 0;
+
+static GtkActionGroup *gfig_actions = NULL;
+
+
+static void gfig_response (GtkWidget *widget,
+ gint response_id,
+ gpointer data);
+static void gfig_load_action_callback (GtkAction *action,
+ gpointer data);
+static void gfig_save_action_callback (GtkAction *action,
+ gpointer data);
+static void gfig_list_load_all (const gchar *path);
+static void gfig_list_free_all (void);
+static void create_notebook_pages (GtkWidget *notebook);
+static void select_filltype_callback (GtkWidget *widget);
+static void gfig_grid_action_callback (GtkAction *action,
+ gpointer data);
+static void gfig_prefs_action_callback (GtkAction *action,
+ gpointer data);
+static void toggle_show_image (void);
+static void gridtype_combo_callback (GtkWidget *widget,
+ gpointer data);
+
+static void load_file_chooser_response (GtkFileChooser *chooser,
+ gint response_id,
+ gpointer data);
+static void save_file_chooser_response (GtkFileChooser *chooser,
+ gint response_id,
+ GFigObj *obj);
+static void paint_combo_callback (GtkWidget *widget,
+ gpointer data);
+
+static void select_button_clicked (gint type);
+static void select_button_clicked_lt (void);
+static void select_button_clicked_gt (void);
+static void select_button_clicked_eq (void);
+static void raise_selected_obj_to_top (GtkWidget *widget,
+ gpointer data);
+static void lower_selected_obj_to_bottom (GtkWidget *widget,
+ gpointer data);
+static void raise_selected_obj (GtkWidget *widget,
+ gpointer data);
+static void lower_selected_obj (GtkWidget *widget,
+ gpointer data);
+
+static void toggle_obj_type (GtkRadioAction *action,
+ GtkRadioAction *current,
+ gpointer data);
+
+static GtkUIManager *create_ui_manager (GtkWidget *window);
+
+
+gboolean
+gfig_dialog (void)
+{
+ GtkWidget *main_hbox;
+ GtkWidget *vbox;
+ GFigObj *gfig;
+ GimpParasite *parasite;
+ gint newlayer;
+ GtkWidget *menubar;
+ GtkWidget *toolbar;
+ GtkWidget *combo;
+ GtkWidget *frame;
+ gint img_width;
+ gint img_height;
+ GimpImageType img_type;
+ GtkWidget *toggle;
+ GtkWidget *right_vbox;
+ GtkWidget *hbox;
+ GtkUIManager *ui_manager;
+ GtkWidget *empty_label;
+ gchar *path;
+
+ gimp_ui_init (PLUG_IN_BINARY, TRUE);
+
+ img_width = gimp_drawable_width (gfig_context->drawable_id);
+ img_height = gimp_drawable_height (gfig_context->drawable_id);
+ img_type = gimp_drawable_type_with_alpha (gfig_context->drawable_id);
+
+ /*
+ * See if there is a "gfig" parasite. If so, this is a gfig layer,
+ * and we start by clearing it to transparent.
+ * If not, we create a new transparent layer.
+ */
+ gfig_list = NULL;
+ undo_level = -1;
+ parasite = gimp_item_get_parasite (gfig_context->drawable_id, "gfig");
+ gfig_context->enable_repaint = FALSE;
+
+ /* debug */
+ gfig_context->debug_styles = FALSE;
+
+ /* initial default style */
+ gfig_read_gimp_style (&gfig_context->default_style, "Base");
+ gfig_context->default_style.paint_type = selvals.painttype;
+
+ if (parasite)
+ {
+ gimp_drawable_fill (gfig_context->drawable_id, GIMP_FILL_TRANSPARENT);
+ gfig_context->using_new_layer = FALSE;
+ gimp_parasite_free (parasite);
+ }
+ else
+ {
+ newlayer = gimp_layer_new (gfig_context->image_id, "GFig",
+ img_width, img_height,
+ img_type,
+ 100.0,
+ gimp_image_get_default_new_layer_mode (gfig_context->image_id));
+ gimp_drawable_fill (newlayer, GIMP_FILL_TRANSPARENT);
+ gimp_image_insert_layer (gfig_context->image_id, newlayer, -1, -1);
+ gfig_context->drawable_id = newlayer;
+ gfig_context->using_new_layer = TRUE;
+ }
+
+ gfig_stock_init ();
+
+ path = gimp_gimprc_query ("gfig-path");
+
+ if (path)
+ {
+ gfig_path = g_filename_from_utf8 (path, -1, NULL, NULL, NULL);
+ g_free (path);
+ }
+ else
+ {
+ gchar *gimprc = gimp_personal_rc_file ("gimprc");
+ gchar *full_path = gimp_config_build_data_path ("gfig");
+ gchar *esc_path = g_strescape (full_path, NULL);
+ g_free (full_path);
+
+ g_message (_("No %s in gimprc:\n"
+ "You need to add an entry like\n"
+ "(%s \"%s\")\n"
+ "to your %s file."),
+ "gfig-path", "gfig-path", esc_path,
+ gimp_filename_to_utf8 (gimprc));
+
+ g_free (gimprc);
+ g_free (esc_path);
+ }
+
+ /* Start building the dialog up */
+ top_level_dlg = gimp_dialog_new (_("Gfig"), PLUG_IN_ROLE,
+ NULL, 0,
+ gimp_standard_help_func, PLUG_IN_PROC,
+
+ _("_Cancel"), GTK_RESPONSE_CANCEL,
+ _("_Close"), GTK_RESPONSE_OK,
+
+ NULL);
+
+ gtk_dialog_set_alternative_button_order (GTK_DIALOG (top_level_dlg),
+ GTK_RESPONSE_OK,
+ GTK_RESPONSE_CANCEL,
+ -1);
+
+ g_signal_connect (top_level_dlg, "response",
+ G_CALLBACK (gfig_response),
+ top_level_dlg);
+
+ /* build the menu */
+ ui_manager = create_ui_manager (top_level_dlg);
+ menubar = gtk_ui_manager_get_widget (ui_manager, "/ui/gfig-menubar");
+ gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (top_level_dlg))),
+ menubar, FALSE, FALSE, 0);
+ gtk_widget_show (menubar);
+ toolbar = gtk_ui_manager_get_widget (ui_manager, "/ui/gfig-toolbar");
+ gtk_toolbar_set_style (GTK_TOOLBAR (toolbar), GTK_TOOLBAR_ICONS);
+ gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (top_level_dlg))),
+ toolbar, FALSE, FALSE, 0);
+ gtk_widget_show (toolbar);
+
+ gfig_dialog_action_set_sensitive ("undo", undo_level >= 0);
+
+ /* Main box */
+ main_hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
+ gtk_container_set_border_width (GTK_CONTAINER (main_hbox), 12);
+ gtk_box_pack_end (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (top_level_dlg))),
+ main_hbox, TRUE, TRUE, 0);
+
+ /* Preview itself */
+ gtk_box_pack_start (GTK_BOX (main_hbox), make_preview (), FALSE, FALSE, 0);
+
+ gtk_widget_show (gfig_context->preview);
+
+ right_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
+ gtk_box_pack_start (GTK_BOX (main_hbox), right_vbox, FALSE, FALSE, 0);
+ gtk_widget_show (right_vbox);
+
+ /* Tool options notebook */
+ frame = gimp_frame_new ( _("Tool Options"));
+ gtk_box_pack_start (GTK_BOX (right_vbox), frame, FALSE, FALSE, 0);
+ gtk_widget_show (frame);
+
+ tool_options_notebook = gtk_notebook_new ();
+ gtk_container_add (GTK_CONTAINER (frame), tool_options_notebook);
+ gtk_notebook_set_show_tabs (GTK_NOTEBOOK (tool_options_notebook), FALSE);
+ gtk_notebook_set_show_border (GTK_NOTEBOOK (tool_options_notebook), FALSE);
+ gtk_widget_show (tool_options_notebook);
+ create_notebook_pages (tool_options_notebook);
+
+ /* Stroke frame on right side */
+ frame = gimp_frame_new (NULL);
+ gtk_box_pack_start (GTK_BOX (right_vbox), frame, FALSE, FALSE, 0);
+ gtk_widget_show (frame);
+
+ gfig_context->paint_type_toggle =
+ toggle = gtk_check_button_new_with_mnemonic (_("_Stroke"));
+
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), selvals.painttype);
+ gtk_frame_set_label_widget (GTK_FRAME (frame), toggle);
+ gtk_widget_show (toggle);
+
+ hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+ gtk_container_add (GTK_CONTAINER (frame), hbox);
+ gtk_widget_show (hbox);
+
+ vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
+ gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 0);
+ gtk_widget_show (vbox);
+
+ gtk_widget_set_sensitive (vbox, selvals.painttype);
+ g_signal_connect (toggle, "toggled",
+ G_CALLBACK (set_paint_type_callback),
+ vbox);
+
+ /* foreground color button in Stroke frame*/
+ gfig_context->fg_color = g_new0 (GimpRGB, 1);
+ gfig_context->fg_color_button = gimp_color_button_new ("Foreground",
+ SEL_BUTTON_WIDTH,
+ SEL_BUTTON_HEIGHT,
+ gfig_context->fg_color,
+ GIMP_COLOR_AREA_SMALL_CHECKS);
+ g_signal_connect (gfig_context->fg_color_button, "color-changed",
+ G_CALLBACK (set_foreground_callback),
+ gfig_context->fg_color);
+ gimp_color_button_set_color (GIMP_COLOR_BUTTON (gfig_context->fg_color_button),
+ &gfig_context->default_style.foreground);
+ gtk_box_pack_start (GTK_BOX (vbox), gfig_context->fg_color_button,
+ FALSE, FALSE, 0);
+ gtk_widget_show (gfig_context->fg_color_button);
+
+ /* brush selector in Stroke frame */
+ gfig_context->brush_select
+ = gimp_brush_select_button_new ("Brush",
+ gfig_context->default_style.brush_name,
+ -1.0, -1, -1);
+ g_signal_connect (gfig_context->brush_select, "brush-set",
+ G_CALLBACK (gfig_brush_changed_callback), NULL);
+ gtk_box_pack_start (GTK_BOX (vbox), gfig_context->brush_select,
+ FALSE, FALSE, 0);
+ gtk_widget_show (gfig_context->brush_select);
+
+ /* Fill frame on right side */
+ frame = gimp_frame_new (_("Fill"));
+ gtk_box_pack_start (GTK_BOX (right_vbox), frame, FALSE, FALSE, 0);
+ gtk_widget_show (frame);
+
+ hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+ gtk_container_add (GTK_CONTAINER (frame), hbox);
+ gtk_widget_show (hbox);
+
+ vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
+ gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 0);
+ gtk_widget_show (vbox);
+
+ /* fill style combo box in Style frame */
+ gfig_context->fillstyle_combo = combo
+ = gimp_int_combo_box_new (_("No fill"), FILL_NONE,
+ _("Color fill"), FILL_COLOR,
+ _("Pattern fill"), FILL_PATTERN,
+ _("Shape gradient"), FILL_GRADIENT,
+ _("Vertical gradient"), FILL_VERTICAL,
+ _("Horizontal gradient"), FILL_HORIZONTAL,
+ NULL);
+ gimp_int_combo_box_set_active (GIMP_INT_COMBO_BOX (combo), 0);
+ g_signal_connect (combo, "changed",
+ G_CALLBACK (select_filltype_callback),
+ NULL);
+ gtk_box_pack_start (GTK_BOX (vbox), combo, FALSE, FALSE, 0);
+ gtk_widget_show (combo);
+
+ fill_type_notebook = gtk_notebook_new ();
+ gtk_box_pack_start (GTK_BOX (vbox), fill_type_notebook, FALSE, FALSE, 0);
+ gtk_notebook_set_show_tabs (GTK_NOTEBOOK (fill_type_notebook), FALSE);
+ gtk_notebook_set_show_border (GTK_NOTEBOOK (fill_type_notebook), FALSE);
+ gtk_widget_show (fill_type_notebook);
+
+ /* An empty page for "No fill" */
+ empty_label = gtk_label_new ("");
+ gtk_widget_show (empty_label);
+ gtk_notebook_append_page (GTK_NOTEBOOK (fill_type_notebook),
+ empty_label, NULL);
+
+ /* A page for the fill color button */
+ gfig_context->bg_color = g_new0 (GimpRGB, 1);
+ gfig_context->bg_color_button = gimp_color_button_new ("Background",
+ SEL_BUTTON_WIDTH, SEL_BUTTON_HEIGHT,
+ gfig_context->bg_color,
+ GIMP_COLOR_AREA_SMALL_CHECKS);
+ g_signal_connect (gfig_context->bg_color_button, "color-changed",
+ G_CALLBACK (set_background_callback),
+ gfig_context->bg_color);
+ gimp_color_button_set_color (GIMP_COLOR_BUTTON (gfig_context->bg_color_button),
+ &gfig_context->default_style.background);
+ gtk_widget_show (gfig_context->bg_color_button);
+ gtk_notebook_append_page (GTK_NOTEBOOK (fill_type_notebook),
+ gfig_context->bg_color_button, NULL);
+
+ /* A page for the pattern selector */
+ gfig_context->pattern_select
+ = gimp_pattern_select_button_new ("Pattern", gfig_context->default_style.pattern);
+ g_signal_connect (gfig_context->pattern_select, "pattern-set",
+ G_CALLBACK (gfig_pattern_changed_callback), NULL);
+ gtk_widget_show (gfig_context->pattern_select);
+ gtk_notebook_append_page (GTK_NOTEBOOK (fill_type_notebook),
+ gfig_context->pattern_select, NULL);
+
+ /* A page for the gradient selector */
+ gfig_context->gradient_select
+ = gimp_gradient_select_button_new ("Gradient", gfig_context->default_style.gradient);
+ g_signal_connect (gfig_context->gradient_select, "gradient-set",
+ G_CALLBACK (gfig_gradient_changed_callback), NULL);
+ gtk_widget_show (gfig_context->gradient_select);
+ gtk_notebook_append_page (GTK_NOTEBOOK (fill_type_notebook),
+ gfig_context->gradient_select, NULL);
+
+
+ vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
+ gtk_box_pack_start (GTK_BOX (right_vbox), vbox, FALSE, FALSE, 0);
+ gtk_widget_show (vbox);
+
+ /* "show image" checkbutton at bottom of style frame */
+ toggle = gtk_check_button_new_with_label (_("Show image"));
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle),
+ gfig_context->show_background);
+ gtk_box_pack_end (GTK_BOX (vbox), toggle, FALSE, FALSE, 0);
+ g_signal_connect (toggle, "toggled",
+ G_CALLBACK (gimp_toggle_button_update),
+ &gfig_context->show_background);
+ g_signal_connect_swapped (toggle, "toggled",
+ G_CALLBACK (gtk_widget_queue_draw),
+ gfig_context->preview);
+ gtk_widget_show (toggle);
+
+ /* "snap to grid" checkbutton at bottom of style frame */
+ toggle = gtk_check_button_new_with_label (C_("checkbutton", "Snap to grid"));
+ gtk_box_pack_end (GTK_BOX (vbox), toggle, FALSE, FALSE, 0);
+ g_signal_connect (toggle, "toggled",
+ G_CALLBACK (gimp_toggle_button_update),
+ &selvals.opts.snap2grid);
+ gtk_widget_show (toggle);
+ gfig_opt_widget.snap2grid = toggle;
+
+ /* "show grid" checkbutton at bottom of style frame */
+ toggle = gtk_check_button_new_with_label (_("Show grid"));
+ gtk_box_pack_end (GTK_BOX (vbox), toggle, FALSE, FALSE, 0);
+ g_signal_connect (toggle, "toggled",
+ G_CALLBACK (gimp_toggle_button_update),
+ &selvals.opts.drawgrid);
+ g_signal_connect (toggle, "toggled",
+ G_CALLBACK (draw_grid_clear),
+ NULL);
+ gtk_widget_show (toggle);
+ gfig_opt_widget.drawgrid = toggle;
+
+ /* Load saved objects */
+ gfig_list_load_all (gfig_path);
+
+ /* Setup initial brush settings */
+ gfig_context->bdesc.name = gimp_context_get_brush ();
+ mygimp_brush_info (&gfig_context->bdesc.width, &gfig_context->bdesc.height);
+
+ gtk_widget_show (main_hbox);
+
+ gtk_widget_show (top_level_dlg);
+
+ gfig = gfig_load_from_parasite ();
+ if (gfig)
+ {
+ gfig_list_insert (gfig);
+ new_obj_2edit (gfig);
+ gfig_style_set_context_from_style (&gfig_context->default_style);
+ gfig_style_apply (&gfig_context->default_style);
+ }
+
+ gfig_context->enable_repaint = TRUE;
+ gfig_paint_callback ();
+
+ gtk_main ();
+
+ /* FIXME */
+ return TRUE;
+}
+
+static void
+gfig_response (GtkWidget *widget,
+ gint response_id,
+ gpointer data)
+{
+ GFigObj *gfig;
+
+ switch (response_id)
+ {
+ case GTK_RESPONSE_DELETE_EVENT:
+ case GTK_RESPONSE_CANCEL:
+ /* if we created a new layer, delete it */
+ if (gfig_context->using_new_layer)
+ {
+ gimp_image_remove_layer (gfig_context->image_id,
+ gfig_context->drawable_id);
+ }
+ else /* revert back to the original figure */
+ {
+ free_all_objs (gfig_context->current_obj->obj_list);
+ gfig_context->current_obj->obj_list = NULL;
+ gfig = gfig_load_from_parasite ();
+ if (gfig)
+ {
+ gfig_list_insert (gfig);
+ new_obj_2edit (gfig);
+ }
+ gfig_context->enable_repaint = TRUE;
+ gfig_paint_callback ();
+ }
+ break;
+
+ case GTK_RESPONSE_OK: /* Close button */
+ gfig_save_as_parasite ();
+ break;
+
+ default:
+ break;
+ }
+
+ gtk_widget_destroy (widget);
+ gtk_main_quit ();
+}
+
+void
+gfig_dialog_action_set_sensitive (const gchar *name,
+ gboolean sensitive)
+{
+ g_return_if_fail (name != NULL);
+
+ if (gfig_actions)
+ {
+ GtkAction *action = gtk_action_group_get_action (gfig_actions, name);
+
+ if (! action)
+ {
+ g_warning ("%s: Unable to set sensitivity of action "
+ "which doesn't exist: %s",
+ G_STRFUNC, name);
+ return;
+ }
+
+ g_object_set (action, "sensitive", sensitive ? TRUE : FALSE, NULL);
+ }
+}
+
+static gchar *
+gfig_get_user_writable_dir (void)
+{
+ if (gfig_path)
+ {
+ GList *list;
+ gchar *dir;
+
+ list = gimp_path_parse (gfig_path, 256, FALSE, NULL);
+ dir = gimp_path_get_user_writable_dir (list);
+ gimp_path_free (list);
+
+ return dir;
+ }
+
+ return g_strdup (gimp_directory ());
+}
+
+static void
+gfig_load_action_callback (GtkAction *action,
+ gpointer data)
+{
+ static GtkWidget *dialog = NULL;
+
+ if (! dialog)
+ {
+ gchar *dir;
+
+ dialog =
+ gtk_file_chooser_dialog_new (_("Load Gfig Object Collection"),
+ GTK_WINDOW (data),
+ GTK_FILE_CHOOSER_ACTION_OPEN,
+
+ _("_Cancel"), GTK_RESPONSE_CANCEL,
+ _("_Open"), GTK_RESPONSE_OK,
+
+ NULL);
+
+ gtk_dialog_set_alternative_button_order (GTK_DIALOG (dialog),
+ GTK_RESPONSE_OK,
+ GTK_RESPONSE_CANCEL,
+ -1);
+
+ gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
+
+ g_object_add_weak_pointer (G_OBJECT (dialog), (gpointer) &dialog);
+
+ g_signal_connect (dialog, "response",
+ G_CALLBACK (load_file_chooser_response),
+ NULL);
+
+ dir = gfig_get_user_writable_dir ();
+ if (dir)
+ {
+ gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog),
+ dir);
+ g_free (dir);
+ }
+
+ gtk_widget_show (dialog);
+ }
+ else
+ {
+ gtk_window_present (GTK_WINDOW (dialog));
+ }
+}
+
+static void
+gfig_save_action_callback (GtkAction *action,
+ gpointer data)
+{
+ static GtkWidget *dialog = NULL;
+
+ if (!dialog)
+ {
+ gchar *dir;
+
+ dialog =
+ gtk_file_chooser_dialog_new (_("Save Gfig Drawing"),
+ GTK_WINDOW (data),
+ GTK_FILE_CHOOSER_ACTION_SAVE,
+
+ _("_Cancel"), GTK_RESPONSE_CANCEL,
+ _("_Save"), GTK_RESPONSE_OK,
+
+ NULL);
+
+ gtk_dialog_set_alternative_button_order (GTK_DIALOG (dialog),
+ GTK_RESPONSE_OK,
+ GTK_RESPONSE_CANCEL,
+ -1);
+ gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
+
+ gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog),
+ TRUE);
+
+ g_object_add_weak_pointer (G_OBJECT (dialog), (gpointer) &dialog);
+
+ /* FIXME: GFigObj should be a GObject and g_signal_connect_object()
+ * should be used here.
+ */
+ g_signal_connect (dialog, "response",
+ G_CALLBACK (save_file_chooser_response),
+ gfig_context->current_obj);
+
+ dir = gfig_get_user_writable_dir ();
+ if (dir)
+ {
+ gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), dir);
+ g_free (dir);
+ }
+
+ gtk_widget_show (dialog);
+ }
+ else
+ {
+ gtk_window_present (GTK_WINDOW (dialog));
+ }
+}
+
+static void
+gfig_close_action_callback (GtkAction *action,
+ gpointer data)
+{
+ gtk_dialog_response (GTK_DIALOG (data), GTK_RESPONSE_OK);
+}
+
+static void
+gfig_undo_action_callback (GtkAction *action,
+ gpointer data)
+{
+ if (undo_level >= 0)
+ {
+ /* Free current objects an reinstate previous */
+ free_all_objs (gfig_context->current_obj->obj_list);
+ gfig_context->current_obj->obj_list = NULL;
+ tmp_bezier = tmp_line = obj_creating = NULL;
+ gfig_context->current_obj->obj_list = undo_table[undo_level];
+ undo_level--;
+ /* Update the screen */
+ gtk_widget_queue_draw (gfig_context->preview);
+ /* And preview */
+ gfig_context->current_obj->obj_status |= GFIG_MODIFIED;
+ if (gfig_context->current_obj->obj_list)
+ gfig_context->selected_obj = gfig_context->current_obj->obj_list->data;
+ else
+ gfig_context->selected_obj = NULL;
+ }
+
+ gfig_dialog_action_set_sensitive ("undo", undo_level >= 0);
+ gfig_paint_callback ();
+}
+
+static void
+gfig_clear_action_callback (GtkWidget *widget,
+ gpointer data)
+{
+ /* Make sure we can get back - if we have some objects to get back to */
+ if (!gfig_context->current_obj->obj_list)
+ return;
+
+ setup_undo ();
+ /* Free all objects */
+ free_all_objs (gfig_context->current_obj->obj_list);
+ gfig_context->current_obj->obj_list = NULL;
+ gfig_context->selected_obj = NULL;
+ obj_creating = NULL;
+ tmp_line = NULL;
+ tmp_bezier = NULL;
+ gtk_widget_queue_draw (gfig_context->preview);
+ gfig_paint_callback ();
+}
+
+void
+draw_item (cairo_t *cr, gboolean fill)
+{
+ cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 1.0);
+
+ if (fill)
+ {
+ cairo_fill_preserve (cr);
+ }
+ else
+ {
+ cairo_set_line_width (cr, 3.0);
+ cairo_stroke_preserve (cr);
+ }
+
+ cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, 1.0);
+ cairo_set_line_width (cr, 1.0);
+ cairo_stroke (cr);
+}
+
+/* Given a point x, y draw a circle */
+void
+draw_circle (GdkPoint *p,
+ gboolean selected,
+ cairo_t *cr)
+{
+ if (!selvals.opts.showcontrol)
+ return;
+
+ cairo_arc (cr,
+ gfig_scale_x (p->x) + .5,
+ gfig_scale_y (p->y) + .5,
+ SQ_SIZE / 2,
+ 0, 2 * G_PI);
+
+ draw_item (cr, selected);
+}
+
+/* Given a point x, y draw a square around it */
+void
+draw_sqr (GdkPoint *p,
+ gboolean selected,
+ cairo_t *cr)
+{
+ if (!selvals.opts.showcontrol)
+ return;
+
+ cairo_rectangle (cr,
+ gfig_scale_x (p->x) + .5 - SQ_SIZE / 2,
+ gfig_scale_y (p->y) + .5 - SQ_SIZE / 2,
+ SQ_SIZE,
+ SQ_SIZE);
+
+ draw_item (cr, selected);
+}
+
+static void
+gfig_list_load_all (const gchar *path)
+{
+ /* Make sure to clear any existing gfigs */
+ gfig_context->current_obj = NULL;
+ gfig_list_free_all ();
+
+ if (! gfig_list)
+ {
+ GFigObj *gfig;
+
+ /* lets have at least one! */
+ gfig = gfig_new ();
+ gfig->draw_name = g_strdup (_("First Gfig"));
+ gfig_list_insert (gfig);
+ }
+
+ gfig_context->current_obj = gfig_list->data; /* set to first entry */
+}
+
+static void
+gfig_list_free_all (void)
+{
+ g_list_free_full (gfig_list, (GDestroyNotify) gfig_free);
+ gfig_list = NULL;
+}
+
+static GtkUIManager *
+create_ui_manager (GtkWidget *window)
+{
+ static GtkActionEntry actions[] =
+ {
+ { "gfig-menubar", NULL, "GFig Menu" },
+
+ { "gfig-file-menu", NULL, "_File" },
+
+ { "open", GIMP_ICON_DOCUMENT_OPEN,
+ N_("_Open..."), "<control>O", NULL,
+ G_CALLBACK (gfig_load_action_callback) },
+
+ { "save", GIMP_ICON_DOCUMENT_SAVE,
+ N_("_Save..."), "<control>S", NULL,
+ G_CALLBACK (gfig_save_action_callback) },
+
+ { "close", GIMP_ICON_CLOSE,
+ N_("_Close"), "<control>C", NULL,
+ G_CALLBACK (gfig_close_action_callback) },
+
+ { "gfig-edit-menu", NULL, "_Edit" },
+
+ { "undo", GIMP_ICON_EDIT_UNDO,
+ N_("_Undo"), "<control>Z", NULL,
+ G_CALLBACK (gfig_undo_action_callback) },
+
+ { "clear", GIMP_ICON_EDIT_CLEAR,
+ N_("_Clear"), NULL, NULL,
+ G_CALLBACK (gfig_clear_action_callback) },
+
+ { "grid", GIMP_ICON_GRID,
+ N_("_Grid"), "<control>G", NULL,
+ G_CALLBACK (gfig_grid_action_callback) },
+
+ { "prefs", GIMP_ICON_PREFERENCES_SYSTEM,
+ N_("_Preferences..."), "<control>P", NULL,
+ G_CALLBACK (gfig_prefs_action_callback) },
+
+ { "raise", GIMP_ICON_GO_UP,
+ N_("_Raise"), "<control>U", N_("Raise selected object"),
+ G_CALLBACK (raise_selected_obj) },
+
+ { "lower", GIMP_ICON_GO_DOWN,
+ N_("_Lower"), "<control>D", N_("Lower selected object"),
+ G_CALLBACK (lower_selected_obj) },
+
+ { "top", GIMP_ICON_GO_TOP,
+ N_("Raise to _top"), "<control>T", N_("Raise selected object to top"),
+ G_CALLBACK (raise_selected_obj_to_top) },
+
+ { "bottom", GIMP_ICON_GO_BOTTOM,
+ N_("Lower to _bottom"), "<control>B", N_("Lower selected object to bottom"),
+ G_CALLBACK (lower_selected_obj_to_bottom) },
+
+ { "show_previous", GIMP_ICON_GO_PREVIOUS,
+ N_("_Previous"), "<control>H", N_("Show previous object"),
+ G_CALLBACK (select_button_clicked_lt) },
+
+ { "show_next", GIMP_ICON_GO_NEXT,
+ N_("_Next"), "<control>L", N_("Show next object"),
+ G_CALLBACK (select_button_clicked_gt) },
+
+ { "show_all", GFIG_STOCK_SHOW_ALL,
+ N_("Show _all"), "<control>A", N_("Show all objects"),
+ G_CALLBACK (select_button_clicked_eq) }
+ };
+ static GtkRadioActionEntry radio_actions[] =
+ {
+ { "line", GFIG_STOCK_LINE,
+ NULL, "L", N_("Create line"), LINE },
+
+ { "rectangle", GFIG_STOCK_RECTANGLE,
+ NULL, "R", N_("Create rectangle"), RECTANGLE },
+
+ { "circle", GFIG_STOCK_CIRCLE,
+ NULL, "C", N_("Create circle"), CIRCLE },
+
+ { "ellipse", GFIG_STOCK_ELLIPSE,
+ NULL, "E", N_("Create ellipse"), ELLIPSE },
+
+ { "arc", GFIG_STOCK_CURVE,
+ NULL, "A", N_("Create arc"), ARC },
+
+ { "polygon", GFIG_STOCK_POLYGON,
+ NULL, "P", N_("Create reg polygon"), POLY },
+
+ { "star", GFIG_STOCK_STAR,
+ NULL, "S", N_("Create star"), STAR },
+
+ { "spiral", GFIG_STOCK_SPIRAL,
+ NULL, "I", N_("Create spiral"), SPIRAL },
+
+ { "bezier", GFIG_STOCK_BEZIER,
+ NULL, "B", N_("Create bezier curve. "
+ "Shift + Button ends object creation."), BEZIER },
+
+ { "move_obj", GFIG_STOCK_MOVE_OBJECT,
+ NULL, "M", N_("Move an object"), MOVE_OBJ },
+
+ { "move_point", GFIG_STOCK_MOVE_POINT,
+ NULL, "V", N_("Move a single point"), MOVE_POINT },
+
+ { "copy", GFIG_STOCK_COPY_OBJECT,
+ NULL, "Y", N_("Copy an object"), COPY_OBJ },
+
+ { "delete", GFIG_STOCK_DELETE_OBJECT,
+ NULL, "D", N_("Delete an object"), DEL_OBJ },
+
+ { "select", GFIG_STOCK_SELECT_OBJECT,
+ NULL, "A", N_("Select an object"), SELECT_OBJ }
+ };
+
+ GtkUIManager *ui_manager = gtk_ui_manager_new ();
+
+ gfig_actions = gtk_action_group_new ("Actions");
+
+ gtk_action_group_set_translation_domain (gfig_actions, NULL);
+
+ gtk_action_group_add_actions (gfig_actions,
+ actions,
+ G_N_ELEMENTS (actions),
+ window);
+ gtk_action_group_add_radio_actions (gfig_actions,
+ radio_actions,
+ G_N_ELEMENTS (radio_actions),
+ LINE,
+ G_CALLBACK (toggle_obj_type),
+ window);
+
+ gtk_window_add_accel_group (GTK_WINDOW (window),
+ gtk_ui_manager_get_accel_group (ui_manager));
+ gtk_accel_group_lock (gtk_ui_manager_get_accel_group (ui_manager));
+
+ gtk_ui_manager_insert_action_group (ui_manager, gfig_actions, -1);
+ g_object_unref (gfig_actions);
+
+ gtk_ui_manager_add_ui_from_string (ui_manager,
+ "<ui>"
+ " <menubar name=\"gfig-menubar\">"
+ " <menu name=\"File\" action=\"gfig-file-menu\">"
+ " <menuitem action=\"open\" />"
+ " <menuitem action=\"save\" />"
+ " <menuitem action=\"close\" />"
+ " </menu>"
+ " <menu name=\"Edit\" action=\"gfig-edit-menu\">"
+ " <menuitem action=\"undo\" />"
+ " <menuitem action=\"clear\" />"
+ " <menuitem action=\"grid\" />"
+ " <menuitem action=\"prefs\" />"
+ " </menu>"
+ " </menubar>"
+ "</ui>",
+ -1, NULL);
+ gtk_ui_manager_add_ui_from_string (ui_manager,
+ "<ui>"
+ " <toolbar name=\"gfig-toolbar\">"
+ " <toolitem action=\"line\" />"
+ " <toolitem action=\"rectangle\" />"
+ " <toolitem action=\"circle\" />"
+ " <toolitem action=\"ellipse\" />"
+ " <toolitem action=\"arc\" />"
+ " <toolitem action=\"polygon\" />"
+ " <toolitem action=\"star\" />"
+ " <toolitem action=\"spiral\" />"
+ " <toolitem action=\"bezier\" />"
+ " <toolitem action=\"move_obj\" />"
+ " <toolitem action=\"move_point\" />"
+ " <toolitem action=\"copy\" />"
+ " <toolitem action=\"delete\" />"
+ " <toolitem action=\"select\" />"
+ " <separator />"
+ " <toolitem action=\"raise\" />"
+ " <toolitem action=\"lower\" />"
+ " <toolitem action=\"top\" />"
+ " <toolitem action=\"bottom\" />"
+ " <separator />"
+ " <toolitem action=\"show_previous\" />"
+ " <toolitem action=\"show_next\" />"
+ " <toolitem action=\"show_all\" />"
+ " </toolbar>"
+ "</ui>",
+ -1, NULL);
+
+ return ui_manager;
+}
+
+static void
+tool_option_no_option (GtkWidget *notebook)
+{
+ GtkWidget *label;
+
+ label = gtk_label_new (_("This tool has no options"));
+ gtk_widget_show (label);
+ gtk_notebook_append_page (GTK_NOTEBOOK (notebook), label, NULL);
+}
+
+static void
+create_notebook_pages (GtkWidget *notebook)
+{
+ tool_option_no_option (notebook); /* Line */
+ tool_option_no_option (notebook); /* Rectangle */
+ tool_option_no_option (notebook); /* Circle */
+ tool_option_no_option (notebook); /* Ellipse */
+ tool_option_no_option (notebook); /* Arc */
+ tool_options_poly (notebook); /* Polygon */
+ tool_options_star (notebook); /* Star */
+ tool_options_spiral (notebook); /* Spiral */
+ tool_options_bezier (notebook); /* Bezier */
+ tool_option_no_option (notebook); /* Dummy */
+ tool_option_no_option (notebook); /* Move Object */
+ tool_option_no_option (notebook); /* Move Point */
+ tool_option_no_option (notebook); /* Copy Object */
+ tool_option_no_option (notebook); /* Delete Object */
+}
+
+static void
+raise_selected_obj_to_top (GtkWidget *widget,
+ gpointer data)
+{
+ if (!gfig_context->selected_obj)
+ return;
+
+ if (g_list_find (gfig_context->current_obj->obj_list,
+ gfig_context->selected_obj))
+ {
+ gfig_context->current_obj->obj_list =
+ g_list_remove (gfig_context->current_obj->obj_list,
+ gfig_context->selected_obj);
+ gfig_context->current_obj->obj_list =
+ g_list_append (gfig_context->current_obj->obj_list,
+ gfig_context->selected_obj);
+ }
+ else
+ {
+ g_message ("Trying to raise object that does not exist.");
+ return;
+ }
+
+ gfig_paint_callback ();
+}
+
+static void
+lower_selected_obj_to_bottom (GtkWidget *widget,
+ gpointer data)
+{
+ if (!gfig_context->selected_obj)
+ return;
+
+ if (g_list_find (gfig_context->current_obj->obj_list,
+ gfig_context->selected_obj))
+ {
+ gfig_context->current_obj->obj_list =
+ g_list_remove (gfig_context->current_obj->obj_list,
+ gfig_context->selected_obj);
+ gfig_context->current_obj->obj_list =
+ g_list_prepend (gfig_context->current_obj->obj_list,
+ gfig_context->selected_obj);
+ }
+ else
+ {
+ g_message ("Trying to lower object that does not exist.");
+ return;
+ }
+
+ gfig_paint_callback ();
+}
+
+static void
+raise_selected_obj (GtkWidget *widget,
+ gpointer data)
+{
+ if (!gfig_context->selected_obj)
+ return;
+
+ if (g_list_find (gfig_context->current_obj->obj_list,
+ gfig_context->selected_obj))
+ {
+ int position;
+
+ position = g_list_index (gfig_context->current_obj->obj_list,
+ gfig_context->selected_obj);
+ gfig_context->current_obj->obj_list =
+ g_list_remove (gfig_context->current_obj->obj_list,
+ gfig_context->selected_obj);
+ gfig_context->current_obj->obj_list =
+ g_list_insert (gfig_context->current_obj->obj_list,
+ gfig_context->selected_obj,
+ position + 1);
+ }
+ else
+ {
+ g_message ("Trying to raise object that does not exist.");
+ return;
+ }
+
+ gfig_paint_callback ();
+}
+
+
+static void
+lower_selected_obj (GtkWidget *widget,
+ gpointer data)
+{
+ if (!gfig_context->selected_obj)
+ return;
+
+ if (g_list_find (gfig_context->current_obj->obj_list,
+ gfig_context->selected_obj))
+ {
+ int position;
+
+ position = g_list_index (gfig_context->current_obj->obj_list,
+ gfig_context->selected_obj);
+ gfig_context->current_obj->obj_list =
+ g_list_remove (gfig_context->current_obj->obj_list,
+ gfig_context->selected_obj);
+ gfig_context->current_obj->obj_list =
+ g_list_insert (gfig_context->current_obj->obj_list,
+ gfig_context->selected_obj,
+ MAX (0, position - 1));
+ }
+ else
+ {
+ g_message ("Trying to lower object that does not exist.");
+ return;
+ }
+
+ gfig_paint_callback ();
+}
+
+
+static void
+select_filltype_callback (GtkWidget *widget)
+{
+ gint value;
+
+ gimp_int_combo_box_get_active (GIMP_INT_COMBO_BOX (widget), &value);
+ gtk_notebook_set_current_page (GTK_NOTEBOOK (fill_type_notebook),
+ MIN (value, FILL_GRADIENT));
+
+ gfig_context_get_current_style ()->fill_type = (FillType) value;
+
+ gfig_paint_callback ();
+}
+
+static gboolean
+gfig_paint_timeout (gpointer data)
+{
+ gfig_paint_callback ();
+
+ paint_timeout = 0;
+
+ return FALSE;
+}
+
+static void
+gfig_paint_delayed (void)
+{
+ if (paint_timeout)
+ g_source_remove (paint_timeout);
+
+ paint_timeout =
+ g_timeout_add (UPDATE_DELAY, gfig_paint_timeout, NULL);
+}
+
+static void
+gfig_prefs_action_callback (GtkAction *widget,
+ gpointer data)
+{
+ static GtkWidget *dialog = NULL;
+
+ if (!dialog)
+ {
+ GtkWidget *main_vbox;
+ GtkWidget *table;
+ GtkWidget *toggle;
+ GtkObject *size_data;
+ GtkWidget *scale;
+ GtkAdjustment *scale_data;
+
+ dialog = gimp_dialog_new (_("Options"), "gimp-gfig-options",
+ GTK_WIDGET (data), 0, NULL, NULL,
+
+ _("_Close"), GTK_RESPONSE_CLOSE,
+
+ NULL);
+
+ gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_CLOSE);
+
+ g_object_add_weak_pointer (G_OBJECT (dialog), (gpointer) &dialog);
+
+ g_signal_connect (dialog, "response",
+ G_CALLBACK (gtk_widget_destroy),
+ NULL);
+
+ main_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
+ gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 12);
+ gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))),
+ main_vbox, TRUE, TRUE, 0);
+ gtk_widget_show (main_vbox);
+
+ /* Put buttons in */
+ toggle = gtk_check_button_new_with_label (_("Show position"));
+ gtk_box_pack_start (GTK_BOX (main_vbox), toggle, FALSE, FALSE, 6);
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle),
+ selvals.showpos);
+ g_signal_connect (toggle, "toggled",
+ G_CALLBACK (gimp_toggle_button_update),
+ &selvals.showpos);
+ g_signal_connect_after (toggle, "toggled",
+ G_CALLBACK (gfig_pos_enable),
+ NULL);
+ gtk_widget_show (toggle);
+
+ toggle = gtk_check_button_new_with_label (_("Show control points"));
+ gtk_box_pack_start (GTK_BOX (main_vbox), toggle, FALSE, FALSE, 6);
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle),
+ selvals.opts.showcontrol);
+ g_signal_connect (toggle, "toggled",
+ G_CALLBACK (gimp_toggle_button_update),
+ &selvals.opts.showcontrol);
+ g_signal_connect (toggle, "toggled",
+ G_CALLBACK (toggle_show_image),
+ NULL);
+ gtk_widget_show (toggle);
+
+ gfig_opt_widget.showcontrol = toggle;
+ g_object_add_weak_pointer (G_OBJECT (gfig_opt_widget.showcontrol),
+ (gpointer) &gfig_opt_widget.showcontrol);
+
+ toggle = gtk_check_button_new_with_label (_("Antialiasing"));
+ gtk_box_pack_start (GTK_BOX (main_vbox), toggle, FALSE, FALSE, 6);
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), selopt.antia);
+ g_signal_connect (toggle, "toggled",
+ G_CALLBACK (gimp_toggle_button_update),
+ &selopt.antia);
+ g_signal_connect (toggle, "toggled",
+ G_CALLBACK (gfig_paint_callback),
+ NULL);
+ gtk_widget_show (toggle);
+
+ table = gtk_table_new (4, 4, FALSE);
+ gtk_table_set_col_spacings (GTK_TABLE (table), 6);
+ gtk_table_set_row_spacings (GTK_TABLE (table), 6);
+ gtk_box_pack_start (GTK_BOX (main_vbox), table, FALSE, FALSE, 6);
+ gtk_widget_show (table);
+
+ size_data = gimp_scale_entry_new (GTK_TABLE (table), 0, 0,
+ _("Max undo:"), 100, 50,
+ selvals.maxundo,
+ MIN_UNDO, MAX_UNDO, 1, 2, 0,
+ TRUE, 0, 0,
+ NULL, NULL);
+ g_signal_connect (size_data, "value-changed",
+ G_CALLBACK (gimp_int_adjustment_update),
+ &selvals.maxundo);
+
+ page_menu_bg = gimp_int_combo_box_new (_("Transparent"), LAYER_TRANS_BG,
+ _("Background"), LAYER_BG_BG,
+ _("Foreground"), LAYER_FG_BG,
+ _("White"), LAYER_WHITE_BG,
+ _("Copy"), LAYER_COPY_BG,
+ NULL);
+ gimp_int_combo_box_set_active (GIMP_INT_COMBO_BOX (page_menu_bg), selvals.onlayerbg);
+
+ g_signal_connect (page_menu_bg, "changed",
+ G_CALLBACK (paint_combo_callback),
+ GINT_TO_POINTER (PAINT_BGS_MENU));
+
+ gimp_help_set_help_data (page_menu_bg,
+ _("Layer background type. Copy causes the "
+ "previous layer to be copied before the "
+ "draw is performed."),
+ NULL);
+
+ gimp_table_attach_aligned (GTK_TABLE (table), 0, 1,
+ _("Background:"), 0.0, 0.5,
+ page_menu_bg, 2, FALSE);
+
+ toggle = gtk_check_button_new_with_label (_("Feather"));
+ gtk_table_attach (GTK_TABLE (table), toggle, 2, 3, 2, 3,
+ GTK_FILL, GTK_FILL, 0, 0);
+ g_signal_connect (toggle, "toggled",
+ G_CALLBACK (gimp_toggle_button_update),
+ &selopt.feather);
+ g_signal_connect (toggle, "toggled",
+ G_CALLBACK (gfig_paint_callback),
+ NULL);
+ gtk_widget_show (toggle);
+
+ scale_data = (GtkAdjustment *)
+ gtk_adjustment_new (selopt.feather_radius, 0.0, 100.0, 1.0, 1.0, 0.0);
+ scale = gtk_scale_new (GTK_ORIENTATION_HORIZONTAL, scale_data);
+ gtk_scale_set_value_pos (GTK_SCALE (scale), GTK_POS_TOP);
+
+ g_signal_connect (scale_data, "value-changed",
+ G_CALLBACK (gimp_double_adjustment_update),
+ &selopt.feather_radius);
+ g_signal_connect (scale_data, "value-changed",
+ G_CALLBACK (gfig_paint_delayed),
+ NULL);
+ gimp_table_attach_aligned (GTK_TABLE (table), 0, 2,
+ _("Radius:"), 0.0, 1.0, scale, 1, FALSE);
+
+ gtk_widget_show (dialog);
+ }
+ else
+ {
+ gtk_window_present (GTK_WINDOW (dialog));
+ }
+}
+
+static void
+gfig_grid_action_callback (GtkAction *action,
+ gpointer data)
+{
+ static GtkWidget *dialog = NULL;
+
+ if (!dialog)
+ {
+ GtkWidget *main_vbox;
+ GtkWidget *hbox;
+ GtkWidget *table;
+ GtkWidget *combo;
+ GtkObject *size_data;
+ GtkObject *sectors_data;
+ GtkObject *radius_data;
+
+ dialog = gimp_dialog_new (_("Grid"), "gimp-gfig-grid",
+ GTK_WIDGET (data), 0, NULL, NULL,
+
+ _("_Close"), GTK_RESPONSE_CLOSE,
+
+ NULL);
+
+ gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_CLOSE);
+
+ g_object_add_weak_pointer (G_OBJECT (dialog), (gpointer) &dialog);
+
+ g_signal_connect (dialog, "response",
+ G_CALLBACK (gtk_widget_destroy),
+ NULL);
+
+ main_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
+ gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 12);
+ gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))),
+ main_vbox, TRUE, TRUE, 0);
+ gtk_widget_show (main_vbox);
+
+ hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+ gtk_box_pack_start (GTK_BOX (main_vbox), hbox, FALSE, FALSE, 0);
+ gtk_widget_show (hbox);
+
+ table = gtk_table_new (3, 3, FALSE);
+ gtk_table_set_col_spacings (GTK_TABLE (table), 6);
+ gtk_table_set_row_spacings (GTK_TABLE (table), 6);
+ gtk_box_pack_start (GTK_BOX (main_vbox), table, FALSE, FALSE, 0);
+ gtk_widget_show (table);
+
+ size_data = gimp_scale_entry_new (GTK_TABLE (table), 0, 0,
+ _("Grid spacing:"), 100, 50,
+ selvals.opts.gridspacing,
+ MIN_GRID, MAX_GRID, 1, 10, 0,
+ TRUE, 0, 0,
+ NULL, NULL);
+ g_signal_connect (size_data, "value-changed",
+ G_CALLBACK (gimp_int_adjustment_update),
+ &selvals.opts.gridspacing);
+ g_signal_connect (size_data, "value-changed",
+ G_CALLBACK (draw_grid_clear),
+ NULL);
+
+ gfig_opt_widget.gridspacing = GTK_ADJUSTMENT (size_data);
+ g_object_add_weak_pointer (G_OBJECT (gfig_opt_widget.gridspacing),
+ (gpointer) &gfig_opt_widget.gridspacing);
+
+ sectors_data = gimp_scale_entry_new (GTK_TABLE (table), 0, 3,
+ _("Polar grid sectors desired:"), 1, 5,
+ selvals.opts.grid_sectors_desired,
+ 5, 360, 5, 1, 0,
+ TRUE, 0, 0,
+ NULL, NULL);
+ g_signal_connect (sectors_data, "value-changed",
+ G_CALLBACK (gimp_int_adjustment_update),
+ &selvals.opts.grid_sectors_desired);
+ g_signal_connect (sectors_data, "value-changed",
+ G_CALLBACK (draw_grid_clear),
+ NULL);
+
+ gfig_opt_widget.grid_sectors_desired = GTK_ADJUSTMENT (sectors_data);
+ g_object_add_weak_pointer (G_OBJECT (gfig_opt_widget.grid_sectors_desired),
+ (gpointer) &gfig_opt_widget.grid_sectors_desired);
+
+
+ gfig_opt_widget.gridspacing = GTK_ADJUSTMENT (size_data);
+ g_object_add_weak_pointer (G_OBJECT (gfig_opt_widget.gridspacing),
+ (gpointer) &gfig_opt_widget.gridspacing);
+
+ radius_data = gimp_scale_entry_new (GTK_TABLE (table), 0, 4,
+ _("Polar grid radius interval:"), 1, 5,
+ selvals.opts.grid_radius_interval,
+ 5, 50, 5, 1, 0,
+ TRUE, 0, 0,
+ NULL, NULL);
+ g_signal_connect (radius_data, "value-changed",
+ G_CALLBACK (gimp_double_adjustment_update),
+ &selvals.opts.grid_radius_interval);
+ g_signal_connect (radius_data, "value-changed",
+ G_CALLBACK (draw_grid_clear),
+ NULL);
+
+ gfig_opt_widget.grid_radius_interval = GTK_ADJUSTMENT (radius_data);
+ g_object_add_weak_pointer (G_OBJECT (gfig_opt_widget.grid_radius_interval),
+ (gpointer) &gfig_opt_widget.grid_radius_interval);
+
+ combo = gimp_int_combo_box_new (_("Rectangle"), RECT_GRID,
+ _("Polar"), POLAR_GRID,
+ _("Isometric"), ISO_GRID,
+ NULL);
+ gimp_int_combo_box_set_active (GIMP_INT_COMBO_BOX (combo), selvals.opts.gridtype);
+
+ g_signal_connect (combo, "changed",
+ G_CALLBACK (gridtype_combo_callback),
+ GINT_TO_POINTER (GRID_TYPE_MENU));
+
+ gimp_table_attach_aligned (GTK_TABLE (table), 0, 1,
+ _("Grid type:"), 0.0, 0.5,
+ combo, 2, FALSE);
+
+ gfig_opt_widget.gridtypemenu = combo;
+ g_object_add_weak_pointer (G_OBJECT (gfig_opt_widget.gridtypemenu),
+ (gpointer) &gfig_opt_widget.gridtypemenu);
+
+ combo = gimp_int_combo_box_new (_("Normal"), GFIG_NORMAL_GC,
+ _("Black"), GFIG_BLACK_GC,
+ _("White"), GFIG_WHITE_GC,
+ _("Grey"), GFIG_GREY_GC,
+ _("Darker"), GFIG_DARKER_GC,
+ _("Lighter"), GFIG_LIGHTER_GC,
+ _("Very dark"), GFIG_VERY_DARK_GC,
+ NULL);
+ gimp_int_combo_box_set_active (GIMP_INT_COMBO_BOX (combo), grid_gc_type);
+
+ g_signal_connect (combo, "changed",
+ G_CALLBACK (gridtype_combo_callback),
+ GINT_TO_POINTER (GRID_RENDER_MENU));
+
+ gimp_table_attach_aligned (GTK_TABLE (table), 0, 2,
+ _("Grid color:"), 0.0, 0.5,
+ combo, 2, FALSE);
+
+ gtk_widget_show (dialog);
+ }
+ else
+ {
+ gtk_window_present (GTK_WINDOW (dialog));
+ }
+}
+
+void
+options_update (GFigObj *old_obj)
+{
+ /* Save old vals */
+ if (selvals.opts.gridspacing != old_obj->opts.gridspacing)
+ {
+ old_obj->opts.gridspacing = selvals.opts.gridspacing;
+ }
+ if (selvals.opts.grid_sectors_desired != old_obj->opts.grid_sectors_desired)
+ {
+ old_obj->opts.grid_sectors_desired = selvals.opts.grid_sectors_desired;
+ }
+ if (selvals.opts.grid_radius_interval != old_obj->opts.grid_radius_interval)
+ {
+ old_obj->opts.grid_radius_interval = selvals.opts.grid_radius_interval;
+ }
+ if (selvals.opts.gridtype != old_obj->opts.gridtype)
+ {
+ old_obj->opts.gridtype = selvals.opts.gridtype;
+ }
+ if (selvals.opts.drawgrid != old_obj->opts.drawgrid)
+ {
+ old_obj->opts.drawgrid = selvals.opts.drawgrid;
+ }
+ if (selvals.opts.snap2grid != old_obj->opts.snap2grid)
+ {
+ old_obj->opts.snap2grid = selvals.opts.snap2grid;
+ }
+ if (selvals.opts.lockongrid != old_obj->opts.lockongrid)
+ {
+ old_obj->opts.lockongrid = selvals.opts.lockongrid;
+ }
+ if (selvals.opts.showcontrol != old_obj->opts.showcontrol)
+ {
+ old_obj->opts.showcontrol = selvals.opts.showcontrol;
+ }
+
+ /* New vals */
+ if (selvals.opts.gridspacing != gfig_context->current_obj->opts.gridspacing)
+ {
+ if (gfig_opt_widget.gridspacing)
+ gtk_adjustment_set_value (gfig_opt_widget.gridspacing,
+ gfig_context->current_obj->opts.gridspacing);
+ }
+ if (selvals.opts.grid_sectors_desired != gfig_context->current_obj->opts.grid_sectors_desired)
+ {
+ if (gfig_opt_widget.grid_sectors_desired)
+ gtk_adjustment_set_value (gfig_opt_widget.grid_sectors_desired,
+ gfig_context->current_obj->opts.grid_sectors_desired);
+ }
+ if (selvals.opts.grid_radius_interval != gfig_context->current_obj->opts.grid_radius_interval)
+ {
+ if (gfig_opt_widget.grid_radius_interval)
+ gtk_adjustment_set_value (gfig_opt_widget.grid_radius_interval,
+ gfig_context->current_obj->opts.grid_radius_interval);
+ }
+ if (selvals.opts.gridtype != gfig_context->current_obj->opts.gridtype)
+ {
+ if (gfig_opt_widget.gridtypemenu)
+ gimp_int_combo_box_set_active (GIMP_INT_COMBO_BOX (gfig_opt_widget.gridtypemenu),
+ gfig_context->current_obj->opts.gridtype);
+ }
+ if (selvals.opts.drawgrid != gfig_context->current_obj->opts.drawgrid)
+ {
+ if (gfig_opt_widget.drawgrid)
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (gfig_opt_widget.drawgrid),
+ gfig_context->current_obj->opts.drawgrid);
+ }
+ if (selvals.opts.snap2grid != gfig_context->current_obj->opts.snap2grid)
+ {
+ if (gfig_opt_widget.snap2grid)
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (gfig_opt_widget.snap2grid),
+ gfig_context->current_obj->opts.snap2grid);
+ }
+ if (selvals.opts.lockongrid != gfig_context->current_obj->opts.lockongrid)
+ {
+ if (gfig_opt_widget.lockongrid)
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (gfig_opt_widget.lockongrid),
+ gfig_context->current_obj->opts.lockongrid);
+ }
+ if (selvals.opts.showcontrol != gfig_context->current_obj->opts.showcontrol)
+ {
+ if (gfig_opt_widget.showcontrol)
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (gfig_opt_widget.showcontrol),
+ gfig_context->current_obj->opts.showcontrol);
+ }
+}
+
+static void
+save_file_chooser_response (GtkFileChooser *chooser,
+ gint response_id,
+ GFigObj *obj)
+{
+ if (response_id == GTK_RESPONSE_OK)
+ {
+ gchar *filename;
+
+ filename = gtk_file_chooser_get_filename (chooser);
+
+ obj->filename = filename;
+
+ gfig_context->current_obj = obj;
+ gfig_save_callbk ();
+ }
+
+ gtk_widget_destroy (GTK_WIDGET (chooser));
+}
+
+static GfigObject *
+gfig_select_obj_by_number (gint count)
+{
+ GList *objs;
+ GfigObject *object = NULL;
+ gint k;
+
+ gfig_context->selected_obj = NULL;
+
+ for (objs = gfig_context->current_obj->obj_list, k = 0;
+ objs;
+ objs = g_list_next (objs), k++)
+ {
+ if (k == obj_show_single)
+ {
+ object = objs->data;
+ gfig_context->selected_obj = object;
+ gfig_style_set_context_from_style (&object->style);
+ break;
+ }
+ }
+
+ return object;
+}
+
+static void
+select_button_clicked (gint type)
+{
+ gint count = 0;
+
+ if (gfig_context->current_obj)
+ {
+ count = g_list_length (gfig_context->current_obj->obj_list);
+ }
+
+ switch (type)
+ {
+ case OBJ_SELECT_LT:
+ obj_show_single--;
+ if (obj_show_single < 0)
+ obj_show_single = count - 1;
+ break;
+
+ case OBJ_SELECT_GT:
+ obj_show_single++;
+ if (obj_show_single >= count)
+ obj_show_single = 0;
+ break;
+
+ case OBJ_SELECT_EQ:
+ obj_show_single = -1; /* Reset to show all */
+ break;
+
+ default:
+ break;
+ }
+
+ if (obj_show_single >= 0)
+ gfig_select_obj_by_number (obj_show_single);
+
+ draw_grid_clear ();
+ gfig_paint_callback ();
+}
+
+static void
+select_button_clicked_lt (void)
+{
+ select_button_clicked (OBJ_SELECT_LT);
+}
+
+static void
+select_button_clicked_gt (void)
+{
+ select_button_clicked (OBJ_SELECT_GT);
+}
+
+static void
+select_button_clicked_eq (void)
+{
+ select_button_clicked (OBJ_SELECT_EQ);
+}
+
+/* Special case for now - options on poly/star/spiral button */
+
+GtkWidget *
+num_sides_widget (const gchar *d_title,
+ gint *num_sides,
+ gint *which_way,
+ gint adj_min,
+ gint adj_max)
+{
+ GtkWidget *table;
+ GtkObject *size_data;
+
+ table = gtk_table_new (which_way ? 2 : 1, 3, FALSE);
+ gtk_table_set_col_spacings (GTK_TABLE (table), 6);
+ gtk_table_set_row_spacings (GTK_TABLE (table), 6);
+ gtk_container_set_border_width (GTK_CONTAINER (table), 12);
+ gtk_widget_show (table);
+
+ size_data = gimp_scale_entry_new (GTK_TABLE (table), 0, 0,
+ _("Sides:"), 0, 0,
+ *num_sides, adj_min, adj_max, 1, 10, 0,
+ TRUE, 0, 0,
+ NULL, NULL);
+ g_signal_connect (size_data, "value-changed",
+ G_CALLBACK (gimp_int_adjustment_update),
+ num_sides);
+
+ if (which_way)
+ {
+ GtkWidget *combo = gimp_int_combo_box_new (_("Right"), 0,
+ _("Left"), 1,
+ NULL);
+
+ gimp_int_combo_box_set_active (GIMP_INT_COMBO_BOX (combo), *which_way);
+
+ g_signal_connect (combo, "changed",
+ G_CALLBACK (gimp_int_combo_box_get_active),
+ which_way);
+
+ gimp_table_attach_aligned (GTK_TABLE (table), 0, 1,
+ _("Orientation:"), 0.0, 0.5,
+ combo, 1, FALSE);
+ }
+ return table;
+}
+
+void
+gfig_paint (BrushType brush_type,
+ gint32 drawable_ID,
+ gint seg_count,
+ gdouble line_pnts[])
+{
+ switch (brush_type)
+ {
+ case BRUSH_BRUSH_TYPE:
+ gimp_paintbrush (drawable_ID,
+ selvals.brushfade,
+ seg_count, line_pnts,
+ GIMP_PAINT_CONSTANT,
+ selvals.brushgradient);
+ break;
+
+ case BRUSH_PENCIL_TYPE:
+ gimp_pencil (drawable_ID,
+ seg_count, line_pnts);
+ break;
+
+ case BRUSH_AIRBRUSH_TYPE:
+ gimp_airbrush (drawable_ID,
+ selvals.airbrushpressure,
+ seg_count, line_pnts);
+ break;
+
+ case BRUSH_PATTERN_TYPE:
+ gimp_clone (drawable_ID,
+ drawable_ID,
+ GIMP_CLONE_PATTERN,
+ 0.0, 0.0,
+ seg_count, line_pnts);
+ break;
+ }
+}
+
+
+static void
+paint_combo_callback (GtkWidget *widget,
+ gpointer data)
+{
+ gint mtype = GPOINTER_TO_INT (data);
+ gint value;
+
+ gimp_int_combo_box_get_active (GIMP_INT_COMBO_BOX (widget), &value);
+
+ switch (mtype)
+ {
+ case PAINT_BGS_MENU:
+ selvals.onlayerbg = (LayersBGType) value;
+ break;
+
+ default:
+ g_return_if_reached ();
+ break;
+ }
+
+ gfig_paint_callback ();
+}
+
+
+static void
+gridtype_combo_callback (GtkWidget *widget,
+ gpointer data)
+{
+ gint mtype = GPOINTER_TO_INT (data);
+ gint value;
+
+ gimp_int_combo_box_get_active (GIMP_INT_COMBO_BOX (widget), &value);
+
+ switch (mtype)
+ {
+ case GRID_TYPE_MENU:
+ selvals.opts.gridtype = value;
+ break;
+
+ case GRID_RENDER_MENU:
+ grid_gc_type = value;
+ break;
+
+ default:
+ g_return_if_reached ();
+ break;
+ }
+
+ draw_grid_clear ();
+}
+
+/*
+ * The edit gfig name attributes dialog
+ * Modified from Gimp source - layer edit.
+ */
+
+typedef struct _GfigListOptions
+{
+ GtkWidget *query_box;
+ GtkWidget *name_entry;
+ GtkWidget *list_entry;
+ GFigObj *obj;
+ gboolean created;
+} GfigListOptions;
+
+static void
+load_file_chooser_response (GtkFileChooser *chooser,
+ gint response_id,
+ gpointer data)
+{
+ if (response_id == GTK_RESPONSE_OK)
+ {
+ gchar *filename;
+ GFigObj *gfig;
+ GFigObj *current_saved;
+
+ filename = gtk_file_chooser_get_filename (chooser);
+
+ if (g_file_test (filename, G_FILE_TEST_IS_REGULAR))
+ {
+ /* Hack - current object MUST be NULL to prevent setup_undo ()
+ * from kicking in.
+ */
+ current_saved = gfig_context->current_obj;
+ gfig_context->current_obj = NULL;
+ gfig = gfig_load (filename, filename);
+ gfig_context->current_obj = current_saved;
+
+ if (gfig)
+ {
+ /* Read only ?*/
+ if (access (filename, W_OK))
+ gfig->obj_status |= GFIG_READONLY;
+
+ gfig_list_insert (gfig);
+ new_obj_2edit (gfig);
+ }
+ }
+
+ g_free (filename);
+ }
+
+ gtk_widget_destroy (GTK_WIDGET (chooser));
+ gfig_paint_callback ();
+}
+
+void
+paint_layer_fill (gdouble x1, gdouble y1, gdouble x2, gdouble y2)
+{
+ GimpFillType fill_type = GIMP_FILL_FOREGROUND;
+ Style *current_style;
+
+ current_style = gfig_context_get_current_style ();
+
+ gimp_context_push ();
+
+ gimp_context_set_paint_mode (GIMP_LAYER_MODE_NORMAL_LEGACY);
+ gimp_context_set_opacity (100.0);
+ gimp_context_set_gradient_repeat_mode (GIMP_REPEAT_NONE);
+ gimp_context_set_gradient_reverse (FALSE);
+
+ switch (current_style->fill_type)
+ {
+ case FILL_NONE:
+ return;
+
+ case FILL_COLOR:
+ fill_type = GIMP_FILL_BACKGROUND;
+ break;
+
+ case FILL_PATTERN:
+ fill_type = GIMP_FILL_PATTERN;
+ break;
+
+ case FILL_GRADIENT:
+ gimp_drawable_edit_gradient_fill (gfig_context->drawable_id,
+ GIMP_GRADIENT_SHAPEBURST_DIMPLED,
+ 0.0, /* offset */
+ FALSE, /* supersampling */
+ 0, /* max_depth */
+ 0.0, /* threshold */
+ FALSE, /* dither */
+ 0.0, 0.0, /* (x1, y1) - ignored */
+ 0.0, 0.0); /* (x2, y2) - ignored */
+ return;
+ case FILL_VERTICAL:
+ gimp_drawable_edit_gradient_fill (gfig_context->drawable_id,
+ GIMP_GRADIENT_LINEAR,
+ 0.0,
+ FALSE,
+ 0,
+ 0.0,
+ FALSE,
+ x1, y1,
+ x1, y2);
+ return;
+ case FILL_HORIZONTAL:
+ gimp_drawable_edit_gradient_fill (gfig_context->drawable_id,
+ GIMP_GRADIENT_LINEAR,
+ 0.0,
+ FALSE,
+ 0,
+ 0.0,
+ FALSE,
+ x1, y1,
+ x2, y1);
+ return;
+ }
+
+ gimp_context_set_opacity (current_style->fill_opacity);
+
+ gimp_drawable_edit_fill (gfig_context->drawable_id,
+ fill_type);
+
+ gimp_context_pop ();
+}
+
+void
+gfig_paint_callback (void)
+{
+ GList *objs;
+ gint ccount = 0;
+ GfigObject *object;
+
+ if (!gfig_context->enable_repaint || !gfig_context->current_obj)
+ return;
+
+ objs = gfig_context->current_obj->obj_list;
+
+ gimp_drawable_fill (gfig_context->drawable_id, GIMP_FILL_TRANSPARENT);
+
+ while (objs)
+ {
+ if (ccount == obj_show_single || obj_show_single == -1)
+ {
+ FillType saved_filltype;
+
+ object = objs->data;
+
+ gfig_style_apply (&object->style);
+
+ saved_filltype = gfig_context_get_current_style ()->fill_type;
+ gfig_context_get_current_style ()->fill_type = object->style.fill_type;
+ object->class->paintfunc (object);
+ gfig_context_get_current_style ()->fill_type = saved_filltype;
+ }
+
+ objs = g_list_next (objs);
+
+ ccount++;
+ }
+
+ gimp_displays_flush ();
+
+ if (back_pixbuf)
+ {
+ g_object_unref (back_pixbuf);
+ back_pixbuf = NULL;
+ }
+
+ gtk_widget_queue_draw (gfig_context->preview);
+}
+
+/* Draw the grid on the screen
+ */
+
+void
+draw_grid_clear (void)
+{
+ /* wipe slate and start again */
+ gtk_widget_queue_draw (gfig_context->preview);
+}
+
+static void
+toggle_show_image (void)
+{
+ /* wipe slate and start again */
+ draw_grid_clear ();
+}
+
+static void
+toggle_obj_type (GtkRadioAction *action,
+ GtkRadioAction *current,
+ gpointer data)
+{
+ static GdkCursor *p_cursors[DEL_OBJ + 1];
+ GdkCursorType ctype = GDK_LAST_CURSOR;
+ DobjType new_type;
+
+ new_type = gtk_radio_action_get_current_value (action);
+ if (selvals.otype != new_type)
+ {
+ /* Mem leak */
+ obj_creating = NULL;
+ tmp_line = NULL;
+ tmp_bezier = NULL;
+
+ if (new_type < MOVE_OBJ) /* Eeeeek */
+ {
+ obj_show_single = -1; /* Cancel select preview */
+ }
+ /* Update draw areas */
+ gtk_widget_queue_draw (gfig_context->preview);
+ }
+
+ selvals.otype = new_type;
+ gtk_notebook_set_current_page (GTK_NOTEBOOK (tool_options_notebook),
+ new_type - 1);
+
+ switch (selvals.otype)
+ {
+ case LINE:
+ case RECTANGLE:
+ case CIRCLE:
+ case ELLIPSE:
+ case ARC:
+ case POLY:
+ case STAR:
+ case SPIRAL:
+ case BEZIER:
+ default:
+ ctype = GDK_CROSSHAIR;
+ break;
+ case MOVE_OBJ:
+ case MOVE_POINT:
+ case COPY_OBJ:
+ case MOVE_COPY_OBJ:
+ ctype = GDK_DIAMOND_CROSS;
+ break;
+ case DEL_OBJ:
+ ctype = GDK_PIRATE;
+ break;
+ }
+
+ if (!p_cursors[selvals.otype])
+ {
+ GdkDisplay *display = gtk_widget_get_display (gfig_context->preview);
+
+ p_cursors[selvals.otype] = gdk_cursor_new_for_display (display, ctype);
+ }
+
+ gdk_window_set_cursor (gtk_widget_get_window (gfig_context->preview),
+ p_cursors[selvals.otype]);
+}
+
+/* This could belong in a separate file ... but makes it easier to lump into
+ * one when compiling the plugin.
+ */
+
+/* Given a number of float co-ords adjust for scaling back to org size */
+/* Size is number of PAIRS of points */
+/* FP + int variants */
+
+static void
+scale_to_orginal_x (gdouble *list)
+{
+ *list *= scale_x_factor;
+}
+
+gint
+gfig_scale_x (gint x)
+{
+ if (!selvals.scaletoimage)
+ return (gint) (x * (1 / scale_x_factor));
+ else
+ return x;
+}
+
+static void
+scale_to_orginal_y (gdouble *list)
+{
+ *list *= scale_y_factor;
+}
+
+gint
+gfig_scale_y (gint y)
+{
+ if (!selvals.scaletoimage)
+ return (gint) (y * (1 / scale_y_factor));
+ else
+ return y;
+}
+
+/* Pairs x followed by y */
+void
+scale_to_original_xy (gdouble *list,
+ gint size)
+{
+ gint i;
+
+ for (i = 0; i < size * 2; i += 2)
+ {
+ scale_to_orginal_x (&list[i]);
+ scale_to_orginal_y (&list[i + 1]);
+ }
+}
+
+/* Pairs x followed by y */
+void
+scale_to_xy (gdouble *list,
+ gint size)
+{
+ gint i;
+
+ for (i = 0; i < size * 2; i += 2)
+ {
+ list[i] *= (org_scale_x_factor / scale_x_factor);
+ list[i + 1] *= (org_scale_y_factor / scale_y_factor);
+ }
+}
+
+void
+gfig_draw_arc (gint x, gint y, gint width, gint height, gint angle1,
+ gint angle2, cairo_t *cr)
+{
+ cairo_save (cr);
+
+ cairo_translate (cr, gfig_scale_x (x), gfig_scale_y (y));
+ cairo_scale (cr, gfig_scale_x (width), gfig_scale_y (height));
+
+ if (angle1 < angle2)
+ cairo_arc (cr, 0., 0., 1., angle1 * G_PI / 180, angle2 * G_PI / 180);
+ else
+ cairo_arc_negative (cr, 0., 0., 1., angle1 * G_PI / 180, angle2 * G_PI / 180);
+
+ cairo_restore (cr);
+
+ draw_item (cr, FALSE);
+}
+
+void
+gfig_draw_line (gint x0, gint y0, gint x1, gint y1, cairo_t *cr)
+{
+ cairo_move_to (cr, gfig_scale_x (x0) + .5, gfig_scale_y (y0) + .5);
+ cairo_line_to (cr, gfig_scale_x (x1) + .5, gfig_scale_y (y1) + .5);
+
+ draw_item (cr, FALSE);
+}