summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJosh Andler <scislac@gmail.com>2009-11-30 20:53:48 +0000
committerJosh Andler <scislac@gmail.com>2009-11-30 20:53:48 +0000
commitc8e6bae8d1b9945a60bfba261ad3a299b0b93e42 (patch)
tree3f8dd2b555dde60416d8bd24480b7c895c6d9ad5 /src
parentinkscape.pot update (diff)
downloadinkscape-c8e6bae8d1b9945a60bfba261ad3a299b0b93e42.tar.gz
inkscape-c8e6bae8d1b9945a60bfba261ad3a299b0b93e42.zip
Spray Tool by the students at Ecole Centrale de Lyon, Lyon, France
(bzr r8851)
Diffstat (limited to 'src')
-rw-r--r--src/Makefile_insert1
-rw-r--r--src/pixmaps/cursor-spray-move.xpm38
-rw-r--r--src/pixmaps/cursor-spray.xpm38
-rw-r--r--src/preferences-skeleton.h1
-rw-r--r--src/spray-context.cpp1199
-rw-r--r--src/spray-context.h125
-rw-r--r--src/tools-switch.cpp8
-rw-r--r--src/tools-switch.h1
-rw-r--r--src/ui/dialog/Makefile_insert2
-rw-r--r--src/ui/dialog/dialog-manager.cpp6
-rw-r--r--src/ui/dialog/inkscape-preferences.cpp6
-rw-r--r--src/ui/dialog/inkscape-preferences.h3
-rw-r--r--src/ui/dialog/spray-option.cpp381
-rw-r--r--src/ui/dialog/spray-option.h130
-rw-r--r--src/ui/icon-names.h10
-rw-r--r--src/ui/view/edit-widget.cpp6
-rw-r--r--src/ui/view/edit-widget.h1
-rw-r--r--src/verbs.cpp16
-rw-r--r--src/verbs.h3
-rw-r--r--src/widgets/toolbox.cpp214
20 files changed, 2186 insertions, 3 deletions
diff --git a/src/Makefile_insert b/src/Makefile_insert
index de986ca16..18beaec37 100644
--- a/src/Makefile_insert
+++ b/src/Makefile_insert
@@ -222,6 +222,7 @@ ink_common_sources += \
sp-tspan.cpp sp-tspan.h \
sp-use.cpp sp-use.h \
sp-use-reference.cpp sp-use-reference.h \
+ spray-context.cpp spray-context.h \
star-context.cpp star-context.h \
streq.h \
strneq.h \
diff --git a/src/pixmaps/cursor-spray-move.xpm b/src/pixmaps/cursor-spray-move.xpm
new file mode 100644
index 000000000..ad898b3a5
--- /dev/null
+++ b/src/pixmaps/cursor-spray-move.xpm
@@ -0,0 +1,38 @@
+/* XPM */
+static char const * cursor_spray_move_xpm[] = {
+"32 32 3 1",
+" c None",
+". c #FFFFFF",
+"+ c #000000",
+" ... ",
+" .+. ",
+" .+. ",
+"....+.... ",
+".+++ +++. ",
+"....+.... ",
+" .+. ",
+" .+. ",
+" ... ",
+" ... ... ... ... ",
+" ..+. ..+. ..+. ..+. ",
+" .+++ .+++ .+++ .+++ ",
+" ..+. .+++ .+++ ..+ ",
+" .... .+++ .+++ .... ",
+" ..+. ..+ ..+ ..+. ",
+" .+++ ..+. ..+. .+++ ",
+" ..+ .+++ .+++ ..+ ",
+" .... ..+ ..+ .... ",
+" ..+. .... .... ..+. ",
+" .+++ ..+. ..+. .+++ ",
+" ..+ .+++ .+++ ..+ ",
+" ..+ ..+ ",
+" ... ... ",
+" ..+. ..+. ",
+" .+++ .+++ ",
+" ..+ ..+ ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" "};
diff --git a/src/pixmaps/cursor-spray.xpm b/src/pixmaps/cursor-spray.xpm
new file mode 100644
index 000000000..9ccefee4f
--- /dev/null
+++ b/src/pixmaps/cursor-spray.xpm
@@ -0,0 +1,38 @@
+/* XPM */
+static char const * cursor_spray_xpm[] = {
+"32 32 3 1",
+" c None",
+". c #FFFFFF",
+"+ c #000000",
+" ... ",
+" .+. ",
+" .+. ",
+"....+.... ",
+".+++ +++. ",
+"....+.... ",
+" .+. ",
+" .+. ",
+" ... .+. +. ",
+" .+.+.+.+. ",
+" .+...+...+. ",
+" +...+.....+. ",
+" . . . .+.+.......+. ",
+" + + + .+.........+. ",
+" . . . .+...........+. ",
+" + + .+.............+. ",
+" . . . .+.............+. ",
+" + + + .+.............+. ",
+" . . .+.............+. ",
+" .+.............+. ",
+" .+.............+. ",
+" .+...........+. ",
+" .+.........+. ",
+" .+.......+. ",
+" .+.....+. ",
+" .+...+. ",
+" .+.+. ",
+" .+. ",
+" . ",
+" ",
+" ",
+" "};
diff --git a/src/preferences-skeleton.h b/src/preferences-skeleton.h
index 6185ff729..80a1bd5ea 100644
--- a/src/preferences-skeleton.h
+++ b/src/preferences-skeleton.h
@@ -114,6 +114,7 @@ static char const preferences_skeleton[] =
" style=\"fill:black;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans;font-style:normal;font-weight:normal;font-size:40px;\" selcue=\"1\"/>\n"
" <eventcontext id=\"nodes\" selcue=\"1\" gradientdrag=\"1\" highlight_color=\"4278190335\" pathflash_enabled=\"1\" pathflash_unselected=\"0\" pathflash_timeout=\"500\" show_handles=\"1\" show_helperpath=\"0\" sculpting_profile=\"1\" />\n"
" <eventcontext id=\"tweak\" selcue=\"0\" gradientdrag=\"0\" show_handles=\"0\" width=\"0.2\" force=\"0.2\" fidelity=\"0.5\" usepressure=\"1\" style=\"fill:red;stroke:none;\" usecurrent=\"0\"/>\n"
+" <eventcontext id=\"spray\" selcue=\"0\" gradientdrag=\"0\" show_handles=\"0\" width=\"0.2\" force=\"0.2\" fidelity=\"0.5\" usepressure=\"1\" style=\"fill:red;stroke:none;\" usecurrent=\"0\"/>\n"
" <eventcontext id=\"gradient\" selcue=\"1\"/>\n"
" <eventcontext id=\"zoom\" selcue=\"1\" gradientdrag=\"0\"/>\n"
" <eventcontext id=\"dropper\" selcue=\"1\" gradientdrag=\"1\" pick=\"1\" setalpha=\"1\"/>\n"
diff --git a/src/spray-context.cpp b/src/spray-context.cpp
new file mode 100644
index 000000000..71dc9648a
--- /dev/null
+++ b/src/spray-context.cpp
@@ -0,0 +1,1199 @@
+#define __SP_SPRAY_CONTEXT_C__
+
+/*
+ * Spray Tool
+ *
+ * Authors:
+ * Pierre-Antoine MARC
+ * Pierre CACLIN
+ * Aurel-Aimé MARMION
+ * Julien LERAY
+ * Benoît LAVORATA
+ * Vincent MONTAGNE
+ * Pierre BARBRY-BLOT
+ *
+ * Copyright (C) 2009 authors
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include "config.h"
+
+#include <gtk/gtk.h>
+#include <gdk/gdkkeysyms.h>
+#include <glibmm/i18n.h>
+
+#include <numeric>
+
+#include "svg/svg.h"
+#include "display/canvas-bpath.h"
+
+#include <glib/gmem.h>
+#include "macros.h"
+#include "document.h"
+#include "selection.h"
+#include "desktop.h"
+#include "desktop-events.h"
+#include "desktop-handles.h"
+#include "unistd.h"
+#include "desktop-style.h"
+#include "message-context.h"
+#include "pixmaps/cursor-spray.xpm"
+#include "pixmaps/cursor-spray-move.xpm"
+#include "pixmaps/cursor-thin.xpm"
+#include "pixmaps/cursor-thicken.xpm"
+#include "pixmaps/cursor-attract.xpm"
+#include "pixmaps/cursor-repel.xpm"
+#include "pixmaps/cursor-push.xpm"
+#include "pixmaps/cursor-roughen.xpm"
+#include "pixmaps/cursor-color.xpm"
+#include <boost/optional.hpp>
+#include "libnr/nr-matrix-ops.h"
+#include "libnr/nr-scale-translate-ops.h"
+#include "xml/repr.h"
+#include "context-fns.h"
+#include "sp-item.h"
+#include "inkscape.h"
+#include "color.h"
+#include "svg/svg-color.h"
+#include "splivarot.h"
+#include "sp-item-group.h"
+#include "sp-shape.h"
+#include "sp-path.h"
+#include "path-chemistry.h"
+#include "sp-gradient.h"
+#include "sp-stop.h"
+#include "sp-stop-fns.h"
+#include "sp-gradient-reference.h"
+#include "sp-linear-gradient.h"
+#include "sp-radial-gradient.h"
+#include "gradient-chemistry.h"
+#include "sp-text.h"
+#include "sp-flowtext.h"
+#include "display/canvas-bpath.h"
+#include "display/canvas-arena.h"
+#include "display/curve.h"
+#include "livarot/Shape.h"
+#include <2geom/isnan.h>
+#include <2geom/transforms.h>
+#include "preferences.h"
+#include "style.h"
+#include "box3d.h"
+#include "sp-item-transform.h"
+#include "filter-chemistry.h"
+#include "sp-gaussian-blur-fns.h"
+#include "sp-gaussian-blur.h"
+
+#include "spray-context.h"
+#include "ui/dialog/dialog-manager.h"
+#include "helper/action.h"
+
+#include <iostream>
+using namespace std;
+
+
+#define DDC_RED_RGBA 0xff0000ff
+
+#define DYNA_MIN_WIDTH 1.0e-6
+
+static void sp_spray_context_class_init(SPSprayContextClass *klass);
+static void sp_spray_context_init(SPSprayContext *ddc);
+static void sp_spray_context_dispose(GObject *object);
+
+static void sp_spray_context_setup(SPEventContext *ec);
+static void sp_spray_context_set(SPEventContext *ec, Inkscape::Preferences::Entry *val);
+static gint sp_spray_context_root_handler(SPEventContext *ec, GdkEvent *event);
+
+static SPEventContextClass *parent_class;
+
+
+
+// The following code implements NormalDistribution wich is used for the density of the spray
+
+
+/*
+ RAND is a macro which returns a pseudo-random numbers from a uniform
+ distribution on the interval [0 1]
+*/
+#define RAND ((double) rand())/((double) RAND_MAX)
+
+/*
+ TWOPI = 2.0*pi
+*/
+#define TWOPI 2.0*3.141592653589793238462643383279502884197169399375
+
+/*
+ RANDN is a macro which returns a pseudo-random numbers from a normal
+ distribution with mean zero and standard deviation one. This macro uses Box
+ Muller's algorithm
+*/
+#define RANDN sqrt(-2.0*log(RAND))*cos(TWOPI*RAND)
+
+
+double NormalDistribution(double mu,double sigma)
+{
+/*
+ This function returns a pseudo-random numbers from a normal distribution with
+ mean equal at mu and standard deviation equal at sigma > 0
+*/
+
+ return (mu+sigma*RANDN);
+
+}
+
+//Fin de la création de NormalDistribution
+
+GtkType
+sp_spray_context_get_type(void)
+{
+ static GType type = 0;
+ if (!type) {
+ GTypeInfo info = {
+ sizeof(SPSprayContextClass),
+ NULL, NULL,
+ (GClassInitFunc) sp_spray_context_class_init,
+ NULL, NULL,
+ sizeof(SPSprayContext),
+ 4,
+ (GInstanceInitFunc) sp_spray_context_init,
+ NULL, /* value_table */
+ };
+ type = g_type_register_static(SP_TYPE_EVENT_CONTEXT, "SPSprayContext", &info, (GTypeFlags)0);
+ }
+ return type;
+}
+
+static void
+sp_spray_context_class_init(SPSprayContextClass *klass)
+{
+ GObjectClass *object_class = (GObjectClass *) klass;
+ SPEventContextClass *event_context_class = (SPEventContextClass *) klass;
+
+ parent_class = (SPEventContextClass*)g_type_class_peek_parent(klass);
+
+ object_class->dispose = sp_spray_context_dispose;
+
+ event_context_class->setup = sp_spray_context_setup;
+ event_context_class->set = sp_spray_context_set;
+ event_context_class->root_handler = sp_spray_context_root_handler;
+}
+/*Method to rotate items*/
+void
+sp_spray_rotate_rel(Geom::Point c,SPDesktop *desktop,SPItem *item, Geom::Rotate const &rotation)
+{
+
+ Geom::Point center = c;
+ Geom::Translate const s(c);
+ Geom::Matrix affine = Geom::Matrix(s).inverse() * Geom::Matrix(rotation) * Geom::Matrix(s);
+
+ // Rotate item.
+ sp_item_set_i2d_affine(item, sp_item_i2d_affine(item) * (Geom::Matrix)affine);
+ // Use each item's own transform writer, consistent with sp_selection_apply_affine()
+ sp_item_write_transform(item, SP_OBJECT_REPR(item), item->transform);
+
+ // Restore the center position (it's changed because the bbox center changed)
+ if (item->isCenterSet()) {
+ item->setCenter(c);
+ item->updateRepr();
+ }
+}
+/*Method to scale items*/
+void
+sp_spray_scale_rel (Geom::Point c, SPDesktop *desktop, SPItem *item, Geom::Scale const &scale)
+{
+ Geom::Translate const s(c);
+
+
+ sp_item_set_i2d_affine(item, sp_item_i2d_affine(item) * s.inverse() * scale * s );
+ sp_item_write_transform(item, SP_OBJECT_REPR(item), item->transform);
+
+
+}
+static void
+sp_spray_context_init(SPSprayContext *tc)
+{
+ SPEventContext *event_context = SP_EVENT_CONTEXT(tc);
+
+
+
+ event_context->cursor_shape = cursor_spray_xpm;
+ event_context->hot_x = 4;
+ event_context->hot_y = 4;
+
+ /* attributes */
+ tc->dragging = FALSE;
+ tc->distrib = 1;
+ tc->width = 0.2;
+ tc->force = 0.2;
+ tc->ratio = 0;
+ tc->tilt=0;
+ tc->mean = 0.2;
+ tc->rot_min=0;
+ tc->rot_max=0;
+ tc->standard_deviation=0.2;
+ tc->scale=1;
+ tc->scale_min = 1;
+ tc->scale_max=1;
+ tc->pressure = TC_DEFAULT_PRESSURE;
+
+ tc->is_dilating = false;
+ tc->has_dilated = false;
+
+ tc->do_h = true;
+ tc->do_s = true;
+ tc->do_l = true;
+ tc->do_o = false;
+
+ new (&tc->style_set_connection) sigc::connection();
+}
+
+static void
+sp_spray_context_dispose(GObject *object)
+{
+ SPSprayContext *tc = SP_SPRAY_CONTEXT(object);
+
+ tc->style_set_connection.disconnect();
+ tc->style_set_connection.~connection();
+
+ if (tc->dilate_area) {
+ gtk_object_destroy(GTK_OBJECT(tc->dilate_area));
+ tc->dilate_area = NULL;
+ }
+
+ if (tc->_message_context) {
+ delete tc->_message_context;
+ }
+
+ G_OBJECT_CLASS(parent_class)->dispose(object);
+}
+
+bool is_transform_modes (gint mode)
+{
+ return (mode == SPRAY_MODE_COPY ||
+ mode == SPRAY_MODE_CLONE ||
+ mode == SPRAY_MODE_SINGLE_PATH ||
+ mode == SPRAY_OPTION);
+}
+
+void
+sp_spray_update_cursor (SPSprayContext *tc, bool with_shift)
+{
+ SPEventContext *event_context = SP_EVENT_CONTEXT(tc);
+ SPDesktop *desktop = event_context->desktop;
+
+ guint num = 0;
+ gchar *sel_message = NULL;
+ if (!desktop->selection->isEmpty()) {
+ num = g_slist_length((GSList *) desktop->selection->itemList());
+ sel_message = g_strdup_printf(ngettext("<b>%i</b> object selected","<b>%i</b> objects selected",num), num);
+ } else {
+ sel_message = g_strdup_printf(_("<b>Nothing</b> selected"));
+ }
+
+
+ switch (tc->mode) {
+ case SPRAY_MODE_COPY:
+ tc->_message_context->setF(Inkscape::NORMAL_MESSAGE, _("%s. Drag, click or scroll to spray <b>copies</b> of the initial selection"), sel_message);
+ break;
+ case SPRAY_MODE_CLONE:
+ tc->_message_context->setF(Inkscape::NORMAL_MESSAGE, _("%s. Drag, click or scroll to spray <b>clones</b> of the initial selection"), sel_message);
+ break;
+ case SPRAY_MODE_SINGLE_PATH:
+ tc->_message_context->setF(Inkscape::NORMAL_MESSAGE, _("%s. Drag, click or scroll to spray in a <b>single path</b> of the initial selection"), sel_message);
+ break;
+ case SPRAY_OPTION:
+ tc->_message_context->setF(Inkscape::NORMAL_MESSAGE, _("%s. Modify <b>spray</b> options"), sel_message);
+ break;
+ }
+ sp_event_context_update_cursor(event_context);
+ g_free(sel_message);
+}
+
+static void
+sp_spray_context_setup(SPEventContext *ec)
+{
+ SPSprayContext *tc = SP_SPRAY_CONTEXT(ec);
+
+ if (((SPEventContextClass *) parent_class)->setup)
+ ((SPEventContextClass *) parent_class)->setup(ec);
+
+ {
+ /* TODO: have a look at sp_dyna_draw_context_setup where the same is done.. generalize? at least make it an arcto! */
+ SPCurve *c = new SPCurve();
+ const double C1 = 0.552;
+ c->moveto(-1,0);
+ c->curveto(-1, C1, -C1, 1, 0, 1 );
+ c->curveto(C1, 1, 1, C1, 1, 0 );
+ c->curveto(1, -C1, C1, -1, 0, -1 );
+ c->curveto(-C1, -1, -1, -C1, -1, 0 );
+ c->closepath();
+ tc->dilate_area = sp_canvas_bpath_new(sp_desktop_controls(ec->desktop), c);
+ c->unref();
+ sp_canvas_bpath_set_fill(SP_CANVAS_BPATH(tc->dilate_area), 0x00000000,(SPWindRule)0);
+ sp_canvas_bpath_set_stroke(SP_CANVAS_BPATH(tc->dilate_area), 0xff9900ff, 1.0, SP_STROKE_LINEJOIN_MITER, SP_STROKE_LINECAP_BUTT);
+ sp_canvas_item_hide(tc->dilate_area);
+ }
+
+ tc->is_drawing = false;
+
+ tc->_message_context = new Inkscape::MessageContext((ec->desktop)->messageStack());
+
+ sp_event_context_read(ec, "distrib");
+ sp_event_context_read(ec, "width");
+ sp_event_context_read(ec, "ratio");
+ sp_event_context_read(ec, "tilt");
+ sp_event_context_read(ec, "rot_min");
+ sp_event_context_read(ec, "rot_max");
+ sp_event_context_read(ec, "scale_min");
+ sp_event_context_read(ec, "scale_max");
+ sp_event_context_read(ec, "mode");
+ sp_event_context_read(ec, "population");
+ sp_event_context_read(ec, "force");
+ sp_event_context_read(ec, "mean");
+ sp_event_context_read(ec, "standard_deviation");
+ sp_event_context_read(ec, "usepressure");
+ sp_event_context_read(ec, "Rotation min");
+ sp_event_context_read(ec, "Rotation max");
+ sp_event_context_read(ec, "Scale");
+ sp_event_context_read(ec, "doh");
+ sp_event_context_read(ec, "dol");
+ sp_event_context_read(ec, "dos");
+ sp_event_context_read(ec, "doo");
+
+ ;
+
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ if (prefs->getBool("/tools/spray/selcue")) {
+ ec->enableSelectionCue();
+ }
+
+ if (prefs->getBool("/tools/spray/gradientdrag")) {
+ ec->enableGrDrag();
+ }
+}
+
+static void
+sp_spray_context_set(SPEventContext *ec, Inkscape::Preferences::Entry *val)
+{
+ SPSprayContext *tc = SP_SPRAY_CONTEXT(ec);
+ Glib::ustring path = val->getEntryName();
+
+ if (path == "width") {
+ tc->width = CLAMP(val->getDouble(0.1), -1000.0, 1000.0);
+ } else if (path == "mode") {
+ tc->mode = val->getInt();
+ sp_spray_update_cursor(tc, false);
+ } else if (path == "distribution") {
+ tc->distrib = val->getInt(1);
+ } else if (path == "population") {
+ tc->population = CLAMP(val->getDouble(), 0.0, 1.0);
+ } else if (path == "tilt") {
+ tc->tilt = CLAMP(val->getDouble(0.1), 0, 1000.0);
+ } else if (path == "ratio") {
+ tc->ratio = CLAMP(val->getDouble(), 0.0, 0.9);
+ } else if (path == "force") {
+ tc->force = CLAMP(val->getDouble(1.0), 0, 1.0);
+ } else if (path == "rot_min") {
+ tc->rot_min = CLAMP(val->getDouble(0), 0, 10.0);
+ } else if (path == "rot_max") {
+ tc->rot_max = CLAMP(val->getDouble(0), 0, 10.0);
+ } else if (path == "scale_min") {
+ tc->scale_min = CLAMP(val->getDouble(1.0), 0, 10.0);
+ } else if (path == "scale_max") {
+ tc->scale_max = CLAMP(val->getDouble(1.0), 0, 10.0);
+ } else if (path == "mean") {
+ tc->mean = CLAMP(val->getDouble(1.0), 0, 1.0);
+ } else if (path == "standard_deviation") {
+ tc->standard_deviation = CLAMP(val->getDouble(1.0), 0, 1.0);
+ } else if (path == "usepressure") {
+ tc->usepressure = val->getBool();
+ } else if (path == "doh") {
+ tc->do_h = val->getBool();
+ } else if (path == "dos") {
+ tc->do_s = val->getBool();
+ } else if (path == "dol") {
+ tc->do_l = val->getBool();
+ } else if (path == "doo") {
+ tc->do_o = val->getBool();
+ }
+}
+
+static void
+sp_spray_extinput(SPSprayContext *tc, GdkEvent *event)
+{
+ if (gdk_event_get_axis (event, GDK_AXIS_PRESSURE, &tc->pressure))
+ tc->pressure = CLAMP (tc->pressure, TC_MIN_PRESSURE, TC_MAX_PRESSURE);
+ else
+ tc->pressure = TC_DEFAULT_PRESSURE;
+}
+
+double
+get_dilate_radius (SPSprayContext *tc)
+{
+
+ return 250 * tc->width/SP_EVENT_CONTEXT(tc)->desktop->current_zoom();
+
+
+}
+
+double
+get_path_force (SPSprayContext *tc)
+{
+ double force = 8 * (tc->usepressure? tc->pressure : TC_DEFAULT_PRESSURE)
+ /sqrt(SP_EVENT_CONTEXT(tc)->desktop->current_zoom());
+ if (force > 3) {
+ force += 4 * (force - 3);
+ }
+ return force * tc->force;
+}
+
+double
+get_path_mean (SPSprayContext *tc)
+{
+ return tc->mean;
+}
+
+double
+get_path_standard_deviation (SPSprayContext *tc)
+{
+ return tc->standard_deviation;
+}
+
+double
+get_move_force (SPSprayContext *tc)
+{
+ double force = (tc->usepressure? tc->pressure : TC_DEFAULT_PRESSURE);
+ return force * tc->force;
+}
+
+double
+get_move_mean (SPSprayContext *tc)
+{
+ return tc->mean;
+}
+
+double
+get_move_standard_deviation (SPSprayContext *tc)
+{
+ return tc->standard_deviation;
+}
+
+/* Method to handle the distribution of the items */
+
+
+void random_position( double &r, double &p, double &a, double &s, int choix)
+{
+ if (choix == 0) // Mode 1 : uniform repartition
+ {
+ r = (1-pow(g_random_double_range(0, 1),2));
+ p = g_random_double_range(0, M_PI*2);
+ }
+ if (choix == 1) //Mode 0 : gaussian repartition
+ {
+ double r_temp =-1;
+while(!((r_temp>=0)&&(r_temp<=1)))
+{
+ r_temp = NormalDistribution(a,s/4);
+}
+// generates a number following a normal distribution
+ p = g_random_double_range(0, M_PI*2);
+ r=r_temp;
+ /* if (r_temp<=0) r=0;
+ else
+ {
+ if (r_temp>1) r=1;
+ else r = r_temp;
+ }*/
+ }
+}
+
+
+
+
+
+bool
+sp_spray_dilate_recursive (SPDesktop *desktop, Inkscape::Selection *selection, SPItem *item, Geom::Point p, Geom::Point vector, gint mode, double radius, double force, double population, double &scale, double scale_min, double scale_max, bool reverse, double mean, double standard_deviation, double ratio,double tilt, double rot_min, double rot_max, gint _distrib )
+{
+
+
+
+ bool did = false;
+
+ if (SP_IS_BOX3D(item) /*&& !is_transform_modes(mode)*/) {
+ // convert 3D boxes to ordinary groups before spraying their shapes
+ item = SP_ITEM(box3d_convert_to_group(SP_BOX3D(item)));
+ selection->add(item);
+ }
+
+/*if (SP_IS_TEXT(item) || SP_IS_FLOWTEXT(item)) {
+ GSList *items = g_slist_prepend (NULL, item);
+ GSList *selected = NULL;
+ GSList *to_select = NULL;
+ SPDocument *doc = SP_OBJECT_DOCUMENT(item);
+ sp_item_list_to_curves (items, &selected, &to_select);
+ g_slist_free (items);
+ SPObject* newObj = doc->getObjectByRepr((Inkscape::XML::Node *) to_select->data);
+ g_slist_free (to_select);
+ item = (SPItem *) newObj;
+ // selection->add(item);
+ }
+*/
+ /*if (SP_IS_GROUP(item) && !SP_IS_BOX3D(item)) {
+ for (SPObject *child = sp_object_first_child(SP_OBJECT(item)) ; child != NULL; child = SP_OBJECT_NEXT(child) ) {
+ if (SP_IS_ITEM(child)) {
+ if (sp_spray_dilate_recursive (desktop,selection, SP_ITEM(child), p, vector, mode, radius, force, population, scale, scale_min, scale_max, reverse, mean, standard_deviation,ratio,tilt, rot_min, rot_max,_distrib))
+ did = true;
+ }
+ }
+
+ } else {*/
+ if (mode == SPRAY_MODE_COPY) {
+
+ Geom::OptRect a = item->getBounds(sp_item_i2doc_affine(item));
+ if (a) {
+ double dr; double dp;
+ random_position(dr,dp,mean,standard_deviation,_distrib);
+ dr=dr*radius;
+ double _fid = g_random_double_range(0,1);
+ SPItem *item_copied;
+ double angle = g_random_double_range(rot_min, rot_max);
+ double _scale = g_random_double_range(scale_min, scale_max);
+ if(_fid<=population)
+ {
+ // duplicate
+ SPDocument *doc = SP_OBJECT_DOCUMENT(item);
+ Inkscape::XML::Document* xml_doc = sp_document_repr_doc(doc);
+ Inkscape::XML::Node *old_repr = SP_OBJECT_REPR(item);
+ Inkscape::XML::Node *parent = old_repr->parent();
+ Inkscape::XML::Node *copy = old_repr->duplicate(xml_doc);
+ parent->appendChild(copy);
+
+ SPObject *new_obj = doc->getObjectByRepr(copy);
+ item_copied = (SPItem *) new_obj; //convertion object->item
+ Geom::Point center=item->getCenter();
+ sp_spray_scale_rel(center,desktop,item_copied, Geom::Scale(_scale,_scale));
+ sp_spray_scale_rel(center,desktop,item_copied, Geom::Scale(scale,scale));
+
+ sp_spray_rotate_rel(center,desktop,item_copied, Geom::Rotate(angle));
+ Geom::Point move = (Geom::Point(cos(tilt)*cos(dp)*dr/(1-ratio)+sin(tilt)*sin(dp)*dr/(1+ratio),-sin(tilt)*cos(dp)*dr/(1-ratio)+cos(tilt)*sin(dp)*dr/(1+ratio)))+(p-a->midpoint());//Move the cursor p
+ sp_item_move_rel(item_copied, Geom::Translate(move[Geom::X], -move[Geom::Y]));
+
+
+
+
+
+ did = true;
+ }
+ }
+
+ } else if (mode == SPRAY_MODE_SINGLE_PATH) {
+
+
+ SPItem *Pere; //Objet initial
+ SPItem *item_copied;//Objet projeté
+ SPItem *Union;//Union précédente
+ SPItem *fils;//Copie du père
+
+ // GSList *items = g_slist_copy((GSList *) selection->itemList()); //Récupère la liste des objects sélectionnés
+//Pere = (SPItem *) items->data;//Le premier objet est le père du spray
+
+ int i=1;
+ for (GSList *items = g_slist_copy((GSList *) selection->itemList());
+ items != NULL;
+ items = items->next) {
+
+ SPItem *item1 = (SPItem *) items->data;
+ if (i==1) {
+ Pere=item1;
+ }
+ if (i==2) {
+ Union=item1;
+ }
+ i++;
+ }
+ SPDocument *doc = SP_OBJECT_DOCUMENT(Pere);
+ Inkscape::XML::Document* xml_doc = sp_document_repr_doc(doc);
+ Inkscape::XML::Node *old_repr = SP_OBJECT_REPR(Pere);
+ //SPObject *old_obj = doc->getObjectByRepr(old_repr);
+ Inkscape::XML::Node *parent = old_repr->parent();
+
+ Geom::OptRect a = Pere->getBounds(sp_item_i2doc_affine(Pere));
+ if (a) {
+ double dr; double dp; //initialisation des variables
+ random_position(dr,dp,mean,standard_deviation,_distrib);
+ dr=dr*radius;
+ double _fid = g_random_double_range(0,1);
+ double angle = (g_random_double_range(rot_min, rot_max));
+ double _scale = g_random_double_range(scale_min, scale_max);
+ if (i==2) {
+ Inkscape::XML::Node *copy1 = old_repr->duplicate(xml_doc);
+ parent->appendChild(copy1);
+ SPObject *new_obj1 = doc->getObjectByRepr(copy1);
+ fils = (SPItem *) new_obj1; //conversion object->item
+ Union=fils;
+ Inkscape::GC::release(copy1);
+ }
+
+ if (_fid<=population) { //Rules the population of objects sprayed
+ // duplicates the father
+ Inkscape::XML::Node *copy2 = old_repr->duplicate(xml_doc);
+ parent->appendChild(copy2);
+ SPObject *new_obj2 = doc->getObjectByRepr(copy2);
+ item_copied = (SPItem *) new_obj2;
+
+ Geom::Point move = (Geom::Point(cos(tilt)*cos(dp)*dr/(1-ratio)+sin(tilt)*sin(dp)*dr/(1+ratio),-sin(tilt)*cos(dp)*dr/(1-ratio)+cos(tilt)*sin(dp)*dr/(1+ratio)))+(p-a->midpoint());//Move around the cursor
+
+ Geom::Point center=Pere->getCenter();
+ sp_spray_scale_rel(center,desktop,item_copied, Geom::Scale(_scale,_scale));
+ sp_spray_scale_rel(center,desktop,item_copied, Geom::Scale(scale,scale));
+ sp_spray_rotate_rel(center,desktop,item_copied, Geom::Rotate(angle));
+ sp_item_move_rel(item_copied, Geom::Translate(move[Geom::X], -move[Geom::Y]));
+
+//UNION et surduplication
+ selection->clear();
+ selection->add(item_copied);
+ selection->add(Union);
+ sp_selected_path_union(selection->desktop());
+ selection->add(Pere);
+ Inkscape::GC::release(copy2);
+ did = true;
+ }
+
+ }
+ } else if (mode == SPRAY_MODE_CLONE) {
+
+ Geom::OptRect a = item->getBounds(sp_item_i2doc_affine(item));
+ if (a) {
+ double dr; double dp;
+ random_position(dr,dp,mean,standard_deviation,_distrib);
+ dr=dr*radius;
+ double _fid = g_random_double_range(0,1);
+ double angle = (g_random_double_range(rot_min, rot_max));
+ double _scale = g_random_double_range(scale_min, scale_max);
+
+ if(_fid<=population)
+ {
+ SPItem *item_copied;
+ SPDocument *doc = SP_OBJECT_DOCUMENT(item);
+ Inkscape::XML::Document* xml_doc = sp_document_repr_doc(doc);
+ Inkscape::XML::Node *old_repr = SP_OBJECT_REPR(item);
+ Inkscape::XML::Node *parent = old_repr->parent();
+
+ //Creation of the clone
+ Inkscape::XML::Node *clone = xml_doc->createElement("svg:use");
+ parent->appendChild(clone); //Ajout du clone à la liste d'enfants du père (selection initiale
+ clone->setAttribute("xlink:href", g_strdup_printf("#%s", old_repr->attribute("id")), false); //Génère le lien entre les attributs du père et du fils
+
+ SPObject *clone_object = doc->getObjectByRepr(clone);
+ item_copied = (SPItem *) clone_object;//conversion object->item
+ Geom::Point center=item->getCenter();
+ sp_spray_scale_rel(center,desktop,item_copied, Geom::Scale(_scale,_scale));
+ sp_spray_scale_rel(center,desktop,item_copied, Geom::Scale(scale,scale));
+ sp_spray_rotate_rel(center,desktop,item_copied, Geom::Rotate(angle));
+ Geom::Point move = (Geom::Point(cos(tilt)*cos(dp)*dr/(1-ratio)+sin(tilt)*sin(dp)*dr/(1+ratio),-sin(tilt)*cos(dp)*dr/(1-ratio)+cos(tilt)*sin(dp)*dr/(1+ratio)))+(p-a->midpoint());
+ sp_item_move_rel(item_copied, Geom::Translate(move[Geom::X], -move[Geom::Y]));
+
+ Inkscape::GC::release(clone);
+
+ did = true;
+ } }}
+ return did;
+
+}
+
+
+bool
+sp_spray_color_recursive (guint mode, SPItem *item, SPItem *item_at_point,
+ guint32 fill_goal, bool do_fill,
+ guint32 stroke_goal, bool do_stroke,
+ float opacity_goal, bool do_opacity,
+ bool do_blur, bool reverse,
+ Geom::Point p, double radius, double force,
+ bool do_h, bool do_s, bool do_l, bool do_o)
+{
+ bool did = false;
+
+ return did;
+}
+
+
+bool
+sp_spray_dilate (SPSprayContext *tc, Geom::Point event_p, Geom::Point p, Geom::Point vector, bool reverse)
+{
+ Inkscape::Selection *selection = sp_desktop_selection(SP_EVENT_CONTEXT(tc)->desktop);
+ SPDesktop *desktop = SP_EVENT_CONTEXT(tc)->desktop;
+
+
+ if (selection->isEmpty()) {
+ return false;
+ }
+
+ bool did = false;
+ double radius = get_dilate_radius(tc);
+
+
+
+ bool do_fill = false, do_stroke = false, do_opacity = false;
+ guint32 fill_goal = sp_desktop_get_color_tool(desktop, "/tools/spray", true, &do_fill);
+ guint32 stroke_goal = sp_desktop_get_color_tool(desktop, "/tools/spray", false, &do_stroke);
+ double opacity_goal = sp_desktop_get_master_opacity_tool(desktop, "/tools/spray", &do_opacity);
+ if (reverse) {
+#if 0
+ // HSL inversion
+ float hsv[3];
+ float rgb[3];
+ sp_color_rgb_to_hsv_floatv (hsv,
+ SP_RGBA32_R_F(fill_goal),
+ SP_RGBA32_G_F(fill_goal),
+ SP_RGBA32_B_F(fill_goal));
+ sp_color_hsv_to_rgb_floatv (rgb, hsv[0]<.5? hsv[0]+.5 : hsv[0]-.5, 1 - hsv[1], 1 - hsv[2]);
+ fill_goal = SP_RGBA32_F_COMPOSE(rgb[0], rgb[1], rgb[2], 1);
+ sp_color_rgb_to_hsv_floatv (hsv,
+ SP_RGBA32_R_F(stroke_goal),
+ SP_RGBA32_G_F(stroke_goal),
+ SP_RGBA32_B_F(stroke_goal));
+ sp_color_hsv_to_rgb_floatv (rgb, hsv[0]<.5? hsv[0]+.5 : hsv[0]-.5, 1 - hsv[1], 1 - hsv[2]);
+ stroke_goal = SP_RGBA32_F_COMPOSE(rgb[0], rgb[1], rgb[2], 1);
+#else
+ // RGB inversion
+ fill_goal = SP_RGBA32_U_COMPOSE(
+ (255 - SP_RGBA32_R_U(fill_goal)),
+ (255 - SP_RGBA32_G_U(fill_goal)),
+ (255 - SP_RGBA32_B_U(fill_goal)),
+ (255 - SP_RGBA32_A_U(fill_goal)));
+ stroke_goal = SP_RGBA32_U_COMPOSE(
+ (255 - SP_RGBA32_R_U(stroke_goal)),
+ (255 - SP_RGBA32_G_U(stroke_goal)),
+ (255 - SP_RGBA32_B_U(stroke_goal)),
+ (255 - SP_RGBA32_A_U(stroke_goal)));
+#endif
+ opacity_goal = 1 - opacity_goal;
+ }
+
+ double path_force = get_path_force(tc);
+ if (radius == 0 || path_force == 0) {
+ return false;
+ }
+ double path_mean = get_path_mean(tc);
+ if (radius == 0 || path_mean == 0) {
+ return false;
+ }
+ double path_standard_deviation = get_path_standard_deviation(tc);
+ if (radius == 0 || path_standard_deviation == 0) {
+ return false;
+ }
+ double move_force = get_move_force(tc);
+ double move_mean = get_move_mean(tc);
+ double move_standard_deviation = get_move_standard_deviation(tc);
+
+
+ for (GSList *items = g_slist_copy((GSList *) selection->itemList());
+ items != NULL;
+ items = items->next) {
+
+ SPItem *item = (SPItem *) items->data;
+
+ /*if (is_color_modes (tc->mode)) {
+ if (do_fill || do_stroke || do_opacity) {
+ if (sp_spray_color_recursive (tc->mode, item, item_at_point,
+ fill_goal, do_fill,
+ stroke_goal, do_stroke,
+ opacity_goal, do_opacity,
+ tc->mode == SPRAY_MODE_BLUR, reverse,
+ p, radius, color_force, tc->do_h, tc->do_s, tc->do_l, tc->do_o))
+ did = true;
+ }
+ }else*/ if (is_transform_modes(tc->mode)) {
+ if (sp_spray_dilate_recursive (desktop,selection, item, p, vector, tc->mode, radius, move_force, tc->population,tc->scale, tc->scale_min, tc->scale_max, reverse, move_mean, move_standard_deviation,tc->ratio,tc->tilt, tc->rot_min, tc->rot_max, tc->distrib))
+ did = true;
+ } else {
+ if (sp_spray_dilate_recursive (desktop,selection, item, p, vector, tc->mode, radius, path_force, tc->population,tc->scale, tc->scale_min, tc->scale_max, reverse, path_mean, path_standard_deviation,tc->ratio,tc->tilt, tc->rot_min, tc->rot_max, tc->distrib))
+ did = true;
+ }
+ }
+
+ return did;
+}
+
+void
+sp_spray_update_area (SPSprayContext *tc)
+{
+ double radius = get_dilate_radius(tc);
+ Geom::Matrix const sm ( Geom::Scale(radius/(1-tc->ratio), radius/(1+tc->ratio)) );
+ sp_canvas_item_affine_absolute(tc->dilate_area, (sm* Geom::Rotate(tc->tilt))* Geom::Translate(SP_EVENT_CONTEXT(tc)->desktop->point()));
+ sp_canvas_item_show(tc->dilate_area);
+}
+
+void
+sp_spray_switch_mode (SPSprayContext *tc, gint mode, bool with_shift)
+{
+ SP_EVENT_CONTEXT(tc)->desktop->setToolboxSelectOneValue ("spray_tool_mode", mode); //sélectionne le bouton numéro "mode"
+ // need to set explicitly, because the prefs may not have changed by the previous
+ tc->mode = mode;
+ sp_spray_update_cursor (tc, with_shift);
+}
+
+void
+sp_spray_switch_mode_temporarily (SPSprayContext *tc, gint mode, bool with_shift)
+{
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ // Juggling about so that prefs have the old value but tc->mode and the button show new mode:
+ gint now_mode = prefs->getInt("/tools/spray/mode", 0);
+ SP_EVENT_CONTEXT(tc)->desktop->setToolboxSelectOneValue ("spray_tool_mode", mode);
+ // button has changed prefs, restore
+ prefs->setInt("/tools/spray/mode", now_mode);
+ // changing prefs changed tc->mode, restore back :)
+ tc->mode = mode;
+ sp_spray_update_cursor (tc, with_shift);
+}
+
+gint
+sp_spray_context_root_handler(SPEventContext *event_context,
+ GdkEvent *event)
+{
+ SPSprayContext *tc = SP_SPRAY_CONTEXT(event_context);
+ SPDesktop *desktop = event_context->desktop;
+
+ gint ret = FALSE;
+
+ switch (event->type) {
+ case GDK_ENTER_NOTIFY:
+ sp_canvas_item_show(tc->dilate_area);
+ break;
+ case GDK_LEAVE_NOTIFY:
+ sp_canvas_item_hide(tc->dilate_area);
+ break;
+ case GDK_BUTTON_PRESS:
+ if (event->button.button == 1 && !event_context->space_panning) {
+
+ if (Inkscape::have_viable_layer(desktop, tc->_message_context) == false) {
+ return TRUE;
+ }
+
+ Geom::Point const motion_w(event->button.x,
+ event->button.y);
+ Geom::Point const motion_dt(desktop->w2d(motion_w));
+ tc->last_push = desktop->dt2doc(motion_dt);
+
+ sp_spray_extinput(tc, event);
+
+ sp_canvas_force_full_redraw_after_interruptions(desktop->canvas, 3);
+ tc->is_drawing = true;
+ tc->is_dilating = true;
+ tc->has_dilated = false;
+
+
+
+ if(tc->is_dilating && event->button.button == 1 && !event_context->space_panning)
+
+ sp_spray_dilate (tc, motion_w, desktop->dt2doc(motion_dt), Geom::Point(0,0), MOD__SHIFT);
+
+
+
+ tc->has_dilated=true;
+
+ ret = TRUE;
+ }
+ break;
+ case GDK_MOTION_NOTIFY:
+ {
+ Geom::Point const motion_w(event->motion.x,
+ event->motion.y);
+ Geom::Point motion_dt(desktop->w2d(motion_w));
+ Geom::Point motion_doc(desktop->dt2doc(motion_dt));
+ sp_spray_extinput(tc, event);
+
+ // draw the dilating cursor
+ double radius = get_dilate_radius(tc);
+ Geom::Matrix const sm (Geom::Scale(radius/(1-tc->ratio), radius/(1+tc->ratio)) );
+ sp_canvas_item_affine_absolute(tc->dilate_area, (sm*Geom::Rotate(tc->tilt))*Geom::Translate(desktop->w2d(motion_w)));
+ sp_canvas_item_show(tc->dilate_area);
+
+ guint num = 0;
+ if (!desktop->selection->isEmpty()) {
+ num = g_slist_length((GSList *) desktop->selection->itemList());
+ }
+ if (num == 0) {
+ tc->_message_context->flash(Inkscape::ERROR_MESSAGE, _("<b>Nothing selected!</b> Select objects to spray."));
+ }
+
+ // dilating:
+ if (tc->is_drawing && ( event->motion.state & GDK_BUTTON1_MASK )) {
+ sp_spray_dilate (tc, motion_w, motion_doc, motion_doc - tc->last_push, event->button.state & GDK_SHIFT_MASK? true : false);
+ //tc->last_push = motion_doc;
+ tc->has_dilated = true;
+
+ // it's slow, so prevent clogging up with events
+ gobble_motion_events(GDK_BUTTON1_MASK);
+ return TRUE;
+ }
+
+ }
+ break;
+/*Spray with the scroll*/
+ case GDK_SCROLL:
+ {
+ if (event->scroll.state & GDK_BUTTON1_MASK)
+ {
+ double temp ;
+ temp=tc->population;
+ tc->population=1.0;
+ desktop->setToolboxAdjustmentValue ("population", tc->population * 100);
+ Geom::Point const scroll_w(event->button.x,event->button.y);
+ Geom::Point const scroll_dt = desktop->point();;
+ Geom::Point motion_doc(desktop->dt2doc(scroll_dt));
+ switch (event->scroll.direction)
+ {
+ case GDK_SCROLL_UP:
+ {
+ if (Inkscape::have_viable_layer(desktop, tc->_message_context) == false)
+ {
+ return TRUE;
+ }
+ tc->last_push = desktop->dt2doc(scroll_dt);
+ sp_spray_extinput(tc, event);
+ sp_canvas_force_full_redraw_after_interruptions(desktop->canvas, 3);
+ tc->is_drawing = true;
+ tc->is_dilating = true;
+ tc->has_dilated = false;
+ if(tc->is_dilating && !event_context->space_panning)
+
+ sp_spray_dilate (tc, scroll_w, desktop->dt2doc(scroll_dt), Geom::Point(0,0),false);
+
+
+
+ tc->has_dilated=true;
+ tc->population=temp;
+
+ desktop->setToolboxAdjustmentValue ("population", tc->population * 100);
+
+ ret = TRUE;
+ }
+ break;
+ case GDK_SCROLL_DOWN:
+ {
+ if (Inkscape::have_viable_layer(desktop, tc->_message_context) == false)
+ {
+ return TRUE;
+ }
+ tc->last_push = desktop->dt2doc(scroll_dt);
+ sp_spray_extinput(tc, event);
+ sp_canvas_force_full_redraw_after_interruptions(desktop->canvas, 3);
+ tc->is_drawing = true;
+ tc->is_dilating = true;
+ tc->has_dilated = false;
+ if(tc->is_dilating && !event_context->space_panning)
+ sp_spray_dilate (tc, scroll_w, desktop->dt2doc(scroll_dt), Geom::Point(0,0), false);
+
+ tc->has_dilated=true;
+
+ ret = TRUE;
+
+
+ }
+ break;
+case GDK_SCROLL_RIGHT:
+ {} break;
+case GDK_SCROLL_LEFT:
+ {} break;
+ }
+ }
+
+
+ break;
+
+ }
+ case GDK_BUTTON_RELEASE:
+ {
+ Geom::Point const motion_w(event->button.x, event->button.y);
+ Geom::Point const motion_dt(desktop->w2d(motion_w));
+
+ sp_canvas_end_forced_full_redraws(desktop->canvas);
+ tc->is_drawing = false;
+
+ if (tc->is_dilating && event->button.button == 1 && !event_context->space_panning) {
+ if (!tc->has_dilated) {
+ // if we did not rub, do a light tap
+ tc->pressure = 0.03;
+ sp_spray_dilate (tc, motion_w, desktop->dt2doc(motion_dt), Geom::Point(0,0), MOD__SHIFT);
+ }
+ tc->is_dilating = false;
+ tc->has_dilated = false;
+ switch (tc->mode) {
+ case SPRAY_MODE_COPY:
+ sp_document_done(sp_desktop_document(SP_EVENT_CONTEXT(tc)->desktop),
+ SP_VERB_CONTEXT_SPRAY, _("Spray with copies"));
+ break;
+ case SPRAY_MODE_CLONE:
+ sp_document_done(sp_desktop_document(SP_EVENT_CONTEXT(tc)->desktop),
+ SP_VERB_CONTEXT_SPRAY, _("Spray with clones"));
+ break;
+ case SPRAY_MODE_SINGLE_PATH:
+ sp_document_done(sp_desktop_document(SP_EVENT_CONTEXT(tc)->desktop),
+ SP_VERB_CONTEXT_SPRAY, _("Spray in single path"));
+ break;
+ }
+ }
+ break;
+ }
+
+ case GDK_KEY_PRESS:
+ switch (get_group0_keyval (&event->key)) {
+case GDK_j: if (MOD__SHIFT_ONLY) {
+ sp_spray_switch_mode(tc, SPRAY_MODE_COPY, MOD__SHIFT);
+ ret = TRUE;
+ }
+case GDK_J: if (MOD__SHIFT_ONLY) {
+ sp_spray_switch_mode(tc, SPRAY_MODE_COPY, MOD__SHIFT);
+ ret = TRUE;
+ }
+
+break;
+ case GDK_m:
+ case GDK_M:
+ case GDK_0:
+
+ break;
+ case GDK_i:
+ case GDK_I:
+ case GDK_k: if (MOD__SHIFT_ONLY) {
+ sp_spray_switch_mode(tc, SPRAY_MODE_SINGLE_PATH, MOD__SHIFT);
+ ret = TRUE;
+ }
+ case GDK_K:if (MOD__SHIFT_ONLY) {
+ sp_spray_switch_mode(tc, SPRAY_MODE_SINGLE_PATH, MOD__SHIFT);
+ ret = TRUE;
+ }
+break;
+
+ case GDK_l: if (MOD__SHIFT_ONLY) {
+ sp_spray_switch_mode(tc, SPRAY_MODE_CLONE, MOD__SHIFT);
+ ret = TRUE;
+ }
+
+ case GDK_L:
+ if (MOD__SHIFT_ONLY) {
+ sp_spray_switch_mode(tc, SPRAY_MODE_CLONE, MOD__SHIFT);
+ ret = TRUE;
+ }
+ break;
+ case GDK_Up:
+ case GDK_KP_Up:
+ if (!MOD__CTRL_ONLY) {
+ tc->scale += 0.05;
+
+ //desktop->setToolboxAdjustmentValue ("spray-force", tc->force * 100);
+ ret = TRUE;
+ }
+ break;
+ case GDK_Down:
+ case GDK_KP_Down:
+ if (!MOD__CTRL_ONLY) {
+
+ tc->scale -= 0.05;
+ if (tc->scale < 0.0)
+ tc->scale = 0.0;
+ //desktop->setToolboxAdjustmentValue ("spray-force", tc->force * 100);
+
+ ret = TRUE;
+
+ }
+ break;
+ case GDK_Right:
+ case GDK_KP_Right:
+ if (!MOD__CTRL_ONLY) {
+ tc->width += 0.01;
+ if (tc->width > 1.0)
+ tc->width = 1.0;
+ desktop->setToolboxAdjustmentValue ("altx-spray", tc->width * 100); // the same spinbutton is for alt+x
+ sp_spray_update_area(tc);
+ ret = TRUE;
+ }
+ break;
+ case GDK_Left:
+ case GDK_KP_Left:
+ if (!MOD__CTRL_ONLY) {
+ tc->width -= 0.01;
+ if (tc->width < 0.01)
+ tc->width = 0.01;
+ desktop->setToolboxAdjustmentValue ("altx-spray", tc->width * 100);
+ sp_spray_update_area(tc);
+ ret = TRUE;
+ }
+ break;
+ case GDK_Home:
+ case GDK_KP_Home:
+ tc->width = 0.01;
+ desktop->setToolboxAdjustmentValue ("altx-spray", tc->width * 100);
+ sp_spray_update_area(tc);
+ ret = TRUE;
+ break;
+ case GDK_End:
+ case GDK_KP_End:
+ tc->width = 1.0;
+ desktop->setToolboxAdjustmentValue ("altx-spray", tc->width * 100);
+ sp_spray_update_area(tc);
+ ret = TRUE;
+ break;
+ case GDK_x:
+ case GDK_X:
+ if (MOD__ALT_ONLY) {
+ desktop->setToolboxFocusTo ("altx-spray");
+ ret = TRUE;
+ }
+ break;
+
+ case GDK_Shift_L:
+ case GDK_Shift_R:
+ sp_spray_update_cursor(tc, true);
+ break;
+/*Set the scale to 1*/
+ case GDK_Control_L:
+ tc->scale=1;
+ default:
+ break;
+ }
+ break;
+
+ case GDK_KEY_RELEASE: {
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ switch (get_group0_keyval(&event->key)) {
+ case GDK_Shift_L:
+ case GDK_Shift_R:
+ sp_spray_update_cursor(tc, false);
+ break;
+ case GDK_Control_L:
+ case GDK_Control_R:
+ sp_spray_switch_mode (tc, prefs->getInt("/tools/spray/mode"), MOD__SHIFT);
+ tc->_message_context->clear();
+ break;
+ default:
+ sp_spray_switch_mode (tc, prefs->getInt("/tools/spray/mode"), MOD__SHIFT);
+ break;
+ }
+ }
+
+ default:
+ break;
+ }
+
+ if (!ret) {
+ if (((SPEventContextClass *) parent_class)->root_handler) {
+ ret = ((SPEventContextClass *) parent_class)->root_handler(event_context, event);
+ }
+ }
+
+ return ret;
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
+
diff --git a/src/spray-context.h b/src/spray-context.h
new file mode 100644
index 000000000..f8822ce39
--- /dev/null
+++ b/src/spray-context.h
@@ -0,0 +1,125 @@
+#ifndef __SP_SPRAY_CONTEXT_H__
+#define __SP_SPRAY_CONTEXT_H__
+
+/*
+ * Spray Tool
+ *
+ * Authors:
+ * Pierre-Antoine MARC
+ * Pierre CACLIN
+ * Aurel-Aimé MARMION
+ * Julien LERAY
+ * Benoît LAVORATA
+ * Vincent MONTAGNE
+ * Pierre BARBRY-BLOT
+ *
+ * Copyright (C) 2009 authors
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include "event-context.h"
+#include <display/display-forward.h>
+#include <libnr/nr-point.h>
+//#include "ui/widget/spray-option.h"
+#include "ui/dialog/dialog.h"
+
+#define SP_TYPE_SPRAY_CONTEXT (sp_spray_context_get_type())
+#define SP_SPRAY_CONTEXT(o) (GTK_CHECK_CAST((o), SP_TYPE_SPRAY_CONTEXT, SPSprayContext))
+#define SP_SPRAY_CONTEXT_CLASS(k) (GTK_CHECK_CLASS_CAST((k), SP_TYPE_SPRAY_CONTEXT, SPSprayContextClass))
+#define SP_IS_SPRAY_CONTEXT(o) (GTK_CHECK_TYPE((o), SP_TYPE_SPRAY_CONTEXT))
+#define SP_IS_SPRAY_CONTEXT_CLASS(k) (GTK_CHECK_CLASS_TYPE((k), SP_TYPE_SPRAY_CONTEXT))
+
+class SPSprayContext;
+class SPSprayContextClass;
+
+namespace Inkscape {
+ namespace UI {
+ namespace Dialog {
+ class Dialog;
+ }
+ }
+}
+
+
+#define SAMPLING_SIZE 8 /* fixme: ?? */
+
+#define TC_MIN_PRESSURE 0.0
+#define TC_MAX_PRESSURE 1.0
+#define TC_DEFAULT_PRESSURE 0.35
+
+enum {
+ SPRAY_MODE_COPY,
+ SPRAY_MODE_CLONE,
+ SPRAY_MODE_SINGLE_PATH,
+ SPRAY_OPTION,
+};
+
+struct SPSprayContext
+{
+ SPEventContext event_context;
+ //Inkscape::UI::Dialog::Dialog *dialog_option;//Attribut de type SprayOptionClass, localisé dans scr/ui/dialog
+ /* extended input data */
+ gdouble pressure;
+
+ /* attributes */
+ guint dragging : 1; /* mouse state: mouse is dragging */
+ guint usepressure : 1;
+ guint usetilt : 1;
+ bool usetext ;
+
+ double width;
+ double ratio;
+ double tilt;
+ double rot_min;
+ double rot_max;
+ double force;
+ double population;
+ double scale_min;
+ double scale_max;
+ double scale;
+ double mean;
+ double standard_deviation;
+
+ gint distrib;
+
+ gint mode;
+
+ Inkscape::MessageContext *_message_context;
+
+ bool is_drawing;
+
+ bool is_dilating;
+ bool has_dilated;
+ Geom::Point last_push;
+ SPCanvasItem *dilate_area;
+
+ bool do_h;
+ bool do_s;
+ bool do_l;
+ bool do_o;
+
+ sigc::connection style_set_connection;
+};
+
+struct SPSprayContextClass
+{
+ SPEventContextClass parent_class;
+};
+
+GtkType sp_spray_context_get_type(void);
+
+
+#endif
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
+
diff --git a/src/tools-switch.cpp b/src/tools-switch.cpp
index 7902a7988..6c53ce61c 100644
--- a/src/tools-switch.cpp
+++ b/src/tools-switch.cpp
@@ -28,6 +28,7 @@
#include "select-context.h"
#include "node-context.h"
#include "tweak-context.h"
+#include "spray-context.h"
#include "sp-path.h"
#include "rect-context.h"
#include "sp-rect.h"
@@ -62,6 +63,7 @@ static char const *const tool_names[] = {
"/tools/select",
"/tools/nodes",
"/tools/tweak",
+ "/tools/spray",
"/tools/shapes/rect",
"/tools/shapes/3dbox",
"/tools/shapes/arc",
@@ -135,6 +137,12 @@ tools_switch(SPDesktop *dt, int num)
inkscape_eventcontext_set(sp_desktop_event_context(dt));
dt->tipsMessageContext()->set(Inkscape::NORMAL_MESSAGE, _("To tweak a path by pushing, select it and drag over it."));
break;
+ case TOOLS_SPRAY:
+ dt->set_event_context(SP_TYPE_SPRAY_CONTEXT, tool_names[num]);
+ dt->activate_guides(true);
+ inkscape_eventcontext_set(sp_desktop_event_context(dt));
+ dt->tipsMessageContext()->set(Inkscape::NORMAL_MESSAGE, _("To spray a path by pushing, select it and drag over it."));
+ break;
case TOOLS_SHAPES_RECT:
dt->set_event_context(SP_TYPE_RECT_CONTEXT, tool_names[num]);
dt->activate_guides(false);
diff --git a/src/tools-switch.h b/src/tools-switch.h
index 36dd8f80b..4cc9aa93d 100644
--- a/src/tools-switch.h
+++ b/src/tools-switch.h
@@ -19,6 +19,7 @@ enum {
TOOLS_SELECT,
TOOLS_NODES,
TOOLS_TWEAK,
+ TOOLS_SPRAY,
TOOLS_SHAPES_RECT,
TOOLS_SHAPES_3DBOX,
TOOLS_SHAPES_ARC,
diff --git a/src/ui/dialog/Makefile_insert b/src/ui/dialog/Makefile_insert
index 565a24ecc..fd1b07394 100644
--- a/src/ui/dialog/Makefile_insert
+++ b/src/ui/dialog/Makefile_insert
@@ -73,6 +73,8 @@ ink_common_sources += \
ui/dialog/print.h \
ui/dialog/scriptdialog.cpp \
ui/dialog/scriptdialog.h \
+ ui/dialog/spray-option.cpp \
+ ui/dialog/spray-option.h \
ui/dialog/svg-fonts-dialog.cpp \
ui/dialog/svg-fonts-dialog.h \
ui/dialog/swatches.cpp \
diff --git a/src/ui/dialog/dialog-manager.cpp b/src/ui/dialog/dialog-manager.cpp
index d1b818d23..7f853bedc 100644
--- a/src/ui/dialog/dialog-manager.cpp
+++ b/src/ui/dialog/dialog-manager.cpp
@@ -40,6 +40,7 @@
#include "ui/dialog/icon-preview.h"
#include "ui/dialog/floating-behavior.h"
#include "ui/dialog/dock-behavior.h"
+#include "ui/dialog/spray-option.h"
#include "preferences.h"
#ifdef ENABLE_SVG_FONTS
@@ -88,7 +89,6 @@ DialogManager::DialogManager() {
int dialogs_type = prefs->getIntLimited("/options/dialogtype/value", DOCK, 0, 1);
if (dialogs_type == FLOATING) {
-
registerFactory("AlignAndDistribute", &create<AlignAndDistribute, FloatingBehavior>);
registerFactory("DocumentMetadata", &create<DocumentMetadata, FloatingBehavior>);
registerFactory("DocumentProperties", &create<DocumentProperties, FloatingBehavior>);
@@ -111,7 +111,8 @@ DialogManager::DialogManager() {
registerFactory("Trace", &create<TraceDialog, FloatingBehavior>);
registerFactory("Transformation", &create<Transformation, FloatingBehavior>);
registerFactory("UndoHistory", &create<UndoHistory, FloatingBehavior>);
- registerFactory("InputDevices", &create<InputDialog, FloatingBehavior>);
+ registerFactory("InputDevices", &create<InputDialog, FloatingBehavior>);
+ registerFactory("SprayOptionClass", &create<SprayOptionClass, FloatingBehavior>);
} else {
@@ -138,6 +139,7 @@ DialogManager::DialogManager() {
registerFactory("Transformation", &create<Transformation, DockBehavior>);
registerFactory("UndoHistory", &create<UndoHistory, DockBehavior>);
registerFactory("InputDevices", &create<InputDialog, DockBehavior>);
+ registerFactory("SprayOptionClass", &create<SprayOptionClass, DockBehavior>);
}
}
diff --git a/src/ui/dialog/inkscape-preferences.cpp b/src/ui/dialog/inkscape-preferences.cpp
index c7dc789ca..6e30ef61a 100644
--- a/src/ui/dialog/inkscape-preferences.cpp
+++ b/src/ui/dialog/inkscape-preferences.cpp
@@ -449,6 +449,12 @@ void InkscapePreferences::initPageTools()
AddSelcueCheckbox(_page_tweak, "/tools/tweak", true);
AddGradientCheckbox(_page_tweak, "/tools/tweak", false);
+ //Spray
+ this->AddPage(_page_spray, _("Spray"), iter_tools, PREFS_PAGE_TOOLS_SPRAY);
+ this->AddNewObjectsStyle(_page_spray, "/tools/spray", _("Paint objects with:"));
+ AddSelcueCheckbox(_page_spray, "/tools/spray", true);
+ AddGradientCheckbox(_page_spray, "/tools/spray", false);
+
//Zoom
this->AddPage(_page_zoom, _("Zoom"), iter_tools, PREFS_PAGE_TOOLS_ZOOM);
AddSelcueCheckbox(_page_zoom, "/tools/zoom", true);
diff --git a/src/ui/dialog/inkscape-preferences.h b/src/ui/dialog/inkscape-preferences.h
index 364b0eb1d..705e7a352 100644
--- a/src/ui/dialog/inkscape-preferences.h
+++ b/src/ui/dialog/inkscape-preferences.h
@@ -43,6 +43,7 @@ enum {
PREFS_PAGE_TOOLS_SELECTOR,
PREFS_PAGE_TOOLS_NODE,
PREFS_PAGE_TOOLS_TWEAK,
+ PREFS_PAGE_TOOLS_SPRAY,
PREFS_PAGE_TOOLS_ZOOM,
PREFS_PAGE_TOOLS_SHAPES,
PREFS_PAGE_TOOLS_SHAPES_RECT,
@@ -118,7 +119,7 @@ protected:
_page_clones, _page_mask, _page_transforms, _page_filters, _page_select,
_page_importexport, _page_cms, _page_grids, _page_svgoutput, _page_misc,
_page_ui, _page_save, _page_bitmaps, _page_spellcheck;
- DialogPage _page_selector, _page_node, _page_tweak, _page_zoom, _page_shapes, _page_pencil, _page_pen,
+ DialogPage _page_selector, _page_node, _page_tweak, _page_spray, _page_zoom, _page_shapes, _page_pencil, _page_pen,
_page_calligraphy, _page_text, _page_gradient, _page_connector, _page_dropper, _page_lpetool;
DialogPage _page_rectangle, _page_3dbox, _page_ellipse, _page_star, _page_spiral, _page_paintbucket, _page_eraser;
diff --git a/src/ui/dialog/spray-option.cpp b/src/ui/dialog/spray-option.cpp
new file mode 100644
index 000000000..8bfe455fa
--- /dev/null
+++ b/src/ui/dialog/spray-option.cpp
@@ -0,0 +1,381 @@
+/*Julien LERAY (julien.leray@ecl2010.ec-lyon.fr), interface for the spray tool*/
+
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <gtkmm/spinbutton.h>
+
+#include "desktop-handles.h"
+#include "unclump.h"
+#include "document.h"
+#include "enums.h"
+#include "graphlayout/graphlayout.h"
+#include "inkscape.h"
+#include "macros.h"
+#include "node-context.h"
+#include "preferences.h"
+#include "removeoverlap/removeoverlap.h"
+#include "selection.h"
+#include "shape-editor.h"
+#include "sp-flowtext.h"
+#include "sp-item-transform.h"
+#include "sp-text.h"
+#include "text-editing.h"
+#include "tools-switch.h"
+#include "ui/icon-names.h"
+#include "util/glib-list-iterators.h"
+#include "verbs.h"
+#include "widgets/icon.h"
+
+#include "spray-option.h"
+
+namespace Inkscape {
+namespace UI {
+namespace Dialog {
+
+
+//Classes qui permettent de créer les environnements Gaussienne, Witdh...
+
+
+
+class Action {
+public:
+ Action(const Glib::ustring &id,
+ const Glib::ustring &tiptext,
+ guint row, guint column,
+ Gtk::Table &parent,
+ Gtk::Tooltips &tooltips,
+ SprayOptionClass &dialog):
+ _dialog(dialog),
+ _id(id),
+ _parent(parent) {}
+
+ virtual ~Action(){}
+ virtual void on_button_click(){}
+ SprayOptionClass &_dialog;
+
+private :
+
+ Glib::ustring _id;
+ Gtk::Table &_parent;
+};
+
+class ActionE : public Action {
+private:
+ Gtk::Label _Label;
+ Gtk::SpinButton _Gap;
+ guint _min, _max;
+ Glib::ustring _pref_path;
+
+public:
+ ActionE(const Glib::ustring &id,
+ const Glib::ustring &tiptext,
+ guint row, guint column,
+ SprayOptionClass &dialog,
+ guint min, guint max,
+ Glib::ustring const &pref_path ):
+ Action(id, tiptext, row, column,
+ dialog._Table(), dialog.tooltips(), dialog),
+ _min(min),
+ _max(max),
+ _pref_path(pref_path)
+ {
+ dialog._Table().set_col_spacings(3);
+
+ double increm = ((double)_max - (double)_min)/10;
+ double val_ini = ((double)_max + (double)_min)/2;
+ _Gap.set_digits(1);
+ _Gap.set_size_request(60, -1);
+ _Gap.set_increments(increm , 0);
+ _Gap.set_range(_min, _max);
+ _Gap.set_value(val_ini);
+ dialog.tooltips().set_tip(_Gap,
+ tiptext);
+ _Gap.signal_changed().connect(sigc::mem_fun(*this, &ActionE::on_button_click)); //rajout douteux
+ _Label.set_label(id);
+
+ dialog._Table().attach(_Label, column, column+1, row, row+1, Gtk::FILL, Gtk::FILL);
+ dialog._Table().attach(_Gap, column+1, column+2, row, row+1, Gtk::EXPAND, Gtk::EXPAND);
+ }
+
+ virtual void on_button_click(){
+ if (!_dialog.getDesktop()) return;
+
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+
+ prefs->setDouble(_pref_path, SP_VERB_CONTEXT_SPRAY);
+
+ double const Gap = _Gap.get_value();
+
+
+ prefs->setDouble(_pref_path, Gap);
+
+ sp_document_done(sp_desktop_document(_dialog.getDesktop()), SP_VERB_CONTEXT_SPRAY,
+ _("Remove overlaps"));
+ }
+
+
+};
+
+class ActionF : public Action {
+private:
+ Gtk::Label _Label;
+ Gtk::Label _Label1;
+ Gtk::Label _Label2;
+ Gtk::SpinButton _Gap1;
+ Gtk::SpinButton _Gap2;
+ Glib::ustring _pref1_path;
+ Glib::ustring _pref2_path;
+
+public:
+ ActionF(const Glib::ustring &id,
+ const Glib::ustring &tiptext,
+ guint row, guint column,
+ SprayOptionClass &dialog,
+ Glib::ustring const &pref1_path,
+ Glib::ustring const &pref2_path ):
+ Action(id, tiptext, row, column,
+ dialog._Table(), dialog.tooltips(), dialog),
+ _pref1_path(pref1_path),
+ _pref2_path(pref2_path)
+ {
+ dialog.F_Table().set_col_spacings(3);
+
+ _Label.set_label(id);
+
+ _Gap1.set_digits(1);
+ _Gap1.set_size_request(60, -1);
+ _Gap1.set_increments(0.1, 0);
+ _Gap1.set_range(0, 10);
+ _Gap1.set_value(1);
+ dialog.tooltips().set_tip(_Gap1,
+ _("Minimum"));
+
+ _Label1.set_label(Q_("Min"));
+
+ _Gap2.set_digits(1);
+ _Gap2.set_size_request(60, -1);
+ _Gap2.set_increments(0.1, 0);
+ _Gap2.set_range(0, 10);
+ _Gap2.set_value(1);
+ dialog.tooltips().set_tip(_Gap2,
+ _("Maximum"));
+
+ _Label2.set_label(_("Max:"));
+
+ _Gap1.signal_changed().connect(sigc::mem_fun(*this, &ActionF::on_button_click));
+ _Gap2.signal_changed().connect(sigc::mem_fun(*this, &ActionF::on_button_click));
+
+ dialog.F_Table().attach(_Label, column, column+1, row, row+1, Gtk::FILL, Gtk::FILL);
+ dialog.F_Table().attach(_Label1, column+1, column+2, row, row+1, Gtk::FILL, Gtk::FILL);
+ dialog.F_Table().attach(_Gap1, column+2, column+3, row, row+1, Gtk::EXPAND, Gtk::EXPAND);
+ dialog.F_Table().attach(_Label2, column+3, column+4, row, row+1, Gtk::FILL, Gtk::FILL);
+ dialog.F_Table().attach(_Gap2, column+4, column+5, row, row+1, Gtk::EXPAND, Gtk::EXPAND);
+
+ }
+
+ virtual void on_button_click(){
+ if (!_dialog.getDesktop()) return;
+
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+
+ prefs->setDouble(_pref1_path, SP_VERB_CONTEXT_SPRAY);
+ prefs->setDouble(_pref2_path, SP_VERB_CONTEXT_SPRAY);
+
+ double const Gap1 = _Gap1.get_value();
+ double const Gap2 = _Gap2.get_value();
+
+ prefs->setDouble(_pref1_path, Gap1);
+ prefs->setDouble(_pref2_path, Gap2);
+
+ sp_document_done(sp_desktop_document(_dialog.getDesktop()), SP_VERB_CONTEXT_SPRAY,
+ _("Remove overlaps"));
+ }
+
+
+};
+
+
+
+void SprayOptionClass::combo_action() {
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ cout<<"combo.get_active_row_number = "<<_combo.get_active_row_number()<<endl;
+
+ int const distrib = _combo.get_active_row_number();
+
+ prefs->setInt("/tools/spray/distribution", distrib);
+
+
+ sp_document_done(sp_desktop_document(this->getDesktop()), SP_VERB_CONTEXT_SPRAY,
+ _("Remove overlaps"));
+
+}
+
+
+
+
+void SprayOptionClass::action() {
+ int r=1;
+ for (list<Action *>::iterator it = _actionList.begin();
+ it != _actionList.end();
+ it ++)
+ (*it)->on_button_click();
+ combo_action();
+}
+
+
+
+
+
+
+void on_selection_changed(Inkscape::Application */*inkscape*/, Inkscape::Selection */*selection*/, SprayOptionClass *daad)
+{
+ daad->randomize_bbox = Geom::OptRect();
+}
+
+/////////////////////////////////////////////////////////
+//Construction de l'interface
+/////////////////////////////////////////////////////////
+
+
+SprayOptionClass::SprayOptionClass()
+ : UI::Widget::Panel ("", "/dialogs/spray", SP_VERB_DIALOG_SPRAY_OPTION),
+ _distributionFrame(_("Distribution")),
+ _Frame(_("Cursor Options")),
+ _FFrame(_("Random Options")),
+ _gaussianTable(1, 5, false),
+ _ETable(3,2,false),
+ _FTable(2,5,false),
+ _unifLabel(_("Uniform")),
+ _gaussLabel(_("Gaussian ")),
+ _anchorLabel(_("Distribution : "))
+
+{
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+
+ //ComboBoxText
+
+ _combo.append_text(_("Uniforme"));
+ _combo.append_text(_("Gaussienne"));
+
+ _combo.set_active(prefs->getInt("/tools/spray/distribution", 1));
+ _combo.signal_changed().connect(sigc::mem_fun(*this, &SprayOptionClass::combo_action));
+
+ _anchorBox.pack_start(_anchorLabel);
+ _anchorBox.pack_start(_combo);
+
+ _gaussianBox.pack_start(_anchorBox);
+
+
+ _distributionBox.pack_start(_gaussianBox);
+ _distributionFrame.add(_distributionBox);
+
+
+ //Hbox Random
+ addFButton(_("Scale : ") ,_("Applique un facteur d'échelle"), 0, 0, "/tools/spray/scale_min","/tools/spray/scale_max");
+ addFButton(_("Rotation : ") ,_("Fait tourner"), 1, 0, "/tools/spray/rot_min","/tools/spray/rot_max");
+ _FHBox.pack_start(_FLabel);
+ _FHBox.pack_start(_FTable);
+
+ //Implementation dans la Vbox Cursor
+ _FVBox.pack_start(_FHBox);
+ _FFrame.add(_FVBox);
+
+ //Hbox Cursor
+ addEButton(_("Ratio : ") ,_("Excentricité de l'ellipse"), 0, 0, 0, 1,"/tools/spray/ratio");
+ addEButton(_("Angle : ") ,_("Angle de l'ellipse"), 1, 0, 0, 5,"/tools/spray/tilt");
+ addEButton(_("Width : ") ,_("Taille de l'ellipse"), 2, 0, 0, 1,"/tools/spray/width");
+ _HBox.pack_start(_Label);
+ _HBox.pack_start(_ETable);
+
+ //Implementation dans la Vbox Cursor
+ _VBox.pack_start(_HBox);
+ _Frame.add(_VBox);
+
+ Gtk::Box *contents = _getContents();
+ contents->set_spacing(4);
+
+
+
+
+
+
+ // Crée dans l'ordre suivant les différentes Frames (cadres de réglages)
+
+ contents->pack_start(_distributionFrame, true, true);
+ contents->pack_start(_FFrame, true, true);
+ contents->pack_start(_Frame, true, true);
+
+
+
+ // Connect to the global selection change, to invalidate cached randomize_bbox
+ g_signal_connect (G_OBJECT (INKSCAPE), "change_selection", G_CALLBACK (on_selection_changed), this);
+ randomize_bbox = Geom::OptRect();
+
+ show_all_children();
+
+
+
+}
+
+SprayOptionClass::~SprayOptionClass()
+{
+ sp_signal_disconnect_by_data (G_OBJECT (INKSCAPE), this);
+
+ for (std::list<Action *>::iterator it = _actionList.begin();
+ it != _actionList.end();
+ it ++)
+ delete *it;
+}
+
+
+
+
+
+
+
+//Fonctions qui lient la demande d'ajout d'une interface graphique à l'action correspondante
+
+void SprayOptionClass::addEButton(const Glib::ustring &id,
+ const Glib::ustring &tiptext,
+ guint row, guint column,
+ guint min, guint max,
+ Glib::ustring const &pref_path)
+{
+ _actionList.push_back( new ActionE(id, tiptext,row, column,*this,min ,max, pref_path ));
+}
+
+void SprayOptionClass::addFButton(const Glib::ustring &id,
+ const Glib::ustring &tiptext,
+ guint row, guint column,
+ Glib::ustring const &pref1_path,
+ Glib::ustring const &pref2_path)
+{
+ _actionList.push_back( new ActionF(id, tiptext,row, column,*this,pref1_path, pref2_path ));
+}
+
+
+
+
+
+SprayOptionClass &SprayOptionClass::get_SprayOptionClass()
+{
+ return *this;
+}
+
+} // namespace Dialog
+} // namespace UI
+} // namespace Inkscape
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/ui/dialog/spray-option.h b/src/ui/dialog/spray-option.h
new file mode 100644
index 000000000..75dfe1e35
--- /dev/null
+++ b/src/ui/dialog/spray-option.h
@@ -0,0 +1,130 @@
+
+/*Julien LERAY (julien.leray@ecl2010.ec-lyon.fr), interface for the spray tool*/
+
+#ifndef INKSCAPE_UI_DIALOG_SPRAY_OPTION_H
+#define INKSCAPE_UI_DIALOG_SPRAY_OPTION_H
+
+#include <gtkmm/notebook.h>
+#include <glibmm/i18n.h>
+
+#include <list>
+#include <gtkmm/frame.h>
+#include <gtkmm/tooltips.h>
+#include <gtkmm/comboboxtext.h>
+#include <gtkmm/table.h>
+#include <gtkmm/buttonbox.h>
+#include <gtkmm/label.h>
+#include "libnr/nr-dim2.h"
+#include "libnr/nr-rect.h"
+
+
+#include "ui/widget/panel.h"
+#include "ui/widget/notebook-page.h"
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <gtkmm/spinbutton.h>
+#include "desktop-handles.h"
+#include "unclump.h"
+#include "document.h"
+#include "enums.h"
+#include "graphlayout/graphlayout.h"
+#include "inkscape.h"
+#include "macros.h"
+#include "node-context.h"
+#include "preferences.h"
+#include "removeoverlap/removeoverlap.h"
+#include "selection.h"
+#include "shape-editor.h"
+#include "sp-flowtext.h"
+#include "sp-item-transform.h"
+#include "sp-text.h"
+#include "text-editing.h"
+#include "tools-switch.h"
+#include "ui/icon-names.h"
+#include "util/glib-list-iterators.h"
+#include "verbs.h"
+#include "widgets/icon.h"
+
+#include "spray-context.h"
+#include "verbs.h"
+
+#include <iostream>
+using namespace std;
+
+using namespace Inkscape::UI::Widget;
+
+class SPItem;
+
+
+namespace Inkscape {
+namespace UI {
+namespace Dialog {
+
+class Action;
+
+class SprayOptionClass : public Widget::Panel {
+
+private:
+
+ SprayOptionClass(SprayOptionClass const &d);
+ SprayOptionClass& operator=(SprayOptionClass const &d);
+
+public:
+ SprayOptionClass();
+ virtual ~SprayOptionClass();
+ void test() { cout<<"appel de test !!"<<endl; }
+ static SprayOptionClass &getInstance() { return *new SprayOptionClass(); }
+
+
+ Gtk::Table &_Table(){return _ETable;}
+ Gtk::Table &F_Table(){return _FTable;}
+ Gtk::Tooltips &tooltips(){return _tooltips;}
+ void action();
+ void combo_action();
+ Geom::OptRect randomize_bbox;
+
+ SprayOptionClass &get_SprayOptionClass();
+
+protected:
+
+ void addGaussianButton(guint row, guint col);
+ void addEButton(const Glib::ustring &id, const Glib::ustring &tiptext, guint row, guint column,
+ guint min, guint max, const Glib::ustring &pref_path);
+ void addFButton(const Glib::ustring &id, const Glib::ustring &tiptext, guint row, guint column,
+ const Glib::ustring &pref1_path, const Glib::ustring &pref2_path);
+
+ std::list<Action *> _actionList;
+ Gtk::Frame _distributionFrame, _Frame, _FFrame ;
+ Gtk::Table _distributionTable, _gaussianTable, _ETable, _FTable;
+ Gtk::HBox _anchorBox;
+ Gtk::HBox _unifBox, _gaussianBox, _HBox, _FHBox, _BoutonBox;
+ Gtk::VBox _distributionBox, _VBox, _FVBox, _ActionBox;
+ Gtk::Label _anchorLabel;
+ Gtk::Label _unifLabel, _gaussLabel, _Label, _FLabel;
+ Gtk::CheckButton _unif, _gauss;
+ Gtk::ComboBoxText _combo;
+ Gtk::Tooltips _tooltips;
+
+};
+
+
+} // namespace Dialog
+} // namespace UI
+} // namespace Inkscape
+
+#endif // INKSCAPE_UI_DIALOG_ALIGN_AND_DISTRIBUTE_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
+
diff --git a/src/ui/icon-names.h b/src/ui/icon-names.h
index f9a6f2a7d..0388b200f 100644
--- a/src/ui/icon-names.h
+++ b/src/ui/icon-names.h
@@ -456,6 +456,14 @@
"snap-nodes-smooth"
#define INKSCAPE_ICON_SNAP_PAGE \
"snap-page"
+#define INKSCAPE_ICON_SPRAY_COPY_MODE \
+ "spray-copy-mode"
+#define INKSCAPE_ICON_SPRAY_CLONE_MODE \
+ "spray-clone-mode"
+#define INKSCAPE_ICON_SPRAY_UNION_MODE \
+ "spray-union-mode"
+#define INKSCAPE_ICON_DIALOG_SPRAY_OPTIONS \
+ "dialog-spray-options"
#define INKSCAPE_ICON_STROKE_CAP_BUTT \
"stroke-cap-butt"
#define INKSCAPE_ICON_STROKE_CAP_ROUND \
@@ -488,6 +496,8 @@
"tool-pointer"
#define INKSCAPE_ICON_TOOL_TWEAK \
"tool-tweak"
+#define INKSCAPE_ICON_TOOL_SPRAY \
+ "tool-spray"
#define INKSCAPE_ICON_TRANSFORM_AFFECT_GRADIENT \
"transform-affect-gradient"
#define INKSCAPE_ICON_TRANSFORM_AFFECT_PATTERN \
diff --git a/src/ui/view/edit-widget.cpp b/src/ui/view/edit-widget.cpp
index 770a9bf87..d34b18771 100644
--- a/src/ui/view/edit-widget.cpp
+++ b/src/ui/view/edit-widget.cpp
@@ -228,6 +228,12 @@ EditWidget::onDialogAlignAndDistribute()
}
void
+EditWidget::onDialogSprayOptionClass()
+{
+ _dlg_mgr.showDialog("SprayOptionClass");
+}
+
+void
EditWidget::onDialogDocumentProperties()
{
// manage (Inkscape::UI::Dialog::DocumentPreferences::create());
diff --git a/src/ui/view/edit-widget.h b/src/ui/view/edit-widget.h
index 2bb708305..452641e80 100644
--- a/src/ui/view/edit-widget.h
+++ b/src/ui/view/edit-widget.h
@@ -70,6 +70,7 @@ public:
void onDialogAbout();
void onDialogAlignAndDistribute();
+ void onDialogSprayOptionClass();
void onDialogInkscapePreferences();
void onDialogDialog();
void onDialogDocumentProperties();
diff --git a/src/verbs.cpp b/src/verbs.cpp
index 29d24c101..56b63e95e 100644
--- a/src/verbs.cpp
+++ b/src/verbs.cpp
@@ -1464,6 +1464,9 @@ ContextVerb::perform(SPAction *action, void *data, void */*pdata*/)
case SP_VERB_CONTEXT_TWEAK:
tools_switch(dt, TOOLS_TWEAK);
break;
+ case SP_VERB_CONTEXT_SPRAY:
+ tools_switch(dt, TOOLS_SPRAY);
+ break;
case SP_VERB_CONTEXT_RECT:
tools_switch(dt, TOOLS_SHAPES_RECT);
break;
@@ -1525,6 +1528,10 @@ ContextVerb::perform(SPAction *action, void *data, void */*pdata*/)
prefs->setInt("/dialogs/preferences/page", PREFS_PAGE_TOOLS_TWEAK);
dt->_dlg_mgr->showDialog("InkscapePreferences");
break;
+ case SP_VERB_CONTEXT_SPRAY_PREFS:
+ prefs->setInt("/dialogs/preferences/page", PREFS_PAGE_TOOLS_SPRAY);
+ dt->_dlg_mgr->showDialog("InkscapePreferences");
+ break;
case SP_VERB_CONTEXT_RECT_PREFS:
prefs->setInt("/dialogs/preferences/page", PREFS_PAGE_TOOLS_SHAPES_RECT);
dt->_dlg_mgr->showDialog("InkscapePreferences");
@@ -1797,6 +1804,9 @@ DialogVerb::perform(SPAction *action, void *data, void */*pdata*/)
case SP_VERB_DIALOG_ALIGN_DISTRIBUTE:
dt->_dlg_mgr->showDialog("AlignAndDistribute");
break;
+ case SP_VERB_DIALOG_SPRAY_OPTION:
+ dt->_dlg_mgr->showDialog("SprayOptionClass");
+ break;
case SP_VERB_DIALOG_TEXT:
sp_text_edit_dialog();
break;
@@ -2503,6 +2513,8 @@ Verb *Verb::_base_verbs[] = {
N_("Edit paths by nodes"), INKSCAPE_ICON_TOOL_NODE_EDITOR),
new ContextVerb(SP_VERB_CONTEXT_TWEAK, "ToolTweak", N_("Tweak"),
N_("Tweak objects by sculpting or painting"), INKSCAPE_ICON_TOOL_TWEAK),
+ new ContextVerb(SP_VERB_CONTEXT_SPRAY, "ToolSpray", N_("Spray"),
+ N_("Spray objects by sculpting or painting"), INKSCAPE_ICON_TOOL_SPRAY),
new ContextVerb(SP_VERB_CONTEXT_RECT, "ToolRect", N_("Rectangle"),
N_("Create rectangles and squares"), INKSCAPE_ICON_DRAW_RECTANGLE),
new ContextVerb(SP_VERB_CONTEXT_3DBOX, "Tool3DBox", N_("3D Box"),
@@ -2544,6 +2556,8 @@ Verb *Verb::_base_verbs[] = {
N_("Open Preferences for the Node tool"), NULL),
new ContextVerb(SP_VERB_CONTEXT_TWEAK_PREFS, "TweakPrefs", N_("Tweak Tool Preferences"),
N_("Open Preferences for the Tweak tool"), NULL),
+ new ContextVerb(SP_VERB_CONTEXT_SPRAY_PREFS, "SprayPrefs", N_("Spray Tool Preferences"),
+ N_("Open Preferences for the Spray tool"), NULL),
new ContextVerb(SP_VERB_CONTEXT_RECT_PREFS, "RectPrefs", N_("Rectangle Preferences"),
N_("Open Preferences for the Rectangle tool"), NULL),
new ContextVerb(SP_VERB_CONTEXT_3DBOX_PREFS, "3DBoxPrefs", N_("3D Box Preferences"),
@@ -2645,6 +2659,8 @@ Verb *Verb::_base_verbs[] = {
N_("Precisely control objects' transformations"), INKSCAPE_ICON_DIALOG_TRANSFORM),
new DialogVerb(SP_VERB_DIALOG_ALIGN_DISTRIBUTE, "DialogAlignDistribute", N_("_Align and Distribute..."),
N_("Align and distribute objects"), INKSCAPE_ICON_DIALOG_ALIGN_AND_DISTRIBUTE),
+ new DialogVerb(SP_VERB_DIALOG_SPRAY_OPTION, "DialogSprayOption", N_("_Spray options..."),
+ N_("Some options for the spray"), INKSCAPE_ICON_DIALOG_SPRAY_OPTIONS),
new DialogVerb(SP_VERB_DIALOG_UNDO_HISTORY, "DialogUndoHistory", N_("Undo _History..."),
N_("Undo History"), INKSCAPE_ICON_EDIT_UNDO_HISTORY),
new DialogVerb(SP_VERB_DIALOG_TEXT, "DialogText", N_("_Text and Font..."),
diff --git a/src/verbs.h b/src/verbs.h
index 87fe27075..3ea2fdee8 100644
--- a/src/verbs.h
+++ b/src/verbs.h
@@ -153,6 +153,7 @@ enum {
SP_VERB_CONTEXT_SELECT,
SP_VERB_CONTEXT_NODE,
SP_VERB_CONTEXT_TWEAK,
+ SP_VERB_CONTEXT_SPRAY,
SP_VERB_CONTEXT_RECT,
SP_VERB_CONTEXT_3DBOX,
SP_VERB_CONTEXT_ARC,
@@ -174,6 +175,7 @@ enum {
SP_VERB_CONTEXT_SELECT_PREFS,
SP_VERB_CONTEXT_NODE_PREFS,
SP_VERB_CONTEXT_TWEAK_PREFS,
+ SP_VERB_CONTEXT_SPRAY_PREFS,
SP_VERB_CONTEXT_RECT_PREFS,
SP_VERB_CONTEXT_3DBOX_PREFS,
SP_VERB_CONTEXT_ARC_PREFS,
@@ -227,6 +229,7 @@ enum {
SP_VERB_DIALOG_SWATCHES,
SP_VERB_DIALOG_TRANSFORM,
SP_VERB_DIALOG_ALIGN_DISTRIBUTE,
+ SP_VERB_DIALOG_SPRAY_OPTION,
SP_VERB_DIALOG_UNDO_HISTORY,
SP_VERB_DIALOG_TEXT,
SP_VERB_DIALOG_XML_EDITOR,
diff --git a/src/widgets/toolbox.cpp b/src/widgets/toolbox.cpp
index e0fe9bfd1..41a70f08a 100644
--- a/src/widgets/toolbox.cpp
+++ b/src/widgets/toolbox.cpp
@@ -86,6 +86,7 @@
#include "../svg/css-ostringstream.h"
#include "../tools-switch.h"
#include "../tweak-context.h"
+#include "../spray-context.h"
#include "../ui/dialog/calligraphic-profile-rename.h"
#include "../ui/icon-names.h"
#include "../ui/widget/style-swatch.h"
@@ -107,6 +108,7 @@ typedef void (*UpdateFunction)(SPDesktop *desktop, SPEventContext *eventcontext,
static void sp_node_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObject* holder);
static void sp_tweak_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObject* holder);
+static void sp_spray_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObject* holder);
static void sp_zoom_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObject* holder);
static void sp_star_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObject* holder);
static void sp_arc_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObject* holder);
@@ -146,6 +148,7 @@ static struct {
{ "SPSelectContext", "select_tool", SP_VERB_CONTEXT_SELECT, SP_VERB_CONTEXT_SELECT_PREFS},
{ "SPNodeContext", "node_tool", SP_VERB_CONTEXT_NODE, SP_VERB_CONTEXT_NODE_PREFS },
{ "SPTweakContext", "tweak_tool", SP_VERB_CONTEXT_TWEAK, SP_VERB_CONTEXT_TWEAK_PREFS },
+ { "SPSprayContext", "spray_tool", SP_VERB_CONTEXT_SPRAY, SP_VERB_CONTEXT_SPRAY_PREFS },
{ "SPZoomContext", "zoom_tool", SP_VERB_CONTEXT_ZOOM, SP_VERB_CONTEXT_ZOOM_PREFS },
{ "SPRectContext", "rect_tool", SP_VERB_CONTEXT_RECT, SP_VERB_CONTEXT_RECT_PREFS },
{ "Box3DContext", "3dbox_tool", SP_VERB_CONTEXT_3DBOX, SP_VERB_CONTEXT_3DBOX_PREFS },
@@ -181,6 +184,8 @@ static struct {
SP_VERB_INVALID, 0, 0},
{ "SPTweakContext", "tweak_toolbox", 0, sp_tweak_toolbox_prep, "TweakToolbar",
SP_VERB_CONTEXT_TWEAK_PREFS, "/tools/tweak", N_("Color/opacity used for color tweaking")},
+ { "SPSprayContext", "spray_toolbox", 0, sp_spray_toolbox_prep, "SprayToolbar",
+ SP_VERB_CONTEXT_SPRAY_PREFS, "/tools/spray", N_("Color/opacity used for color spraying")},
{ "SPZoomContext", "zoom_toolbox", 0, sp_zoom_toolbox_prep, "ZoomToolbar",
SP_VERB_INVALID, 0, 0},
{ "SPStarContext", "star_toolbox", 0, sp_star_toolbox_prep, "StarToolbar",
@@ -299,6 +304,21 @@ static gchar const * ui_descr =
" <toolitem action='TweakDoO' />"
" </toolbar>"
+ " <toolbar name='SprayToolbar'>"
+ " <toolitem action='SprayModeAction' />"
+ " <separator />"
+ " <toolitem action='SprayWidthAction' />"
+ " <separator />"
+ " <toolitem action='SprayPressureAction' />"
+ " <separator />"
+ " <toolitem action='SprayPopulationAction' />"
+ " <separator />"
+ " <toolitem action='SprayMeanAction' />"
+ " <toolitem action='SprayStandard_deviationAction' />"
+ " <separator />"
+ " <toolitem action='DialogSprayOption' />"
+ " </toolbar>"
+
" <toolbar name='ZoomToolbar'>"
" <toolitem action='ZoomIn' />"
" <toolitem action='ZoomOut' />"
@@ -718,6 +738,7 @@ Glib::RefPtr<Gtk::ActionGroup> create_or_fetch_actions( SPDesktop* desktop )
//SP_VERB_EDIT_TILE,
//SP_VERB_EDIT_UNTILE,
SP_VERB_DIALOG_ALIGN_DISTRIBUTE,
+ SP_VERB_DIALOG_SPRAY_OPTION,
SP_VERB_DIALOG_DISPLAY,
SP_VERB_DIALOG_FILL_STROKE,
SP_VERB_DIALOG_NAMEDVIEW,
@@ -1627,6 +1648,7 @@ setup_tool_toolbox(GtkWidget *toolbox, SPDesktop *desktop)
" <toolitem action='ToolSelector' />"
" <toolitem action='ToolNode' />"
" <toolitem action='ToolTweak' />"
+ " <toolitem action='ToolSpray' />"
" <toolitem action='ToolZoom' />"
" <toolitem action='ToolRect' />"
" <toolitem action='Tool3DBox' />"
@@ -4372,6 +4394,198 @@ static void sp_tweak_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainAction
//########################
+//## Spray ##
+//########################
+
+static void sp_spray_width_value_changed( GtkAdjustment *adj, GObject */*tbl*/ )
+{
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ prefs->setDouble( "/tools/spray/width", adj->value );
+}
+
+static void sp_spray_force_value_changed( GtkAdjustment *adj, GObject */*tbl*/ )
+{
+ //Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ //prefs->setDouble( "/tools/spray/force", adj->value * 0.01 );
+}
+
+static void sp_spray_mean_value_changed( GtkAdjustment *adj, GObject */*tbl*/ )
+{
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ prefs->setDouble( "/tools/spray/mean", adj->value );
+}
+
+static void sp_spray_standard_deviation_value_changed( GtkAdjustment *adj, GObject */*tbl*/ )
+{
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ prefs->setDouble( "/tools/spray/standard_deviation", adj->value );
+}
+
+static void sp_spray_pressure_state_changed( GtkToggleAction *act, gpointer /*data*/ )
+{
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ prefs->setBool("/tools/spray/usepressure", gtk_toggle_action_get_active(act));
+}
+
+static void sp_spray_mode_changed( EgeSelectOneAction *act, GObject *tbl )
+{
+ int mode = ege_select_one_action_get_active( act );
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ prefs->setInt("/tools/spray/mode", mode);
+}
+
+static void sp_spray_population_value_changed( GtkAdjustment *adj, GObject */*tbl*/ )
+{
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ prefs->setDouble( "/tools/spray/population", adj->value );
+}
+
+/*static void spray_toggle_doh (GtkToggleAction *act, gpointer ) {
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ prefs->setBool("/tools/spray/doh", gtk_toggle_action_get_active(act));
+}
+static void spray_toggle_dos (GtkToggleAction *act, gpointer ) {
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ prefs->setBool("/tools/spray/dos", gtk_toggle_action_get_active(act));
+}
+static void spray_toggle_dol (GtkToggleAction *act, gpointer ) {
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ prefs->setBool("/tools/spray/dol", gtk_toggle_action_get_active(act));
+}
+static void spray_toggle_doo (GtkToggleAction *act, gpointer ) {
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ prefs->setBool("/tools/spray/doo", gtk_toggle_action_get_active(act));
+}
+*/
+static void sp_spray_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObject* holder)
+{
+ Inkscape::IconSize secondarySize = prefToSize("/toolbox/secondary", 1);
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+
+ {
+ /* Width */
+ gchar const* labels[] = {_("(pinch spray)"), 0, 0, 0, _("(default)"), 0, 0, 0, 0, _("(broad spray)")};
+ gdouble values[] = {1, 3, 5, 10, 15, 20, 30, 50, 75, 100};
+ EgeAdjustmentAction *eact = create_adjustment_action( "SprayWidthAction",
+ _("Width"), _("Width:"), _("The width of the spray area (relative to the visible canvas area)"),
+ "/tools/spray/width", 15,
+ GTK_WIDGET(desktop->canvas), NULL, holder, TRUE, "altx-spray",
+ 1, 100, 1.0, 0.0,
+ labels, values, G_N_ELEMENTS(labels),
+ sp_spray_width_value_changed, 0.01, 0, 100 );
+ ege_adjustment_action_set_appearance( eact, TOOLBAR_SLIDER_HINT );
+ gtk_action_group_add_action( mainActions, GTK_ACTION(eact) );
+ gtk_action_set_sensitive( GTK_ACTION(eact), TRUE );
+ }
+
+ {
+ /* Mean */
+ gchar const* labels[] = {_("(minimum mean)"), 0, 0, _("(default)"), 0, 0, 0, _("(maximum mean)")};
+ gdouble values[] = {1, 5, 10, 20, 30, 50, 70, 100};
+ EgeAdjustmentAction *eact = create_adjustment_action( "SprayMeanAction",
+ _("Mean"), _("Mean:"), _("The mean of the spray action"),
+ "/tools/spray/mean", 20,
+ GTK_WIDGET(desktop->canvas), NULL, holder, TRUE, "spray-mean",
+ 1, 100, 1.0, 0.0,
+ labels, values, G_N_ELEMENTS(labels),
+ sp_spray_mean_value_changed, 0.01, 0, 100 );
+ ege_adjustment_action_set_appearance( eact, TOOLBAR_SLIDER_HINT );
+ gtk_action_group_add_action( mainActions, GTK_ACTION(eact) );
+ gtk_action_set_sensitive( GTK_ACTION(eact), TRUE );
+ }
+
+ {
+ /* Standard_deviation */
+ gchar const* labels[] = {_("(minimum standard_deviation)"), 0, 0, _("(default)"), 0, 0, 0, _("(maximum standard_deviation)")};
+ gdouble values[] = {1, 5, 10, 20, 30, 50, 70, 100};
+ EgeAdjustmentAction *eact = create_adjustment_action( "SprayStandard_deviationAction",
+ _("SD"), _("SD:"), _("The standard deviation of the spray action"),
+ "/tools/spray/standard_deviation", 20,
+ GTK_WIDGET(desktop->canvas), NULL, holder, TRUE, "spray-standard_deviation",
+ 1, 100, 1.0, 0.0,
+ labels, values, G_N_ELEMENTS(labels),
+ sp_spray_standard_deviation_value_changed, 0.01, 0, 100 );
+ ege_adjustment_action_set_appearance( eact, TOOLBAR_SLIDER_HINT );
+ gtk_action_group_add_action( mainActions, GTK_ACTION(eact) );
+ gtk_action_set_sensitive( GTK_ACTION(eact), TRUE );
+ }
+
+ /* Mode */
+ {
+ GtkListStore* model = gtk_list_store_new( 3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING );
+
+ GtkTreeIter iter;
+ gtk_list_store_append( model, &iter );
+ gtk_list_store_set( model, &iter,
+ 0, _("Spray with copies"),
+ 1, _("Spray copies of the initial selection"),
+ 2, INKSCAPE_ICON_SPRAY_COPY_MODE,
+ -1 );
+
+ gtk_list_store_append( model, &iter );
+ gtk_list_store_set( model, &iter,
+ 0, _("Spray with clones"),
+ 1, _("Spray clones of the initial selection"),
+ 2, INKSCAPE_ICON_SPRAY_CLONE_MODE,
+ -1 );
+
+ gtk_list_store_append( model, &iter );
+ gtk_list_store_set( model, &iter,
+ 0, _("Spray single path"),
+ 1, _("Spray objects in a single path"),
+ 2, INKSCAPE_ICON_SPRAY_UNION_MODE,
+ -1 );
+
+ EgeSelectOneAction* act = ege_select_one_action_new( "SprayModeAction", _("Mode"), (""), NULL, GTK_TREE_MODEL(model) );
+ g_object_set( act, "short_label", _("Mode:"), NULL );
+ gtk_action_group_add_action( mainActions, GTK_ACTION(act) );
+ g_object_set_data( holder, "mode_action", act );
+
+ ege_select_one_action_set_appearance( act, "full" );
+ ege_select_one_action_set_radio_action_type( act, INK_RADIO_ACTION_TYPE );
+ g_object_set( G_OBJECT(act), "icon-property", "iconId", NULL );
+ ege_select_one_action_set_icon_column( act, 2 );
+ ege_select_one_action_set_icon_size( act, secondarySize );
+ ege_select_one_action_set_tooltip_column( act, 1 );
+
+ gint mode = prefs->getInt("/tools/spray/mode", 0);
+ ege_select_one_action_set_active( act, mode );
+ g_signal_connect_after( G_OBJECT(act), "changed", G_CALLBACK(sp_spray_mode_changed), holder );
+
+ g_object_set_data( G_OBJECT(holder), "spray_tool_mode", act);
+ }
+
+ { /* Population */
+ gchar const* labels[] = {_("(rough, simplified)"), 0, 0, _("(default)"), 0, 0, _("(fine, but many nodes)")};
+ gdouble values[] = {10, 25, 35, 50, 60, 80, 100};
+ EgeAdjustmentAction *eact = create_adjustment_action( "SprayPopulationAction",
+ _("Population"), _("Population:"),
+ _("This setting adjusts the number of items sprayed"),
+ "/tools/spray/population", 50,
+ GTK_WIDGET(desktop->canvas), NULL, holder, TRUE, "spray-population",
+ 1, 100, 1.0, 10.0,
+ labels, values, G_N_ELEMENTS(labels),
+ sp_spray_population_value_changed, 0.01, 0, 100 );
+ gtk_action_group_add_action( mainActions, GTK_ACTION(eact) );
+ gtk_action_set_sensitive( GTK_ACTION(eact), TRUE );
+ g_object_set_data( holder, "spray_population", eact );
+ }
+
+ /* Use Pressure button */
+ {
+ InkToggleAction* act = ink_toggle_action_new( "SprayPressureAction",
+ _("Pressure"),
+ _("Use the pressure of the input device to alter the force of spray action"),
+ "use_pressure",
+ Inkscape::ICON_SIZE_DECORATION );
+ gtk_action_group_add_action( mainActions, GTK_ACTION( act ) );
+ g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(sp_spray_pressure_state_changed), NULL);
+ gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(act), prefs->getBool("/tools/spray/usepressure", true) );
+ }
+}
+
+
+//########################
//## Calligraphy ##
//########################
static void update_presets_list (GObject *tbl)