From 19b7109971d305f262abb99c776a32206d8cfedd Mon Sep 17 00:00:00 2001 From: Krzysztof Kosi??ski Date: Thu, 14 Jan 2010 10:31:02 +0100 Subject: Do not append a segment when finishing an open path with right click in the pen tool. Fixed bugs: - https://launchpad.net/bugs/208768 (bzr r8975) --- src/pen-context.cpp | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) (limited to 'src/pen-context.cpp') diff --git a/src/pen-context.cpp b/src/pen-context.cpp index 144717332..a717537ab 100644 --- a/src/pen-context.cpp +++ b/src/pen-context.cpp @@ -557,20 +557,22 @@ static gint pen_handle_button_press(SPPenContext *const pc, GdkEventButton const default: break; } - } else if (bevent.button == 3 || pc->expecting_clicks_for_LPE == 1) { // when the last click for a waiting LPE occurs we want to finish the path - if (pc->npoints != 0) { - - spdc_pen_finish_segment(pc, event_dt, bevent.state); - if (pc->green_closed) { - // finishing at the start anchor, close curve - spdc_pen_finish(pc, TRUE); - } else { - // finishing at some other anchor, finish curve but not close - spdc_pen_finish(pc, FALSE); - } - - ret = TRUE; + } else if (pc->expecting_clicks_for_LPE == 1 && pc->npoints != 0) { + // when the last click for a waiting LPE occurs we want to finish the path + spdc_pen_finish_segment(pc, event_dt, bevent.state); + if (pc->green_closed) { + // finishing at the start anchor, close curve + spdc_pen_finish(pc, TRUE); + } else { + // finishing at some other anchor, finish curve but not close + spdc_pen_finish(pc, FALSE); } + + ret = TRUE; + } else if (bevent.button == 3 && pc->npoints != 0) { + // right click - finish path + spdc_pen_finish(pc, FALSE); + ret = TRUE; } if (pc->expecting_clicks_for_LPE > 0) { -- cgit v1.2.3 From c4aa590bedcf358acf15bdf0d8134ae99e3be167 Mon Sep 17 00:00:00 2001 From: Diederik van Lierop Date: Sat, 23 Jan 2010 14:36:56 +0100 Subject: Remove redundancy from snapping API (type of snapsource no longer has to be specified explicitly) (bzr r9014) --- src/pen-context.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'src/pen-context.cpp') diff --git a/src/pen-context.cpp b/src/pen-context.cpp index a717537ab..b71bc2e54 100644 --- a/src/pen-context.cpp +++ b/src/pen-context.cpp @@ -468,14 +468,14 @@ static gint pen_handle_button_press(SPPenContext *const pc, GdkEventButton const case SP_PEN_CONTEXT_POINT: if (pc->npoints == 0) { - Geom::Point p; + Geom::Point p; if ((bevent.state & GDK_CONTROL_MASK) && (pc->polylines_only || pc->polylines_paraxial)) { - p = event_dt; - if (!(bevent.state & GDK_SHIFT_MASK)) { - SnapManager &m = desktop->namedview->snap_manager; - m.setup(desktop); - m.freeSnapReturnByRef(Inkscape::SnapPreferences::SNAPPOINT_NODE, p, Inkscape::SNAPSOURCE_HANDLE); - } + p = event_dt; + if (!(bevent.state & GDK_SHIFT_MASK)) { + SnapManager &m = desktop->namedview->snap_manager; + m.setup(desktop); + m.freeSnapReturnByRef(p, Inkscape::SNAPSOURCE_NODE_HANDLE); + } spdc_create_single_dot(event_context, p, "/tools/freehand/pen", bevent.state); ret = TRUE; break; @@ -970,7 +970,7 @@ static gint pen_handle_key_press(SPPenContext *const pc, GdkEvent *event) { - gint ret = FALSE; + gint ret = FALSE; Inkscape::Preferences *prefs = Inkscape::Preferences::get(); gdouble const nudge = prefs->getDoubleLimited("/options/nudgedistance/value", 2, 0, 1000); // in px -- cgit v1.2.3 From e52fb9fac3f1bbd924c0ca3b6b5e214a095d44af Mon Sep 17 00:00:00 2001 From: Diederik van Lierop Date: Sat, 30 Jan 2010 23:04:33 +0100 Subject: Finally introducing the pre-snap indicator (bzr r9034) --- src/pen-context.cpp | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) (limited to 'src/pen-context.cpp') diff --git a/src/pen-context.cpp b/src/pen-context.cpp index b71bc2e54..9cf4d5420 100644 --- a/src/pen-context.cpp +++ b/src/pen-context.cpp @@ -469,7 +469,7 @@ static gint pen_handle_button_press(SPPenContext *const pc, GdkEventButton const if (pc->npoints == 0) { Geom::Point p; - if ((bevent.state & GDK_CONTROL_MASK) && (pc->polylines_only || pc->polylines_paraxial)) { + if ((bevent.state & GDK_CONTROL_MASK) && (pc->polylines_only || pc->polylines_paraxial)) { p = event_dt; if (!(bevent.state & GDK_SHIFT_MASK)) { SnapManager &m = desktop->namedview->snap_manager; @@ -479,7 +479,7 @@ static gint pen_handle_button_press(SPPenContext *const pc, GdkEventButton const spdc_create_single_dot(event_context, p, "/tools/freehand/pen", bevent.state); ret = TRUE; break; - } + } // TODO: Perhaps it would be nicer to rearrange the following case // distinction so that the case of a waiting LPE is treated separately @@ -632,6 +632,10 @@ pen_handle_motion_notify(SPPenContext *const pc, GdkEventMotion const &mevent) spdc_endpoint_snap(pc, p, mevent.state); spdc_pen_set_subsequent_point(pc, p, true); ret = TRUE; + } else if (sp_event_context_knot_mouseover(pc)) { + SnapManager &m = dt->namedview->snap_manager; + m.setup(dt); + m.preSnap(Inkscape::SnapCandidatePoint(p, Inkscape::SNAPSOURCE_NODE_HANDLE)); } break; case SP_PEN_CONTEXT_CONTROL: @@ -677,6 +681,11 @@ pen_handle_motion_notify(SPPenContext *const pc, GdkEventMotion const &mevent) pc->_message_context->clear(); pc->anchor_statusbar = false; } + if (sp_event_context_knot_mouseover(pc)) { + SnapManager &m = dt->namedview->snap_manager; + m.setup(dt); + m.preSnap(Inkscape::SnapCandidatePoint(p, Inkscape::SNAPSOURCE_NODE_HANDLE)); + } } break; case SP_PEN_CONTEXT_CONTROL: @@ -698,6 +707,11 @@ pen_handle_motion_notify(SPPenContext *const pc, GdkEventMotion const &mevent) /* This is perfectly valid */ break; default: + if (sp_event_context_knot_mouseover(pc)) { + SnapManager &m = dt->namedview->snap_manager; + m.setup(dt); + m.preSnap(Inkscape::SnapCandidatePoint(p, Inkscape::SNAPSOURCE_NODE_HANDLE)); + } break; } break; -- cgit v1.2.3 From 195208c56145d9b9673aff0bb2f8795f5bc6fe22 Mon Sep 17 00:00:00 2001 From: Diederik van Lierop Date: Sat, 6 Feb 2010 15:59:28 +0100 Subject: Tiny bit of refactoring (inverting some logic) (bzr r9059) --- src/pen-context.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/pen-context.cpp') diff --git a/src/pen-context.cpp b/src/pen-context.cpp index 9cf4d5420..74c402c42 100644 --- a/src/pen-context.cpp +++ b/src/pen-context.cpp @@ -632,7 +632,7 @@ pen_handle_motion_notify(SPPenContext *const pc, GdkEventMotion const &mevent) spdc_endpoint_snap(pc, p, mevent.state); spdc_pen_set_subsequent_point(pc, p, true); ret = TRUE; - } else if (sp_event_context_knot_mouseover(pc)) { + } else if (!sp_event_context_knot_mouseover(pc)) { SnapManager &m = dt->namedview->snap_manager; m.setup(dt); m.preSnap(Inkscape::SnapCandidatePoint(p, Inkscape::SNAPSOURCE_NODE_HANDLE)); @@ -681,7 +681,7 @@ pen_handle_motion_notify(SPPenContext *const pc, GdkEventMotion const &mevent) pc->_message_context->clear(); pc->anchor_statusbar = false; } - if (sp_event_context_knot_mouseover(pc)) { + if (!sp_event_context_knot_mouseover(pc)) { SnapManager &m = dt->namedview->snap_manager; m.setup(dt); m.preSnap(Inkscape::SnapCandidatePoint(p, Inkscape::SNAPSOURCE_NODE_HANDLE)); @@ -707,7 +707,7 @@ pen_handle_motion_notify(SPPenContext *const pc, GdkEventMotion const &mevent) /* This is perfectly valid */ break; default: - if (sp_event_context_knot_mouseover(pc)) { + if (!sp_event_context_knot_mouseover(pc)) { SnapManager &m = dt->namedview->snap_manager; m.setup(dt); m.preSnap(Inkscape::SnapCandidatePoint(p, Inkscape::SNAPSOURCE_NODE_HANDLE)); -- cgit v1.2.3 From 76e1015affb07da45fb04e3f7a5a6d9d7c5a272c Mon Sep 17 00:00:00 2001 From: Diederik van Lierop Date: Mon, 22 Feb 2010 23:18:29 +0100 Subject: 1) Making snapping behaviour for paraxial lines (in the pen tool) similar to other tools 2) Always apply the constraint when asking for a constrained snap 3) Show snap indicator when applying a constraint (bzr r9105) --- src/pen-context.cpp | 54 ++++++++++++++++++++++++++++++++--------------------- 1 file changed, 33 insertions(+), 21 deletions(-) (limited to 'src/pen-context.cpp') diff --git a/src/pen-context.cpp b/src/pen-context.cpp index 74c402c42..bb52b1950 100644 --- a/src/pen-context.cpp +++ b/src/pen-context.cpp @@ -76,7 +76,7 @@ static bool pen_within_tolerance = false; static SPDrawContextClass *pen_parent_class; static int pen_next_paraxial_direction(const SPPenContext *const pc, Geom::Point const &pt, Geom::Point const &origin, guint state); -static void pen_set_to_nearest_horiz_vert(const SPPenContext *const pc, Geom::Point &pt, guint const state); +static void pen_set_to_nearest_horiz_vert(const SPPenContext *const pc, Geom::Point &pt, guint const state, bool snap); static int pen_last_paraxial_dir = 0; // last used direction in horizontal/vertical mode; 0 = horizontal, 1 = vertical @@ -298,21 +298,22 @@ sp_pen_context_set(SPEventContext *ec, Inkscape::Preferences::Entry *val) static void spdc_endpoint_snap(SPPenContext const *const pc, Geom::Point &p, guint const state) { - if ((state & GDK_CONTROL_MASK)) { //CTRL enables angular snapping + if ((state & GDK_CONTROL_MASK) && !pc->polylines_paraxial) { //CTRL enables angular snapping if (pc->npoints > 0) { spdc_endpoint_snap_rotation(pc, p, pc->p[0], state); } } else { - if (!(state & GDK_SHIFT_MASK)) { //SHIFT disables all snapping, except the angular snapping above - //After all, the user explicitely asked for angular snapping by - //pressing CTRL + // We cannot use shift here to disable snapping because the shift-key is already used + // to toggle the paraxial direction; if the user wants to disable snapping (s)he will + // have to use the %-key, the menu, or the snap toolbar + if ((pc->npoints > 0) && pc->polylines_paraxial) { + // snap constrained + pen_set_to_nearest_horiz_vert(pc, p, state, true); + } else { + // snap freely spdc_endpoint_snap_free(pc, p, state); } } - if (pc->polylines_paraxial) { - // TODO: must we avoid one of the snaps in the previous case distinction in some situations? - pen_set_to_nearest_horiz_vert(pc, p, state); - } } /** @@ -507,11 +508,7 @@ static gint pen_handle_button_press(SPPenContext *const pc, GdkEventButton const /* Create green anchor */ p = event_dt; - if (!pc->polylines_paraxial) { - // only snap the starting point if we're not in horizontal/vertical mode - // because otherwise it gets shifted; TODO: why do we snap here at all?? - spdc_endpoint_snap(pc, p, bevent.state); - } + spdc_endpoint_snap(pc, p, bevent.state); pc->green_anchor = sp_draw_anchor_new(pc, pc->green_curve, TRUE, p); } spdc_pen_set_initial_point(pc, p); @@ -1259,7 +1256,7 @@ spdc_pen_set_subsequent_point(SPPenContext *const pc, Geom::Point const p, bool if (pc->polylines_paraxial && !statusbar) { // we are drawing horizontal/vertical lines and hit an anchor; draw an L-shaped path Geom::Point intermed = p; - pen_set_to_nearest_horiz_vert(pc, intermed, status); + pen_set_to_nearest_horiz_vert(pc, intermed, status, false); pc->red_curve->lineto(intermed); pc->red_curve->lineto(p); is_curve = false; @@ -1446,18 +1443,33 @@ static int pen_next_paraxial_direction(const SPPenContext *const pc, } } -void pen_set_to_nearest_horiz_vert(const SPPenContext *const pc, Geom::Point &pt, guint const state) +void pen_set_to_nearest_horiz_vert(const SPPenContext *const pc, Geom::Point &pt, guint const state, bool snap) { Geom::Point const &origin = pc->p[0]; int next_dir = pen_next_paraxial_direction(pc, pt, origin, state); - if (next_dir == 0) { - // line is forced to be horizontal - pt[Geom::Y] = origin[Geom::Y]; + if (!snap) { + if (next_dir == 0) { + // line is forced to be horizontal + pt[Geom::Y] = origin[Geom::Y]; + } else { + // line is forced to be vertical + pt[Geom::X] = origin[Geom::X]; + } } else { - // line is forced to be vertical - pt[Geom::X] = origin[Geom::X]; + // Create a horizontal or vertical constraint line + Inkscape::Snapper::ConstraintLine cl(origin, next_dir ? Geom::Point(0, 1) : Geom::Point(1, 0)); + + // Snap along the constraint line; if we didn't snap then still the constraint will be applied + SnapManager &m = pc->desktop->namedview->snap_manager; + + Inkscape::Selection *selection = sp_desktop_selection (pc->desktop); + // selection->singleItem() is the item that is currently being drawn. This item will not be snapped to (to avoid self-snapping) + // TODO: Allow snapping to the stationary parts of the item, and only ignore the last segment + + m.setup(pc->desktop, true, selection->singleItem()); + m.constrainedSnapReturnByRef(pt, Inkscape::SNAPSOURCE_NODE_HANDLE, cl); } } -- cgit v1.2.3 From a202fbbd5f6368a096e056d05bbd53b77ad753c6 Mon Sep 17 00:00:00 2001 From: Diederik van Lierop Date: Tue, 23 Feb 2010 21:47:07 +0100 Subject: Pen tool in paraxial mode: fix automatic orientation of first line segment Fixed bugs: - https://launchpad.net/bugs/522335 (bzr r9108) --- src/pen-context.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'src/pen-context.cpp') diff --git a/src/pen-context.cpp b/src/pen-context.cpp index bb52b1950..6e545be9d 100644 --- a/src/pen-context.cpp +++ b/src/pen-context.cpp @@ -1331,6 +1331,7 @@ spdc_pen_finish_segment(SPPenContext *const pc, Geom::Point const p, guint const if (pc->polylines_paraxial) { pen_last_paraxial_dir = pen_next_paraxial_direction(pc, p, pc->p[0], state); } + ++pc->num_clicks; if (!pc->red_curve->is_empty()) { @@ -1430,7 +1431,11 @@ static int pen_next_paraxial_direction(const SPPenContext *const pc, * horizontal or vertical segment; for all subsequent mouse clicks, we use the direction * orthogonal to the last one; pressing Shift toggles the direction */ - if (pc->num_clicks == 0) { + // num_clicks is not reliable because spdc_pen_finish_segment is sometimes called too early + // (on first mouse release), in which case num_clicks immediately becomes 1. + // if (pc->num_clicks == 0) { + + if (pc->green_curve->is_empty()) { // first mouse click double dist_h = fabs(pt[Geom::X] - origin[Geom::X]); double dist_v = fabs(pt[Geom::Y] - origin[Geom::Y]); -- cgit v1.2.3 From 5eb162caff84f49dc1895dee3a0ed3f2ccc83611 Mon Sep 17 00:00:00 2001 From: Diederik van Lierop Date: Sat, 27 Feb 2010 21:53:58 +0100 Subject: Pen tool in paraxial mode: Fix automatic selection of the correct paraxial direction after deleting the last node (bzr r9116) --- src/pen-context.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src/pen-context.cpp') diff --git a/src/pen-context.cpp b/src/pen-context.cpp index 6e545be9d..30c1e0ea9 100644 --- a/src/pen-context.cpp +++ b/src/pen-context.cpp @@ -1169,6 +1169,7 @@ pen_handle_key_press(SPPenContext *const pc, GdkEvent *event) sp_canvas_item_hide(pc->cl1); pc->state = SP_PEN_CONTEXT_POINT; spdc_pen_set_subsequent_point(pc, pt, true); + pen_last_paraxial_dir = !pen_last_paraxial_dir; ret = TRUE; } break; -- cgit v1.2.3 From 761a833eef65ccb005b8210085430673f8d8870a Mon Sep 17 00:00:00 2001 From: Diederik van Lierop Date: Sun, 28 Feb 2010 15:29:57 +0100 Subject: Pen context, paraxial mode: don't add a L-shaped path to close the shape when the nodes are already perfectly aligned (e.g. due to snapping to a grid) (bzr r9117) --- src/pen-context.cpp | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) (limited to 'src/pen-context.cpp') diff --git a/src/pen-context.cpp b/src/pen-context.cpp index 30c1e0ea9..5b9f6808a 100644 --- a/src/pen-context.cpp +++ b/src/pen-context.cpp @@ -657,10 +657,11 @@ pen_handle_motion_notify(SPPenContext *const pc, GdkEventMotion const &mevent) if (!anchor) { /* Snap node only if not hitting anchor */ spdc_endpoint_snap(pc, p, mevent.state); + spdc_pen_set_subsequent_point(pc, p, true, mevent.state); + } else { + spdc_pen_set_subsequent_point(pc, anchor->dp, false, mevent.state); } - spdc_pen_set_subsequent_point(pc, p, !anchor, mevent.state); - if (anchor && !pc->anchor_statusbar) { pc->_message_context->set(Inkscape::NORMAL_MESSAGE, _("Click or click and drag to close and finish the path.")); pc->anchor_statusbar = true; @@ -1255,16 +1256,20 @@ spdc_pen_set_subsequent_point(SPPenContext *const pc, Geom::Point const p, bool bool is_curve; pc->red_curve->moveto(pc->p[0]); if (pc->polylines_paraxial && !statusbar) { - // we are drawing horizontal/vertical lines and hit an anchor; draw an L-shaped path - Geom::Point intermed = p; - pen_set_to_nearest_horiz_vert(pc, intermed, status, false); - pc->red_curve->lineto(intermed); + // we are drawing horizontal/vertical lines and hit an anchor; + Geom::Point const origin = pc->p[0]; + // if the previous point and the anchor are not aligned either horizontally or vertically... + if ((abs(p[Geom::X] - origin[Geom::X]) > 1e-9) && (abs(p[Geom::Y] - origin[Geom::Y]) > 1e-9)) { + // ...then we should draw an L-shaped path, consisting of two paraxial segments + Geom::Point intermed = p; + pen_set_to_nearest_horiz_vert(pc, intermed, status, false); + pc->red_curve->lineto(intermed); + } pc->red_curve->lineto(p); is_curve = false; } else { // one of the 'regular' modes - if (pc->p[1] != pc->p[0]) - { + if (pc->p[1] != pc->p[0]) { pc->red_curve->curveto(pc->p[1], p, p); is_curve = true; } else { @@ -1451,7 +1456,7 @@ static int pen_next_paraxial_direction(const SPPenContext *const pc, void pen_set_to_nearest_horiz_vert(const SPPenContext *const pc, Geom::Point &pt, guint const state, bool snap) { - Geom::Point const &origin = pc->p[0]; + Geom::Point const origin = pc->p[0]; int next_dir = pen_next_paraxial_direction(pc, pt, origin, state); -- cgit v1.2.3