X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=src%2Ftweak-context.cpp;h=3b93c659b664df6455948bd9ab6da916bd32eb6f;hb=0dc33d4ce43e0bb49c63aa53b826ec4a1ff68e28;hp=e670a2db4fe3d62a47331a7dd3bf68f6ec5fc35d;hpb=8b9a820756fdf348239872236be2257f854e094a;p=inkscape.git diff --git a/src/tweak-context.cpp b/src/tweak-context.cpp index e670a2db4..3b93c659b 100644 --- a/src/tweak-context.cpp +++ b/src/tweak-context.cpp @@ -1,10 +1,10 @@ -#define __SP_TWEAK_CONTEXT_C__ - /* * tweaking paths without node editing * * Authors: * bulia byak + * Jon A. Cruz + * Abhishek Sharma * * Copyright (C) 2007 authors * @@ -20,8 +20,6 @@ #include #include "svg/svg.h" -#include "display/canvas-bpath.h" -#include "display/bezier-utils.h" #include #include "macros.h" @@ -30,9 +28,9 @@ #include "desktop.h" #include "desktop-events.h" #include "desktop-handles.h" -#include "desktop-affine.h" #include "desktop-style.h" #include "message-context.h" +#include "pixmaps/cursor-tweak-move.xpm" #include "pixmaps/cursor-thin.xpm" #include "pixmaps/cursor-thicken.xpm" #include "pixmaps/cursor-attract.xpm" @@ -56,24 +54,31 @@ #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/sp-canvas.h" #include "display/canvas-bpath.h" #include "display/canvas-arena.h" #include "display/curve.h" #include "livarot/Shape.h" -#include "2geom/isnan.h" -#include "prefs-utils.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 "tweak-context.h" +using Inkscape::DocumentUndo; + #define DDC_RED_RGBA 0xff0000ff #define DYNA_MIN_WIDTH 1.0e-6 @@ -83,7 +88,7 @@ static void sp_tweak_context_init(SPTweakContext *ddc); static void sp_tweak_context_dispose(GObject *object); static void sp_tweak_context_setup(SPEventContext *ec); -static void sp_tweak_context_set(SPEventContext *ec, gchar const *key, gchar const *val); +static void sp_tweak_context_set(SPEventContext *ec, Inkscape::Preferences::Entry *val); static gint sp_tweak_context_root_handler(SPEventContext *ec, GdkEvent *event); static SPEventContextClass *parent_class; @@ -170,35 +175,101 @@ sp_tweak_context_dispose(GObject *object) G_OBJECT_CLASS(parent_class)->dispose(object); } +bool is_transform_mode (gint mode) +{ + return (mode == TWEAK_MODE_MOVE || + mode == TWEAK_MODE_MOVE_IN_OUT || + mode == TWEAK_MODE_MOVE_JITTER || + mode == TWEAK_MODE_SCALE || + mode == TWEAK_MODE_ROTATE || + mode == TWEAK_MODE_MORELESS); +} + +bool is_color_mode (gint mode) +{ + return (mode == TWEAK_MODE_COLORPAINT || mode == TWEAK_MODE_COLORJITTER || mode == TWEAK_MODE_BLUR); +} + void -sp_tweak_update_cursor (SPTweakContext *tc, gint mode) +sp_tweak_update_cursor (SPTweakContext *tc, bool with_shift) { - SPEventContext *event_context = SP_EVENT_CONTEXT(tc); - switch (mode) { - case TWEAK_MODE_PUSH: - event_context->cursor_shape = cursor_push_xpm; + 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("%i object selected","%i objects selected",num), num); + } else { + sel_message = g_strdup_printf(_("Nothing selected")); + } + + + switch (tc->mode) { + case TWEAK_MODE_MOVE: + tc->_message_context->setF(Inkscape::NORMAL_MESSAGE, _("%s. Drag to move."), sel_message); + event_context->cursor_shape = cursor_tweak_move_xpm; + break; + case TWEAK_MODE_MOVE_IN_OUT: + tc->_message_context->setF(Inkscape::NORMAL_MESSAGE, _("%s. Drag or click to move in; with Shift to move out."), sel_message); + event_context->cursor_shape = cursor_tweak_move_xpm; break; - case TWEAK_MODE_SHRINK: - event_context->cursor_shape = cursor_thin_xpm; + case TWEAK_MODE_MOVE_JITTER: + tc->_message_context->setF(Inkscape::NORMAL_MESSAGE, _("%s. Drag or click to move randomly."), sel_message); + event_context->cursor_shape = cursor_tweak_move_xpm; break; - case TWEAK_MODE_GROW: - event_context->cursor_shape = cursor_thicken_xpm; + case TWEAK_MODE_SCALE: + tc->_message_context->setF(Inkscape::NORMAL_MESSAGE, _("%s. Drag or click to scale down; with Shift to scale up."), sel_message); + event_context->cursor_shape = cursor_tweak_move_xpm; break; - case TWEAK_MODE_ATTRACT: - event_context->cursor_shape = cursor_attract_xpm; + case TWEAK_MODE_ROTATE: + tc->_message_context->setF(Inkscape::NORMAL_MESSAGE, _("%s. Drag or click to rotate clockwise; with Shift, counterclockwise."), sel_message); + event_context->cursor_shape = cursor_tweak_move_xpm; break; - case TWEAK_MODE_REPEL: - event_context->cursor_shape = cursor_repel_xpm; + case TWEAK_MODE_MORELESS: + tc->_message_context->setF(Inkscape::NORMAL_MESSAGE, _("%s. Drag or click to duplicate; with Shift, delete."), sel_message); + event_context->cursor_shape = cursor_tweak_move_xpm; + break; + case TWEAK_MODE_PUSH: + tc->_message_context->setF(Inkscape::NORMAL_MESSAGE, _("%s. Drag to push paths."), sel_message); + event_context->cursor_shape = cursor_push_xpm; + break; + case TWEAK_MODE_SHRINK_GROW: + tc->_message_context->setF(Inkscape::NORMAL_MESSAGE, _("%s. Drag or click to inset paths; with Shift to outset."), sel_message); + if (with_shift) { + event_context->cursor_shape = cursor_thicken_xpm; + } else { + event_context->cursor_shape = cursor_thin_xpm; + } + break; + case TWEAK_MODE_ATTRACT_REPEL: + tc->_message_context->setF(Inkscape::NORMAL_MESSAGE, _("%s. Drag or click to attract paths; with Shift to repel."), sel_message); + if (with_shift) { + event_context->cursor_shape = cursor_repel_xpm; + } else { + event_context->cursor_shape = cursor_attract_xpm; + } break; case TWEAK_MODE_ROUGHEN: + tc->_message_context->setF(Inkscape::NORMAL_MESSAGE, _("%s. Drag or click to roughen paths."), sel_message); event_context->cursor_shape = cursor_roughen_xpm; break; case TWEAK_MODE_COLORPAINT: + tc->_message_context->setF(Inkscape::NORMAL_MESSAGE, _("%s. Drag or click to paint objects with color."), sel_message); + event_context->cursor_shape = cursor_color_xpm; + break; case TWEAK_MODE_COLORJITTER: + tc->_message_context->setF(Inkscape::NORMAL_MESSAGE, _("%s. Drag or click to randomize colors."), sel_message); + event_context->cursor_shape = cursor_color_xpm; + break; + case TWEAK_MODE_BLUR: + tc->_message_context->setF(Inkscape::NORMAL_MESSAGE, _("%s. Drag or click to increase blur; with Shift to decrease."), sel_message); event_context->cursor_shape = cursor_color_xpm; break; } sp_event_context_update_cursor(event_context); + g_free(sel_message); } static bool @@ -207,9 +278,8 @@ sp_tweak_context_style_set(SPCSSAttr const *css, SPTweakContext *tc) if (tc->mode == TWEAK_MODE_COLORPAINT) { // intercept color setting only in this mode // we cannot store properties with uris css = sp_css_attr_unset_uris ((SPCSSAttr *) css); - - sp_repr_css_change (inkscape_get_repr (INKSCAPE, "tools.tweak"), (SPCSSAttr *) css, "style"); - + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + prefs->setStyle("/tools/tweak/style", const_cast(css)); return true; } return false; @@ -241,6 +311,10 @@ sp_tweak_context_setup(SPEventContext *ec) 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, "width"); sp_event_context_read(ec, "mode"); sp_event_context_read(ec, "fidelity"); @@ -251,51 +325,45 @@ sp_tweak_context_setup(SPEventContext *ec) sp_event_context_read(ec, "dos"); sp_event_context_read(ec, "doo"); - tc->is_drawing = false; - - tc->_message_context = new Inkscape::MessageContext((ec->desktop)->messageStack()); - tc->style_set_connection = ec->desktop->connectSetStyle( // catch style-setting signal in this tool sigc::bind(sigc::ptr_fun(&sp_tweak_context_style_set), tc) ); - - if (prefs_get_int_attribute("tools.tweak", "selcue", 0) != 0) { + + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + if (prefs->getBool("/tools/tweak/selcue")) { ec->enableSelectionCue(); } - if (prefs_get_int_attribute("tools.tweak", "gradientdrag", 0) != 0) { + if (prefs->getBool("/tools/tweak/gradientdrag")) { ec->enableGrDrag(); } } static void -sp_tweak_context_set(SPEventContext *ec, gchar const *key, gchar const *val) +sp_tweak_context_set(SPEventContext *ec, Inkscape::Preferences::Entry *val) { SPTweakContext *tc = SP_TWEAK_CONTEXT(ec); - - if (!strcmp(key, "width")) { - double const dval = ( val ? g_ascii_strtod (val, NULL) : 0.1 ); - tc->width = CLAMP(dval, -1000.0, 1000.0); - } else if (!strcmp(key, "mode")) { - gint64 const dval = ( val ? g_ascii_strtoll (val, NULL, 10) : 0 ); - tc->mode = dval; - sp_tweak_update_cursor(tc, tc->mode); - } else if (!strcmp(key, "fidelity")) { - double const dval = ( val ? g_ascii_strtod (val, NULL) : 0.0 ); - tc->fidelity = CLAMP(dval, 0.0, 1.0); - } else if (!strcmp(key, "force")) { - double const dval = ( val ? g_ascii_strtod (val, NULL) : 1.0 ); - tc->force = CLAMP(dval, 0, 1.0); - } else if (!strcmp(key, "usepressure")) { - tc->usepressure = (val && strcmp(val, "0")); - } else if (!strcmp(key, "doh")) { - tc->do_h = (val && strcmp(val, "0")); - } else if (!strcmp(key, "dos")) { - tc->do_s = (val && strcmp(val, "0")); - } else if (!strcmp(key, "dol")) { - tc->do_l = (val && strcmp(val, "0")); - } else if (!strcmp(key, "doo")) { - tc->do_o = (val && strcmp(val, "0")); + 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_tweak_update_cursor(tc, false); + } else if (path == "fidelity") { + tc->fidelity = CLAMP(val->getDouble(), 0.0, 1.0); + } else if (path == "force") { + tc->force = 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(); } } @@ -316,7 +384,7 @@ get_dilate_radius (SPTweakContext *tc) } double -get_dilate_force (SPTweakContext *tc) +get_path_force (SPTweakContext *tc) { double force = 8 * (tc->usepressure? tc->pressure : TC_DEFAULT_PRESSURE) /sqrt(SP_EVENT_CONTEXT(tc)->desktop->current_zoom()); @@ -326,26 +394,156 @@ get_dilate_force (SPTweakContext *tc) return force * tc->force; } +double +get_move_force (SPTweakContext *tc) +{ + double force = (tc->usepressure? tc->pressure : TC_DEFAULT_PRESSURE); + return force * tc->force; +} + bool -sp_tweak_dilate_recursive (Inkscape::Selection *selection, SPItem *item, NR::Point p, NR::Point vector, gint mode, double radius, double force, double fidelity) +sp_tweak_dilate_recursive (Inkscape::Selection *selection, SPItem *item, Geom::Point p, Geom::Point vector, gint mode, double radius, double force, double fidelity, bool reverse) { bool did = false; - if (SP_IS_BOX3D(item)) { + if (SP_IS_BOX3D(item) && !is_transform_mode(mode) && !is_color_mode(mode)) { // convert 3D boxes to ordinary groups before tweaking their shapes item = SP_ITEM(box3d_convert_to_group(SP_BOX3D(item))); selection->add(item); } - if (SP_IS_GROUP(item)) { - for (SPObject *child = sp_object_first_child(SP_OBJECT(item)) ; child != NULL; child = SP_OBJECT_NEXT(child) ) { + 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)) { + GSList *children = NULL; + for (SPObject *child = item->firstChild() ; child; child = child->getNext() ) { if (SP_IS_ITEM(child)) { - if (sp_tweak_dilate_recursive (selection, SP_ITEM(child), p, vector, mode, radius, force, fidelity)) - did = true; + children = g_slist_prepend(children, child); } } - } else if (SP_IS_PATH(item) || SP_IS_SHAPE(item) || SP_IS_TEXT(item) || SP_IS_FLOWTEXT(item)) { + for (GSList *i = children; i; i = i->next) { + SPItem *child = SP_ITEM(i->data); + if (sp_tweak_dilate_recursive (selection, SP_ITEM(child), p, vector, mode, radius, force, fidelity, reverse)) + did = true; + } + + g_slist_free(children); + + } else { + if (mode == TWEAK_MODE_MOVE) { + + Geom::OptRect a = item->getBounds(item->i2doc_affine()); + if (a) { + double x = Geom::L2(a->midpoint() - p)/radius; + if (a->contains(p)) x = 0; + if (x < 1) { + Geom::Point move = force * 0.5 * (cos(M_PI * x) + 1) * vector; + sp_item_move_rel(item, Geom::Translate(move[Geom::X], -move[Geom::Y])); + did = true; + } + } + + } else if (mode == TWEAK_MODE_MOVE_IN_OUT) { + + Geom::OptRect a = item->getBounds(item->i2doc_affine()); + if (a) { + double x = Geom::L2(a->midpoint() - p)/radius; + if (a->contains(p)) x = 0; + if (x < 1) { + Geom::Point move = force * 0.5 * (cos(M_PI * x) + 1) * + (reverse? (a->midpoint() - p) : (p - a->midpoint())); + sp_item_move_rel(item, Geom::Translate(move[Geom::X], -move[Geom::Y])); + did = true; + } + } + + } else if (mode == TWEAK_MODE_MOVE_JITTER) { + + Geom::OptRect a = item->getBounds(item->i2doc_affine()); + if (a) { + double dp = g_random_double_range(0, M_PI*2); + double dr = g_random_double_range(0, radius); + double x = Geom::L2(a->midpoint() - p)/radius; + if (a->contains(p)) x = 0; + if (x < 1) { + Geom::Point move = force * 0.5 * (cos(M_PI * x) + 1) * Geom::Point(cos(dp)*dr, sin(dp)*dr); + sp_item_move_rel(item, Geom::Translate(move[Geom::X], -move[Geom::Y])); + did = true; + } + } + + } else if (mode == TWEAK_MODE_SCALE) { + + Geom::OptRect a = item->getBounds(item->i2doc_affine()); + if (a) { + double x = Geom::L2(a->midpoint() - p)/radius; + if (a->contains(p)) x = 0; + if (x < 1) { + double scale = 1 + (reverse? force : -force) * 0.05 * (cos(M_PI * x) + 1); + sp_item_scale_rel(item, Geom::Scale(scale, scale)); + did = true; + } + } + + } else if (mode == TWEAK_MODE_ROTATE) { + + Geom::OptRect a = item->getBounds(item->i2doc_affine()); + if (a) { + double x = Geom::L2(a->midpoint() - p)/radius; + if (a->contains(p)) x = 0; + if (x < 1) { + double angle = (reverse? force : -force) * 0.05 * (cos(M_PI * x) + 1) * M_PI; + sp_item_rotate_rel(item, Geom::Rotate(angle)); + did = true; + } + } + + } else if (mode == TWEAK_MODE_MORELESS) { + + Geom::OptRect a = item->getBounds(item->i2doc_affine()); + if (a) { + double x = Geom::L2(a->midpoint() - p)/radius; + if (a->contains(p)) x = 0; + if (x < 1) { + double prob = force * 0.5 * (cos(M_PI * x) + 1); + double chance = g_random_double_range(0, 1); + if (chance <= prob) { + if (reverse) { // delete + sp_object_ref(SP_OBJECT(item), NULL); + SP_OBJECT(item)->deleteObject(true, true); + sp_object_unref(SP_OBJECT(item), NULL); + } else { // duplicate + SPDocument *doc = SP_OBJECT_DOCUMENT(item); + Inkscape::XML::Document* xml_doc = doc->getReprDoc(); + Inkscape::XML::Node *old_repr = SP_OBJECT_REPR(item); + SPObject *old_obj = doc->getObjectByRepr(old_repr); + 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); + if (selection->includes(old_obj)) { + selection->add(new_obj); + } + Inkscape::GC::release(copy); + } + did = true; + } + } + } + + } else if (SP_IS_PATH(item) || SP_IS_SHAPE(item)) { Inkscape::XML::Node *newrepr = NULL; gint pos = 0; @@ -366,9 +564,9 @@ sp_tweak_dilate_recursive (Inkscape::Selection *selection, SPItem *item, NR::Poi // skip those paths whose bboxes are entirely out of reach with our radius - boost::optional bbox = item->getBounds(from_2geom(sp_item_i2doc_affine(item))); + Geom::OptRect bbox = item->getBounds(item->i2doc_affine()); if (bbox) { - bbox->growBy(radius); + bbox->expandBy(radius); if (!bbox->contains(p)) { return false; } @@ -384,9 +582,9 @@ sp_tweak_dilate_recursive (Inkscape::Selection *selection, SPItem *item, NR::Poi Shape *theShape = new Shape; Shape *theRes = new Shape; - NR::Matrix i2doc(from_2geom(sp_item_i2doc_affine(item))); + Geom::Matrix i2doc(item->i2doc_affine()); - orig->ConvertWithBackData((0.08 - (0.07 * fidelity)) / NR::expansion(i2doc)); // default 0.059 + orig->ConvertWithBackData((0.08 - (0.07 * fidelity)) / i2doc.descrim()); // default 0.059 orig->Fill(theShape, 0); SPCSSAttr *css = sp_repr_css_attr(SP_OBJECT_REPR(item), "style"); @@ -404,21 +602,21 @@ sp_tweak_dilate_recursive (Inkscape::Selection *selection, SPItem *item, NR::Poi theRes->ConvertToShape(theShape, fill_nonZero); } - if (NR::L2(vector) != 0) - vector = 1/NR::L2(vector) * vector; + if (Geom::L2(vector) != 0) + vector = 1/Geom::L2(vector) * vector; bool did_this = false; - if (mode == TWEAK_MODE_SHRINK || mode == TWEAK_MODE_GROW) { + if (mode == TWEAK_MODE_SHRINK_GROW) { if (theShape->MakeTweak(tweak_mode_grow, theRes, - mode == TWEAK_MODE_GROW? force : -force, + reverse? force : -force, join_straight, 4.0, - true, p, NR::Point(0,0), radius, &i2doc) == 0) // 0 means the shape was actually changed + true, p, Geom::Point(0,0), radius, &i2doc) == 0) // 0 means the shape was actually changed did_this = true; - } else if (mode == TWEAK_MODE_ATTRACT || mode == TWEAK_MODE_REPEL) { + } else if (mode == TWEAK_MODE_ATTRACT_REPEL) { if (theShape->MakeTweak(tweak_mode_repel, theRes, - mode == TWEAK_MODE_REPEL? force : -force, + reverse? force : -force, join_straight, 4.0, - true, p, NR::Point(0,0), radius, &i2doc) == 0) + true, p, Geom::Point(0,0), radius, &i2doc) == 0) did_this = true; } else if (mode == TWEAK_MODE_PUSH) { if (theShape->MakeTweak(tweak_mode_push, theRes, @@ -430,7 +628,7 @@ sp_tweak_dilate_recursive (Inkscape::Selection *selection, SPItem *item, NR::Poi if (theShape->MakeTweak(tweak_mode_roughen, theRes, force, join_straight, 4.0, - true, p, NR::Point(0,0), radius, &i2doc) == 0) + true, p, Geom::Point(0,0), radius, &i2doc) == 0) did_this = true; } @@ -441,10 +639,10 @@ sp_tweak_dilate_recursive (Inkscape::Selection *selection, SPItem *item, NR::Poi res->Reset(); theRes->ConvertToForme(res); - double th_max = (0.6 - 0.59*sqrt(fidelity)) / NR::expansion(i2doc); + double th_max = (0.6 - 0.59*sqrt(fidelity)) / i2doc.descrim(); double threshold = MAX(th_max, th_max*force); res->ConvertEvenLines(threshold); - res->Simplify(threshold / (SP_ACTIVE_DESKTOP->current_zoom())); + res->Simplify(threshold / (selection->desktop()->current_zoom())); if (newrepr) { // converting to path, need to replace the repr bool is_selected = selection->includes(item); @@ -496,6 +694,8 @@ sp_tweak_dilate_recursive (Inkscape::Selection *selection, SPItem *item, NR::Poi did = true; } + } + return did; } @@ -595,7 +795,7 @@ tweak_profile (double dist, double radius) void tweak_colors_in_gradient (SPItem *item, bool fill_or_stroke, - guint32 const rgb_goal, NR::Point p_w, double radius, double force, guint mode, + guint32 const rgb_goal, Geom::Point p_w, double radius, double force, guint mode, bool do_h, bool do_s, bool do_l, bool /*do_o*/) { SPGradient *gradient = sp_item_gradient (item, fill_or_stroke); @@ -603,8 +803,8 @@ tweak_colors_in_gradient (SPItem *item, bool fill_or_stroke, if (!gradient || !SP_IS_GRADIENT(gradient)) return; - NR::Matrix i2d = from_2geom(sp_item_i2doc_affine (item)); - NR::Point p = p_w * i2d.inverse(); + Geom::Matrix i2d (item->i2doc_affine ()); + Geom::Point p = p_w * i2d.inverse(); p *= (gradient->gradientTransform).inverse(); // now p is in gradient's original coordinates @@ -613,46 +813,50 @@ tweak_colors_in_gradient (SPItem *item, bool fill_or_stroke, if (SP_IS_LINEARGRADIENT(gradient)) { SPLinearGradient *lg = SP_LINEARGRADIENT(gradient); - NR::Point p1(lg->x1.computed, lg->y1.computed); - NR::Point p2(lg->x2.computed, lg->y2.computed); - NR::Point pdiff(p2 - p1); - double vl = NR::L2(pdiff); + Geom::Point p1(lg->x1.computed, lg->y1.computed); + Geom::Point p2(lg->x2.computed, lg->y2.computed); + Geom::Point pdiff(p2 - p1); + double vl = Geom::L2(pdiff); // This is the matrix which moves and rotates the gradient line // so it's oriented along the X axis: - NR::Matrix norm = NR::Matrix(NR::translate(-p1)) * NR::Matrix(NR::rotate(-atan2(pdiff[NR::Y], pdiff[NR::X]))); + Geom::Matrix norm = Geom::Matrix(Geom::Translate(-p1)) * Geom::Matrix(Geom::Rotate(-atan2(pdiff[Geom::Y], pdiff[Geom::X]))); // Transform the mouse point by it to find out its projection onto the gradient line: - NR::Point pnorm = p * norm; + Geom::Point pnorm = p * norm; // Scale its X coordinate to match the length of the gradient line: - pos = pnorm[NR::X] / vl; + pos = pnorm[Geom::X] / vl; // Calculate radius in lenfth-of-gradient-line units r = radius / vl; } else if (SP_IS_RADIALGRADIENT(gradient)) { SPRadialGradient *rg = SP_RADIALGRADIENT(gradient); - NR::Point c (rg->cx.computed, rg->cy.computed); - pos = NR::L2(p - c) / rg->r.computed; + Geom::Point c (rg->cx.computed, rg->cy.computed); + pos = Geom::L2(p - c) / rg->r.computed; r = radius / rg->r.computed; } // Normalize pos to 0..1, taking into accound gradient spread: double pos_e = pos; - if (gradient->spread == SP_GRADIENT_SPREAD_PAD) { - if (pos > 1) + if (gradient->getSpread() == SP_GRADIENT_SPREAD_PAD) { + if (pos > 1) { pos_e = 1; - if (pos < 0) + } + if (pos < 0) { pos_e = 0; - } else if (gradient->spread == SP_GRADIENT_SPREAD_REPEAT) { - if (pos > 1 || pos < 0) + } + } else if (gradient->getSpread() == SP_GRADIENT_SPREAD_REPEAT) { + if (pos > 1 || pos < 0) { pos_e = pos - floor(pos); - } else if (gradient->spread == SP_GRADIENT_SPREAD_REFLECT) { + } + } else if (gradient->getSpread() == SP_GRADIENT_SPREAD_REFLECT) { if (pos > 1 || pos < 0) { bool odd = ((int)(floor(pos)) % 2 == 1); pos_e = pos - floor(pos); - if (odd) + if (odd) { pos_e = 1 - pos_e; + } } } @@ -661,10 +865,10 @@ tweak_colors_in_gradient (SPItem *item, bool fill_or_stroke, double offset_l = 0; double offset_h = 0; SPObject *child_prev = NULL; - for (SPObject *child = sp_object_first_child(vector); - child != NULL; child = SP_OBJECT_NEXT(child)) { - if (!SP_IS_STOP(child)) + for (SPObject *child = vector->firstChild(); child; child = child->getNext()) { + if (!SP_IS_STOP(child)) { continue; + } SPStop *stop = SP_STOP (child); offset_h = stop->offset; @@ -714,18 +918,20 @@ sp_tweak_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, - NR::Point p, double radius, double force, + 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; if (SP_IS_GROUP(item)) { - for (SPObject *child = sp_object_first_child(SP_OBJECT(item)) ; child != NULL; child = SP_OBJECT_NEXT(child) ) { + for (SPObject *child = item->firstChild() ; child; child = child->getNext() ) { if (SP_IS_ITEM(child)) { if (sp_tweak_color_recursive (mode, SP_ITEM(child), item_at_point, fill_goal, do_fill, stroke_goal, do_stroke, opacity_goal, do_opacity, + do_blur, reverse, p, radius, force, do_h, do_s, do_l, do_o)) did = true; } @@ -736,15 +942,15 @@ sp_tweak_color_recursive (guint mode, SPItem *item, SPItem *item_at_point, if (!style) { return false; } - boost::optional bbox = item->getBounds(from_2geom(sp_item_i2doc_affine(item)), + Geom::OptRect bbox = item->getBounds(item->i2doc_affine(), SPItem::GEOMETRIC_BBOX); if (!bbox) { return false; } - NR::Rect brush(p - NR::Point(radius, radius), p + NR::Point(radius, radius)); + Geom::Rect brush(p - Geom::Point(radius, radius), p + Geom::Point(radius, radius)); - NR::Point center = bbox->midpoint(); + Geom::Point center = bbox->midpoint(); double this_force; // if item == item_at_point, use max force @@ -760,11 +966,59 @@ sp_tweak_color_recursive (guint mode, SPItem *item, SPItem *item_at_point, // else if object > 0.5 brush: test 4 corners of bbox and center on being in the brush, choose max // else if still smaller, then check only the object center: } else { - this_force = force * tweak_profile (NR::L2 (p - center), radius); + this_force = force * tweak_profile (Geom::L2 (p - center), radius); } if (this_force > 0.002) { + if (do_blur) { + Geom::OptRect bbox = item->getBounds(item->i2doc_affine(), + SPItem::GEOMETRIC_BBOX); + if (!bbox) { + return did; + } + + double blur_now = 0; + Geom::Matrix i2d = item->i2d_affine (); + if (style->filter.set && style->getFilter()) { + //cycle through filter primitives + SPObject *primitive_obj = style->getFilter()->children; + while (primitive_obj) { + if (SP_IS_FILTER_PRIMITIVE(primitive_obj)) { + SPFilterPrimitive *primitive = SP_FILTER_PRIMITIVE(primitive_obj); + //if primitive is gaussianblur + if(SP_IS_GAUSSIANBLUR(primitive)) { + SPGaussianBlur * spblur = SP_GAUSSIANBLUR(primitive); + float num = spblur->stdDeviation.getNumber(); + blur_now += num * i2d.descrim(); // sum all blurs in the filter + } + } + primitive_obj = primitive_obj->next; + } + } + double perimeter = bbox->dimensions()[Geom::X] + bbox->dimensions()[Geom::Y]; + blur_now = blur_now / perimeter; + + double blur_new; + if (reverse) + blur_new = blur_now - 0.06 * force; + else + blur_new = blur_now + 0.06 * force; + if (blur_new < 0.0005 && blur_new < blur_now) { + blur_new = 0; + } + + if (blur_new == 0) { + remove_filter(item, false); + } else { + double radius = blur_new * perimeter; + SPFilter *filter = modify_filter_gaussian_blur_from_item(SP_OBJECT_DOCUMENT(item), item, radius); + + sp_style_set_property_url(item, "filter", filter, false); + } + return true; // do not do colors, blur is a separate mode + } + if (do_fill) { if (style->fill.isPaintserver()) { tweak_colors_in_gradient (item, true, fill_goal, p, radius, this_force, mode, do_h, do_s, do_l, do_o); @@ -796,7 +1050,7 @@ sp_tweak_color_recursive (guint mode, SPItem *item, SPItem *item_at_point, bool -sp_tweak_dilate (SPTweakContext *tc, NR::Point event_p, NR::Point p, NR::Point vector) +sp_tweak_dilate (SPTweakContext *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; @@ -807,18 +1061,52 @@ sp_tweak_dilate (SPTweakContext *tc, NR::Point event_p, NR::Point p, NR::Point v bool did = false; double radius = get_dilate_radius(tc); - double force = get_dilate_force(tc); - if (radius == 0 || force == 0) { - return false; - } - double color_force = MIN(sqrt(force)/20.0, 1); - SPItem *item_at_point = SP_EVENT_CONTEXT(tc)->desktop->item_at_point(event_p, TRUE); + SPItem *item_at_point = SP_EVENT_CONTEXT(tc)->desktop->getItemAtPoint(event_p, TRUE); bool do_fill = false, do_stroke = false, do_opacity = false; - guint32 fill_goal = sp_desktop_get_color_tool(desktop, "tools.tweak", true, &do_fill); - guint32 stroke_goal = sp_desktop_get_color_tool(desktop, "tools.tweak", false, &do_stroke); - double opacity_goal = sp_desktop_get_master_opacity_tool(desktop, "tools.tweak", &do_opacity); + guint32 fill_goal = sp_desktop_get_color_tool(desktop, "/tools/tweak", true, &do_fill); + guint32 stroke_goal = sp_desktop_get_color_tool(desktop, "/tools/tweak", false, &do_stroke); + double opacity_goal = sp_desktop_get_master_opacity_tool(desktop, "/tools/tweak", &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 move_force = get_move_force(tc); + double color_force = MIN(sqrt(path_force)/20.0, 1); for (GSList *items = g_slist_copy((GSList *) selection->itemList()); items != NULL; @@ -826,17 +1114,21 @@ sp_tweak_dilate (SPTweakContext *tc, NR::Point event_p, NR::Point p, NR::Point v SPItem *item = (SPItem *) items->data; - if (tc->mode == TWEAK_MODE_COLORPAINT || tc->mode == TWEAK_MODE_COLORJITTER) { + if (is_color_mode (tc->mode)) { if (do_fill || do_stroke || do_opacity) { if (sp_tweak_color_recursive (tc->mode, item, item_at_point, fill_goal, do_fill, stroke_goal, do_stroke, opacity_goal, do_opacity, + tc->mode == TWEAK_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_mode(tc->mode)) { + if (sp_tweak_dilate_recursive (selection, item, p, vector, tc->mode, radius, move_force, tc->fidelity, reverse)) + did = true; } else { - if (sp_tweak_dilate_recursive (selection, item, p, vector, tc->mode, radius, force, tc->fidelity)) + if (sp_tweak_dilate_recursive (selection, item, p, vector, tc->mode, radius, path_force, tc->fidelity, reverse)) did = true; } } @@ -848,31 +1140,32 @@ void sp_tweak_update_area (SPTweakContext *tc) { double radius = get_dilate_radius(tc); - NR::Matrix const sm (NR::scale(radius, radius) * NR::translate(SP_EVENT_CONTEXT(tc)->desktop->point())); + Geom::Matrix const sm (Geom::Scale(radius, radius) * Geom::Translate(SP_EVENT_CONTEXT(tc)->desktop->point())); sp_canvas_item_affine_absolute(tc->dilate_area, sm); sp_canvas_item_show(tc->dilate_area); } void -sp_tweak_switch_mode (SPTweakContext *tc, gint mode) +sp_tweak_switch_mode (SPTweakContext *tc, gint mode, bool with_shift) { SP_EVENT_CONTEXT(tc)->desktop->setToolboxSelectOneValue ("tweak_tool_mode", mode); // need to set explicitly, because the prefs may not have changed by the previous tc->mode = mode; - sp_tweak_update_cursor (tc, mode); + sp_tweak_update_cursor (tc, with_shift); } void -sp_tweak_switch_mode_temporarily (SPTweakContext *tc, gint mode) +sp_tweak_switch_mode_temporarily (SPTweakContext *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_get_int_attribute("tools.tweak", "mode", 0); + gint now_mode = prefs->getInt("/tools/tweak/mode", 0); SP_EVENT_CONTEXT(tc)->desktop->setToolboxSelectOneValue ("tweak_tool_mode", mode); // button has changed prefs, restore - prefs_set_int_attribute("tools.tweak", "mode", now_mode); + prefs->setInt("/tools/tweak/mode", now_mode); // changing prefs changed tc->mode, restore back :) tc->mode = mode; - sp_tweak_update_cursor (tc, mode); + sp_tweak_update_cursor (tc, with_shift); } gint @@ -898,9 +1191,9 @@ sp_tweak_context_root_handler(SPEventContext *event_context, return TRUE; } - NR::Point const button_w(event->button.x, + Geom::Point const button_w(event->button.x, event->button.y); - NR::Point const button_dt(desktop->w2d(button_w)); + Geom::Point const button_dt(desktop->w2d(button_w)); tc->last_push = desktop->dt2doc(button_dt); sp_tweak_extinput(tc, event); @@ -915,15 +1208,15 @@ sp_tweak_context_root_handler(SPEventContext *event_context, break; case GDK_MOTION_NOTIFY: { - NR::Point const motion_w(event->motion.x, + Geom::Point const motion_w(event->motion.x, event->motion.y); - NR::Point motion_dt(desktop->w2d(motion_w)); - NR::Point motion_doc(desktop->dt2doc(motion_dt)); + Geom::Point motion_dt(desktop->w2d(motion_w)); + Geom::Point motion_doc(desktop->dt2doc(motion_dt)); sp_tweak_extinput(tc, event); // draw the dilating cursor double radius = get_dilate_radius(tc); - NR::Matrix const sm (NR::scale(radius, radius) * NR::translate(desktop->w2d(motion_w))); + Geom::Matrix const sm (Geom::Scale(radius, radius) * Geom::Translate(desktop->w2d(motion_w))); sp_canvas_item_affine_absolute(tc->dilate_area, sm); sp_canvas_item_show(tc->dilate_area); @@ -932,56 +1225,12 @@ sp_tweak_context_root_handler(SPEventContext *event_context, num = g_slist_length((GSList *) desktop->selection->itemList()); } if (num == 0) { - tc->_message_context->set(Inkscape::NORMAL_MESSAGE, _("Nothing selected! Select objects to tweak.")); - } else { - switch (tc->mode) { - case TWEAK_MODE_PUSH: - tc->_message_context->setF(Inkscape::NORMAL_MESSAGE, - ngettext("Pushing %d selected object", - "Pushing %d selected objects", num), num); - break; - case TWEAK_MODE_SHRINK: - tc->_message_context->setF(Inkscape::NORMAL_MESSAGE, - ngettext("Shrinking %d selected object", - "Shrinking %d selected objects", num), num); - break; - case TWEAK_MODE_GROW: - tc->_message_context->setF(Inkscape::NORMAL_MESSAGE, - ngettext("Growing %d selected object", - "Growing %d selected objects", num), num); - break; - case TWEAK_MODE_ATTRACT: - tc->_message_context->setF(Inkscape::NORMAL_MESSAGE, - ngettext("Attracting %d selected object", - "Attracting %d selected objects", num), num); - break; - case TWEAK_MODE_REPEL: - tc->_message_context->setF(Inkscape::NORMAL_MESSAGE, - ngettext("Repelling %d selected object", - "Repelling %d selected objects", num), num); - break; - case TWEAK_MODE_ROUGHEN: - tc->_message_context->setF(Inkscape::NORMAL_MESSAGE, - ngettext("Roughening %d selected object", - "Roughening %d selected objects", num), num); - break; - case TWEAK_MODE_COLORPAINT: - tc->_message_context->setF(Inkscape::NORMAL_MESSAGE, - ngettext("Painting %d selected object", - "Painting %d selected objects", num), num); - break; - case TWEAK_MODE_COLORJITTER: - tc->_message_context->setF(Inkscape::NORMAL_MESSAGE, - ngettext("Jittering colors in %d selected object", - "Jittering colors in %d selected objects", num), num); - break; - } + tc->_message_context->flash(Inkscape::ERROR_MESSAGE, _("Nothing selected! Select objects to tweak.")); } - // dilating: if (tc->is_drawing && ( event->motion.state & GDK_BUTTON1_MASK )) { - sp_tweak_dilate (tc, motion_w, motion_doc, motion_doc - tc->last_push); + sp_tweak_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 @@ -995,8 +1244,8 @@ sp_tweak_context_root_handler(SPEventContext *event_context, case GDK_BUTTON_RELEASE: { - NR::Point const motion_w(event->button.x, event->button.y); - NR::Point const motion_dt(desktop->w2d(motion_w)); + 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; @@ -1005,42 +1254,62 @@ sp_tweak_context_root_handler(SPEventContext *event_context, if (!tc->has_dilated) { // if we did not rub, do a light tap tc->pressure = 0.03; - sp_tweak_dilate (tc, motion_w, desktop->dt2doc(motion_dt), NR::Point(0,0)); + sp_tweak_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 TWEAK_MODE_PUSH: - sp_document_done(sp_desktop_document(SP_EVENT_CONTEXT(tc)->desktop), - SP_VERB_CONTEXT_TWEAK, _("Push tweak")); + case TWEAK_MODE_MOVE: + DocumentUndo::done(sp_desktop_document(SP_EVENT_CONTEXT(tc)->desktop), + SP_VERB_CONTEXT_TWEAK, _("Move tweak")); + break; + case TWEAK_MODE_MOVE_IN_OUT: + DocumentUndo::done(sp_desktop_document(SP_EVENT_CONTEXT(tc)->desktop), + SP_VERB_CONTEXT_TWEAK, _("Move in/out tweak")); break; - case TWEAK_MODE_SHRINK: - sp_document_done(sp_desktop_document(SP_EVENT_CONTEXT(tc)->desktop), - SP_VERB_CONTEXT_TWEAK, _("Shrink tweak")); + case TWEAK_MODE_MOVE_JITTER: + DocumentUndo::done(sp_desktop_document(SP_EVENT_CONTEXT(tc)->desktop), + SP_VERB_CONTEXT_TWEAK, _("Move jitter tweak")); break; - case TWEAK_MODE_GROW: - sp_document_done(sp_desktop_document(SP_EVENT_CONTEXT(tc)->desktop), - SP_VERB_CONTEXT_TWEAK, _("Grow tweak")); + case TWEAK_MODE_SCALE: + DocumentUndo::done(sp_desktop_document(SP_EVENT_CONTEXT(tc)->desktop), + SP_VERB_CONTEXT_TWEAK, _("Scale tweak")); break; - case TWEAK_MODE_ATTRACT: - sp_document_done(sp_desktop_document(SP_EVENT_CONTEXT(tc)->desktop), - SP_VERB_CONTEXT_TWEAK, _("Attract tweak")); + case TWEAK_MODE_ROTATE: + DocumentUndo::done(sp_desktop_document(SP_EVENT_CONTEXT(tc)->desktop), + SP_VERB_CONTEXT_TWEAK, _("Rotate tweak")); + break; + case TWEAK_MODE_MORELESS: + DocumentUndo::done(sp_desktop_document(SP_EVENT_CONTEXT(tc)->desktop), + SP_VERB_CONTEXT_TWEAK, _("Duplicate/delete tweak")); + break; + case TWEAK_MODE_PUSH: + DocumentUndo::done(sp_desktop_document(SP_EVENT_CONTEXT(tc)->desktop), + SP_VERB_CONTEXT_TWEAK, _("Push path tweak")); break; - case TWEAK_MODE_REPEL: - sp_document_done(sp_desktop_document(SP_EVENT_CONTEXT(tc)->desktop), - SP_VERB_CONTEXT_TWEAK, _("Repel tweak")); + case TWEAK_MODE_SHRINK_GROW: + DocumentUndo::done(sp_desktop_document(SP_EVENT_CONTEXT(tc)->desktop), + SP_VERB_CONTEXT_TWEAK, _("Shrink/grow path tweak")); + break; + case TWEAK_MODE_ATTRACT_REPEL: + DocumentUndo::done(sp_desktop_document(SP_EVENT_CONTEXT(tc)->desktop), + SP_VERB_CONTEXT_TWEAK, _("Attract/repel path tweak")); break; case TWEAK_MODE_ROUGHEN: - sp_document_done(sp_desktop_document(SP_EVENT_CONTEXT(tc)->desktop), - SP_VERB_CONTEXT_TWEAK, _("Roughen tweak")); + DocumentUndo::done(sp_desktop_document(SP_EVENT_CONTEXT(tc)->desktop), + SP_VERB_CONTEXT_TWEAK, _("Roughen path tweak")); break; case TWEAK_MODE_COLORPAINT: - sp_document_done(sp_desktop_document(SP_EVENT_CONTEXT(tc)->desktop), - SP_VERB_CONTEXT_TWEAK, _("Color paint tweak")); - break; + DocumentUndo::done(sp_desktop_document(SP_EVENT_CONTEXT(tc)->desktop), + SP_VERB_CONTEXT_TWEAK, _("Color paint tweak")); + break; case TWEAK_MODE_COLORJITTER: - sp_document_done(sp_desktop_document(SP_EVENT_CONTEXT(tc)->desktop), - SP_VERB_CONTEXT_TWEAK, _("Color jitter tweak")); + DocumentUndo::done(sp_desktop_document(SP_EVENT_CONTEXT(tc)->desktop), + SP_VERB_CONTEXT_TWEAK, _("Color jitter tweak")); + break; + case TWEAK_MODE_BLUR: + DocumentUndo::done(sp_desktop_document(SP_EVENT_CONTEXT(tc)->desktop), + SP_VERB_CONTEXT_TWEAK, _("Blur tweak")); break; } } @@ -1049,67 +1318,106 @@ sp_tweak_context_root_handler(SPEventContext *event_context, case GDK_KEY_PRESS: switch (get_group0_keyval (&event->key)) { - case GDK_p: - case GDK_P: + case GDK_m: + case GDK_M: + case GDK_0: + if (MOD__SHIFT_ONLY) { + sp_tweak_switch_mode(tc, TWEAK_MODE_MOVE, MOD__SHIFT); + ret = TRUE; + } + break; + case GDK_i: + case GDK_I: case GDK_1: if (MOD__SHIFT_ONLY) { - sp_tweak_switch_mode(tc, TWEAK_MODE_PUSH); + sp_tweak_switch_mode(tc, TWEAK_MODE_MOVE_IN_OUT, MOD__SHIFT); ret = TRUE; } break; - case GDK_s: - case GDK_S: + case GDK_z: + case GDK_Z: case GDK_2: if (MOD__SHIFT_ONLY) { - sp_tweak_switch_mode(tc, TWEAK_MODE_SHRINK); + sp_tweak_switch_mode(tc, TWEAK_MODE_MOVE_JITTER, MOD__SHIFT); ret = TRUE; } break; - case GDK_g: - case GDK_G: + case GDK_less: + case GDK_comma: + case GDK_greater: + case GDK_period: case GDK_3: if (MOD__SHIFT_ONLY) { - sp_tweak_switch_mode(tc, TWEAK_MODE_GROW); + sp_tweak_switch_mode(tc, TWEAK_MODE_SCALE, MOD__SHIFT); ret = TRUE; } break; - case GDK_a: - case GDK_A: + case GDK_bracketright: + case GDK_bracketleft: case GDK_4: if (MOD__SHIFT_ONLY) { - sp_tweak_switch_mode(tc, TWEAK_MODE_ATTRACT); + sp_tweak_switch_mode(tc, TWEAK_MODE_ROTATE, MOD__SHIFT); ret = TRUE; } break; - case GDK_e: - case GDK_E: + case GDK_d: + case GDK_D: case GDK_5: if (MOD__SHIFT_ONLY) { - sp_tweak_switch_mode(tc, TWEAK_MODE_REPEL); + sp_tweak_switch_mode(tc, TWEAK_MODE_MORELESS, MOD__SHIFT); + ret = TRUE; + } + break; + case GDK_p: + case GDK_P: + case GDK_6: + if (MOD__SHIFT_ONLY) { + sp_tweak_switch_mode(tc, TWEAK_MODE_PUSH, MOD__SHIFT); + ret = TRUE; + } + break; + case GDK_s: + case GDK_S: + case GDK_7: + if (MOD__SHIFT_ONLY) { + sp_tweak_switch_mode(tc, TWEAK_MODE_SHRINK_GROW, MOD__SHIFT); + ret = TRUE; + } + break; + case GDK_a: + case GDK_A: + case GDK_8: + if (MOD__SHIFT_ONLY) { + sp_tweak_switch_mode(tc, TWEAK_MODE_ATTRACT_REPEL, MOD__SHIFT); ret = TRUE; } break; case GDK_r: case GDK_R: - case GDK_6: + case GDK_9: if (MOD__SHIFT_ONLY) { - sp_tweak_switch_mode(tc, TWEAK_MODE_ROUGHEN); + sp_tweak_switch_mode(tc, TWEAK_MODE_ROUGHEN, MOD__SHIFT); ret = TRUE; } break; case GDK_c: case GDK_C: - case GDK_7: if (MOD__SHIFT_ONLY) { - sp_tweak_switch_mode(tc, TWEAK_MODE_COLORPAINT); + sp_tweak_switch_mode(tc, TWEAK_MODE_COLORPAINT, MOD__SHIFT); ret = TRUE; } break; case GDK_j: case GDK_J: - case GDK_8: if (MOD__SHIFT_ONLY) { - sp_tweak_switch_mode(tc, TWEAK_MODE_COLORJITTER); + sp_tweak_switch_mode(tc, TWEAK_MODE_COLORJITTER, MOD__SHIFT); + ret = TRUE; + } + break; + case GDK_b: + case GDK_B: + if (MOD__SHIFT_ONLY) { + sp_tweak_switch_mode(tc, TWEAK_MODE_BLUR, MOD__SHIFT); ret = TRUE; } break; @@ -1178,43 +1486,37 @@ sp_tweak_context_root_handler(SPEventContext *event_context, } break; - case GDK_Control_L: - case GDK_Control_R: - if (MOD__SHIFT) { - sp_tweak_switch_mode_temporarily(tc, TWEAK_MODE_GROW); - } else { - sp_tweak_switch_mode_temporarily(tc, TWEAK_MODE_SHRINK); - } - break; case GDK_Shift_L: case GDK_Shift_R: - if (MOD__CTRL) { - sp_tweak_switch_mode_temporarily(tc, TWEAK_MODE_GROW); - } + sp_tweak_update_cursor(tc, true); + break; + + case GDK_Control_L: + case GDK_Control_R: + sp_tweak_switch_mode_temporarily(tc, TWEAK_MODE_SHRINK_GROW, MOD__SHIFT); break; default: break; } break; - case GDK_KEY_RELEASE: + 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_tweak_update_cursor(tc, false); + break; case GDK_Control_L: case GDK_Control_R: - sp_tweak_switch_mode (tc, prefs_get_int_attribute("tools.tweak", "mode", 0)); + sp_tweak_switch_mode (tc, prefs->getInt("/tools/tweak/mode"), MOD__SHIFT); tc->_message_context->clear(); break; - case GDK_Shift_L: - case GDK_Shift_R: - if (MOD__CTRL) { - sp_tweak_switch_mode_temporarily(tc, TWEAK_MODE_SHRINK); - } - break; - break; default: - sp_tweak_switch_mode (tc, prefs_get_int_attribute("tools.tweak", "mode", 0)); + sp_tweak_switch_mode (tc, prefs->getInt("/tools/tweak/mode"), MOD__SHIFT); break; } + } default: break; @@ -1239,4 +1541,4 @@ sp_tweak_context_root_handler(SPEventContext *event_context, fill-column:99 End: */ -// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 : +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :