tweak-context.cpp revision c0537dcfe264414d52ad86579d57cb0cb2183dcb
096dfde2c1cb7bb1e0a4b76e21f2abf548b900d5Campbell Barton * tweaking paths without node editing
096dfde2c1cb7bb1e0a4b76e21f2abf548b900d5Campbell Barton * Jon A. Cruz <jon@joncruz.org>
096dfde2c1cb7bb1e0a4b76e21f2abf548b900d5Campbell Barton * Abhishek Sharma
096dfde2c1cb7bb1e0a4b76e21f2abf548b900d5Campbell Barton * Copyright (C) 2007 authors
096dfde2c1cb7bb1e0a4b76e21f2abf548b900d5Campbell Barton * Released under GNU GPL, read the file 'COPYING' for more information
#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-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 "preferences.h"
#include "style.h"
#include "box3d.h"
#include "sp-item-transform.h"
#include "filter-chemistry.h"
#include "filters/gaussian-blur.h"
#include "tweak-context.h"
if (!type) {
sizeof(SPTweakContextClass),
sizeof(SPTweakContext),
return type;
return (mode == TWEAK_MODE_COLORPAINT || mode == TWEAK_MODE_COLORJITTER || mode == TWEAK_MODE_BLUR);
sel_message = g_strdup_printf(ngettext("<b>%i</b> object selected","<b>%i</b> objects selected",num), num);
case TWEAK_MODE_MOVE:
case TWEAK_MODE_MOVE_IN_OUT:
tc->_message_context->setF(Inkscape::NORMAL_MESSAGE, _("%s. Drag or click to <b>move in</b>; with Shift to <b>move out</b>."), sel_message);
case TWEAK_MODE_MOVE_JITTER:
tc->_message_context->setF(Inkscape::NORMAL_MESSAGE, _("%s. Drag or click to <b>move randomly</b>."), sel_message);
case TWEAK_MODE_SCALE:
tc->_message_context->setF(Inkscape::NORMAL_MESSAGE, _("%s. Drag or click to <b>scale down</b>; with Shift to <b>scale up</b>."), sel_message);
case TWEAK_MODE_ROTATE:
tc->_message_context->setF(Inkscape::NORMAL_MESSAGE, _("%s. Drag or click to <b>rotate clockwise</b>; with Shift, <b>counterclockwise</b>."), sel_message);
case TWEAK_MODE_MORELESS:
tc->_message_context->setF(Inkscape::NORMAL_MESSAGE, _("%s. Drag or click to <b>duplicate</b>; with Shift, <b>delete</b>."), sel_message);
case TWEAK_MODE_PUSH:
tc->_message_context->setF(Inkscape::NORMAL_MESSAGE, _("%s. Drag to <b>push paths</b>."), sel_message);
case TWEAK_MODE_SHRINK_GROW:
tc->_message_context->setF(Inkscape::NORMAL_MESSAGE, _("%s. Drag or click to <b>inset paths</b>; with Shift to <b>outset</b>."), sel_message);
if (with_shift) {
case TWEAK_MODE_ATTRACT_REPEL:
tc->_message_context->setF(Inkscape::NORMAL_MESSAGE, _("%s. Drag or click to <b>attract paths</b>; with Shift to <b>repel</b>."), sel_message);
if (with_shift) {
case TWEAK_MODE_ROUGHEN:
tc->_message_context->setF(Inkscape::NORMAL_MESSAGE, _("%s. Drag or click to <b>roughen paths</b>."), sel_message);
case TWEAK_MODE_COLORPAINT:
tc->_message_context->setF(Inkscape::NORMAL_MESSAGE, _("%s. Drag or click to <b>paint objects</b> with color."), sel_message);
case TWEAK_MODE_COLORJITTER:
tc->_message_context->setF(Inkscape::NORMAL_MESSAGE, _("%s. Drag or click to <b>randomize colors</b>."), sel_message);
case TWEAK_MODE_BLUR:
tc->_message_context->setF(Inkscape::NORMAL_MESSAGE, _("%s. Drag or click to <b>increase blur</b>; with Shift to <b>decrease</b>."), sel_message);
/* TODO: have a look at sp_dyna_draw_context_setup where the same is done.. generalize? at least make it an arcto! */
c->closepath();
c->unref();
sp_canvas_bpath_set_stroke(SP_CANVAS_BPATH(tc->dilate_area), 0xff9900ff, 1.0, SP_STROKE_LINEJOIN_MITER, SP_STROKE_LINECAP_BUTT);
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_tweak_dilate_recursive (selection, SP_ITEM(child), p, vector, mode, radius, force, fidelity, reverse))
did = true;
if (a->contains(p)) x = 0;
did = true;
if (a->contains(p)) x = 0;
did = true;
if (a->contains(p)) x = 0;
did = true;
if (a->contains(p)) x = 0;
did = true;
if (a->contains(p)) x = 0;
did = true;
if (a->contains(p)) x = 0;
did = true;
if (!newrepr) {
if (bbox) {
bool did_this = false;
did_this = true;
did_this = true;
did_this = true;
did_this = true;
if (did_this) {
if (is_selected) {
if (is_selected)
if (newrepr) {
if (newrepr) {
delete theShape;
delete theRes;
delete orig;
delete res;
if (did_this) {
did = true;
return did;
if (!do_h) {
if (!do_s) {
if (!do_l) {
if (do_h) {
if (hsl_c[0] < 0) {
if (do_s) {
if (do_l) {
if (radius == 0) {
double pos = 0;
Geom::Affine norm = Geom::Affine(Geom::Translate(-p1)) * Geom::Affine(Geom::Rotate(-atan2(pdiff[Geom::Y], pdiff[Geom::X])));
if (pos < 0) {
pos_e = 0;
if (odd) {
double offset_l = 0;
double offset_h = 0;
if (child_prev) {
bool did = false;
did = true;
if (!style) {
if (!bbox) {
double this_force;
if (do_blur) {
if (!bbox) {
return did;
double blur_now = 0;
while (primitive_obj) {
double blur_new;
if (reverse) {
blur_new = 0;
if (blur_new == 0) {
if (do_fill) {
tweak_colors_in_gradient (item, true, fill_goal, p, radius, this_force, mode, do_h, do_s, do_l, do_o);
did = true;
did = true;
if (do_stroke) {
tweak_colors_in_gradient (item, false, stroke_goal, p, radius, this_force, mode, do_h, do_s, do_l, do_o);
did = true;
did = true;
return did;
sp_tweak_dilate (SPTweakContext *tc, Geom::Point event_p, Geom::Point p, Geom::Point vector, bool reverse)
bool did = false;
if (reverse) {
did = true;
if (sp_tweak_dilate_recursive (selection, item, p, vector, tc->mode, radius, move_force, tc->fidelity, reverse)) {
did = true;
if (sp_tweak_dilate_recursive (selection, item, p, vector, tc->mode, radius, path_force, tc->fidelity, reverse)) {
did = true;
return did;
Geom::Affine const sm (Geom::Scale(radius, radius) * Geom::Translate(SP_EVENT_CONTEXT(tc)->desktop->point()));
case GDK_ENTER_NOTIFY:
case GDK_LEAVE_NOTIFY:
case GDK_BUTTON_PRESS:
return TRUE;
case GDK_MOTION_NOTIFY:
if (num == 0) {
tc->_message_context->flash(Inkscape::ERROR_MESSAGE, _("<b>Nothing selected!</b> Select objects to tweak."));
sp_tweak_dilate (tc, motion_w, motion_doc, motion_doc - tc->last_push, event->button.state & GDK_SHIFT_MASK? true : false);
return TRUE;
case GDK_BUTTON_RELEASE:
case TWEAK_MODE_MOVE:
case TWEAK_MODE_MOVE_IN_OUT:
case TWEAK_MODE_MOVE_JITTER:
case TWEAK_MODE_SCALE:
case TWEAK_MODE_ROTATE:
case TWEAK_MODE_MORELESS:
case TWEAK_MODE_PUSH:
case TWEAK_MODE_SHRINK_GROW:
case TWEAK_MODE_ATTRACT_REPEL:
case TWEAK_MODE_ROUGHEN:
case TWEAK_MODE_COLORPAINT:
case TWEAK_MODE_COLORJITTER:
case TWEAK_MODE_BLUR:
case GDK_KEY_PRESS:
case GDK_m:
case GDK_M:
case GDK_0:
if (MOD__SHIFT_ONLY) {
case GDK_i:
case GDK_I:
case GDK_1:
if (MOD__SHIFT_ONLY) {
case GDK_z:
case GDK_Z:
case GDK_2:
if (MOD__SHIFT_ONLY) {
case GDK_less:
case GDK_comma:
case GDK_greater:
case GDK_period:
case GDK_3:
if (MOD__SHIFT_ONLY) {
case GDK_bracketright:
case GDK_bracketleft:
case GDK_4:
if (MOD__SHIFT_ONLY) {
case GDK_d:
case GDK_D:
case GDK_5:
if (MOD__SHIFT_ONLY) {
case GDK_p:
case GDK_P:
case GDK_6:
if (MOD__SHIFT_ONLY) {
case GDK_s:
case GDK_S:
case GDK_7:
if (MOD__SHIFT_ONLY) {
case GDK_a:
case GDK_A:
case GDK_8:
if (MOD__SHIFT_ONLY) {
case GDK_r:
case GDK_R:
case GDK_9:
if (MOD__SHIFT_ONLY) {
case GDK_c:
case GDK_C:
if (MOD__SHIFT_ONLY) {
case GDK_j:
case GDK_J:
if (MOD__SHIFT_ONLY) {
case GDK_b:
case GDK_B:
if (MOD__SHIFT_ONLY) {
case GDK_Up:
case GDK_KP_Up:
if (!MOD__CTRL_ONLY) {
case GDK_Down:
case GDK_KP_Down:
if (!MOD__CTRL_ONLY) {
case GDK_Right:
case GDK_KP_Right:
if (!MOD__CTRL_ONLY) {
desktop->setToolboxAdjustmentValue ("altx-tweak", tc->width * 100); // the same spinbutton is for alt+x
case GDK_Left:
case GDK_KP_Left:
if (!MOD__CTRL_ONLY) {
case GDK_Home:
case GDK_KP_Home:
case GDK_End:
case GDK_KP_End:
case GDK_x:
case GDK_X:
if (MOD__ALT_ONLY) {
case GDK_Shift_L:
case GDK_Shift_R:
case GDK_Control_L:
case GDK_Control_R:
case GDK_KEY_RELEASE: {
case GDK_Shift_L:
case GDK_Shift_R:
case GDK_Control_L:
case GDK_Control_R:
if (!ret) {
return ret;