1 /*
2  * Copyright (C) 1995 Spencer Kimball and Peter Mattis
3  *
4  * This is a plug-in for GIMP.
5  *
6  * Generates images containing vector type drawings.
7  *
8  * Copyright (C) 1997 Andy Thomas  alt@picnic.demon.co.uk
9  *
10  * This program is free software: you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 3 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
22  */
23 
24 #include "config.h"
25 
26 #include <stdlib.h>
27 #include <string.h>
28 #include <errno.h>
29 
30 #ifdef HAVE_UNISTD_H
31 #include <unistd.h>
32 #endif
33 
34 #include <glib.h>
35 
36 #ifdef G_OS_WIN32
37 #include <libgimpbase/gimpwin32-io.h>
38 #endif
39 
40 #include <libgimp/gimp.h>
41 #include <libgimp/gimpui.h>
42 
43 #include "libgimp/stdplugins-intl.h"
44 
45 #include "gfig.h"
46 #include "gfig-style.h"
47 #include "gfig-dialog.h"
48 #include "gfig-arc.h"
49 #include "gfig-bezier.h"
50 #include "gfig-circle.h"
51 #include "gfig-dobject.h"
52 #include "gfig-ellipse.h"
53 #include "gfig-grid.h"
54 #include "gfig-line.h"
55 #include "gfig-poly.h"
56 #include "gfig-preview.h"
57 #include "gfig-rectangle.h"
58 #include "gfig-spiral.h"
59 #include "gfig-star.h"
60 #include "gfig-stock.h"
61 
62 #define SEL_BUTTON_WIDTH  100
63 #define SEL_BUTTON_HEIGHT  20
64 
65 #define GRID_TYPE_MENU      1
66 #define GRID_RENDER_MENU    2
67 
68 #define PAINT_BGS_MENU      2
69 #define PAINT_TYPE_MENU     3
70 
71 #define OBJ_SELECT_GT       1
72 #define OBJ_SELECT_LT       2
73 #define OBJ_SELECT_EQ       4
74 
75 #define UPDATE_DELAY 300 /* From GtkRange in GTK+ 2.22 */
76 
77 /* Globals */
78 gint   undo_level;  /* Last slot filled in -1 = no undo */
79 GList *undo_table[MAX_UNDO];
80 
81 /* Values when first invoked */
82 SelectItVals selvals =
83 {
84   {
85     MIN_GRID + (MAX_GRID - MIN_GRID)/2, /* Gridspacing     */
86     RECT_GRID,            /* Default to rectangle type     */
87     FALSE,                /* drawgrid                      */
88     FALSE,                /* snap2grid                     */
89     FALSE,                /* lockongrid                    */
90     TRUE,                 /* show control points           */
91     0.0,                  /* grid_radius_min               */
92     10.0,                 /* grid_radius_interval          */
93     0.0,                  /* grid_rotation                 */
94     5.0,                  /* grid_granularity              */
95     120                   /* grid_sectors_desired          */
96   },
97   FALSE,                  /* show image                    */
98   MIN_UNDO + (MAX_UNDO - MIN_UNDO)/2,  /* Max level of undos */
99   TRUE,                   /* Show pos updates              */
100   0.0,                    /* Brush fade                    */
101   0.0,                    /* Brush gradient                */
102   20.0,                   /* Air brush pressure            */
103   ORIGINAL_LAYER,         /* Draw all objects on one layer */
104   LAYER_TRANS_BG,         /* New layers background         */
105   PAINT_BRUSH_TYPE,       /* Default to use brushes        */
106   FALSE,                  /* reverse lines                 */
107   TRUE,                   /* Scale to image when painting  */
108   1.0,                    /* Scale to image fp             */
109   BRUSH_BRUSH_TYPE,       /* Default to use a brush        */
110   LINE                    /* Initial object type           */
111 };
112 
113 selection_option selopt =
114 {
115   ADD,          /* type */
116   FALSE,        /* Antia */
117   FALSE,        /* Feather */
118   10.0,         /* feather radius */
119   ARC_SEGMENT,  /* Arc as a segment */
120   FILL_PATTERN, /* Fill as pattern */
121   100.0,        /* Max opacity */
122 };
123 
124 /* Should be kept in sync with GfigOpts */
125 typedef struct
126 {
127   GtkAdjustment *gridspacing;
128   GtkAdjustment *grid_sectors_desired;
129   GtkAdjustment *grid_radius_interval;
130   GtkWidget     *gridtypemenu;
131   GtkWidget     *drawgrid;
132   GtkWidget     *snap2grid;
133   GtkWidget     *lockongrid;
134   GtkWidget     *showcontrol;
135 } GfigOptWidgets;
136 
137 static GfigOptWidgets  gfig_opt_widget = { NULL, NULL, NULL, NULL, NULL, NULL };
138 static gchar          *gfig_path       = NULL;
139 static GtkWidget      *page_menu_bg;
140 static GtkWidget      *tool_options_notebook;
141 static GtkWidget      *fill_type_notebook;
142 static guint           paint_timeout   = 0;
143 
144 static GtkActionGroup *gfig_actions    = NULL;
145 
146 
147 static void       gfig_response              (GtkWidget *widget,
148                                               gint       response_id,
149                                               gpointer   data);
150 static void       gfig_load_action_callback  (GtkAction *action,
151                                               gpointer   data);
152 static void       gfig_save_action_callback  (GtkAction *action,
153                                               gpointer   data);
154 static void       gfig_list_load_all         (const gchar *path);
155 static void       gfig_list_free_all         (void);
156 static void       create_notebook_pages      (GtkWidget *notebook);
157 static void       select_filltype_callback   (GtkWidget *widget);
158 static void       gfig_grid_action_callback  (GtkAction *action,
159                                               gpointer   data);
160 static void       gfig_prefs_action_callback (GtkAction *action,
161                                               gpointer   data);
162 static void       toggle_show_image          (void);
163 static void       gridtype_combo_callback    (GtkWidget *widget,
164                                               gpointer data);
165 
166 static void      load_file_chooser_response  (GtkFileChooser *chooser,
167                                               gint            response_id,
168                                               gpointer        data);
169 static void      save_file_chooser_response  (GtkFileChooser *chooser,
170                                               gint            response_id,
171                                               GFigObj        *obj);
172 static void     paint_combo_callback         (GtkWidget *widget,
173                                               gpointer   data);
174 
175 static void     select_button_clicked        (gint       type);
176 static void     select_button_clicked_lt     (void);
177 static void     select_button_clicked_gt     (void);
178 static void     select_button_clicked_eq     (void);
179 static void     raise_selected_obj_to_top    (GtkWidget *widget,
180                                               gpointer   data);
181 static void     lower_selected_obj_to_bottom (GtkWidget *widget,
182                                               gpointer   data);
183 static void     raise_selected_obj           (GtkWidget *widget,
184                                               gpointer   data);
185 static void     lower_selected_obj           (GtkWidget *widget,
186                                               gpointer   data);
187 
188 static void     toggle_obj_type              (GtkRadioAction *action,
189                                               GtkRadioAction *current,
190                                               gpointer        data);
191 
192 static GtkUIManager *create_ui_manager       (GtkWidget *window);
193 
194 
195 gboolean
gfig_dialog(void)196 gfig_dialog (void)
197 {
198   GtkWidget    *main_hbox;
199   GtkWidget    *vbox;
200   GFigObj      *gfig;
201   GimpParasite *parasite;
202   gint          newlayer;
203   GtkWidget    *menubar;
204   GtkWidget    *toolbar;
205   GtkWidget    *combo;
206   GtkWidget    *frame;
207   gint          img_width;
208   gint          img_height;
209   GimpImageType img_type;
210   GtkWidget    *toggle;
211   GtkWidget    *right_vbox;
212   GtkWidget    *hbox;
213   GtkUIManager *ui_manager;
214   GtkWidget    *empty_label;
215   gchar        *path;
216 
217   gimp_ui_init (PLUG_IN_BINARY, TRUE);
218 
219   img_width  = gimp_drawable_width (gfig_context->drawable_id);
220   img_height = gimp_drawable_height (gfig_context->drawable_id);
221   img_type   = gimp_drawable_type_with_alpha (gfig_context->drawable_id);
222 
223   /*
224    * See if there is a "gfig" parasite.  If so, this is a gfig layer,
225    * and we start by clearing it to transparent.
226    * If not, we create a new transparent layer.
227    */
228   gfig_list = NULL;
229   undo_level = -1;
230   parasite = gimp_item_get_parasite (gfig_context->drawable_id, "gfig");
231   gfig_context->enable_repaint = FALSE;
232 
233   /* debug */
234   gfig_context->debug_styles = FALSE;
235 
236   /* initial default style */
237   gfig_read_gimp_style (&gfig_context->default_style, "Base");
238   gfig_context->default_style.paint_type = selvals.painttype;
239 
240   if (parasite)
241     {
242       gimp_drawable_fill (gfig_context->drawable_id, GIMP_FILL_TRANSPARENT);
243       gfig_context->using_new_layer = FALSE;
244       gimp_parasite_free (parasite);
245     }
246   else
247     {
248       newlayer = gimp_layer_new (gfig_context->image_id, "GFig",
249                                  img_width, img_height,
250                                  img_type,
251                                  100.0,
252                                  gimp_image_get_default_new_layer_mode (gfig_context->image_id));
253       gimp_drawable_fill (newlayer, GIMP_FILL_TRANSPARENT);
254       gimp_image_insert_layer (gfig_context->image_id, newlayer, -1, -1);
255       gfig_context->drawable_id = newlayer;
256       gfig_context->using_new_layer = TRUE;
257     }
258 
259   gfig_stock_init ();
260 
261   path = gimp_gimprc_query ("gfig-path");
262 
263   if (path)
264     {
265       gfig_path = g_filename_from_utf8 (path, -1, NULL, NULL, NULL);
266       g_free (path);
267     }
268   else
269     {
270       gchar *gimprc    = gimp_personal_rc_file ("gimprc");
271       gchar *full_path = gimp_config_build_data_path ("gfig");
272       gchar *esc_path  = g_strescape (full_path, NULL);
273       g_free (full_path);
274 
275       g_message (_("No %s in gimprc:\n"
276                    "You need to add an entry like\n"
277                    "(%s \"%s\")\n"
278                    "to your %s file."),
279                    "gfig-path", "gfig-path", esc_path,
280                    gimp_filename_to_utf8 (gimprc));
281 
282       g_free (gimprc);
283       g_free (esc_path);
284     }
285 
286   /* Start building the dialog up */
287   top_level_dlg = gimp_dialog_new (_("Gfig"), PLUG_IN_ROLE,
288                                    NULL, 0,
289                                    gimp_standard_help_func, PLUG_IN_PROC,
290 
291                                    _("_Cancel"), GTK_RESPONSE_CANCEL,
292                                    _("_Close"),  GTK_RESPONSE_OK,
293 
294                                    NULL);
295 
296   gtk_dialog_set_alternative_button_order (GTK_DIALOG (top_level_dlg),
297                                            GTK_RESPONSE_OK,
298                                            GTK_RESPONSE_CANCEL,
299                                            -1);
300 
301   g_signal_connect (top_level_dlg, "response",
302                     G_CALLBACK (gfig_response),
303                     top_level_dlg);
304 
305   /* build the menu */
306   ui_manager = create_ui_manager (top_level_dlg);
307   menubar = gtk_ui_manager_get_widget (ui_manager, "/ui/gfig-menubar");
308   gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (top_level_dlg))),
309                       menubar, FALSE, FALSE, 0);
310   gtk_widget_show (menubar);
311   toolbar = gtk_ui_manager_get_widget (ui_manager, "/ui/gfig-toolbar");
312   gtk_toolbar_set_style (GTK_TOOLBAR (toolbar), GTK_TOOLBAR_ICONS);
313   gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (top_level_dlg))),
314                       toolbar, FALSE, FALSE, 0);
315   gtk_widget_show (toolbar);
316 
317   gfig_dialog_action_set_sensitive ("undo", undo_level >= 0);
318 
319   /* Main box */
320   main_hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
321   gtk_container_set_border_width (GTK_CONTAINER (main_hbox), 12);
322   gtk_box_pack_end (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (top_level_dlg))),
323                     main_hbox, TRUE, TRUE, 0);
324 
325   /* Preview itself */
326   gtk_box_pack_start (GTK_BOX (main_hbox), make_preview (), FALSE, FALSE, 0);
327 
328   gtk_widget_show (gfig_context->preview);
329 
330   right_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
331   gtk_box_pack_start (GTK_BOX (main_hbox), right_vbox, FALSE, FALSE, 0);
332   gtk_widget_show (right_vbox);
333 
334   /* Tool options notebook */
335   frame = gimp_frame_new ( _("Tool Options"));
336   gtk_box_pack_start (GTK_BOX (right_vbox), frame, FALSE, FALSE, 0);
337   gtk_widget_show (frame);
338 
339   tool_options_notebook = gtk_notebook_new ();
340   gtk_container_add (GTK_CONTAINER (frame), tool_options_notebook);
341   gtk_notebook_set_show_tabs (GTK_NOTEBOOK (tool_options_notebook), FALSE);
342   gtk_notebook_set_show_border (GTK_NOTEBOOK (tool_options_notebook), FALSE);
343   gtk_widget_show (tool_options_notebook);
344   create_notebook_pages (tool_options_notebook);
345 
346   /* Stroke frame on right side */
347   frame = gimp_frame_new (NULL);
348   gtk_box_pack_start (GTK_BOX (right_vbox), frame, FALSE, FALSE, 0);
349   gtk_widget_show (frame);
350 
351   gfig_context->paint_type_toggle =
352     toggle = gtk_check_button_new_with_mnemonic (_("_Stroke"));
353 
354   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), selvals.painttype);
355   gtk_frame_set_label_widget (GTK_FRAME (frame), toggle);
356   gtk_widget_show (toggle);
357 
358   hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
359   gtk_container_add (GTK_CONTAINER (frame), hbox);
360   gtk_widget_show (hbox);
361 
362   vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
363   gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 0);
364   gtk_widget_show (vbox);
365 
366   gtk_widget_set_sensitive (vbox, selvals.painttype);
367   g_signal_connect (toggle, "toggled",
368                     G_CALLBACK (set_paint_type_callback),
369                     vbox);
370 
371   /* foreground color button in Stroke frame*/
372   gfig_context->fg_color = g_new0 (GimpRGB, 1);
373   gfig_context->fg_color_button = gimp_color_button_new ("Foreground",
374                                                     SEL_BUTTON_WIDTH,
375                                                     SEL_BUTTON_HEIGHT,
376                                                     gfig_context->fg_color,
377                                                     GIMP_COLOR_AREA_SMALL_CHECKS);
378   g_signal_connect (gfig_context->fg_color_button, "color-changed",
379                     G_CALLBACK (set_foreground_callback),
380                     gfig_context->fg_color);
381   gimp_color_button_set_color (GIMP_COLOR_BUTTON (gfig_context->fg_color_button),
382                                &gfig_context->default_style.foreground);
383   gtk_box_pack_start (GTK_BOX (vbox), gfig_context->fg_color_button,
384                       FALSE, FALSE, 0);
385   gtk_widget_show (gfig_context->fg_color_button);
386 
387   /* brush selector in Stroke frame */
388   gfig_context->brush_select
389     = gimp_brush_select_button_new ("Brush",
390                                     gfig_context->default_style.brush_name,
391                                     -1.0, -1, -1);
392   g_signal_connect (gfig_context->brush_select, "brush-set",
393                     G_CALLBACK (gfig_brush_changed_callback), NULL);
394   gtk_box_pack_start (GTK_BOX (vbox), gfig_context->brush_select,
395                       FALSE, FALSE, 0);
396   gtk_widget_show (gfig_context->brush_select);
397 
398   /* Fill frame on right side */
399   frame = gimp_frame_new (_("Fill"));
400   gtk_box_pack_start (GTK_BOX (right_vbox), frame, FALSE, FALSE, 0);
401   gtk_widget_show (frame);
402 
403   hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
404   gtk_container_add (GTK_CONTAINER (frame), hbox);
405   gtk_widget_show (hbox);
406 
407   vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
408   gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 0);
409   gtk_widget_show (vbox);
410 
411   /* fill style combo box in Style frame  */
412   gfig_context->fillstyle_combo = combo
413     = gimp_int_combo_box_new (_("No fill"),             FILL_NONE,
414                               _("Color fill"),          FILL_COLOR,
415                               _("Pattern fill"),        FILL_PATTERN,
416                               _("Shape gradient"),      FILL_GRADIENT,
417                               _("Vertical gradient"),   FILL_VERTICAL,
418                               _("Horizontal gradient"), FILL_HORIZONTAL,
419                               NULL);
420   gimp_int_combo_box_set_active (GIMP_INT_COMBO_BOX (combo), 0);
421   g_signal_connect (combo, "changed",
422                     G_CALLBACK (select_filltype_callback),
423                     NULL);
424   gtk_box_pack_start (GTK_BOX (vbox), combo, FALSE, FALSE, 0);
425   gtk_widget_show (combo);
426 
427   fill_type_notebook = gtk_notebook_new ();
428   gtk_box_pack_start (GTK_BOX (vbox), fill_type_notebook, FALSE, FALSE, 0);
429   gtk_notebook_set_show_tabs (GTK_NOTEBOOK (fill_type_notebook), FALSE);
430   gtk_notebook_set_show_border (GTK_NOTEBOOK (fill_type_notebook), FALSE);
431   gtk_widget_show (fill_type_notebook);
432 
433   /* An empty page for "No fill" */
434   empty_label = gtk_label_new ("");
435   gtk_widget_show (empty_label);
436   gtk_notebook_append_page (GTK_NOTEBOOK (fill_type_notebook),
437                             empty_label, NULL);
438 
439   /* A page for the fill color button */
440   gfig_context->bg_color = g_new0 (GimpRGB, 1);
441   gfig_context->bg_color_button = gimp_color_button_new ("Background",
442                                            SEL_BUTTON_WIDTH, SEL_BUTTON_HEIGHT,
443                                            gfig_context->bg_color,
444                                            GIMP_COLOR_AREA_SMALL_CHECKS);
445   g_signal_connect (gfig_context->bg_color_button, "color-changed",
446                     G_CALLBACK (set_background_callback),
447                     gfig_context->bg_color);
448   gimp_color_button_set_color (GIMP_COLOR_BUTTON (gfig_context->bg_color_button),
449                                &gfig_context->default_style.background);
450   gtk_widget_show (gfig_context->bg_color_button);
451   gtk_notebook_append_page (GTK_NOTEBOOK (fill_type_notebook),
452                             gfig_context->bg_color_button, NULL);
453 
454   /* A page for the pattern selector */
455   gfig_context->pattern_select
456     = gimp_pattern_select_button_new ("Pattern", gfig_context->default_style.pattern);
457   g_signal_connect (gfig_context->pattern_select, "pattern-set",
458                     G_CALLBACK (gfig_pattern_changed_callback), NULL);
459   gtk_widget_show (gfig_context->pattern_select);
460   gtk_notebook_append_page (GTK_NOTEBOOK (fill_type_notebook),
461                             gfig_context->pattern_select, NULL);
462 
463   /* A page for the gradient selector */
464   gfig_context->gradient_select
465     = gimp_gradient_select_button_new ("Gradient", gfig_context->default_style.gradient);
466   g_signal_connect (gfig_context->gradient_select, "gradient-set",
467                     G_CALLBACK (gfig_gradient_changed_callback), NULL);
468   gtk_widget_show (gfig_context->gradient_select);
469   gtk_notebook_append_page (GTK_NOTEBOOK (fill_type_notebook),
470                             gfig_context->gradient_select, NULL);
471 
472 
473   vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
474   gtk_box_pack_start (GTK_BOX (right_vbox), vbox, FALSE, FALSE, 0);
475   gtk_widget_show (vbox);
476 
477   /* "show image" checkbutton at bottom of style frame */
478   toggle = gtk_check_button_new_with_label (_("Show image"));
479   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle),
480                                 gfig_context->show_background);
481   gtk_box_pack_end (GTK_BOX (vbox), toggle, FALSE, FALSE, 0);
482   g_signal_connect (toggle, "toggled",
483                     G_CALLBACK (gimp_toggle_button_update),
484                     &gfig_context->show_background);
485   g_signal_connect_swapped (toggle, "toggled",
486                     G_CALLBACK (gtk_widget_queue_draw),
487                     gfig_context->preview);
488   gtk_widget_show (toggle);
489 
490   /* "snap to grid" checkbutton at bottom of style frame */
491   toggle = gtk_check_button_new_with_label (C_("checkbutton", "Snap to grid"));
492   gtk_box_pack_end (GTK_BOX (vbox), toggle, FALSE, FALSE, 0);
493   g_signal_connect (toggle, "toggled",
494                     G_CALLBACK (gimp_toggle_button_update),
495                     &selvals.opts.snap2grid);
496   gtk_widget_show (toggle);
497   gfig_opt_widget.snap2grid = toggle;
498 
499   /* "show grid" checkbutton at bottom of style frame */
500   toggle = gtk_check_button_new_with_label (_("Show grid"));
501   gtk_box_pack_end (GTK_BOX (vbox), toggle, FALSE, FALSE, 0);
502   g_signal_connect (toggle, "toggled",
503                     G_CALLBACK (gimp_toggle_button_update),
504                     &selvals.opts.drawgrid);
505   g_signal_connect (toggle, "toggled",
506                     G_CALLBACK (draw_grid_clear),
507                     NULL);
508   gtk_widget_show (toggle);
509   gfig_opt_widget.drawgrid = toggle;
510 
511   /* Load saved objects */
512   gfig_list_load_all (gfig_path);
513 
514   /* Setup initial brush settings */
515   gfig_context->bdesc.name = gimp_context_get_brush ();
516   mygimp_brush_info (&gfig_context->bdesc.width, &gfig_context->bdesc.height);
517 
518   gtk_widget_show (main_hbox);
519 
520   gtk_widget_show (top_level_dlg);
521 
522   gfig = gfig_load_from_parasite ();
523   if (gfig)
524     {
525       gfig_list_insert (gfig);
526       new_obj_2edit (gfig);
527       gfig_style_set_context_from_style (&gfig_context->default_style);
528       gfig_style_apply (&gfig_context->default_style);
529     }
530 
531   gfig_context->enable_repaint = TRUE;
532   gfig_paint_callback ();
533 
534   gtk_main ();
535 
536   /* FIXME */
537   return TRUE;
538 }
539 
540 static void
gfig_response(GtkWidget * widget,gint response_id,gpointer data)541 gfig_response (GtkWidget *widget,
542                gint       response_id,
543                gpointer   data)
544 {
545   GFigObj *gfig;
546 
547   switch (response_id)
548     {
549     case GTK_RESPONSE_DELETE_EVENT:
550     case GTK_RESPONSE_CANCEL:
551       /* if we created a new layer, delete it */
552       if (gfig_context->using_new_layer)
553         {
554           gimp_image_remove_layer (gfig_context->image_id,
555                                    gfig_context->drawable_id);
556         }
557       else /* revert back to the original figure */
558         {
559           free_all_objs (gfig_context->current_obj->obj_list);
560           gfig_context->current_obj->obj_list = NULL;
561           gfig = gfig_load_from_parasite ();
562           if (gfig)
563             {
564               gfig_list_insert (gfig);
565               new_obj_2edit (gfig);
566             }
567           gfig_context->enable_repaint = TRUE;
568           gfig_paint_callback ();
569         }
570       break;
571 
572     case GTK_RESPONSE_OK:  /* Close button */
573       gfig_save_as_parasite ();
574       break;
575 
576     default:
577       break;
578     }
579 
580   gtk_widget_destroy (widget);
581   gtk_main_quit ();
582 }
583 
584 void
gfig_dialog_action_set_sensitive(const gchar * name,gboolean sensitive)585 gfig_dialog_action_set_sensitive (const gchar *name,
586                                   gboolean     sensitive)
587 {
588   g_return_if_fail (name != NULL);
589 
590   if (gfig_actions)
591     {
592       GtkAction *action = gtk_action_group_get_action (gfig_actions, name);
593 
594       if (! action)
595         {
596           g_warning ("%s: Unable to set sensitivity of action "
597                      "which doesn't exist: %s",
598                      G_STRFUNC, name);
599           return;
600         }
601 
602       g_object_set (action, "sensitive", sensitive ? TRUE : FALSE, NULL);
603     }
604 }
605 
606 static gchar *
gfig_get_user_writable_dir(void)607 gfig_get_user_writable_dir (void)
608 {
609   if (gfig_path)
610     {
611       GList *list;
612       gchar *dir;
613 
614       list = gimp_path_parse (gfig_path, 256, FALSE, NULL);
615       dir = gimp_path_get_user_writable_dir (list);
616       gimp_path_free (list);
617 
618       return dir;
619     }
620 
621   return g_strdup (gimp_directory ());
622 }
623 
624 static void
gfig_load_action_callback(GtkAction * action,gpointer data)625 gfig_load_action_callback (GtkAction *action,
626                            gpointer   data)
627 {
628   static GtkWidget *dialog = NULL;
629 
630   if (! dialog)
631     {
632       gchar *dir;
633 
634       dialog =
635         gtk_file_chooser_dialog_new (_("Load Gfig Object Collection"),
636                                      GTK_WINDOW (data),
637                                      GTK_FILE_CHOOSER_ACTION_OPEN,
638 
639                                      _("_Cancel"), GTK_RESPONSE_CANCEL,
640                                      _("_Open"),   GTK_RESPONSE_OK,
641 
642                                      NULL);
643 
644       gtk_dialog_set_alternative_button_order (GTK_DIALOG (dialog),
645                                                GTK_RESPONSE_OK,
646                                                GTK_RESPONSE_CANCEL,
647                                                -1);
648 
649       gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
650 
651       g_object_add_weak_pointer (G_OBJECT (dialog), (gpointer) &dialog);
652 
653       g_signal_connect (dialog, "response",
654                         G_CALLBACK (load_file_chooser_response),
655                         NULL);
656 
657       dir = gfig_get_user_writable_dir ();
658       if (dir)
659         {
660           gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog),
661                                                dir);
662           g_free (dir);
663         }
664 
665       gtk_widget_show (dialog);
666     }
667   else
668     {
669       gtk_window_present (GTK_WINDOW (dialog));
670     }
671 }
672 
673 static void
gfig_save_action_callback(GtkAction * action,gpointer data)674 gfig_save_action_callback (GtkAction *action,
675                            gpointer   data)
676 {
677   static GtkWidget *dialog = NULL;
678 
679   if (!dialog)
680     {
681       gchar *dir;
682 
683       dialog =
684         gtk_file_chooser_dialog_new (_("Save Gfig Drawing"),
685                                      GTK_WINDOW (data),
686                                      GTK_FILE_CHOOSER_ACTION_SAVE,
687 
688                                      _("_Cancel"), GTK_RESPONSE_CANCEL,
689                                      _("_Save"),   GTK_RESPONSE_OK,
690 
691                                      NULL);
692 
693       gtk_dialog_set_alternative_button_order (GTK_DIALOG (dialog),
694                                                GTK_RESPONSE_OK,
695                                                GTK_RESPONSE_CANCEL,
696                                                -1);
697       gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
698 
699       gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog),
700                                                       TRUE);
701 
702       g_object_add_weak_pointer (G_OBJECT (dialog), (gpointer) &dialog);
703 
704       /* FIXME: GFigObj should be a GObject and g_signal_connect_object()
705        *        should be used here.
706        */
707       g_signal_connect (dialog, "response",
708                         G_CALLBACK (save_file_chooser_response),
709                         gfig_context->current_obj);
710 
711       dir = gfig_get_user_writable_dir ();
712       if (dir)
713         {
714           gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), dir);
715           g_free (dir);
716         }
717 
718       gtk_widget_show (dialog);
719     }
720   else
721     {
722       gtk_window_present (GTK_WINDOW (dialog));
723     }
724 }
725 
726 static void
gfig_close_action_callback(GtkAction * action,gpointer data)727 gfig_close_action_callback (GtkAction *action,
728                             gpointer   data)
729 {
730   gtk_dialog_response (GTK_DIALOG (data), GTK_RESPONSE_OK);
731 }
732 
733 static void
gfig_undo_action_callback(GtkAction * action,gpointer data)734 gfig_undo_action_callback (GtkAction *action,
735                            gpointer   data)
736 {
737   if (undo_level >= 0)
738     {
739       /* Free current objects an reinstate previous */
740       free_all_objs (gfig_context->current_obj->obj_list);
741       gfig_context->current_obj->obj_list = NULL;
742       tmp_bezier = tmp_line = obj_creating = NULL;
743       gfig_context->current_obj->obj_list = undo_table[undo_level];
744       undo_level--;
745       /* Update the screen */
746       gtk_widget_queue_draw (gfig_context->preview);
747       /* And preview */
748       gfig_context->current_obj->obj_status |= GFIG_MODIFIED;
749       if (gfig_context->current_obj->obj_list)
750         gfig_context->selected_obj = gfig_context->current_obj->obj_list->data;
751       else
752         gfig_context->selected_obj = NULL;
753     }
754 
755   gfig_dialog_action_set_sensitive ("undo", undo_level >= 0);
756   gfig_paint_callback ();
757 }
758 
759 static void
gfig_clear_action_callback(GtkWidget * widget,gpointer data)760 gfig_clear_action_callback (GtkWidget *widget,
761                           gpointer   data)
762 {
763   /* Make sure we can get back - if we have some objects to get back to */
764   if (!gfig_context->current_obj->obj_list)
765     return;
766 
767   setup_undo ();
768   /* Free all objects */
769   free_all_objs (gfig_context->current_obj->obj_list);
770   gfig_context->current_obj->obj_list = NULL;
771   gfig_context->selected_obj = NULL;
772   obj_creating = NULL;
773   tmp_line = NULL;
774   tmp_bezier = NULL;
775   gtk_widget_queue_draw (gfig_context->preview);
776   gfig_paint_callback ();
777 }
778 
779 void
draw_item(cairo_t * cr,gboolean fill)780 draw_item (cairo_t *cr, gboolean fill)
781 {
782   cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 1.0);
783 
784   if (fill)
785     {
786       cairo_fill_preserve (cr);
787     }
788   else
789     {
790       cairo_set_line_width (cr, 3.0);
791       cairo_stroke_preserve (cr);
792     }
793 
794   cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, 1.0);
795   cairo_set_line_width (cr, 1.0);
796   cairo_stroke (cr);
797 }
798 
799 /* Given a point x, y draw a circle */
800 void
draw_circle(GdkPoint * p,gboolean selected,cairo_t * cr)801 draw_circle (GdkPoint *p,
802              gboolean  selected,
803              cairo_t  *cr)
804 {
805   if (!selvals.opts.showcontrol)
806     return;
807 
808   cairo_arc (cr,
809              gfig_scale_x (p->x) + .5,
810              gfig_scale_y (p->y) + .5,
811              SQ_SIZE / 2,
812              0, 2 * G_PI);
813 
814   draw_item (cr, selected);
815 }
816 
817 /* Given a point x, y draw a square around it */
818 void
draw_sqr(GdkPoint * p,gboolean selected,cairo_t * cr)819 draw_sqr (GdkPoint *p,
820           gboolean  selected,
821           cairo_t  *cr)
822 {
823   if (!selvals.opts.showcontrol)
824     return;
825 
826   cairo_rectangle (cr,
827                    gfig_scale_x (p->x) + .5 - SQ_SIZE / 2,
828                    gfig_scale_y (p->y) + .5 - SQ_SIZE / 2,
829                    SQ_SIZE,
830                    SQ_SIZE);
831 
832   draw_item (cr, selected);
833 }
834 
835 static void
gfig_list_load_all(const gchar * path)836 gfig_list_load_all (const gchar *path)
837 {
838   /*  Make sure to clear any existing gfigs  */
839   gfig_context->current_obj = NULL;
840   gfig_list_free_all ();
841 
842   if (! gfig_list)
843     {
844       GFigObj *gfig;
845 
846       /* lets have at least one! */
847       gfig = gfig_new ();
848       gfig->draw_name = g_strdup (_("First Gfig"));
849       gfig_list_insert (gfig);
850     }
851 
852   gfig_context->current_obj = gfig_list->data;  /* set to first entry */
853 }
854 
855 static void
gfig_list_free_all(void)856 gfig_list_free_all (void)
857 {
858   g_list_free_full (gfig_list, (GDestroyNotify) gfig_free);
859   gfig_list = NULL;
860 }
861 
862 static GtkUIManager *
create_ui_manager(GtkWidget * window)863 create_ui_manager (GtkWidget *window)
864 {
865   static GtkActionEntry actions[] =
866   {
867     { "gfig-menubar", NULL, "GFig Menu" },
868 
869     { "gfig-file-menu", NULL, "_File" },
870 
871     { "open", GIMP_ICON_DOCUMENT_OPEN,
872       N_("_Open..."), "<control>O", NULL,
873       G_CALLBACK (gfig_load_action_callback) },
874 
875     { "save", GIMP_ICON_DOCUMENT_SAVE,
876       N_("_Save..."), "<control>S", NULL,
877       G_CALLBACK (gfig_save_action_callback) },
878 
879     { "close", GIMP_ICON_CLOSE,
880       N_("_Close"), "<control>C", NULL,
881       G_CALLBACK (gfig_close_action_callback) },
882 
883     { "gfig-edit-menu", NULL, "_Edit" },
884 
885     { "undo", GIMP_ICON_EDIT_UNDO,
886       N_("_Undo"), "<control>Z", NULL,
887       G_CALLBACK (gfig_undo_action_callback) },
888 
889     { "clear", GIMP_ICON_EDIT_CLEAR,
890       N_("_Clear"), NULL, NULL,
891       G_CALLBACK (gfig_clear_action_callback) },
892 
893     { "grid", GIMP_ICON_GRID,
894       N_("_Grid"), "<control>G", NULL,
895       G_CALLBACK (gfig_grid_action_callback) },
896 
897     { "prefs", GIMP_ICON_PREFERENCES_SYSTEM,
898       N_("_Preferences..."), "<control>P", NULL,
899       G_CALLBACK (gfig_prefs_action_callback) },
900 
901     { "raise", GIMP_ICON_GO_UP,
902       N_("_Raise"), "<control>U", N_("Raise selected object"),
903       G_CALLBACK (raise_selected_obj) },
904 
905     { "lower", GIMP_ICON_GO_DOWN,
906       N_("_Lower"), "<control>D", N_("Lower selected object"),
907       G_CALLBACK (lower_selected_obj) },
908 
909     { "top", GIMP_ICON_GO_TOP,
910       N_("Raise to _top"), "<control>T", N_("Raise selected object to top"),
911       G_CALLBACK (raise_selected_obj_to_top) },
912 
913     { "bottom", GIMP_ICON_GO_BOTTOM,
914       N_("Lower to _bottom"), "<control>B", N_("Lower selected object to bottom"),
915       G_CALLBACK (lower_selected_obj_to_bottom) },
916 
917     { "show_previous", GIMP_ICON_GO_PREVIOUS,
918       N_("_Previous"), "<control>H", N_("Show previous object"),
919       G_CALLBACK (select_button_clicked_lt) },
920 
921     { "show_next", GIMP_ICON_GO_NEXT,
922       N_("_Next"), "<control>L", N_("Show next object"),
923       G_CALLBACK (select_button_clicked_gt) },
924 
925     { "show_all", GFIG_STOCK_SHOW_ALL,
926       N_("Show _all"), "<control>A", N_("Show all objects"),
927       G_CALLBACK (select_button_clicked_eq) }
928   };
929   static GtkRadioActionEntry radio_actions[] =
930   {
931     { "line", GFIG_STOCK_LINE,
932       NULL, "L", N_("Create line"), LINE },
933 
934     { "rectangle", GFIG_STOCK_RECTANGLE,
935       NULL, "R", N_("Create rectangle"), RECTANGLE },
936 
937     { "circle", GFIG_STOCK_CIRCLE,
938       NULL, "C", N_("Create circle"), CIRCLE },
939 
940     { "ellipse", GFIG_STOCK_ELLIPSE,
941       NULL, "E", N_("Create ellipse"), ELLIPSE },
942 
943     { "arc", GFIG_STOCK_CURVE,
944       NULL, "A", N_("Create arc"), ARC },
945 
946     { "polygon", GFIG_STOCK_POLYGON,
947       NULL, "P", N_("Create reg polygon"), POLY },
948 
949     { "star", GFIG_STOCK_STAR,
950       NULL, "S", N_("Create star"), STAR },
951 
952     { "spiral", GFIG_STOCK_SPIRAL,
953        NULL, "I", N_("Create spiral"), SPIRAL },
954 
955     { "bezier", GFIG_STOCK_BEZIER,
956       NULL, "B", N_("Create bezier curve. "
957                     "Shift + Button ends object creation."), BEZIER },
958 
959     { "move_obj", GFIG_STOCK_MOVE_OBJECT,
960       NULL, "M", N_("Move an object"), MOVE_OBJ },
961 
962     { "move_point", GFIG_STOCK_MOVE_POINT,
963       NULL, "V", N_("Move a single point"), MOVE_POINT },
964 
965     { "copy", GFIG_STOCK_COPY_OBJECT,
966       NULL, "Y", N_("Copy an object"), COPY_OBJ },
967 
968     { "delete", GFIG_STOCK_DELETE_OBJECT,
969       NULL, "D", N_("Delete an object"), DEL_OBJ },
970 
971     { "select", GFIG_STOCK_SELECT_OBJECT,
972       NULL, "A", N_("Select an object"), SELECT_OBJ }
973   };
974 
975   GtkUIManager   *ui_manager = gtk_ui_manager_new ();
976 
977   gfig_actions = gtk_action_group_new ("Actions");
978 
979   gtk_action_group_set_translation_domain (gfig_actions, NULL);
980 
981   gtk_action_group_add_actions (gfig_actions,
982                                 actions,
983                                 G_N_ELEMENTS (actions),
984                                 window);
985   gtk_action_group_add_radio_actions (gfig_actions,
986                                       radio_actions,
987                                       G_N_ELEMENTS (radio_actions),
988                                       LINE,
989                                       G_CALLBACK (toggle_obj_type),
990                                       window);
991 
992   gtk_window_add_accel_group (GTK_WINDOW (window),
993                               gtk_ui_manager_get_accel_group (ui_manager));
994   gtk_accel_group_lock (gtk_ui_manager_get_accel_group (ui_manager));
995 
996   gtk_ui_manager_insert_action_group (ui_manager, gfig_actions, -1);
997   g_object_unref (gfig_actions);
998 
999   gtk_ui_manager_add_ui_from_string (ui_manager,
1000                                      "<ui>"
1001                                      "  <menubar name=\"gfig-menubar\">"
1002                                      "    <menu name=\"File\" action=\"gfig-file-menu\">"
1003                                      "      <menuitem action=\"open\" />"
1004                                      "      <menuitem action=\"save\" />"
1005                                      "      <menuitem action=\"close\" />"
1006                                      "    </menu>"
1007                                      "    <menu name=\"Edit\" action=\"gfig-edit-menu\">"
1008                                      "      <menuitem action=\"undo\" />"
1009                                      "      <menuitem action=\"clear\" />"
1010                                      "      <menuitem action=\"grid\" />"
1011                                      "      <menuitem action=\"prefs\" />"
1012                                      "    </menu>"
1013                                      "  </menubar>"
1014                                      "</ui>",
1015                                      -1, NULL);
1016   gtk_ui_manager_add_ui_from_string (ui_manager,
1017                                      "<ui>"
1018                                      "  <toolbar name=\"gfig-toolbar\">"
1019                                      "    <toolitem action=\"line\" />"
1020                                      "    <toolitem action=\"rectangle\" />"
1021                                      "    <toolitem action=\"circle\" />"
1022                                      "    <toolitem action=\"ellipse\" />"
1023                                      "    <toolitem action=\"arc\" />"
1024                                      "    <toolitem action=\"polygon\" />"
1025                                      "    <toolitem action=\"star\" />"
1026                                      "    <toolitem action=\"spiral\" />"
1027                                      "    <toolitem action=\"bezier\" />"
1028                                      "    <toolitem action=\"move_obj\" />"
1029                                      "    <toolitem action=\"move_point\" />"
1030                                      "    <toolitem action=\"copy\" />"
1031                                      "    <toolitem action=\"delete\" />"
1032                                      "    <toolitem action=\"select\" />"
1033                                      "    <separator />"
1034                                      "    <toolitem action=\"raise\" />"
1035                                      "    <toolitem action=\"lower\" />"
1036                                      "    <toolitem action=\"top\" />"
1037                                      "    <toolitem action=\"bottom\" />"
1038                                      "    <separator />"
1039                                      "    <toolitem action=\"show_previous\" />"
1040                                      "    <toolitem action=\"show_next\" />"
1041                                      "    <toolitem action=\"show_all\" />"
1042                                      "  </toolbar>"
1043                                      "</ui>",
1044                                      -1, NULL);
1045 
1046   return ui_manager;
1047 }
1048 
1049 static void
tool_option_no_option(GtkWidget * notebook)1050 tool_option_no_option (GtkWidget *notebook)
1051 {
1052   GtkWidget *label;
1053 
1054   label = gtk_label_new (_("This tool has no options"));
1055   gtk_widget_show (label);
1056   gtk_notebook_append_page (GTK_NOTEBOOK (notebook), label, NULL);
1057 }
1058 
1059 static void
create_notebook_pages(GtkWidget * notebook)1060 create_notebook_pages (GtkWidget *notebook)
1061 {
1062   tool_option_no_option (notebook);   /* Line          */
1063   tool_option_no_option (notebook);   /* Rectangle     */
1064   tool_option_no_option (notebook);   /* Circle        */
1065   tool_option_no_option (notebook);   /* Ellipse       */
1066   tool_option_no_option (notebook);   /* Arc           */
1067   tool_options_poly (notebook);       /* Polygon       */
1068   tool_options_star (notebook);       /* Star          */
1069   tool_options_spiral (notebook);     /* Spiral        */
1070   tool_options_bezier (notebook);     /* Bezier        */
1071   tool_option_no_option (notebook);   /* Dummy         */
1072   tool_option_no_option (notebook);   /* Move Object   */
1073   tool_option_no_option (notebook);   /* Move Point    */
1074   tool_option_no_option (notebook);   /* Copy Object   */
1075   tool_option_no_option (notebook);   /* Delete Object */
1076 }
1077 
1078 static void
raise_selected_obj_to_top(GtkWidget * widget,gpointer data)1079 raise_selected_obj_to_top (GtkWidget *widget,
1080                            gpointer   data)
1081 {
1082   if (!gfig_context->selected_obj)
1083     return;
1084 
1085   if (g_list_find (gfig_context->current_obj->obj_list,
1086                    gfig_context->selected_obj))
1087     {
1088       gfig_context->current_obj->obj_list =
1089         g_list_remove (gfig_context->current_obj->obj_list,
1090                        gfig_context->selected_obj);
1091       gfig_context->current_obj->obj_list =
1092         g_list_append (gfig_context->current_obj->obj_list,
1093                        gfig_context->selected_obj);
1094     }
1095   else
1096     {
1097       g_message ("Trying to raise object that does not exist.");
1098       return;
1099     }
1100 
1101   gfig_paint_callback ();
1102 }
1103 
1104 static void
lower_selected_obj_to_bottom(GtkWidget * widget,gpointer data)1105 lower_selected_obj_to_bottom (GtkWidget *widget,
1106                               gpointer   data)
1107 {
1108   if (!gfig_context->selected_obj)
1109     return;
1110 
1111   if (g_list_find (gfig_context->current_obj->obj_list,
1112                    gfig_context->selected_obj))
1113     {
1114       gfig_context->current_obj->obj_list =
1115         g_list_remove (gfig_context->current_obj->obj_list,
1116                        gfig_context->selected_obj);
1117       gfig_context->current_obj->obj_list =
1118         g_list_prepend (gfig_context->current_obj->obj_list,
1119                         gfig_context->selected_obj);
1120     }
1121   else
1122     {
1123       g_message ("Trying to lower object that does not exist.");
1124       return;
1125     }
1126 
1127   gfig_paint_callback ();
1128 }
1129 
1130 static void
raise_selected_obj(GtkWidget * widget,gpointer data)1131 raise_selected_obj (GtkWidget *widget,
1132                     gpointer   data)
1133 {
1134   if (!gfig_context->selected_obj)
1135     return;
1136 
1137   if (g_list_find (gfig_context->current_obj->obj_list,
1138                    gfig_context->selected_obj))
1139     {
1140       int position;
1141 
1142       position = g_list_index (gfig_context->current_obj->obj_list,
1143                                gfig_context->selected_obj);
1144       gfig_context->current_obj->obj_list =
1145         g_list_remove (gfig_context->current_obj->obj_list,
1146                        gfig_context->selected_obj);
1147       gfig_context->current_obj->obj_list =
1148         g_list_insert (gfig_context->current_obj->obj_list,
1149                        gfig_context->selected_obj,
1150                        position + 1);
1151     }
1152   else
1153     {
1154       g_message ("Trying to raise object that does not exist.");
1155       return;
1156     }
1157 
1158   gfig_paint_callback ();
1159 }
1160 
1161 
1162 static void
lower_selected_obj(GtkWidget * widget,gpointer data)1163 lower_selected_obj (GtkWidget *widget,
1164                     gpointer   data)
1165 {
1166   if (!gfig_context->selected_obj)
1167     return;
1168 
1169   if (g_list_find (gfig_context->current_obj->obj_list,
1170                    gfig_context->selected_obj))
1171     {
1172       int position;
1173 
1174       position = g_list_index (gfig_context->current_obj->obj_list,
1175                                gfig_context->selected_obj);
1176       gfig_context->current_obj->obj_list =
1177         g_list_remove (gfig_context->current_obj->obj_list,
1178                        gfig_context->selected_obj);
1179       gfig_context->current_obj->obj_list =
1180         g_list_insert (gfig_context->current_obj->obj_list,
1181                        gfig_context->selected_obj,
1182                        MAX (0, position - 1));
1183     }
1184   else
1185     {
1186       g_message ("Trying to lower object that does not exist.");
1187       return;
1188     }
1189 
1190   gfig_paint_callback ();
1191 }
1192 
1193 
1194 static void
select_filltype_callback(GtkWidget * widget)1195 select_filltype_callback (GtkWidget *widget)
1196 {
1197   gint value;
1198 
1199   gimp_int_combo_box_get_active (GIMP_INT_COMBO_BOX (widget), &value);
1200   gtk_notebook_set_current_page (GTK_NOTEBOOK (fill_type_notebook),
1201                                  MIN (value, FILL_GRADIENT));
1202 
1203   gfig_context_get_current_style ()->fill_type = (FillType) value;
1204 
1205   gfig_paint_callback ();
1206 }
1207 
1208 static gboolean
gfig_paint_timeout(gpointer data)1209 gfig_paint_timeout (gpointer data)
1210 {
1211   gfig_paint_callback ();
1212 
1213   paint_timeout = 0;
1214 
1215   return FALSE;
1216 }
1217 
1218 static void
gfig_paint_delayed(void)1219 gfig_paint_delayed (void)
1220 {
1221   if (paint_timeout)
1222     g_source_remove (paint_timeout);
1223 
1224   paint_timeout =
1225     g_timeout_add (UPDATE_DELAY, gfig_paint_timeout, NULL);
1226 }
1227 
1228 static void
gfig_prefs_action_callback(GtkAction * widget,gpointer data)1229 gfig_prefs_action_callback (GtkAction *widget,
1230                             gpointer   data)
1231 {
1232   static GtkWidget *dialog = NULL;
1233 
1234   if (!dialog)
1235     {
1236       GtkWidget     *main_vbox;
1237       GtkWidget     *table;
1238       GtkWidget     *toggle;
1239       GtkObject     *size_data;
1240       GtkWidget     *scale;
1241       GtkAdjustment *scale_data;
1242 
1243       dialog = gimp_dialog_new (_("Options"), "gimp-gfig-options",
1244                                 GTK_WIDGET (data), 0, NULL, NULL,
1245 
1246                                 _("_Close"),  GTK_RESPONSE_CLOSE,
1247 
1248                                 NULL);
1249 
1250       gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_CLOSE);
1251 
1252       g_object_add_weak_pointer (G_OBJECT (dialog), (gpointer) &dialog);
1253 
1254       g_signal_connect (dialog, "response",
1255                         G_CALLBACK (gtk_widget_destroy),
1256                         NULL);
1257 
1258       main_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
1259       gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 12);
1260       gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))),
1261                           main_vbox, TRUE, TRUE, 0);
1262       gtk_widget_show (main_vbox);
1263 
1264       /* Put buttons in */
1265       toggle = gtk_check_button_new_with_label (_("Show position"));
1266       gtk_box_pack_start (GTK_BOX (main_vbox), toggle, FALSE, FALSE, 6);
1267       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle),
1268                                     selvals.showpos);
1269       g_signal_connect (toggle, "toggled",
1270                         G_CALLBACK (gimp_toggle_button_update),
1271                         &selvals.showpos);
1272       g_signal_connect_after (toggle, "toggled",
1273                               G_CALLBACK (gfig_pos_enable),
1274                               NULL);
1275       gtk_widget_show (toggle);
1276 
1277       toggle = gtk_check_button_new_with_label (_("Show control points"));
1278       gtk_box_pack_start (GTK_BOX (main_vbox), toggle, FALSE, FALSE, 6);
1279       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle),
1280                                     selvals.opts.showcontrol);
1281       g_signal_connect (toggle, "toggled",
1282                         G_CALLBACK (gimp_toggle_button_update),
1283                         &selvals.opts.showcontrol);
1284       g_signal_connect (toggle, "toggled",
1285                         G_CALLBACK (toggle_show_image),
1286                         NULL);
1287       gtk_widget_show (toggle);
1288 
1289       gfig_opt_widget.showcontrol = toggle;
1290       g_object_add_weak_pointer (G_OBJECT (gfig_opt_widget.showcontrol),
1291                                  (gpointer) &gfig_opt_widget.showcontrol);
1292 
1293       toggle = gtk_check_button_new_with_label (_("Antialiasing"));
1294       gtk_box_pack_start (GTK_BOX (main_vbox), toggle, FALSE, FALSE, 6);
1295       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), selopt.antia);
1296       g_signal_connect (toggle, "toggled",
1297                         G_CALLBACK (gimp_toggle_button_update),
1298                         &selopt.antia);
1299       g_signal_connect (toggle, "toggled",
1300                         G_CALLBACK (gfig_paint_callback),
1301                         NULL);
1302       gtk_widget_show (toggle);
1303 
1304       table = gtk_table_new (4, 4, FALSE);
1305       gtk_table_set_col_spacings (GTK_TABLE (table), 6);
1306       gtk_table_set_row_spacings (GTK_TABLE (table), 6);
1307       gtk_box_pack_start (GTK_BOX (main_vbox), table, FALSE, FALSE, 6);
1308       gtk_widget_show (table);
1309 
1310       size_data = gimp_scale_entry_new (GTK_TABLE (table), 0, 0,
1311                                         _("Max undo:"), 100, 50,
1312                                         selvals.maxundo,
1313                                         MIN_UNDO, MAX_UNDO, 1, 2, 0,
1314                                         TRUE, 0, 0,
1315                                         NULL, NULL);
1316       g_signal_connect (size_data, "value-changed",
1317                         G_CALLBACK (gimp_int_adjustment_update),
1318                         &selvals.maxundo);
1319 
1320       page_menu_bg = gimp_int_combo_box_new (_("Transparent"), LAYER_TRANS_BG,
1321                                              _("Background"),  LAYER_BG_BG,
1322                                              _("Foreground"),  LAYER_FG_BG,
1323                                              _("White"),       LAYER_WHITE_BG,
1324                                              _("Copy"),        LAYER_COPY_BG,
1325                                              NULL);
1326       gimp_int_combo_box_set_active (GIMP_INT_COMBO_BOX (page_menu_bg), selvals.onlayerbg);
1327 
1328       g_signal_connect (page_menu_bg, "changed",
1329                         G_CALLBACK (paint_combo_callback),
1330                         GINT_TO_POINTER (PAINT_BGS_MENU));
1331 
1332       gimp_help_set_help_data (page_menu_bg,
1333                                _("Layer background type. Copy causes the "
1334                                  "previous layer to be copied before the "
1335                                  "draw is performed."),
1336                                NULL);
1337 
1338       gimp_table_attach_aligned (GTK_TABLE (table), 0, 1,
1339                                  _("Background:"), 0.0, 0.5,
1340                                  page_menu_bg, 2, FALSE);
1341 
1342       toggle = gtk_check_button_new_with_label (_("Feather"));
1343       gtk_table_attach (GTK_TABLE (table), toggle, 2, 3, 2, 3,
1344                         GTK_FILL, GTK_FILL, 0, 0);
1345       g_signal_connect (toggle, "toggled",
1346                         G_CALLBACK (gimp_toggle_button_update),
1347                         &selopt.feather);
1348       g_signal_connect (toggle, "toggled",
1349                         G_CALLBACK (gfig_paint_callback),
1350                         NULL);
1351       gtk_widget_show (toggle);
1352 
1353       scale_data = (GtkAdjustment *)
1354         gtk_adjustment_new (selopt.feather_radius, 0.0, 100.0, 1.0, 1.0, 0.0);
1355       scale = gtk_scale_new (GTK_ORIENTATION_HORIZONTAL, scale_data);
1356       gtk_scale_set_value_pos (GTK_SCALE (scale), GTK_POS_TOP);
1357 
1358       g_signal_connect (scale_data, "value-changed",
1359                         G_CALLBACK (gimp_double_adjustment_update),
1360                         &selopt.feather_radius);
1361       g_signal_connect (scale_data, "value-changed",
1362                         G_CALLBACK (gfig_paint_delayed),
1363                         NULL);
1364       gimp_table_attach_aligned (GTK_TABLE (table), 0, 2,
1365                                  _("Radius:"), 0.0, 1.0, scale, 1, FALSE);
1366 
1367       gtk_widget_show (dialog);
1368     }
1369   else
1370     {
1371       gtk_window_present (GTK_WINDOW (dialog));
1372     }
1373 }
1374 
1375 static void
gfig_grid_action_callback(GtkAction * action,gpointer data)1376 gfig_grid_action_callback (GtkAction *action,
1377                            gpointer   data)
1378 {
1379   static GtkWidget *dialog = NULL;
1380 
1381   if (!dialog)
1382     {
1383       GtkWidget *main_vbox;
1384       GtkWidget *hbox;
1385       GtkWidget *table;
1386       GtkWidget *combo;
1387       GtkObject *size_data;
1388       GtkObject *sectors_data;
1389       GtkObject *radius_data;
1390 
1391       dialog = gimp_dialog_new (_("Grid"), "gimp-gfig-grid",
1392                                 GTK_WIDGET (data), 0, NULL, NULL,
1393 
1394                                 _("_Close"),  GTK_RESPONSE_CLOSE,
1395 
1396                                 NULL);
1397 
1398       gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_CLOSE);
1399 
1400       g_object_add_weak_pointer (G_OBJECT (dialog), (gpointer) &dialog);
1401 
1402       g_signal_connect (dialog, "response",
1403                         G_CALLBACK (gtk_widget_destroy),
1404                         NULL);
1405 
1406       main_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
1407       gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 12);
1408       gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))),
1409                           main_vbox, TRUE, TRUE, 0);
1410       gtk_widget_show (main_vbox);
1411 
1412       hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
1413       gtk_box_pack_start (GTK_BOX (main_vbox), hbox, FALSE, FALSE, 0);
1414       gtk_widget_show (hbox);
1415 
1416       table = gtk_table_new (3, 3, FALSE);
1417       gtk_table_set_col_spacings (GTK_TABLE (table), 6);
1418       gtk_table_set_row_spacings (GTK_TABLE (table), 6);
1419       gtk_box_pack_start (GTK_BOX (main_vbox), table, FALSE, FALSE, 0);
1420       gtk_widget_show (table);
1421 
1422       size_data = gimp_scale_entry_new (GTK_TABLE (table), 0, 0,
1423                                         _("Grid spacing:"), 100, 50,
1424                                         selvals.opts.gridspacing,
1425                                         MIN_GRID, MAX_GRID, 1, 10, 0,
1426                                         TRUE, 0, 0,
1427                                         NULL, NULL);
1428       g_signal_connect (size_data, "value-changed",
1429                         G_CALLBACK (gimp_int_adjustment_update),
1430                         &selvals.opts.gridspacing);
1431       g_signal_connect (size_data, "value-changed",
1432                         G_CALLBACK (draw_grid_clear),
1433                         NULL);
1434 
1435       gfig_opt_widget.gridspacing = GTK_ADJUSTMENT (size_data);
1436       g_object_add_weak_pointer (G_OBJECT (gfig_opt_widget.gridspacing),
1437                                  (gpointer) &gfig_opt_widget.gridspacing);
1438 
1439       sectors_data = gimp_scale_entry_new (GTK_TABLE (table), 0, 3,
1440                                         _("Polar grid sectors desired:"), 1, 5,
1441                                         selvals.opts.grid_sectors_desired,
1442                                         5, 360, 5, 1, 0,
1443                                         TRUE, 0, 0,
1444                                         NULL, NULL);
1445       g_signal_connect (sectors_data, "value-changed",
1446                         G_CALLBACK (gimp_int_adjustment_update),
1447                         &selvals.opts.grid_sectors_desired);
1448       g_signal_connect (sectors_data, "value-changed",
1449                         G_CALLBACK (draw_grid_clear),
1450                         NULL);
1451 
1452       gfig_opt_widget.grid_sectors_desired = GTK_ADJUSTMENT (sectors_data);
1453       g_object_add_weak_pointer (G_OBJECT (gfig_opt_widget.grid_sectors_desired),
1454                                  (gpointer) &gfig_opt_widget.grid_sectors_desired);
1455 
1456 
1457       gfig_opt_widget.gridspacing = GTK_ADJUSTMENT (size_data);
1458       g_object_add_weak_pointer (G_OBJECT (gfig_opt_widget.gridspacing),
1459                                  (gpointer) &gfig_opt_widget.gridspacing);
1460 
1461       radius_data = gimp_scale_entry_new (GTK_TABLE (table), 0, 4,
1462                                         _("Polar grid radius interval:"), 1, 5,
1463                                         selvals.opts.grid_radius_interval,
1464                                         5, 50, 5, 1, 0,
1465                                         TRUE, 0, 0,
1466                                         NULL, NULL);
1467       g_signal_connect (radius_data, "value-changed",
1468                         G_CALLBACK (gimp_double_adjustment_update),
1469                         &selvals.opts.grid_radius_interval);
1470       g_signal_connect (radius_data, "value-changed",
1471                         G_CALLBACK (draw_grid_clear),
1472                         NULL);
1473 
1474       gfig_opt_widget.grid_radius_interval = GTK_ADJUSTMENT (radius_data);
1475       g_object_add_weak_pointer (G_OBJECT (gfig_opt_widget.grid_radius_interval),
1476                                  (gpointer) &gfig_opt_widget.grid_radius_interval);
1477 
1478       combo = gimp_int_combo_box_new (_("Rectangle"), RECT_GRID,
1479                                       _("Polar"),     POLAR_GRID,
1480                                       _("Isometric"), ISO_GRID,
1481                                       NULL);
1482       gimp_int_combo_box_set_active (GIMP_INT_COMBO_BOX (combo), selvals.opts.gridtype);
1483 
1484       g_signal_connect (combo, "changed",
1485                         G_CALLBACK (gridtype_combo_callback),
1486                         GINT_TO_POINTER (GRID_TYPE_MENU));
1487 
1488       gimp_table_attach_aligned (GTK_TABLE (table), 0, 1,
1489                                  _("Grid type:"), 0.0, 0.5,
1490                                  combo, 2, FALSE);
1491 
1492       gfig_opt_widget.gridtypemenu = combo;
1493       g_object_add_weak_pointer (G_OBJECT (gfig_opt_widget.gridtypemenu),
1494                                  (gpointer) &gfig_opt_widget.gridtypemenu);
1495 
1496       combo = gimp_int_combo_box_new (_("Normal"),    GFIG_NORMAL_GC,
1497                                       _("Black"),     GFIG_BLACK_GC,
1498                                       _("White"),     GFIG_WHITE_GC,
1499                                       _("Grey"),      GFIG_GREY_GC,
1500                                       _("Darker"),    GFIG_DARKER_GC,
1501                                       _("Lighter"),   GFIG_LIGHTER_GC,
1502                                       _("Very dark"), GFIG_VERY_DARK_GC,
1503                                       NULL);
1504       gimp_int_combo_box_set_active (GIMP_INT_COMBO_BOX (combo), grid_gc_type);
1505 
1506       g_signal_connect (combo, "changed",
1507                         G_CALLBACK (gridtype_combo_callback),
1508                         GINT_TO_POINTER (GRID_RENDER_MENU));
1509 
1510       gimp_table_attach_aligned (GTK_TABLE (table), 0, 2,
1511                                  _("Grid color:"), 0.0, 0.5,
1512                                  combo, 2, FALSE);
1513 
1514       gtk_widget_show (dialog);
1515     }
1516   else
1517     {
1518       gtk_window_present (GTK_WINDOW (dialog));
1519     }
1520 }
1521 
1522 void
options_update(GFigObj * old_obj)1523 options_update (GFigObj *old_obj)
1524 {
1525   /* Save old vals */
1526   if (selvals.opts.gridspacing != old_obj->opts.gridspacing)
1527     {
1528       old_obj->opts.gridspacing = selvals.opts.gridspacing;
1529     }
1530   if (selvals.opts.grid_sectors_desired != old_obj->opts.grid_sectors_desired)
1531     {
1532       old_obj->opts.grid_sectors_desired = selvals.opts.grid_sectors_desired;
1533     }
1534   if (selvals.opts.grid_radius_interval != old_obj->opts.grid_radius_interval)
1535     {
1536       old_obj->opts.grid_radius_interval = selvals.opts.grid_radius_interval;
1537     }
1538   if (selvals.opts.gridtype != old_obj->opts.gridtype)
1539     {
1540       old_obj->opts.gridtype = selvals.opts.gridtype;
1541     }
1542   if (selvals.opts.drawgrid != old_obj->opts.drawgrid)
1543     {
1544       old_obj->opts.drawgrid = selvals.opts.drawgrid;
1545     }
1546   if (selvals.opts.snap2grid != old_obj->opts.snap2grid)
1547     {
1548       old_obj->opts.snap2grid = selvals.opts.snap2grid;
1549     }
1550   if (selvals.opts.lockongrid != old_obj->opts.lockongrid)
1551     {
1552       old_obj->opts.lockongrid = selvals.opts.lockongrid;
1553     }
1554   if (selvals.opts.showcontrol != old_obj->opts.showcontrol)
1555     {
1556       old_obj->opts.showcontrol = selvals.opts.showcontrol;
1557     }
1558 
1559   /* New vals */
1560   if (selvals.opts.gridspacing != gfig_context->current_obj->opts.gridspacing)
1561     {
1562       if (gfig_opt_widget.gridspacing)
1563         gtk_adjustment_set_value (gfig_opt_widget.gridspacing,
1564                                   gfig_context->current_obj->opts.gridspacing);
1565     }
1566   if (selvals.opts.grid_sectors_desired != gfig_context->current_obj->opts.grid_sectors_desired)
1567     {
1568       if (gfig_opt_widget.grid_sectors_desired)
1569         gtk_adjustment_set_value (gfig_opt_widget.grid_sectors_desired,
1570                                   gfig_context->current_obj->opts.grid_sectors_desired);
1571     }
1572   if (selvals.opts.grid_radius_interval != gfig_context->current_obj->opts.grid_radius_interval)
1573     {
1574       if (gfig_opt_widget.grid_radius_interval)
1575         gtk_adjustment_set_value (gfig_opt_widget.grid_radius_interval,
1576                                   gfig_context->current_obj->opts.grid_radius_interval);
1577     }
1578   if (selvals.opts.gridtype != gfig_context->current_obj->opts.gridtype)
1579     {
1580       if (gfig_opt_widget.gridtypemenu)
1581         gimp_int_combo_box_set_active (GIMP_INT_COMBO_BOX (gfig_opt_widget.gridtypemenu),
1582                                        gfig_context->current_obj->opts.gridtype);
1583     }
1584   if (selvals.opts.drawgrid != gfig_context->current_obj->opts.drawgrid)
1585     {
1586       if (gfig_opt_widget.drawgrid)
1587         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (gfig_opt_widget.drawgrid),
1588                                       gfig_context->current_obj->opts.drawgrid);
1589     }
1590   if (selvals.opts.snap2grid != gfig_context->current_obj->opts.snap2grid)
1591     {
1592       if (gfig_opt_widget.snap2grid)
1593         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (gfig_opt_widget.snap2grid),
1594                                       gfig_context->current_obj->opts.snap2grid);
1595     }
1596   if (selvals.opts.lockongrid != gfig_context->current_obj->opts.lockongrid)
1597     {
1598       if (gfig_opt_widget.lockongrid)
1599         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (gfig_opt_widget.lockongrid),
1600                                       gfig_context->current_obj->opts.lockongrid);
1601     }
1602   if (selvals.opts.showcontrol != gfig_context->current_obj->opts.showcontrol)
1603     {
1604       if (gfig_opt_widget.showcontrol)
1605         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (gfig_opt_widget.showcontrol),
1606                                       gfig_context->current_obj->opts.showcontrol);
1607     }
1608 }
1609 
1610 static void
save_file_chooser_response(GtkFileChooser * chooser,gint response_id,GFigObj * obj)1611 save_file_chooser_response (GtkFileChooser *chooser,
1612                             gint            response_id,
1613                             GFigObj        *obj)
1614 {
1615   if (response_id == GTK_RESPONSE_OK)
1616     {
1617       gchar   *filename;
1618 
1619       filename = gtk_file_chooser_get_filename (chooser);
1620 
1621       obj->filename = filename;
1622 
1623       gfig_context->current_obj = obj;
1624       gfig_save_callbk ();
1625     }
1626 
1627   gtk_widget_destroy (GTK_WIDGET (chooser));
1628 }
1629 
1630 static GfigObject *
gfig_select_obj_by_number(gint count)1631 gfig_select_obj_by_number (gint count)
1632 {
1633   GList      *objs;
1634   GfigObject *object = NULL;
1635   gint        k;
1636 
1637   gfig_context->selected_obj = NULL;
1638 
1639   for (objs = gfig_context->current_obj->obj_list, k = 0;
1640        objs;
1641        objs = g_list_next (objs), k++)
1642     {
1643       if (k == obj_show_single)
1644         {
1645           object = objs->data;
1646           gfig_context->selected_obj = object;
1647           gfig_style_set_context_from_style (&object->style);
1648           break;
1649         }
1650     }
1651 
1652   return object;
1653 }
1654 
1655 static void
select_button_clicked(gint type)1656 select_button_clicked (gint type)
1657 {
1658   gint   count = 0;
1659 
1660   if (gfig_context->current_obj)
1661     {
1662       count = g_list_length (gfig_context->current_obj->obj_list);
1663     }
1664 
1665   switch (type)
1666     {
1667     case OBJ_SELECT_LT:
1668       obj_show_single--;
1669       if (obj_show_single < 0)
1670         obj_show_single = count - 1;
1671       break;
1672 
1673     case OBJ_SELECT_GT:
1674       obj_show_single++;
1675       if (obj_show_single >= count)
1676         obj_show_single = 0;
1677       break;
1678 
1679     case OBJ_SELECT_EQ:
1680       obj_show_single = -1; /* Reset to show all */
1681       break;
1682 
1683     default:
1684       break;
1685     }
1686 
1687   if (obj_show_single >= 0)
1688     gfig_select_obj_by_number (obj_show_single);
1689 
1690   draw_grid_clear ();
1691   gfig_paint_callback ();
1692 }
1693 
1694 static void
select_button_clicked_lt(void)1695 select_button_clicked_lt (void)
1696 {
1697   select_button_clicked (OBJ_SELECT_LT);
1698 }
1699 
1700 static void
select_button_clicked_gt(void)1701 select_button_clicked_gt (void)
1702 {
1703   select_button_clicked (OBJ_SELECT_GT);
1704 }
1705 
1706 static void
select_button_clicked_eq(void)1707 select_button_clicked_eq (void)
1708 {
1709   select_button_clicked (OBJ_SELECT_EQ);
1710 }
1711 
1712 /* Special case for now - options on poly/star/spiral button */
1713 
1714 GtkWidget *
num_sides_widget(const gchar * d_title,gint * num_sides,gint * which_way,gint adj_min,gint adj_max)1715 num_sides_widget (const gchar *d_title,
1716                   gint        *num_sides,
1717                   gint        *which_way,
1718                   gint         adj_min,
1719                   gint         adj_max)
1720 {
1721   GtkWidget *table;
1722   GtkObject *size_data;
1723 
1724   table = gtk_table_new (which_way ? 2 : 1, 3, FALSE);
1725   gtk_table_set_col_spacings (GTK_TABLE (table), 6);
1726   gtk_table_set_row_spacings (GTK_TABLE (table), 6);
1727   gtk_container_set_border_width (GTK_CONTAINER (table), 12);
1728   gtk_widget_show (table);
1729 
1730   size_data = gimp_scale_entry_new (GTK_TABLE (table), 0, 0,
1731                                     _("Sides:"), 0, 0,
1732                                     *num_sides, adj_min, adj_max, 1, 10, 0,
1733                                     TRUE, 0, 0,
1734                                     NULL, NULL);
1735   g_signal_connect (size_data, "value-changed",
1736                     G_CALLBACK (gimp_int_adjustment_update),
1737                     num_sides);
1738 
1739   if (which_way)
1740     {
1741       GtkWidget *combo = gimp_int_combo_box_new (_("Right"),      0,
1742                                                  _("Left"), 1,
1743                                                  NULL);
1744 
1745       gimp_int_combo_box_set_active (GIMP_INT_COMBO_BOX (combo), *which_way);
1746 
1747       g_signal_connect (combo, "changed",
1748                         G_CALLBACK (gimp_int_combo_box_get_active),
1749                         which_way);
1750 
1751       gimp_table_attach_aligned (GTK_TABLE (table), 0, 1,
1752                                  _("Orientation:"), 0.0, 0.5,
1753                                  combo, 1, FALSE);
1754     }
1755   return table;
1756 }
1757 
1758 void
gfig_paint(BrushType brush_type,gint32 drawable_ID,gint seg_count,gdouble line_pnts[])1759 gfig_paint (BrushType brush_type,
1760             gint32    drawable_ID,
1761             gint      seg_count,
1762             gdouble   line_pnts[])
1763 {
1764   switch (brush_type)
1765     {
1766     case BRUSH_BRUSH_TYPE:
1767       gimp_paintbrush (drawable_ID,
1768                        selvals.brushfade,
1769                        seg_count, line_pnts,
1770                        GIMP_PAINT_CONSTANT,
1771                        selvals.brushgradient);
1772       break;
1773 
1774     case BRUSH_PENCIL_TYPE:
1775       gimp_pencil (drawable_ID,
1776                    seg_count, line_pnts);
1777       break;
1778 
1779     case BRUSH_AIRBRUSH_TYPE:
1780       gimp_airbrush (drawable_ID,
1781                      selvals.airbrushpressure,
1782                      seg_count, line_pnts);
1783       break;
1784 
1785     case BRUSH_PATTERN_TYPE:
1786       gimp_clone (drawable_ID,
1787                   drawable_ID,
1788                   GIMP_CLONE_PATTERN,
1789                   0.0, 0.0,
1790                   seg_count, line_pnts);
1791       break;
1792     }
1793 }
1794 
1795 
1796 static void
paint_combo_callback(GtkWidget * widget,gpointer data)1797 paint_combo_callback (GtkWidget *widget,
1798                       gpointer   data)
1799 {
1800   gint mtype = GPOINTER_TO_INT (data);
1801   gint value;
1802 
1803   gimp_int_combo_box_get_active (GIMP_INT_COMBO_BOX (widget), &value);
1804 
1805   switch (mtype)
1806     {
1807     case PAINT_BGS_MENU:
1808       selvals.onlayerbg = (LayersBGType) value;
1809       break;
1810 
1811     default:
1812       g_return_if_reached ();
1813       break;
1814     }
1815 
1816   gfig_paint_callback ();
1817 }
1818 
1819 
1820 static void
gridtype_combo_callback(GtkWidget * widget,gpointer data)1821 gridtype_combo_callback (GtkWidget *widget,
1822                          gpointer   data)
1823 {
1824   gint mtype = GPOINTER_TO_INT (data);
1825   gint value;
1826 
1827   gimp_int_combo_box_get_active (GIMP_INT_COMBO_BOX (widget), &value);
1828 
1829   switch (mtype)
1830     {
1831     case GRID_TYPE_MENU:
1832       selvals.opts.gridtype = value;
1833       break;
1834 
1835     case GRID_RENDER_MENU:
1836       grid_gc_type = value;
1837       break;
1838 
1839     default:
1840       g_return_if_reached ();
1841       break;
1842     }
1843 
1844   draw_grid_clear ();
1845 }
1846 
1847 /*
1848  *  The edit gfig name attributes dialog
1849  *  Modified from Gimp source - layer edit.
1850  */
1851 
1852 typedef struct _GfigListOptions
1853 {
1854   GtkWidget *query_box;
1855   GtkWidget *name_entry;
1856   GtkWidget *list_entry;
1857   GFigObj   *obj;
1858   gboolean   created;
1859 } GfigListOptions;
1860 
1861 static void
load_file_chooser_response(GtkFileChooser * chooser,gint response_id,gpointer data)1862 load_file_chooser_response (GtkFileChooser *chooser,
1863                             gint            response_id,
1864                             gpointer        data)
1865 {
1866   if (response_id == GTK_RESPONSE_OK)
1867     {
1868       gchar   *filename;
1869       GFigObj *gfig;
1870       GFigObj *current_saved;
1871 
1872       filename = gtk_file_chooser_get_filename (chooser);
1873 
1874       if (g_file_test (filename, G_FILE_TEST_IS_REGULAR))
1875         {
1876           /* Hack - current object MUST be NULL to prevent setup_undo ()
1877            * from kicking in.
1878            */
1879           current_saved = gfig_context->current_obj;
1880           gfig_context->current_obj = NULL;
1881           gfig = gfig_load (filename, filename);
1882           gfig_context->current_obj = current_saved;
1883 
1884           if (gfig)
1885             {
1886               /* Read only ?*/
1887               if (access (filename, W_OK))
1888                 gfig->obj_status |= GFIG_READONLY;
1889 
1890               gfig_list_insert (gfig);
1891               new_obj_2edit (gfig);
1892             }
1893         }
1894 
1895       g_free (filename);
1896     }
1897 
1898   gtk_widget_destroy (GTK_WIDGET (chooser));
1899   gfig_paint_callback ();
1900 }
1901 
1902 void
paint_layer_fill(gdouble x1,gdouble y1,gdouble x2,gdouble y2)1903 paint_layer_fill (gdouble x1, gdouble y1, gdouble x2, gdouble y2)
1904 {
1905   GimpFillType fill_type = GIMP_FILL_FOREGROUND;
1906   Style *current_style;
1907 
1908   current_style = gfig_context_get_current_style ();
1909 
1910   gimp_context_push ();
1911 
1912   gimp_context_set_paint_mode (GIMP_LAYER_MODE_NORMAL_LEGACY);
1913   gimp_context_set_opacity (100.0);
1914   gimp_context_set_gradient_repeat_mode (GIMP_REPEAT_NONE);
1915   gimp_context_set_gradient_reverse (FALSE);
1916 
1917   switch (current_style->fill_type)
1918     {
1919     case FILL_NONE:
1920       return;
1921 
1922     case FILL_COLOR:
1923       fill_type = GIMP_FILL_BACKGROUND;
1924       break;
1925 
1926     case FILL_PATTERN:
1927       fill_type = GIMP_FILL_PATTERN;
1928       break;
1929 
1930     case FILL_GRADIENT:
1931       gimp_drawable_edit_gradient_fill (gfig_context->drawable_id,
1932                                         GIMP_GRADIENT_SHAPEBURST_DIMPLED,
1933                                         0.0,       /* offset             */
1934                                         FALSE,     /* supersampling      */
1935                                         0,         /* max_depth          */
1936                                         0.0,       /* threshold          */
1937                                         FALSE,     /* dither             */
1938                                         0.0, 0.0,  /* (x1, y1) - ignored */
1939                                         0.0, 0.0); /* (x2, y2) - ignored */
1940       return;
1941     case FILL_VERTICAL:
1942       gimp_drawable_edit_gradient_fill (gfig_context->drawable_id,
1943                                         GIMP_GRADIENT_LINEAR,
1944                                         0.0,
1945                                         FALSE,
1946                                         0,
1947                                         0.0,
1948                                         FALSE,
1949                                         x1, y1,
1950                                         x1, y2);
1951       return;
1952     case FILL_HORIZONTAL:
1953       gimp_drawable_edit_gradient_fill (gfig_context->drawable_id,
1954                                         GIMP_GRADIENT_LINEAR,
1955                                         0.0,
1956                                         FALSE,
1957                                         0,
1958                                         0.0,
1959                                         FALSE,
1960                                         x1, y1,
1961                                         x2, y1);
1962       return;
1963     }
1964 
1965   gimp_context_set_opacity (current_style->fill_opacity);
1966 
1967   gimp_drawable_edit_fill (gfig_context->drawable_id,
1968                            fill_type);
1969 
1970   gimp_context_pop ();
1971 }
1972 
1973 void
gfig_paint_callback(void)1974 gfig_paint_callback (void)
1975 {
1976   GList      *objs;
1977   gint        ccount = 0;
1978   GfigObject *object;
1979 
1980   if (!gfig_context->enable_repaint || !gfig_context->current_obj)
1981     return;
1982 
1983   objs = gfig_context->current_obj->obj_list;
1984 
1985   gimp_drawable_fill (gfig_context->drawable_id, GIMP_FILL_TRANSPARENT);
1986 
1987   while (objs)
1988     {
1989       if (ccount == obj_show_single || obj_show_single == -1)
1990         {
1991           FillType saved_filltype;
1992 
1993           object = objs->data;
1994 
1995           gfig_style_apply (&object->style);
1996 
1997           saved_filltype = gfig_context_get_current_style ()->fill_type;
1998           gfig_context_get_current_style ()->fill_type = object->style.fill_type;
1999           object->class->paintfunc (object);
2000           gfig_context_get_current_style ()->fill_type = saved_filltype;
2001         }
2002 
2003       objs = g_list_next (objs);
2004 
2005       ccount++;
2006     }
2007 
2008   gimp_displays_flush ();
2009 
2010   if (back_pixbuf)
2011     {
2012       g_object_unref (back_pixbuf);
2013       back_pixbuf = NULL;
2014     }
2015 
2016   gtk_widget_queue_draw (gfig_context->preview);
2017 }
2018 
2019 /* Draw the grid on the screen
2020  */
2021 
2022 void
draw_grid_clear(void)2023 draw_grid_clear (void)
2024 {
2025   /* wipe slate and start again */
2026   gtk_widget_queue_draw (gfig_context->preview);
2027 }
2028 
2029 static void
toggle_show_image(void)2030 toggle_show_image (void)
2031 {
2032   /* wipe slate and start again */
2033   draw_grid_clear ();
2034 }
2035 
2036 static void
toggle_obj_type(GtkRadioAction * action,GtkRadioAction * current,gpointer data)2037 toggle_obj_type (GtkRadioAction *action,
2038                  GtkRadioAction *current,
2039                  gpointer        data)
2040 {
2041   static GdkCursor *p_cursors[DEL_OBJ + 1];
2042   GdkCursorType     ctype = GDK_LAST_CURSOR;
2043   DobjType          new_type;
2044 
2045   new_type = gtk_radio_action_get_current_value (action);
2046   if (selvals.otype != new_type)
2047     {
2048       /* Mem leak */
2049       obj_creating = NULL;
2050       tmp_line = NULL;
2051       tmp_bezier = NULL;
2052 
2053       if (new_type < MOVE_OBJ) /* Eeeeek */
2054         {
2055           obj_show_single = -1; /* Cancel select preview */
2056         }
2057       /* Update draw areas */
2058       gtk_widget_queue_draw (gfig_context->preview);
2059     }
2060 
2061   selvals.otype = new_type;
2062   gtk_notebook_set_current_page (GTK_NOTEBOOK (tool_options_notebook),
2063                                  new_type - 1);
2064 
2065   switch (selvals.otype)
2066     {
2067     case LINE:
2068     case RECTANGLE:
2069     case CIRCLE:
2070     case ELLIPSE:
2071     case ARC:
2072     case POLY:
2073     case STAR:
2074     case SPIRAL:
2075     case BEZIER:
2076     default:
2077       ctype = GDK_CROSSHAIR;
2078       break;
2079     case MOVE_OBJ:
2080     case MOVE_POINT:
2081     case COPY_OBJ:
2082     case MOVE_COPY_OBJ:
2083       ctype = GDK_DIAMOND_CROSS;
2084       break;
2085     case DEL_OBJ:
2086       ctype = GDK_PIRATE;
2087       break;
2088     }
2089 
2090   if (!p_cursors[selvals.otype])
2091     {
2092       GdkDisplay *display = gtk_widget_get_display (gfig_context->preview);
2093 
2094       p_cursors[selvals.otype] = gdk_cursor_new_for_display (display, ctype);
2095     }
2096 
2097   gdk_window_set_cursor (gtk_widget_get_window (gfig_context->preview),
2098                          p_cursors[selvals.otype]);
2099 }
2100 
2101 /* This could belong in a separate file ... but makes it easier to lump into
2102  * one when compiling the plugin.
2103  */
2104 
2105 /* Given a number of float co-ords adjust for scaling back to org size */
2106 /* Size is number of PAIRS of points */
2107 /* FP + int variants */
2108 
2109 static void
scale_to_orginal_x(gdouble * list)2110 scale_to_orginal_x (gdouble *list)
2111 {
2112   *list *= scale_x_factor;
2113 }
2114 
2115 gint
gfig_scale_x(gint x)2116 gfig_scale_x (gint x)
2117 {
2118   if (!selvals.scaletoimage)
2119     return (gint) (x * (1 / scale_x_factor));
2120   else
2121     return x;
2122 }
2123 
2124 static void
scale_to_orginal_y(gdouble * list)2125 scale_to_orginal_y (gdouble *list)
2126 {
2127   *list *= scale_y_factor;
2128 }
2129 
2130 gint
gfig_scale_y(gint y)2131 gfig_scale_y (gint y)
2132 {
2133   if (!selvals.scaletoimage)
2134     return (gint) (y * (1 / scale_y_factor));
2135   else
2136     return y;
2137 }
2138 
2139 /* Pairs x followed by y */
2140 void
scale_to_original_xy(gdouble * list,gint size)2141 scale_to_original_xy (gdouble *list,
2142                       gint     size)
2143 {
2144   gint i;
2145 
2146   for (i = 0; i < size * 2; i += 2)
2147     {
2148       scale_to_orginal_x (&list[i]);
2149       scale_to_orginal_y (&list[i + 1]);
2150     }
2151 }
2152 
2153 /* Pairs x followed by y */
2154 void
scale_to_xy(gdouble * list,gint size)2155 scale_to_xy (gdouble *list,
2156              gint     size)
2157 {
2158   gint i;
2159 
2160   for (i = 0; i < size * 2; i += 2)
2161     {
2162       list[i] *= (org_scale_x_factor / scale_x_factor);
2163       list[i + 1] *= (org_scale_y_factor / scale_y_factor);
2164     }
2165 }
2166 
2167 void
gfig_draw_arc(gint x,gint y,gint width,gint height,gint angle1,gint angle2,cairo_t * cr)2168 gfig_draw_arc (gint x, gint y, gint width, gint height, gint angle1,
2169                gint angle2, cairo_t *cr)
2170 {
2171   cairo_save (cr);
2172 
2173   cairo_translate (cr, gfig_scale_x (x), gfig_scale_y (y));
2174   cairo_scale (cr, gfig_scale_x (width), gfig_scale_y (height));
2175 
2176   if (angle1 < angle2)
2177     cairo_arc (cr, 0., 0., 1., angle1 * G_PI / 180, angle2 * G_PI / 180);
2178   else
2179     cairo_arc_negative (cr, 0., 0., 1., angle1 * G_PI / 180, angle2 * G_PI / 180);
2180 
2181   cairo_restore (cr);
2182 
2183   draw_item (cr, FALSE);
2184 }
2185 
2186 void
gfig_draw_line(gint x0,gint y0,gint x1,gint y1,cairo_t * cr)2187 gfig_draw_line (gint x0, gint y0, gint x1, gint y1, cairo_t *cr)
2188 {
2189   cairo_move_to (cr, gfig_scale_x (x0) + .5, gfig_scale_y (y0) + .5);
2190   cairo_line_to (cr, gfig_scale_x (x1) + .5, gfig_scale_y (y1) + .5);
2191 
2192   draw_item (cr, FALSE);
2193 }
2194