mirror of https://github.com/GNOME/gimp.git
2111 lines
62 KiB
C
2111 lines
62 KiB
C
/*
|
|
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
|
*
|
|
* This is a plug-in for the 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 2 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, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <errno.h>
|
|
|
|
#ifdef HAVE_UNISTD_H
|
|
#include <unistd.h>
|
|
#endif
|
|
|
|
#include <string.h>
|
|
|
|
#include <gtk/gtk.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-spiral.h"
|
|
#include "gfig-star.h"
|
|
#include "gfig-stock.h"
|
|
|
|
#include "pix-data.h"
|
|
|
|
#define PREVIEW_SIZE 400
|
|
|
|
#define SCALE_WIDTH 120
|
|
|
|
#define BRUSH_PREVIEW_SZ 32
|
|
#define SEL_BUTTON_WIDTH 100
|
|
#define SEL_BUTTON_HEIGHT 20
|
|
|
|
#define PREVIEW_MASK (GDK_EXPOSURE_MASK | \
|
|
GDK_POINTER_MOTION_MASK | \
|
|
GDK_BUTTON_PRESS_MASK | \
|
|
GDK_BUTTON_RELEASE_MASK | \
|
|
GDK_BUTTON_MOTION_MASK | \
|
|
GDK_KEY_PRESS_MASK | \
|
|
GDK_KEY_RELEASE_MASK)
|
|
|
|
#define GRID_TYPE_MENU 1
|
|
#define GRID_RENDER_MENU 2
|
|
#define GRID_IGNORE 0
|
|
#define GRID_HIGHTLIGHT 1
|
|
#define GRID_RESTORE 2
|
|
|
|
#define PAINT_LAYERS_MENU 1
|
|
#define PAINT_BGS_MENU 2
|
|
#define PAINT_TYPE_MENU 3
|
|
|
|
#define SELECT_TYPE_MENU 1
|
|
#define SELECT_ARCTYPE_MENU 2
|
|
#define SELECT_TYPE_MENU_FILL 3
|
|
#define SELECT_TYPE_MENU_WHEN 4
|
|
|
|
#define OBJ_SELECT_GT 1
|
|
#define OBJ_SELECT_LT 2
|
|
#define OBJ_SELECT_EQ 4
|
|
|
|
/* 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 */
|
|
},
|
|
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 bursh 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 */
|
|
FALSE, /* Approx circles by drawing lines */
|
|
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 */
|
|
};
|
|
|
|
/* Must keep in step with the above */
|
|
typedef struct
|
|
{
|
|
void *gridspacing;
|
|
GtkWidget *gridtypemenu;
|
|
GtkWidget *drawgrid;
|
|
GtkWidget *snap2grid;
|
|
GtkWidget *lockongrid;
|
|
GtkWidget *showcontrol;
|
|
} GfigOptWidgets;
|
|
|
|
static GfigOptWidgets gfig_opt_widget;
|
|
static gchar *gfig_path = NULL;
|
|
static GtkWidget *page_menu_bg;
|
|
|
|
|
|
static void gfig_response (GtkWidget *widget,
|
|
gint response_id,
|
|
gpointer data);
|
|
static void load_button_callback (GtkWidget *widget,
|
|
gpointer data);
|
|
static void merge_button_callback (GtkWidget *widget,
|
|
gpointer data);
|
|
static void gfig_new_gc (void);
|
|
static void gfig_save_menu_callback (GtkWidget *widget,
|
|
gpointer data);
|
|
static void gfig_list_load_all (const gchar *path);
|
|
static void gfig_list_free_all (void);
|
|
static void create_save_file_chooser (GFigObj *obj,
|
|
gchar *tpath,
|
|
GtkWidget *parent);
|
|
static GtkWidget *draw_buttons (GtkWidget *ww);
|
|
static void select_combo_callback (GtkWidget *widget,
|
|
gpointer data);
|
|
static void adjust_grid_callback (GtkWidget *widget,
|
|
gpointer data);
|
|
static void options_dialog_callback (GtkWidget *widget,
|
|
gpointer data);
|
|
static gint gfig_scale_x (gint x);
|
|
static gint gfig_scale_y (gint y);
|
|
static void toggle_show_image (void);
|
|
static void gridtype_combo_callback (GtkWidget *widget,
|
|
gpointer data);
|
|
|
|
static void gfig_load_file_chooser_response (GtkFileChooser *chooser,
|
|
gint response_id,
|
|
gpointer data);
|
|
static void file_chooser_response (GtkFileChooser *chooser,
|
|
gint response_id,
|
|
GFigObj *obj);
|
|
static GtkWidget *but_with_pix (const gchar *stock_id,
|
|
GSList **group,
|
|
gint baction);
|
|
static gint bezier_button_press (GtkWidget *widget,
|
|
GdkEventButton *event,
|
|
gpointer data);
|
|
static void paint_combo_callback (GtkWidget *widget,
|
|
gpointer data);
|
|
|
|
static void select_button_clicked (GtkWidget *widget,
|
|
gpointer data);
|
|
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);
|
|
|
|
gint
|
|
gfig_dialog (void)
|
|
{
|
|
GtkWidget *main_hbox;
|
|
GtkWidget *vbox;
|
|
GFigObj *gfig;
|
|
GimpParasite *parasite;
|
|
gint newlayer;
|
|
GtkWidget *menubar;
|
|
GtkWidget *menuitem;
|
|
GtkWidget *menu;
|
|
GtkWidget *combo;
|
|
GtkWidget *frame;
|
|
gint k;
|
|
gint img_width;
|
|
gint img_height;
|
|
GtkWidget *toggle;
|
|
|
|
gimp_ui_init ("gfig", TRUE);
|
|
|
|
img_width = gimp_drawable_width (gfig_context->drawable_id);
|
|
img_height = gimp_drawable_height (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_water_mark = -1;
|
|
parasite = gimp_drawable_parasite_find (gfig_context->drawable_id, "gfig");
|
|
for (k=0; k < 1000; k++)
|
|
gfig_context->style[k] = NULL;
|
|
gfig_context->num_styles = 0;
|
|
gfig_context->enable_repaint = FALSE;
|
|
|
|
/* debug */
|
|
gfig_context->debug_styles = FALSE;
|
|
|
|
/* initial gimp and default styles */
|
|
gfig_read_gimp_style (&gfig_context->gimp_style, "Gimp");
|
|
gfig_context->current_style = &gfig_context->default_style;
|
|
gfig_style_append (&gfig_context->gimp_style);
|
|
gfig_read_gimp_style (&gfig_context->default_style, "Base");
|
|
gfig_style_append (&gfig_context->default_style);
|
|
|
|
if (parasite)
|
|
{
|
|
gimp_drawable_fill (gfig_context->drawable_id, GIMP_TRANSPARENT_FILL);
|
|
gfig_context->using_new_layer = FALSE;
|
|
gimp_parasite_free (parasite);
|
|
}
|
|
else
|
|
{
|
|
newlayer = gimp_layer_new (gfig_context->image_id, "GFig", img_width, img_height,
|
|
GIMP_RGBA_IMAGE, 100., GIMP_NORMAL_MODE);
|
|
gimp_drawable_fill (newlayer, GIMP_TRANSPARENT_FILL);
|
|
gimp_image_add_layer (gfig_context->image_id, newlayer, -1);
|
|
gfig_context->drawable_id = newlayer;
|
|
gfig_context->using_new_layer = TRUE;
|
|
}
|
|
|
|
gfig_drawable = gimp_drawable_get (gfig_context->drawable_id);
|
|
|
|
gfig_stock_init ();
|
|
|
|
gfig_path = gimp_gimprc_query ("gfig-path");
|
|
|
|
if (! gfig_path)
|
|
{
|
|
gchar *gimprc = gimp_personal_rc_file ("gimprc");
|
|
gchar *full_path;
|
|
gchar *esc_path;
|
|
|
|
full_path =
|
|
g_strconcat ("${gimp_dir}", G_DIR_SEPARATOR_S, "gfig",
|
|
G_SEARCHPATH_SEPARATOR_S,
|
|
"${gimp_data_dir}", G_DIR_SEPARATOR_S, "gfig",
|
|
NULL);
|
|
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"), "gfig",
|
|
NULL, 0,
|
|
gimp_standard_help_func, HELP_ID,
|
|
|
|
GTK_STOCK_UNDO, RESPONSE_UNDO,
|
|
GTK_STOCK_CLEAR, RESPONSE_CLEAR,
|
|
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
|
|
GTK_STOCK_CLOSE, GTK_RESPONSE_OK,
|
|
_("Paint"), RESPONSE_PAINT,
|
|
|
|
NULL);
|
|
|
|
g_signal_connect (top_level_dlg, "response",
|
|
G_CALLBACK (gfig_response),
|
|
top_level_dlg);
|
|
g_signal_connect (top_level_dlg, "destroy",
|
|
G_CALLBACK (gtk_main_quit),
|
|
NULL);
|
|
|
|
gtk_dialog_set_response_sensitive (GTK_DIALOG (top_level_dlg),
|
|
RESPONSE_UNDO, undo_water_mark >= 0);
|
|
|
|
/* build the menu */
|
|
menubar = gtk_menu_bar_new ();
|
|
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (top_level_dlg)->vbox),
|
|
menubar, FALSE, FALSE, 0);
|
|
gtk_widget_show (menubar);
|
|
|
|
/* File menu */
|
|
menuitem = gtk_menu_item_new_with_mnemonic ("_File");
|
|
gtk_menu_shell_append (GTK_MENU_SHELL (menubar), menuitem);
|
|
gtk_widget_show (menuitem);
|
|
|
|
menu = gtk_menu_new ();
|
|
gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), menu);
|
|
gtk_widget_show (menu);
|
|
|
|
menuitem = gtk_menu_item_new_with_mnemonic ("_Open");
|
|
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
|
|
g_signal_connect (menuitem, "activate",
|
|
G_CALLBACK (load_button_callback),
|
|
NULL);
|
|
gtk_widget_show (menuitem);
|
|
|
|
menuitem = gtk_menu_item_new_with_mnemonic ("_Import");
|
|
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
|
|
g_signal_connect (menuitem, "activate",
|
|
G_CALLBACK (merge_button_callback),
|
|
NULL);
|
|
gtk_widget_show (menuitem);
|
|
|
|
menuitem = gtk_menu_item_new_with_mnemonic ("_Save");
|
|
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
|
|
g_signal_connect (menuitem, "activate",
|
|
G_CALLBACK (gfig_save_menu_callback),
|
|
NULL);
|
|
gtk_widget_show (menuitem);
|
|
|
|
/* Grid menu */
|
|
menuitem = gtk_menu_item_new_with_mnemonic ("_Edit");
|
|
gtk_menu_shell_append (GTK_MENU_SHELL (menubar), menuitem);
|
|
gtk_widget_show (menuitem);
|
|
|
|
menu = gtk_menu_new ();
|
|
gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), menu);
|
|
gtk_widget_show (menu);
|
|
|
|
menuitem = gtk_menu_item_new_with_mnemonic ("_Grid");
|
|
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
|
|
g_signal_connect (menuitem, "activate",
|
|
G_CALLBACK (adjust_grid_callback),
|
|
NULL);
|
|
gtk_widget_show (menuitem);
|
|
|
|
menuitem = gtk_menu_item_new_with_mnemonic ("_Options");
|
|
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
|
|
g_signal_connect (menuitem, "activate",
|
|
G_CALLBACK (options_dialog_callback),
|
|
NULL);
|
|
gtk_widget_show (menuitem);
|
|
|
|
|
|
main_hbox = gtk_hbox_new (FALSE, 12);
|
|
gtk_container_set_border_width (GTK_CONTAINER (main_hbox), 12);
|
|
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (top_level_dlg)->vbox), main_hbox,
|
|
TRUE, TRUE, 0);
|
|
|
|
/* Add buttons beside the preview frame */
|
|
vbox = gtk_vbox_new (FALSE, 0);
|
|
gtk_box_pack_start (GTK_BOX (main_hbox), vbox, FALSE, FALSE, 0);
|
|
gtk_widget_show (vbox);
|
|
|
|
gtk_box_pack_start (GTK_BOX (vbox),
|
|
draw_buttons (top_level_dlg), FALSE, FALSE, 0);
|
|
|
|
/* Preview itself */
|
|
gtk_box_pack_start (GTK_BOX (main_hbox), make_preview (), FALSE, FALSE, 0);
|
|
|
|
gtk_widget_show (gfig_context->preview);
|
|
|
|
/* Style frame on right side */
|
|
frame = gimp_frame_new ("Style");
|
|
gtk_box_pack_start (GTK_BOX (main_hbox), frame, FALSE, FALSE, 0);
|
|
gtk_widget_show (frame);
|
|
|
|
vbox = gtk_vbox_new (FALSE, 3);
|
|
gtk_container_add (GTK_CONTAINER (frame), vbox);
|
|
gtk_widget_show (vbox);
|
|
|
|
/* foreground color button in Style frame*/
|
|
gfig_context->fg_color = (GimpRGB*)g_malloc (sizeof (GimpRGB));
|
|
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->current_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);
|
|
|
|
/* background color button in Style frame */
|
|
gfig_context->bg_color = (GimpRGB*)g_malloc (sizeof (GimpRGB));
|
|
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->current_style->background);
|
|
gtk_box_pack_start (GTK_BOX (vbox), gfig_context->bg_color_button, FALSE, FALSE, 0);
|
|
gtk_widget_show (gfig_context->bg_color_button);
|
|
|
|
/* brush selector in Style frame */
|
|
gfig_context->brush_select
|
|
= gimp_brush_select_widget_new ("Brush", gfig_context->current_style->brush_name,
|
|
-1, -1, -1,
|
|
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);
|
|
|
|
/* pattern selector in Style frame */
|
|
gfig_context->pattern_select
|
|
= gimp_pattern_select_widget_new ("Pattern", gfig_context->current_style->pattern,
|
|
gfig_pattern_changed_callback,
|
|
NULL);
|
|
gtk_box_pack_start (GTK_BOX (vbox), gfig_context->pattern_select,
|
|
FALSE, FALSE, 0);
|
|
gtk_widget_show (gfig_context->pattern_select);
|
|
|
|
/* gradient selector in Style frame */
|
|
gfig_context->gradient_select
|
|
= gimp_gradient_select_widget_new ("Gradient", gfig_context->current_style->gradient,
|
|
gfig_gradient_changed_callback,
|
|
NULL);
|
|
gtk_box_pack_start (GTK_BOX (vbox), gfig_context->gradient_select,
|
|
FALSE, FALSE, 0);
|
|
gtk_widget_show (gfig_context->gradient_select);
|
|
|
|
/* fill style combo box in Style frame */
|
|
gfig_context->fillstyle_combo = combo
|
|
= gimp_int_combo_box_new (_("No fill"), FILL_NONE,
|
|
_("FG fill"), FILL_FOREGROUND,
|
|
_("BG fill"), FILL_BACKGROUND,
|
|
_("Pattern fill"), FILL_PATTERN,
|
|
_("Gradient fill"), FILL_GRADIENT,
|
|
NULL);
|
|
gimp_int_combo_box_set_active (GIMP_INT_COMBO_BOX (combo), 0);
|
|
g_signal_connect (combo, "changed",
|
|
G_CALLBACK (select_combo_callback),
|
|
GINT_TO_POINTER (SELECT_TYPE_MENU_FILL));
|
|
gtk_box_pack_start (GTK_BOX (vbox), combo, FALSE, FALSE, 0);
|
|
gtk_widget_show (combo);
|
|
|
|
/* "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 (toggle, "toggled",
|
|
G_CALLBACK (gfig_preview_expose),
|
|
NULL);
|
|
gtk_widget_show (toggle);
|
|
|
|
/* "snap to grid" checkbutton at bottom of style frame */
|
|
toggle = gtk_check_button_new_with_label (_("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_new_gc (); /* Need this for drawing */
|
|
|
|
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 RESPONSE_UNDO:
|
|
if (undo_water_mark >= 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_water_mark];
|
|
undo_water_mark--;
|
|
/* Update the screen */
|
|
gtk_widget_queue_draw (gfig_context->preview);
|
|
/* And preview */
|
|
gfig_context->current_obj->obj_status |= GFIG_MODIFIED;
|
|
}
|
|
|
|
gtk_dialog_set_response_sensitive (GTK_DIALOG (widget),
|
|
RESPONSE_UNDO, undo_water_mark >= 0);
|
|
gfig_paint_callback ();
|
|
break;
|
|
|
|
case RESPONSE_CLEAR:
|
|
/* 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;
|
|
obj_creating = NULL;
|
|
tmp_line = NULL;
|
|
tmp_bezier = NULL;
|
|
gtk_widget_queue_draw (gfig_context->preview);
|
|
gfig_paint_callback ();
|
|
break;
|
|
|
|
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 ();
|
|
}
|
|
|
|
gtk_widget_destroy (widget);
|
|
break;
|
|
|
|
case GTK_RESPONSE_OK: /* Close button */
|
|
gfig_style_copy (&gfig_context->default_style,
|
|
gfig_context->current_style, "object");
|
|
gfig_save_as_parasite ();
|
|
gtk_widget_destroy (widget);
|
|
break;
|
|
|
|
case RESPONSE_PAINT:
|
|
gfig_paint_callback ();
|
|
break;
|
|
|
|
default:
|
|
gtk_widget_destroy (widget);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void
|
|
load_button_callback (GtkWidget *widget,
|
|
gpointer data)
|
|
{
|
|
static GtkWidget *window = NULL;
|
|
|
|
/* Load a single object */
|
|
window = gtk_file_chooser_dialog_new (_("Load Gfig object collection"),
|
|
GTK_WINDOW (gtk_widget_get_toplevel (widget)),
|
|
GTK_FILE_CHOOSER_ACTION_OPEN,
|
|
|
|
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
|
|
GTK_STOCK_OPEN, GTK_RESPONSE_OK,
|
|
|
|
NULL);
|
|
|
|
gtk_dialog_set_default_response (GTK_DIALOG (window), GTK_RESPONSE_OK);
|
|
|
|
g_signal_connect (window, "destroy",
|
|
G_CALLBACK (gtk_widget_destroyed),
|
|
&window);
|
|
g_signal_connect (window, "response",
|
|
G_CALLBACK (gfig_load_file_chooser_response),
|
|
window);
|
|
|
|
gtk_widget_show (window);
|
|
}
|
|
|
|
static void
|
|
merge_button_callback (GtkWidget *widget,
|
|
gpointer data)
|
|
{
|
|
GList *sellist;
|
|
GFigObj *sel_obj;
|
|
DAllObjs *obj_copies;
|
|
GtkWidget *list = (GtkWidget *) data;
|
|
|
|
/* Must update which object we are editing */
|
|
/* Get the list and which item is selected */
|
|
/* Only allow single selections */
|
|
|
|
/* apparently this function (call) is all broken at the moment */
|
|
g_return_if_fail (list != NULL);
|
|
|
|
sellist = GTK_LIST (list)->selection;
|
|
|
|
sel_obj = (GFigObj *) g_object_get_data (G_OBJECT (sellist->data),
|
|
"user_data");
|
|
|
|
if (sel_obj && sel_obj->obj_list && sel_obj != gfig_context->current_obj)
|
|
{
|
|
/* Copy list tag onto current & redraw */
|
|
obj_copies = copy_all_objs (sel_obj->obj_list);
|
|
prepend_to_all_obj (gfig_context->current_obj, obj_copies);
|
|
|
|
/* redraw all */
|
|
gtk_widget_queue_draw (gfig_context->preview);
|
|
}
|
|
}
|
|
|
|
static void
|
|
gfig_new_gc (void)
|
|
{
|
|
GdkColor fg, bg;
|
|
|
|
/* create a new graphics context */
|
|
gfig_gc = gdk_gc_new (gfig_context->preview->window);
|
|
|
|
gdk_gc_set_function (gfig_gc, GDK_INVERT);
|
|
|
|
fg.pixel = 0xFFFFFFFF;
|
|
bg.pixel = 0x00000000;
|
|
gdk_gc_set_foreground (gfig_gc, &fg);
|
|
gdk_gc_set_background (gfig_gc, &bg);
|
|
|
|
gdk_gc_set_line_attributes (gfig_gc, 1,
|
|
GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_MITER);
|
|
}
|
|
|
|
|
|
static void
|
|
gfig_save_menu_callback (GtkWidget *widget,
|
|
gpointer data)
|
|
{
|
|
create_save_file_chooser (gfig_context->current_obj, NULL, GTK_WIDGET (data));
|
|
}
|
|
|
|
/* Given a point x, y draw a circle */
|
|
void
|
|
draw_circle (GdkPoint *p)
|
|
{
|
|
if (!selvals.opts.showcontrol)
|
|
return;
|
|
|
|
gdk_draw_arc (gfig_context->preview->window,
|
|
gfig_gc,
|
|
0,
|
|
p->x - SQ_SIZE/2,
|
|
p->y - SQ_SIZE/2,
|
|
SQ_SIZE,
|
|
SQ_SIZE,
|
|
0,
|
|
360*64);
|
|
}
|
|
|
|
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_foreach (gfig_list, (GFunc) gfig_free, NULL);
|
|
g_list_free (gfig_list);
|
|
gfig_list = NULL;
|
|
}
|
|
|
|
static void
|
|
create_save_file_chooser (GFigObj *obj,
|
|
gchar *tpath,
|
|
GtkWidget *parent)
|
|
{
|
|
static GtkWidget *window = NULL;
|
|
|
|
if (! window)
|
|
{
|
|
window =
|
|
gtk_file_chooser_dialog_new (_("Save Gfig Drawing"),
|
|
GTK_WINDOW (parent),
|
|
GTK_FILE_CHOOSER_ACTION_SAVE,
|
|
|
|
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
|
|
GTK_STOCK_SAVE, GTK_RESPONSE_OK,
|
|
|
|
NULL);
|
|
|
|
g_signal_connect (window, "destroy",
|
|
G_CALLBACK (gtk_widget_destroyed),
|
|
&window);
|
|
g_signal_connect (window, "response",
|
|
G_CALLBACK (file_chooser_response),
|
|
obj);
|
|
}
|
|
|
|
if (tpath)
|
|
{
|
|
gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (window), tpath);
|
|
}
|
|
else if (gfig_path)
|
|
{
|
|
GList *list;
|
|
gchar *dir;
|
|
|
|
list = gimp_path_parse (gfig_path, 16, FALSE, 0);
|
|
dir = gimp_path_get_user_writable_dir (list);
|
|
gimp_path_free (list);
|
|
|
|
if (! dir)
|
|
dir = g_strdup (gimp_directory ());
|
|
|
|
gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (window), dir);
|
|
|
|
g_free (dir);
|
|
}
|
|
else
|
|
{
|
|
const gchar *tmp = g_get_tmp_dir ();
|
|
|
|
gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (window), tmp);
|
|
}
|
|
|
|
|
|
gtk_window_present (GTK_WINDOW (window));
|
|
}
|
|
|
|
#define SKIP_ROW if (col != 0) {++row; col = 0;} \
|
|
gtk_table_set_row_spacing (GTK_TABLE (table), row, 12); ++row
|
|
|
|
#define TABLE_APPEND(button, text) \
|
|
gtk_table_attach_defaults (GTK_TABLE (table), (button), col, col+1, row, row+1);\
|
|
gtk_widget_show (button);\
|
|
gimp_help_set_help_data (button, (text), NULL);\
|
|
++col; if (col == ncol) { ++row; col = 0; }
|
|
|
|
static GtkWidget *
|
|
draw_buttons (GtkWidget *ww)
|
|
{
|
|
GtkWidget *button;
|
|
GtkWidget *frame;
|
|
GtkWidget *image;
|
|
GSList *group = NULL;
|
|
GtkWidget *table;
|
|
gint col, row;
|
|
gint ncol;
|
|
|
|
|
|
/* Create group */
|
|
frame = gimp_frame_new ("Toolbox");
|
|
|
|
table = gtk_table_new (9, 4, FALSE);
|
|
gtk_container_add (GTK_CONTAINER (frame), table);
|
|
gtk_widget_show (table);
|
|
|
|
ncol = 4;
|
|
row = col = 0;
|
|
|
|
/* Put buttons in */
|
|
button = but_with_pix (GFIG_STOCK_LINE, &group, LINE);
|
|
TABLE_APPEND (button, _("Create line"));
|
|
|
|
button = but_with_pix (GFIG_STOCK_CIRCLE, &group, CIRCLE);
|
|
TABLE_APPEND (button, _("Create circle"));
|
|
|
|
button = but_with_pix (GFIG_STOCK_ELLIPSE, &group, ELLIPSE);
|
|
TABLE_APPEND (button, _("Create ellipse"));
|
|
|
|
button = but_with_pix (GFIG_STOCK_CURVE, &group, ARC);
|
|
TABLE_APPEND (button, _("Create arc"));
|
|
|
|
button = but_with_pix (GFIG_STOCK_POLYGON, &group, POLY);
|
|
g_signal_connect (button, "button_press_event",
|
|
G_CALLBACK (poly_button_press),
|
|
NULL);
|
|
TABLE_APPEND (button, _("Create reg polygon"));
|
|
|
|
button = but_with_pix (GFIG_STOCK_STAR, &group, STAR);
|
|
g_signal_connect (button, "button_press_event",
|
|
G_CALLBACK (star_button_press),
|
|
NULL);
|
|
TABLE_APPEND (button, _("Create star"));
|
|
|
|
button = but_with_pix (GFIG_STOCK_SPIRAL, &group, SPIRAL);
|
|
g_signal_connect (button, "button_press_event",
|
|
G_CALLBACK (spiral_button_press),
|
|
NULL);
|
|
TABLE_APPEND (button, _("Create spiral"));
|
|
|
|
button = but_with_pix (GFIG_STOCK_BEZIER, &group, BEZIER);
|
|
g_signal_connect (button, "button_press_event",
|
|
G_CALLBACK (bezier_button_press),
|
|
NULL);
|
|
TABLE_APPEND (button, _("Create bezier curve. "
|
|
"Shift + Button ends object creation."));
|
|
|
|
SKIP_ROW;
|
|
|
|
button = but_with_pix (GFIG_STOCK_MOVE_OBJECT, &group, MOVE_OBJ);
|
|
TABLE_APPEND (button, _("Move an object"));
|
|
|
|
button = but_with_pix (GFIG_STOCK_MOVE_POINT, &group, MOVE_POINT);
|
|
TABLE_APPEND (button, _("Move a single point"));
|
|
|
|
button = but_with_pix (GFIG_STOCK_COPY_OBJECT, &group, COPY_OBJ);
|
|
TABLE_APPEND (button, _("Copy an object"));
|
|
|
|
button = but_with_pix (GFIG_STOCK_DELETE_OBJECT, &group, DEL_OBJ);
|
|
TABLE_APPEND (button, _("Delete an object"));
|
|
|
|
button = but_with_pix (GIMP_STOCK_TOOL_RECT_SELECT, &group, SELECT_OBJ);
|
|
TABLE_APPEND (button, _("Select an object"));
|
|
|
|
SKIP_ROW;
|
|
|
|
button = gtk_button_new ();
|
|
g_signal_connect (button, "clicked",
|
|
G_CALLBACK (raise_selected_obj),
|
|
NULL);
|
|
image = gtk_image_new_from_stock (GTK_STOCK_GO_UP,
|
|
GTK_ICON_SIZE_BUTTON);
|
|
gtk_container_add (GTK_CONTAINER (button), image);
|
|
gtk_widget_show (image);
|
|
TABLE_APPEND (button, _("Raise selected object"));
|
|
|
|
button = gtk_button_new ();
|
|
g_signal_connect (button, "clicked",
|
|
G_CALLBACK (lower_selected_obj),
|
|
NULL);
|
|
image = gtk_image_new_from_stock (GTK_STOCK_GO_DOWN,
|
|
GTK_ICON_SIZE_BUTTON);
|
|
gtk_container_add (GTK_CONTAINER (button), image);
|
|
gtk_widget_show (image);
|
|
TABLE_APPEND (button, _("Lower selected object"));
|
|
|
|
button = gtk_button_new ();
|
|
g_signal_connect (button, "clicked",
|
|
G_CALLBACK (raise_selected_obj_to_top),
|
|
NULL);
|
|
image = gtk_image_new_from_stock (GTK_STOCK_GOTO_TOP,
|
|
GTK_ICON_SIZE_BUTTON);
|
|
gtk_container_add (GTK_CONTAINER (button), image);
|
|
gtk_widget_show (image);
|
|
TABLE_APPEND (button, _("Raise selected object to top"));
|
|
|
|
button = gtk_button_new ();
|
|
g_signal_connect (button, "clicked",
|
|
G_CALLBACK (lower_selected_obj_to_bottom),
|
|
NULL);
|
|
image = gtk_image_new_from_stock (GTK_STOCK_GOTO_BOTTOM,
|
|
GTK_ICON_SIZE_BUTTON);
|
|
gtk_container_add (GTK_CONTAINER (button), image);
|
|
gtk_widget_show (image);
|
|
TABLE_APPEND (button, _("Lower selected object to bottom"));
|
|
|
|
button = gtk_button_new ();
|
|
g_signal_connect (button, "clicked",
|
|
G_CALLBACK (select_button_clicked),
|
|
GINT_TO_POINTER (OBJ_SELECT_LT));
|
|
image = gtk_image_new_from_stock (GTK_STOCK_GO_BACK,
|
|
GTK_ICON_SIZE_BUTTON);
|
|
gtk_container_add (GTK_CONTAINER (button), image);
|
|
gtk_widget_show (image);
|
|
TABLE_APPEND (button, _("Show previous object"));
|
|
|
|
button = gtk_button_new ();
|
|
g_signal_connect (button, "clicked",
|
|
G_CALLBACK (select_button_clicked),
|
|
GINT_TO_POINTER (OBJ_SELECT_GT));
|
|
image = gtk_image_new_from_stock (GTK_STOCK_GO_FORWARD,
|
|
GTK_ICON_SIZE_BUTTON);
|
|
gtk_container_add (GTK_CONTAINER (button), image);
|
|
gtk_widget_show (image);
|
|
TABLE_APPEND (button, _("Show next object"));
|
|
|
|
button = gtk_button_new_with_label (_("All"));
|
|
g_signal_connect (button, "clicked",
|
|
G_CALLBACK (select_button_clicked),
|
|
GINT_TO_POINTER (OBJ_SELECT_EQ));
|
|
TABLE_APPEND (button, _("Show all objects"));
|
|
|
|
gtk_widget_show (frame);
|
|
|
|
return frame;
|
|
}
|
|
|
|
static void
|
|
raise_selected_obj_to_top (GtkWidget *widget,
|
|
gpointer data)
|
|
{
|
|
DAllObjs *entry;
|
|
DAllObjs *prev_entry = NULL;
|
|
DAllObjs *found_entry = NULL;
|
|
|
|
if (!gfig_context->selected_obj)
|
|
return;
|
|
|
|
entry = gfig_context->current_obj->obj_list;
|
|
|
|
while (entry)
|
|
{
|
|
if (entry->obj == gfig_context->selected_obj)
|
|
{
|
|
/* Found the entry to raise, remove it from list */
|
|
found_entry = entry;
|
|
|
|
if (prev_entry)
|
|
prev_entry->next = entry->next;
|
|
else
|
|
gfig_context->current_obj->obj_list = entry->next;
|
|
}
|
|
|
|
prev_entry = entry;
|
|
entry = entry->next;
|
|
}
|
|
|
|
if (!found_entry)
|
|
{
|
|
g_message ("Trying to raise object that does not exist.");
|
|
return;
|
|
}
|
|
|
|
/* tack found entry onto end of list */
|
|
prev_entry->next = found_entry;
|
|
found_entry->next = NULL;
|
|
|
|
gfig_paint_callback ();
|
|
}
|
|
|
|
static void
|
|
lower_selected_obj_to_bottom (GtkWidget *widget,
|
|
gpointer data)
|
|
{
|
|
DAllObjs *entry;
|
|
DAllObjs *prev_entry = NULL;
|
|
DAllObjs *found_entry = NULL;
|
|
|
|
if (!gfig_context->selected_obj)
|
|
return;
|
|
|
|
entry = gfig_context->current_obj->obj_list;
|
|
|
|
while (entry)
|
|
{
|
|
if (entry->obj == gfig_context->selected_obj)
|
|
{
|
|
/* Found the entry to lower, remove it from list */
|
|
found_entry = entry;
|
|
|
|
if (prev_entry)
|
|
{
|
|
prev_entry->next = found_entry->next;
|
|
break;
|
|
}
|
|
else
|
|
/* it's already at the bottom */
|
|
return;
|
|
}
|
|
|
|
prev_entry = entry;
|
|
entry = entry->next;
|
|
}
|
|
|
|
if (!found_entry)
|
|
{
|
|
g_message ("Trying to raise object that does not exist.");
|
|
return;
|
|
}
|
|
|
|
/* stick found entry into beginning of list */
|
|
found_entry->next = gfig_context->current_obj->obj_list;
|
|
gfig_context->current_obj->obj_list = found_entry;
|
|
|
|
gfig_paint_callback ();
|
|
}
|
|
|
|
static void
|
|
raise_selected_obj (GtkWidget *widget,
|
|
gpointer data)
|
|
{
|
|
DAllObjs *entry;
|
|
DAllObjs *prev_entry = NULL;
|
|
DAllObjs *following_entry = NULL;
|
|
DAllObjs *found_entry = NULL;
|
|
|
|
if (!gfig_context->selected_obj)
|
|
return;
|
|
|
|
entry = gfig_context->current_obj->obj_list;
|
|
|
|
while (entry)
|
|
{
|
|
if (entry->obj == gfig_context->selected_obj)
|
|
{
|
|
/* Found the entry to raise, remove it from list */
|
|
found_entry = entry;
|
|
|
|
following_entry = found_entry->next;
|
|
|
|
/* see if already on top */
|
|
if (!following_entry)
|
|
return;
|
|
|
|
if (prev_entry)
|
|
prev_entry->next = following_entry;
|
|
else
|
|
gfig_context->current_obj->obj_list = following_entry;
|
|
|
|
found_entry->next = following_entry->next;
|
|
|
|
following_entry->next = found_entry;
|
|
|
|
break;
|
|
}
|
|
|
|
prev_entry = entry;
|
|
entry = entry->next;
|
|
}
|
|
|
|
if (!found_entry)
|
|
{
|
|
g_message ("Trying to raise object that does not exist.");
|
|
return;
|
|
}
|
|
|
|
gfig_paint_callback ();
|
|
}
|
|
|
|
|
|
static void
|
|
lower_selected_obj (GtkWidget *widget,
|
|
gpointer data)
|
|
{
|
|
DAllObjs *entry;
|
|
DAllObjs *prev_prev_entry = NULL;
|
|
DAllObjs *prev_entry = NULL;
|
|
DAllObjs *following_entry = NULL;
|
|
DAllObjs *found_entry = NULL;
|
|
|
|
if (!gfig_context->selected_obj)
|
|
return;
|
|
|
|
entry = gfig_context->current_obj->obj_list;
|
|
|
|
while (entry)
|
|
{
|
|
if (entry->obj == gfig_context->selected_obj)
|
|
{
|
|
/* Found the entry to lower, remove it from list */
|
|
found_entry = entry;
|
|
|
|
following_entry = found_entry->next;
|
|
|
|
/* see if already on bottom */
|
|
if (!prev_entry)
|
|
return;
|
|
|
|
prev_entry->next = following_entry;
|
|
found_entry->next = prev_entry;
|
|
|
|
if (prev_prev_entry)
|
|
prev_prev_entry->next = found_entry;
|
|
else
|
|
gfig_context->current_obj->obj_list = found_entry;
|
|
|
|
break;
|
|
}
|
|
|
|
prev_prev_entry = prev_entry;
|
|
prev_entry = entry;
|
|
entry = entry->next;
|
|
}
|
|
|
|
if (!found_entry)
|
|
{
|
|
g_message ("Trying to raise object that does not exist.");
|
|
return;
|
|
}
|
|
|
|
gfig_paint_callback ();
|
|
}
|
|
|
|
|
|
static void
|
|
select_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 SELECT_TYPE_MENU:
|
|
selopt.type = (SelectionType) value;
|
|
break;
|
|
case SELECT_ARCTYPE_MENU:
|
|
selopt.as_pie = (ArcType) value;
|
|
break;
|
|
case SELECT_TYPE_MENU_FILL:
|
|
gfig_context->current_style->fill_type = (FillType) value;
|
|
break;
|
|
default:
|
|
g_return_if_reached ();
|
|
break;
|
|
}
|
|
|
|
gfig_paint_callback ();
|
|
}
|
|
|
|
static void
|
|
options_dialog_callback (GtkWidget *widget,
|
|
gpointer data)
|
|
{
|
|
GtkWidget *options_dlg;
|
|
GtkWidget *table;
|
|
GtkWidget *toggle;
|
|
GtkWidget *vbox;
|
|
GtkObject *size_data;
|
|
GtkWidget *scale;
|
|
GtkObject *scale_data;
|
|
|
|
options_dlg = gimp_dialog_new (_("Options"), "gfig",
|
|
NULL, 0,
|
|
gimp_standard_help_func, HELP_ID,
|
|
|
|
GTK_STOCK_CLOSE, GTK_RESPONSE_OK,
|
|
|
|
NULL);
|
|
|
|
vbox = GTK_DIALOG (options_dlg)->vbox;
|
|
|
|
gtk_container_set_border_width (GTK_CONTAINER (vbox), 12);
|
|
|
|
|
|
/* Put buttons in */
|
|
toggle = gtk_check_button_new_with_label (_("Show position"));
|
|
gtk_box_pack_start (GTK_BOX (vbox), toggle, FALSE, FALSE, 6);
|
|
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 (_("Hide control points"));
|
|
gtk_box_pack_start (GTK_BOX (vbox), toggle, FALSE, FALSE, 6);
|
|
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;
|
|
|
|
toggle = gtk_check_button_new_with_label (_("Antialiasing"));
|
|
gtk_box_pack_start (GTK_BOX (vbox), toggle, FALSE, FALSE, 6);
|
|
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 (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), 0);
|
|
|
|
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 =
|
|
gtk_adjustment_new (selopt.feather_radius, 0.0, 100.0, 1.0, 1.0, 0.0);
|
|
scale = gtk_hscale_new (GTK_ADJUSTMENT (scale_data));
|
|
gtk_scale_set_value_pos (GTK_SCALE (scale), GTK_POS_TOP);
|
|
gtk_range_set_update_policy (GTK_RANGE (scale), GTK_UPDATE_DELAYED);
|
|
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_callback),
|
|
NULL);
|
|
gimp_table_attach_aligned (GTK_TABLE (table), 0, 2,
|
|
_("Radius:"), 0.5, 0.5,
|
|
scale, 1, FALSE);
|
|
|
|
gimp_dialog_run (GIMP_DIALOG (options_dlg));
|
|
gtk_widget_destroy (options_dlg);
|
|
}
|
|
|
|
static void
|
|
adjust_grid_callback (GtkWidget *widget,
|
|
gpointer data)
|
|
{
|
|
GtkWidget *grid_dlg;
|
|
GtkWidget *vbox;
|
|
GtkWidget *hbox;
|
|
GtkWidget *table;
|
|
GtkObject *size_data;
|
|
GtkWidget *combo;
|
|
|
|
grid_dlg = gimp_dialog_new (_("Grid"), "gfig",
|
|
NULL, 0,
|
|
gimp_standard_help_func, HELP_ID,
|
|
|
|
GTK_STOCK_CLOSE, GTK_RESPONSE_OK,
|
|
|
|
NULL);
|
|
|
|
vbox = GTK_DIALOG (grid_dlg)->vbox;
|
|
|
|
hbox = gtk_hbox_new (FALSE, 6);
|
|
gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 6);
|
|
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 (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 = size_data;
|
|
|
|
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), 0);
|
|
|
|
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;
|
|
|
|
combo = gimp_int_combo_box_new (_("Normal"), GTK_STATE_NORMAL,
|
|
_("Black"), GFIG_BLACK_GC,
|
|
_("White"), GFIG_WHITE_GC,
|
|
_("Grey"), GFIG_GREY_GC,
|
|
_("Darker"), GTK_STATE_ACTIVE,
|
|
_("Lighter"), GTK_STATE_PRELIGHT,
|
|
_("Very dark"), GTK_STATE_SELECTED,
|
|
NULL);
|
|
gimp_int_combo_box_set_active (GIMP_INT_COMBO_BOX (combo), 0);
|
|
|
|
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);
|
|
|
|
gimp_dialog_run (GIMP_DIALOG (grid_dlg));
|
|
gtk_widget_destroy (grid_dlg);
|
|
}
|
|
|
|
void
|
|
update_options (GFigObj *old_obj)
|
|
{
|
|
/* Save old vals */
|
|
if (selvals.opts.gridspacing != old_obj->opts.gridspacing)
|
|
{
|
|
old_obj->opts.gridspacing = selvals.opts.gridspacing;
|
|
}
|
|
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)
|
|
{
|
|
gtk_adjustment_set_value (GTK_ADJUSTMENT (gfig_opt_widget.gridspacing),
|
|
gfig_context->current_obj->opts.gridspacing);
|
|
}
|
|
if (selvals.opts.drawgrid != gfig_context->current_obj->opts.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)
|
|
{
|
|
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 0
|
|
/* Maurits: code not implemented */
|
|
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (gfig_opt_widget.lockongrid),
|
|
gfig_context->current_obj->opts.lockongrid);
|
|
#endif
|
|
}
|
|
if (selvals.opts.showcontrol != gfig_context->current_obj->opts.showcontrol)
|
|
{
|
|
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (gfig_opt_widget.showcontrol),
|
|
gfig_context->current_obj->opts.showcontrol);
|
|
}
|
|
if (selvals.opts.gridtype != gfig_context->current_obj->opts.gridtype)
|
|
{
|
|
gimp_int_combo_box_set_active (GIMP_INT_COMBO_BOX (gfig_opt_widget.gridtypemenu),
|
|
gfig_context->current_obj->opts.gridtype);
|
|
}
|
|
}
|
|
|
|
static void
|
|
file_chooser_response (GtkFileChooser *chooser,
|
|
gint response_id,
|
|
GFigObj *obj)
|
|
{
|
|
if (response_id == GTK_RESPONSE_OK)
|
|
{
|
|
gchar *filename;
|
|
GFigObj *real_current;
|
|
|
|
filename = gtk_file_chooser_get_filename (chooser);
|
|
|
|
obj->filename = filename;
|
|
|
|
real_current = gfig_context->current_obj;
|
|
gfig_context->current_obj = obj;
|
|
gfig_save_callbk ();
|
|
gfig_context->current_obj = gfig_context->current_obj;
|
|
}
|
|
|
|
gtk_widget_destroy (GTK_WIDGET (chooser));
|
|
}
|
|
|
|
static Dobject *
|
|
gfig_select_obj_by_number (gint count)
|
|
{
|
|
DAllObjs *objs = gfig_context->current_obj->obj_list;
|
|
gint k = 0;
|
|
|
|
gfig_context->selected_obj = NULL;
|
|
|
|
while (objs)
|
|
{
|
|
if (k == obj_show_single)
|
|
{
|
|
gfig_context->selected_obj = objs->obj;
|
|
gfig_context->current_style = &objs->obj->style;
|
|
gfig_style_set_context_from_style (&objs->obj->style);
|
|
break;
|
|
}
|
|
|
|
objs = objs->next;
|
|
|
|
k++;
|
|
}
|
|
|
|
return objs->obj;
|
|
}
|
|
|
|
static void
|
|
select_button_clicked (GtkWidget *widget,
|
|
gpointer data)
|
|
{
|
|
gint type = GPOINTER_TO_INT (data);
|
|
gint count = 0;
|
|
DAllObjs *objs;
|
|
|
|
if (gfig_context->current_obj)
|
|
{
|
|
for (objs = gfig_context->current_obj->obj_list; objs; objs = objs->next)
|
|
count++;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
objs = gfig_context->current_obj->obj_list;
|
|
|
|
if (obj_show_single >= 0)
|
|
gfig_select_obj_by_number (obj_show_single);
|
|
|
|
draw_grid_clear ();
|
|
}
|
|
|
|
static GtkWidget *
|
|
but_with_pix (const gchar *stock_id,
|
|
GSList **group,
|
|
gint baction)
|
|
{
|
|
GtkWidget *button;
|
|
|
|
button = gtk_radio_button_new_with_label (*group, stock_id);
|
|
gtk_button_set_use_stock (GTK_BUTTON (button), TRUE);
|
|
gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (button), FALSE);
|
|
g_signal_connect (button, "toggled",
|
|
G_CALLBACK (toggle_obj_type),
|
|
GINT_TO_POINTER (baction));
|
|
gtk_widget_show (button);
|
|
|
|
*group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (button));
|
|
|
|
return button;
|
|
}
|
|
|
|
|
|
/* Special case for now - options on poly/star/spiral button */
|
|
|
|
void
|
|
num_sides_dialog (gchar *d_title,
|
|
gint *num_sides,
|
|
gint *which_way,
|
|
gint adj_min,
|
|
gint adj_max)
|
|
{
|
|
GtkWidget *window;
|
|
GtkWidget *table;
|
|
GtkObject *size_data;
|
|
|
|
window = gimp_dialog_new (d_title, "gfig",
|
|
NULL, 0,
|
|
gimp_standard_help_func, HELP_ID,
|
|
|
|
GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
|
|
|
|
NULL);
|
|
|
|
g_signal_connect (window, "response",
|
|
G_CALLBACK (gtk_widget_destroy),
|
|
NULL);
|
|
|
|
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_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), table,
|
|
FALSE, FALSE, 0);
|
|
gtk_widget_show (table);
|
|
|
|
size_data = gimp_scale_entry_new (GTK_TABLE (table), 0, 0,
|
|
_("Number of Sides/Points/Turns:"), 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 (_("Clockwise"), 0,
|
|
_("Anti-Clockwise"), 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);
|
|
}
|
|
|
|
gtk_widget_show (window);
|
|
}
|
|
|
|
static gint
|
|
bezier_button_press (GtkWidget *widget,
|
|
GdkEventButton *event,
|
|
gpointer data)
|
|
{
|
|
if ((event->type == GDK_2BUTTON_PRESS) &&
|
|
(event->button == 1))
|
|
bezier_dialog ();
|
|
return FALSE;
|
|
}
|
|
|
|
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_PATTERN_CLONE,
|
|
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_TYPE_MENU:
|
|
selvals.painttype = (PaintType) value;
|
|
|
|
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
|
|
gfig_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 (void)
|
|
{
|
|
GimpBucketFillMode fill_mode;
|
|
|
|
switch (gfig_context->current_style->fill_type)
|
|
{
|
|
case FILL_NONE:
|
|
return;
|
|
case FILL_FOREGROUND:
|
|
fill_mode = GIMP_FG_BUCKET_FILL;
|
|
break;
|
|
case FILL_BACKGROUND:
|
|
fill_mode = GIMP_BG_BUCKET_FILL;
|
|
break;
|
|
case FILL_PATTERN:
|
|
fill_mode = GIMP_PATTERN_BUCKET_FILL;
|
|
break;
|
|
default:
|
|
return;
|
|
}
|
|
|
|
gimp_edit_bucket_fill (gfig_context->drawable_id,
|
|
fill_mode, /* Fill mode */
|
|
GIMP_NORMAL_MODE,
|
|
gfig_context->current_style->fill_opacity, /* Fill opacity */
|
|
0.0, /* threshold - ignored */
|
|
FALSE, /* Sample merged - ignored */
|
|
0.0, /* x - ignored */
|
|
0.0); /* y - ignored */
|
|
}
|
|
|
|
void
|
|
gfig_paint_callback (void)
|
|
{
|
|
DAllObjs *objs;
|
|
gint layer_count = 0;
|
|
gchar buf[128];
|
|
gint count;
|
|
gint ccount = 0;
|
|
Style *style0;
|
|
|
|
if (!gfig_context->enable_repaint || !gfig_context->current_obj)
|
|
return;
|
|
|
|
objs = gfig_context->current_obj->obj_list;
|
|
|
|
count = gfig_obj_counts (objs);
|
|
|
|
gimp_drawable_fill (gfig_context->drawable_id, GIMP_TRANSPARENT_FILL);
|
|
|
|
/* remember current style because it will be changed while painting */
|
|
style0 = gfig_context->current_style;
|
|
|
|
while (objs)
|
|
{
|
|
if (ccount == obj_show_single || obj_show_single == -1)
|
|
{
|
|
sprintf (buf, _("Gfig layer %d"), layer_count++);
|
|
|
|
gfig_style_apply (&objs->obj->style);
|
|
|
|
objs->obj->class->paintfunc (objs->obj);
|
|
|
|
gimp_selection_clear (gfig_context->image_id);
|
|
|
|
}
|
|
|
|
objs = objs->next;
|
|
|
|
ccount++;
|
|
}
|
|
|
|
/* set style back to its value on entry*/
|
|
gfig_context->current_style = style0;
|
|
|
|
gimp_displays_flush ();
|
|
|
|
if (back_pixbuf)
|
|
{
|
|
g_object_unref (back_pixbuf);
|
|
back_pixbuf = NULL;
|
|
}
|
|
|
|
gfig_preview_expose (gfig_context->preview, NULL);
|
|
}
|
|
|
|
/* Given a point x, y draw a square around it */
|
|
void
|
|
draw_sqr (GdkPoint *p)
|
|
{
|
|
if (!selvals.opts.showcontrol)
|
|
return;
|
|
|
|
gdk_draw_rectangle (gfig_context->preview->window,
|
|
gfig_gc,
|
|
0,
|
|
gfig_scale_x (p->x) - SQ_SIZE/2,
|
|
gfig_scale_y (p->y) - SQ_SIZE/2,
|
|
SQ_SIZE,
|
|
SQ_SIZE);
|
|
}
|
|
|
|
/* Draw the grid on the screen
|
|
*/
|
|
|
|
void
|
|
draw_grid_clear ()
|
|
{
|
|
/* 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 ();
|
|
}
|
|
|
|
void
|
|
toggle_obj_type (GtkWidget *widget,
|
|
gpointer data)
|
|
{
|
|
static GdkCursor *p_cursors[DEL_OBJ + 1];
|
|
GdkCursorType ctype = GDK_LAST_CURSOR;
|
|
|
|
if (selvals.otype != (DobjType) GPOINTER_TO_INT (data))
|
|
{
|
|
/* Mem leak */
|
|
obj_creating = NULL;
|
|
tmp_line = NULL;
|
|
tmp_bezier = NULL;
|
|
|
|
if ((DobjType)data < MOVE_OBJ)
|
|
{
|
|
obj_show_single = -1; /* Cancel select preview */
|
|
}
|
|
/* Update draw areas */
|
|
gtk_widget_queue_draw (gfig_context->preview);
|
|
}
|
|
|
|
selvals.otype = (DobjType) GPOINTER_TO_INT (data);
|
|
|
|
switch (selvals.otype)
|
|
{
|
|
case LINE:
|
|
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 (gfig_context->preview->window, 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 varients */
|
|
|
|
static void
|
|
scale_to_orginal_x (gdouble *list)
|
|
{
|
|
*list *= scale_x_factor;
|
|
}
|
|
|
|
static 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;
|
|
}
|
|
|
|
static 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);
|
|
}
|
|
}
|
|
|
|
/* Given an list of PAIRS of doubles reverse the list */
|
|
/* Size is number of pairs to swap */
|
|
void
|
|
reverse_pairs_list (gdouble *list,
|
|
gint size)
|
|
{
|
|
gint i;
|
|
|
|
struct cs
|
|
{
|
|
gdouble i1;
|
|
gdouble i2;
|
|
} copyit, *orglist;
|
|
|
|
orglist = (struct cs *) list;
|
|
|
|
/* Uses struct copies */
|
|
for (i = 0; i < size / 2; i++)
|
|
{
|
|
copyit = orglist[i];
|
|
orglist[i] = orglist[size - 1 - i];
|
|
orglist[size - 1 - i] = copyit;
|
|
}
|
|
}
|
|
|
|
void
|
|
gfig_draw_arc (gint x, gint y, gint width, gint height, gint angle1,
|
|
gint angle2)
|
|
{
|
|
gdk_draw_arc (gfig_context->preview->window,
|
|
gfig_gc,
|
|
FALSE,
|
|
gfig_scale_x (x - width),
|
|
gfig_scale_y (y - height),
|
|
gfig_scale_x (2 * width),
|
|
gfig_scale_y (2 * height),
|
|
angle1 * 64,
|
|
angle2 * 64);
|
|
}
|
|
|
|
void
|
|
gfig_draw_line (gint x0, gint y0, gint x1, gint y1)
|
|
{
|
|
gdk_draw_line (gfig_context->preview->window,
|
|
gfig_gc,
|
|
gfig_scale_x (x0),
|
|
gfig_scale_y (y0),
|
|
gfig_scale_x (x1),
|
|
gfig_scale_y (y1));
|
|
}
|