summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorDiederik van Lierop <mailat-signdiedenrezidotnl>2010-01-30 22:04:33 +0000
committerDiederik van Lierop <mailat-signdiedenrezidotnl>2010-01-30 22:04:33 +0000
commite52fb9fac3f1bbd924c0ca3b6b5e214a095d44af (patch)
tree05abc6241c288c5adf39733b914059e393f2fc75 /src
parentReally fix btool build. (diff)
downloadinkscape-e52fb9fac3f1bbd924c0ca3b6b5e214a095d44af.tar.gz
inkscape-e52fb9fac3f1bbd924c0ca3b6b5e214a095d44af.zip
Finally introducing the pre-snap indicator
(bzr r9034)
Diffstat (limited to 'src')
-rw-r--r--src/arc-context.cpp57
-rw-r--r--src/box3d-context.cpp11
-rw-r--r--src/connector-context.cpp3
-rw-r--r--src/display/snap-indicator.cpp13
-rw-r--r--src/display/snap-indicator.h2
-rw-r--r--src/event-context.cpp10
-rw-r--r--src/event-context.h1
-rw-r--r--src/gradient-context.cpp9
-rw-r--r--src/knot.cpp112
-rw-r--r--src/knotholder.cpp15
-rw-r--r--src/knotholder.h2
-rw-r--r--src/object-edit.cpp86
-rw-r--r--src/pen-context.cpp18
-rw-r--r--src/pencil-context.cpp7
-rw-r--r--src/rect-context.cpp7
-rw-r--r--src/shape-editor.cpp10
-rw-r--r--src/shape-editor.h2
-rw-r--r--src/snap.cpp16
-rw-r--r--src/snap.h2
-rw-r--r--src/spiral-context.cpp7
-rw-r--r--src/star-context.cpp29
-rw-r--r--src/star-context.h30
22 files changed, 289 insertions, 160 deletions
diff --git a/src/arc-context.cpp b/src/arc-context.cpp
index 9cb6e8222..ccaaedd14 100644
--- a/src/arc-context.cpp
+++ b/src/arc-context.cpp
@@ -116,15 +116,15 @@ static void sp_arc_context_init(SPArcContext *arc_context)
static void sp_arc_context_finish(SPEventContext *ec)
{
SPArcContext *ac = SP_ARC_CONTEXT(ec);
- SPDesktop *desktop = ec->desktop;
+ SPDesktop *desktop = ec->desktop;
- sp_canvas_item_ungrab(SP_CANVAS_ITEM(desktop->acetate), GDK_CURRENT_TIME);
- sp_arc_finish(ac);
+ sp_canvas_item_ungrab(SP_CANVAS_ITEM(desktop->acetate), GDK_CURRENT_TIME);
+ sp_arc_finish(ac);
ac->sel_changed_connection.disconnect();
if (((SPEventContextClass *) parent_class)->finish) {
- ((SPEventContextClass *) parent_class)->finish(ec);
- }
+ ((SPEventContextClass *) parent_class)->finish(ec);
+ }
}
static void sp_arc_context_dispose(GObject *object)
@@ -274,6 +274,13 @@ static gint sp_arc_context_root_handler(SPEventContext *event_context, GdkEvent
gobble_motion_events(GDK_BUTTON1_MASK);
ret = TRUE;
+ } else if (sp_event_context_knot_mouseover(ac)){
+ SnapManager &m = desktop->namedview->snap_manager;
+ m.setup(desktop);
+
+ Geom::Point const motion_w(event->motion.x, event->motion.y);
+ Geom::Point motion_dt(desktop->w2d(motion_w));
+ m.preSnap(Inkscape::SnapCandidatePoint(motion_dt, Inkscape::SNAPSOURCE_NODE_HANDLE));
}
break;
case GDK_BUTTON_RELEASE:
@@ -283,7 +290,7 @@ static gint sp_arc_context_root_handler(SPEventContext *event_context, GdkEvent
sp_event_context_discard_delayed_snap_event(event_context);
if (!event_context->within_tolerance) {
// we've been dragging, finish the arc
- sp_arc_finish(ac);
+ sp_arc_finish(ac);
} else if (event_context->item_to_select) {
// no dragging, select clicked item if any
if (event->button.state & GDK_SHIFT_MASK) {
@@ -335,14 +342,14 @@ static gint sp_arc_context_root_handler(SPEventContext *event_context, GdkEvent
}
break;
case GDK_Escape:
- if (dragging) {
- dragging = false;
- sp_event_context_discard_delayed_snap_event(event_context);
- // if drawing, cancel, otherwise pass it up for deselecting
- sp_arc_cancel(ac);
- ret = TRUE;
- }
- break;
+ if (dragging) {
+ dragging = false;
+ sp_event_context_discard_delayed_snap_event(event_context);
+ // if drawing, cancel, otherwise pass it up for deselecting
+ sp_arc_cancel(ac);
+ ret = TRUE;
+ }
+ break;
case GDK_space:
if (dragging) {
sp_canvas_item_ungrab(SP_CANVAS_ITEM(desktop->acetate),
@@ -480,13 +487,13 @@ static void sp_arc_finish(SPArcContext *ac)
if (ac->item != NULL) {
- SPGenericEllipse *ge = SP_GENERICELLIPSE(SP_ARC(ac->item));
- if (ge->rx.computed == 0 || ge->ry.computed == 0) {
- sp_arc_cancel(ac); // Don't allow the creating of zero sized arc, for example when the start and and point snap to the snap grid point
- return;
- }
+ SPGenericEllipse *ge = SP_GENERICELLIPSE(SP_ARC(ac->item));
+ if (ge->rx.computed == 0 || ge->ry.computed == 0) {
+ sp_arc_cancel(ac); // Don't allow the creating of zero sized arc, for example when the start and and point snap to the snap grid point
+ return;
+ }
- SPDesktop *desktop = SP_EVENT_CONTEXT(ac)->desktop;
+ SPDesktop *desktop = SP_EVENT_CONTEXT(ac)->desktop;
SP_OBJECT(ac->item)->updateRepr();
@@ -502,14 +509,14 @@ static void sp_arc_finish(SPArcContext *ac)
static void sp_arc_cancel(SPArcContext *ac)
{
- SPDesktop *desktop = SP_EVENT_CONTEXT(ac)->desktop;
+ SPDesktop *desktop = SP_EVENT_CONTEXT(ac)->desktop;
- sp_desktop_selection(desktop)->clear();
- sp_canvas_item_ungrab(SP_CANVAS_ITEM(desktop->acetate), 0);
+ sp_desktop_selection(desktop)->clear();
+ sp_canvas_item_ungrab(SP_CANVAS_ITEM(desktop->acetate), 0);
if (ac->item != NULL) {
- SP_OBJECT(ac->item)->deleteObject();
- ac->item = NULL;
+ SP_OBJECT(ac->item)->deleteObject();
+ ac->item = NULL;
}
ac->within_tolerance = false;
diff --git a/src/box3d-context.cpp b/src/box3d-context.cpp
index ad9c51f0f..bf9bd7b6f 100644
--- a/src/box3d-context.cpp
+++ b/src/box3d-context.cpp
@@ -358,8 +358,8 @@ static gint sp_box3d_context_root_handler(SPEventContext *event_context, GdkEven
}
if (!bc->extruded) {
- bc->drag_ptB = from_2geom(motion_dt);
- bc->drag_ptC = from_2geom(motion_dt);
+ bc->drag_ptB = from_2geom(motion_dt);
+ bc->drag_ptC = from_2geom(motion_dt);
bc->drag_ptB_proj = cur_persp->perspective_impl->tmat.preimage (from_2geom(motion_dt), 0, Proj::Z);
bc->drag_ptC_proj = bc->drag_ptB_proj;
@@ -387,6 +387,13 @@ static gint sp_box3d_context_root_handler(SPEventContext *event_context, GdkEven
sp_box3d_drag(*bc, event->motion.state);
ret = TRUE;
+ } else if (sp_event_context_knot_mouseover(bc)) {
+ SnapManager &m = desktop->namedview->snap_manager;
+ m.setup(desktop);
+
+ Geom::Point const motion_w(event->motion.x, event->motion.y);
+ Geom::Point motion_dt(desktop->w2d(motion_w));
+ m.preSnap(Inkscape::SnapCandidatePoint(motion_dt, Inkscape::SNAPSOURCE_NODE_HANDLE));
}
break;
case GDK_BUTTON_RELEASE:
diff --git a/src/connector-context.cpp b/src/connector-context.cpp
index bfdef1032..294e129b3 100644
--- a/src/connector-context.cpp
+++ b/src/connector-context.cpp
@@ -976,6 +976,9 @@ connector_handle_motion_notify(SPConnectorContext *const cc, GdkEventMotion cons
/* This is perfectly valid */
break;
default:
+ if (sp_event_context_knot_mouseover(cc)) {
+ m.preSnap(Inkscape::SnapCandidatePoint(p, Inkscape::SNAPSOURCE_OTHER_HANDLE));
+ }
break;
}
}
diff --git a/src/display/snap-indicator.cpp b/src/display/snap-indicator.cpp
index dd80524f1..b135dd9fe 100644
--- a/src/display/snap-indicator.cpp
+++ b/src/display/snap-indicator.cpp
@@ -43,7 +43,7 @@ SnapIndicator::~SnapIndicator()
}
void
-SnapIndicator::set_new_snaptarget(Inkscape::SnappedPoint const &p)
+SnapIndicator::set_new_snaptarget(Inkscape::SnappedPoint const &p, bool pre_snap)
{
remove_snaptarget(); //only display one snaptarget at a time
@@ -220,7 +220,7 @@ SnapIndicator::set_new_snaptarget(Inkscape::SnappedPoint const &p)
"anchor", GTK_ANCHOR_CENTER,
"size", 10.0,
"stroked", TRUE,
- "stroke_color", 0xff0000ff,
+ "stroke_color", pre_snap ? 0x7f7f7fff : 0xff0000ff,
"mode", SP_KNOT_MODE_XOR,
"shape", SP_KNOT_SHAPE_DIAMOND,
NULL );
@@ -230,7 +230,7 @@ SnapIndicator::set_new_snaptarget(Inkscape::SnappedPoint const &p)
"anchor", GTK_ANCHOR_CENTER,
"size", 10.0,
"stroked", TRUE,
- "stroke_color", 0xff0000ff,
+ "stroke_color", pre_snap ? 0x7f7f7fff : 0xff0000ff,
"mode", SP_KNOT_MODE_XOR,
"shape", SP_KNOT_SHAPE_CROSS,
NULL );
@@ -241,15 +241,20 @@ SnapIndicator::set_new_snaptarget(Inkscape::SnappedPoint const &p)
SP_CTRL(canvasitem)->moveto(p.getPoint());
_snaptarget = _desktop->add_temporary_canvasitem(canvasitem, timeout_val);
+ // Display the tooltip, which reveals the type of snap source and the type of snap target
gchar *tooltip_str = g_strconcat(source_name, _(" to "), target_name, NULL);
Geom::Point tooltip_pos = p.getPoint() + _desktop->w2d(Geom::Point(15, -15));
SPCanvasItem *canvas_tooltip = sp_canvastext_new(sp_desktop_tempgroup(_desktop), _desktop, tooltip_pos, tooltip_str);
+ if (pre_snap) {
+ SP_CANVASTEXT(canvas_tooltip)->rgba = 0x7f7f7fff;
+ }
g_free(tooltip_str);
sp_canvastext_set_anchor((SPCanvasText* )canvas_tooltip, -1, 1);
_snaptarget_tooltip = _desktop->add_temporary_canvasitem(canvas_tooltip, timeout_val);
+ // Display the bounding box, if we snapped to one
Geom::OptRect const bbox = p.getTargetBBox();
if (bbox) {
SPCanvasItem* box = sp_canvas_item_new(sp_desktop_tempgroup (_desktop),
@@ -257,7 +262,7 @@ SnapIndicator::set_new_snaptarget(Inkscape::SnappedPoint const &p)
NULL);
SP_CTRLRECT(box)->setRectangle(*bbox);
- SP_CTRLRECT(box)->setColor(0xff0000ff, 0, 0);
+ SP_CTRLRECT(box)->setColor(pre_snap ? 0x7f7f7fff : 0xff0000ff, 0, 0);
SP_CTRLRECT(box)->setDashed(true);
sp_canvas_item_move_to_z(box, 0);
_snaptarget_bbox = _desktop->add_temporary_canvasitem(box, timeout_val);
diff --git a/src/display/snap-indicator.h b/src/display/snap-indicator.h
index feb118baa..259af8ae6 100644
--- a/src/display/snap-indicator.h
+++ b/src/display/snap-indicator.h
@@ -26,7 +26,7 @@ public:
SnapIndicator(SPDesktop *desktop);
virtual ~SnapIndicator();
- void set_new_snaptarget(Inkscape::SnappedPoint const &p);
+ void set_new_snaptarget(Inkscape::SnappedPoint const &p, bool pre_snap = false);
void remove_snaptarget();
void set_new_snapsource(Inkscape::SnapCandidatePoint const &p);
diff --git a/src/event-context.cpp b/src/event-context.cpp
index 5592741d9..1e47b9d9d 100644
--- a/src/event-context.cpp
+++ b/src/event-context.cpp
@@ -58,6 +58,7 @@
#include "selcue.h"
#include "lpe-tool-context.h"
#include "ui/tool/control-point.h"
+#include "shape-editor.h"
static void sp_event_context_class_init(SPEventContextClass *klass);
static void sp_event_context_init(SPEventContext *event_context);
@@ -743,6 +744,15 @@ gint sp_event_context_private_item_handler(SPEventContext *ec, SPItem *item,
return ret;
}
+bool sp_event_context_knot_mouseover(SPEventContext *ec)
+{
+ if (ec->shape_editor) {
+ return !(ec->shape_editor->knot_mouseover());
+ }
+
+ return false;
+}
+
/**
* @brief An observer that relays pref changes to the derived classes
*/
diff --git a/src/event-context.h b/src/event-context.h
index 97abee0d5..be06f0a34 100644
--- a/src/event-context.h
+++ b/src/event-context.h
@@ -171,6 +171,7 @@ SPItem *sp_event_context_find_item (SPDesktop *desktop, Geom::Point const &p, bo
SPItem *sp_event_context_over_item (SPDesktop *desktop, SPItem *item, Geom::Point const &p);
ShapeEditor *sp_event_context_get_shape_editor (SPEventContext *ec);
+bool sp_event_context_knot_mouseover(SPEventContext *ec);
void ec_shape_event_attr_changed(Inkscape::XML::Node *shape_repr,
gchar const *name, gchar const *old_value, gchar const *new_value,
diff --git a/src/gradient-context.cpp b/src/gradient-context.cpp
index a1fcf582b..b73d258fd 100644
--- a/src/gradient-context.cpp
+++ b/src/gradient-context.cpp
@@ -593,6 +593,15 @@ sp_gradient_context_root_handler(SPEventContext *event_context, GdkEvent *event)
ret = TRUE;
} else {
+ if (sp_event_context_knot_mouseover(event_context)) {
+ SnapManager &m = desktop->namedview->snap_manager;
+ m.setup(desktop);
+
+ Geom::Point const motion_w(event->motion.x, event->motion.y);
+ Geom::Point const motion_dt = event_context->desktop->w2d(motion_w);
+ m.preSnap(Inkscape::SnapCandidatePoint(motion_dt, Inkscape::SNAPSOURCE_NODE_HANDLE));
+ }
+
bool over_line = false;
if (drag->lines) {
for (GSList *l = drag->lines; l != NULL; l = l->next) {
diff --git a/src/knot.cpp b/src/knot.cpp
index b17e41b24..cc26653e5 100644
--- a/src/knot.cpp
+++ b/src/knot.cpp
@@ -284,7 +284,7 @@ void sp_knot_start_dragging(SPKnot *knot, Geom::Point const &p, gint x, gint y,
*/
static int sp_knot_handler(SPCanvasItem */*item*/, GdkEvent *event, SPKnot *knot)
{
- g_assert(knot != NULL);
+ g_assert(knot != NULL);
g_assert(SP_IS_KNOT(knot));
/* Run client universal event handler, if present */
@@ -302,7 +302,7 @@ static int sp_knot_handler(SPCanvasItem */*item*/, GdkEvent *event, SPKnot *knot
tolerance = prefs->getIntLimited("/options/dragtolerance/value", 0, 0, 100);
switch (event->type) {
- case GDK_2BUTTON_PRESS:
+ case GDK_2BUTTON_PRESS:
if (event->button.button == 1) {
g_signal_emit(knot, knot_signals[DOUBLECLICKED], 0, event->button.state);
@@ -311,23 +311,23 @@ static int sp_knot_handler(SPCanvasItem */*item*/, GdkEvent *event, SPKnot *knot
consumed = TRUE;
}
break;
- case GDK_BUTTON_PRESS:
+ case GDK_BUTTON_PRESS:
if (event->button.button == 1 && !knot->desktop->event_context->space_panning) {
Geom::Point const p = knot->desktop->w2d(Geom::Point(event->button.x, event->button.y));
sp_knot_start_dragging(knot, p, (gint) event->button.x, (gint) event->button.y, event->button.time);
- consumed = TRUE;
+ consumed = TRUE;
}
break;
- case GDK_BUTTON_RELEASE:
- if (event->button.button == 1 && !knot->desktop->event_context->space_panning) {
- // If we have any pending snap event, then invoke it now
- if (knot->desktop->event_context->_delayed_snap_event) {
- sp_event_context_snap_watchdog_callback(knot->desktop->event_context->_delayed_snap_event);
- }
+ case GDK_BUTTON_RELEASE:
+ if (event->button.button == 1 && !knot->desktop->event_context->space_panning) {
+ // If we have any pending snap event, then invoke it now
+ if (knot->desktop->event_context->_delayed_snap_event) {
+ sp_event_context_snap_watchdog_callback(knot->desktop->event_context->_delayed_snap_event);
+ }
- sp_event_context_discard_delayed_snap_event(knot->desktop->event_context);
+ sp_event_context_discard_delayed_snap_event(knot->desktop->event_context);
- knot->pressure = 0;
+ knot->pressure = 0;
if (transform_escaped) {
transform_escaped = false;
consumed = TRUE;
@@ -356,7 +356,7 @@ static int sp_knot_handler(SPCanvasItem */*item*/, GdkEvent *event, SPKnot *knot
}
}
break;
- case GDK_MOTION_NOTIFY:
+ case GDK_MOTION_NOTIFY:
if (grabbed && !knot->desktop->event_context->space_panning) {
consumed = TRUE;
@@ -389,7 +389,7 @@ static int sp_knot_handler(SPCanvasItem */*item*/, GdkEvent *event, SPKnot *knot
moved = TRUE;
}
break;
- case GDK_ENTER_NOTIFY:
+ case GDK_ENTER_NOTIFY:
sp_knot_set_flag(knot, SP_KNOT_MOUSEOVER, TRUE);
sp_knot_set_flag(knot, SP_KNOT_GRABBED, FALSE);
@@ -401,7 +401,7 @@ static int sp_knot_handler(SPCanvasItem */*item*/, GdkEvent *event, SPKnot *knot
moved = FALSE;
consumed = TRUE;
break;
- case GDK_LEAVE_NOTIFY:
+ case GDK_LEAVE_NOTIFY:
sp_knot_set_flag(knot, SP_KNOT_MOUSEOVER, FALSE);
sp_knot_set_flag(knot, SP_KNOT_GRABBED, FALSE);
@@ -413,35 +413,35 @@ static int sp_knot_handler(SPCanvasItem */*item*/, GdkEvent *event, SPKnot *knot
moved = FALSE;
consumed = TRUE;
break;
- case GDK_KEY_PRESS: // keybindings for knot
+ case GDK_KEY_PRESS: // keybindings for knot
switch (get_group0_keyval(&event->key)) {
- case GDK_Escape:
- sp_knot_set_flag(knot, SP_KNOT_GRABBED, FALSE);
- if (!nograb) {
- sp_canvas_item_ungrab(knot->item, event->button.time);
- }
- if (moved) {
- sp_knot_set_flag(knot,
- SP_KNOT_DRAGGING,
- FALSE);
- g_signal_emit(knot,
- knot_signals[UNGRABBED], 0,
- event->button.state);
- sp_document_undo(sp_desktop_document(knot->desktop));
- knot->desktop->messageStack()->flash(Inkscape::NORMAL_MESSAGE, _("Node or handle drag canceled."));
- transform_escaped = true;
- consumed = TRUE;
- }
- grabbed = FALSE;
- moved = FALSE;
- sp_event_context_discard_delayed_snap_event(knot->desktop->event_context);
- break;
- default:
- consumed = FALSE;
- break;
- }
- break;
- default:
+ case GDK_Escape:
+ sp_knot_set_flag(knot, SP_KNOT_GRABBED, FALSE);
+ if (!nograb) {
+ sp_canvas_item_ungrab(knot->item, event->button.time);
+ }
+ if (moved) {
+ sp_knot_set_flag(knot,
+ SP_KNOT_DRAGGING,
+ FALSE);
+ g_signal_emit(knot,
+ knot_signals[UNGRABBED], 0,
+ event->button.state);
+ sp_document_undo(sp_desktop_document(knot->desktop));
+ knot->desktop->messageStack()->flash(Inkscape::NORMAL_MESSAGE, _("Node or handle drag canceled."));
+ transform_escaped = true;
+ consumed = TRUE;
+ }
+ grabbed = FALSE;
+ moved = FALSE;
+ sp_event_context_discard_delayed_snap_event(knot->desktop->event_context);
+ break;
+ default:
+ consumed = FALSE;
+ break;
+ }
+ break;
+ default:
break;
}
@@ -452,14 +452,14 @@ static int sp_knot_handler(SPCanvasItem */*item*/, GdkEvent *event, SPKnot *knot
void sp_knot_handler_request_position(GdkEvent *event, SPKnot *knot)
{
- Geom::Point const motion_w(event->motion.x, event->motion.y);
- Geom::Point const motion_dt = knot->desktop->w2d(motion_w);
- Geom::Point p = motion_dt - knot->grabbed_rel_pos;
- sp_knot_request_position (knot, p, event->motion.state);
- knot->desktop->scroll_to_point (motion_dt);
- knot->desktop->set_coordinate_status(knot->pos); // display the coordinate of knot, not cursor - they may be different!
- if (event->motion.state & GDK_BUTTON1_MASK)
- gobble_motion_events(GDK_BUTTON1_MASK);
+ Geom::Point const motion_w(event->motion.x, event->motion.y);
+ Geom::Point const motion_dt = knot->desktop->w2d(motion_w);
+ Geom::Point p = motion_dt - knot->grabbed_rel_pos;
+ sp_knot_request_position (knot, p, event->motion.state);
+ knot->desktop->scroll_to_point (motion_dt);
+ knot->desktop->set_coordinate_status(knot->pos); // display the coordinate of knot, not cursor - they may be different!
+ if (event->motion.state & GDK_BUTTON1_MASK)
+ gobble_motion_events(GDK_BUTTON1_MASK);
}
/**
@@ -620,20 +620,20 @@ void sp_knot_set_flag(SPKnot *knot, guint flag, bool set)
}
switch (flag) {
- case SP_KNOT_VISIBLE:
+ case SP_KNOT_VISIBLE:
if (set) {
sp_canvas_item_show(knot->item);
} else {
sp_canvas_item_hide(knot->item);
}
break;
- case SP_KNOT_MOUSEOVER:
- case SP_KNOT_DRAGGING:
+ case SP_KNOT_MOUSEOVER:
+ case SP_KNOT_DRAGGING:
sp_knot_set_ctrl_state(knot);
break;
- case SP_KNOT_GRABBED:
+ case SP_KNOT_GRABBED:
break;
- default:
+ default:
g_assert_not_reached();
break;
}
diff --git a/src/knotholder.cpp b/src/knotholder.cpp
index 45cb140c0..314ad807c 100644
--- a/src/knotholder.cpp
+++ b/src/knotholder.cpp
@@ -91,6 +91,21 @@ KnotHolder::update_knots()
}
}
+/**
+ * \brief Returns true if at least one of the KnotHolderEntities has the mouse hovering above it
+ */
+bool KnotHolder::knot_mouseover()
+{
+ for(std::list<KnotHolderEntity *>::iterator i = entity.begin(); i != entity.end(); ++i) {
+ SPKnot *knot = (*i)->knot;
+ if (knot && (knot->flags & SP_KNOT_MOUSEOVER)) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
void
KnotHolder::knot_clicked_handler(SPKnot *knot, guint state)
{
diff --git a/src/knotholder.h b/src/knotholder.h
index fa1abd071..0b37d211c 100644
--- a/src/knotholder.h
+++ b/src/knotholder.h
@@ -49,6 +49,8 @@ public:
const SPItem *getItem() { return item; }
+ bool knot_mouseover();
+
friend class ShapeEditor;
protected:
diff --git a/src/object-edit.cpp b/src/object-edit.cpp
index 6b83413e4..1d81aa7f5 100644
--- a/src/object-edit.cpp
+++ b/src/object-edit.cpp
@@ -194,7 +194,7 @@ RectKnotHolderEntityRY::knot_set(Geom::Point const &p, Geom::Point const &/*orig
Geom::Point const s = snap_knot_position_constrained(p, Inkscape::Snapper::ConstraintLine(Geom::Point(rect->x.computed + rect->width.computed, rect->y.computed), Geom::Point(0, 1)));
if (state & GDK_CONTROL_MASK) { // When holding control then rx will be kept equal to ry,
- // resulting in a perfect circle (and not an ellipse)
+ // resulting in a perfect circle (and not an ellipse)
gdouble temp = MIN(rect->height.computed, rect->width.computed) / 2.0;
rect->rx.computed = rect->ry.computed = CLAMP(s[Geom::Y] - rect->y.computed, 0.0, temp);
rect->ry._set = rect->rx._set = true;
@@ -277,19 +277,19 @@ RectKnotHolderEntityWH::set_internal(Geom::Point const &p, Geom::Point const &or
Geom::Point p_handle(rect->x.computed + rect->width.computed, rect->y.computed + rect->height.computed);
if (fabs(minx) > fabs(miny)) {
- // snap to horizontal or diagonal
+ // snap to horizontal or diagonal
if (minx != 0 && fabs(miny/minx) > 0.5 * 1/ratio && (SGN(minx) == SGN(miny))) {
// closer to the diagonal and in same-sign quarters, change both using ratio
- s = snap_knot_position_constrained(p, Inkscape::Snapper::ConstraintLine(p_handle, Geom::Point(-ratio, -1)));
- minx = s[Geom::X] - origin[Geom::X];
- miny = s[Geom::Y] - origin[Geom::Y];
- rect->height.computed = MAX(h_orig + minx / ratio, 0);
+ s = snap_knot_position_constrained(p, Inkscape::Snapper::ConstraintLine(p_handle, Geom::Point(-ratio, -1)));
+ minx = s[Geom::X] - origin[Geom::X];
+ miny = s[Geom::Y] - origin[Geom::Y];
+ rect->height.computed = MAX(h_orig + minx / ratio, 0);
} else {
// closer to the horizontal, change only width, height is h_orig
- s = snap_knot_position_constrained(p, Inkscape::Snapper::ConstraintLine(p_handle, Geom::Point(-1, 0)));
- minx = s[Geom::X] - origin[Geom::X];
- miny = s[Geom::Y] - origin[Geom::Y];
- rect->height.computed = MAX(h_orig, 0);
+ s = snap_knot_position_constrained(p, Inkscape::Snapper::ConstraintLine(p_handle, Geom::Point(-1, 0)));
+ minx = s[Geom::X] - origin[Geom::X];
+ miny = s[Geom::Y] - origin[Geom::Y];
+ rect->height.computed = MAX(h_orig, 0);
}
rect->width.computed = MAX(w_orig + minx, 0);
@@ -297,16 +297,16 @@ RectKnotHolderEntityWH::set_internal(Geom::Point const &p, Geom::Point const &or
// snap to vertical or diagonal
if (miny != 0 && fabs(minx/miny) > 0.5 * ratio && (SGN(minx) == SGN(miny))) {
// closer to the diagonal and in same-sign quarters, change both using ratio
- s = snap_knot_position_constrained(p, Inkscape::Snapper::ConstraintLine(p_handle, Geom::Point(-ratio, -1)));
- minx = s[Geom::X] - origin[Geom::X];
- miny = s[Geom::Y] - origin[Geom::Y];
- rect->width.computed = MAX(w_orig + miny * ratio, 0);
+ s = snap_knot_position_constrained(p, Inkscape::Snapper::ConstraintLine(p_handle, Geom::Point(-ratio, -1)));
+ minx = s[Geom::X] - origin[Geom::X];
+ miny = s[Geom::Y] - origin[Geom::Y];
+ rect->width.computed = MAX(w_orig + miny * ratio, 0);
} else {
// closer to the vertical, change only height, width is w_orig
- s = snap_knot_position_constrained(p, Inkscape::Snapper::ConstraintLine(p_handle, Geom::Point(0, -1)));
- minx = s[Geom::X] - origin[Geom::X];
- miny = s[Geom::Y] - origin[Geom::Y];
- rect->width.computed = MAX(w_orig, 0);
+ s = snap_knot_position_constrained(p, Inkscape::Snapper::ConstraintLine(p_handle, Geom::Point(0, -1)));
+ minx = s[Geom::X] - origin[Geom::X];
+ miny = s[Geom::Y] - origin[Geom::Y];
+ rect->width.computed = MAX(w_orig, 0);
}
rect->height.computed = MAX(h_orig + miny, 0);
@@ -316,8 +316,8 @@ RectKnotHolderEntityWH::set_internal(Geom::Point const &p, Geom::Point const &or
} else {
// move freely
- s = snap_knot_position(p);
- rect->width.computed = MAX(s[Geom::X] - rect->x.computed, 0);
+ s = snap_knot_position(p);
+ rect->width.computed = MAX(s[Geom::X] - rect->x.computed, 0);
rect->height.computed = MAX(s[Geom::Y] - rect->y.computed, 0);
rect->width._set = rect->height._set = true;
}
@@ -367,54 +367,54 @@ RectKnotHolderEntityXY::knot_set(Geom::Point const &p, Geom::Point const &origin
gdouble ratio = (w_orig / h_orig);
if (fabs(minx) > fabs(miny)) {
- // snap to horizontal or diagonal
+ // snap to horizontal or diagonal
if (minx != 0 && fabs(miny/minx) > 0.5 * 1/ratio && (SGN(minx) == SGN(miny))) {
// closer to the diagonal and in same-sign quarters, change both using ratio
- s = snap_knot_position_constrained(p, Inkscape::Snapper::ConstraintLine(p_handle, Geom::Point(-ratio, -1)));
- minx = s[Geom::X] - origin[Geom::X];
- miny = s[Geom::Y] - origin[Geom::Y];
- rect->y.computed = MIN(origin[Geom::Y] + minx / ratio, opposite_y);
+ s = snap_knot_position_constrained(p, Inkscape::Snapper::ConstraintLine(p_handle, Geom::Point(-ratio, -1)));
+ minx = s[Geom::X] - origin[Geom::X];
+ miny = s[Geom::Y] - origin[Geom::Y];
+ rect->y.computed = MIN(origin[Geom::Y] + minx / ratio, opposite_y);
rect->height.computed = MAX(h_orig - minx / ratio, 0);
} else {
// closer to the horizontal, change only width, height is h_orig
- s = snap_knot_position_constrained(p, Inkscape::Snapper::ConstraintLine(p_handle, Geom::Point(-1, 0)));
- minx = s[Geom::X] - origin[Geom::X];
- miny = s[Geom::Y] - origin[Geom::Y];
- rect->y.computed = MIN(origin[Geom::Y], opposite_y);
+ s = snap_knot_position_constrained(p, Inkscape::Snapper::ConstraintLine(p_handle, Geom::Point(-1, 0)));
+ minx = s[Geom::X] - origin[Geom::X];
+ miny = s[Geom::Y] - origin[Geom::Y];
+ rect->y.computed = MIN(origin[Geom::Y], opposite_y);
rect->height.computed = MAX(h_orig, 0);
}
rect->x.computed = MIN(s[Geom::X], opposite_x);
rect->width.computed = MAX(w_orig - minx, 0);
} else {
// snap to vertical or diagonal
- if (miny != 0 && fabs(minx/miny) > 0.5 *ratio && (SGN(minx) == SGN(miny))) {
+ if (miny != 0 && fabs(minx/miny) > 0.5 *ratio && (SGN(minx) == SGN(miny))) {
// closer to the diagonal and in same-sign quarters, change both using ratio
- s = snap_knot_position_constrained(p, Inkscape::Snapper::ConstraintLine(p_handle, Geom::Point(-ratio, -1)));
- minx = s[Geom::X] - origin[Geom::X];
- miny = s[Geom::Y] - origin[Geom::Y];
- rect->x.computed = MIN(origin[Geom::X] + miny * ratio, opposite_x);
+ s = snap_knot_position_constrained(p, Inkscape::Snapper::ConstraintLine(p_handle, Geom::Point(-ratio, -1)));
+ minx = s[Geom::X] - origin[Geom::X];
+ miny = s[Geom::Y] - origin[Geom::Y];
+ rect->x.computed = MIN(origin[Geom::X] + miny * ratio, opposite_x);
rect->width.computed = MAX(w_orig - miny * ratio, 0);
} else {
// closer to the vertical, change only height, width is w_orig
- s = snap_knot_position_constrained(p, Inkscape::Snapper::ConstraintLine(p_handle, Geom::Point(0, -1)));
- minx = s[Geom::X] - origin[Geom::X];
- miny = s[Geom::Y] - origin[Geom::Y];
- rect->x.computed = MIN(origin[Geom::X], opposite_x);
+ s = snap_knot_position_constrained(p, Inkscape::Snapper::ConstraintLine(p_handle, Geom::Point(0, -1)));
+ minx = s[Geom::X] - origin[Geom::X];
+ miny = s[Geom::Y] - origin[Geom::Y];
+ rect->x.computed = MIN(origin[Geom::X], opposite_x);
rect->width.computed = MAX(w_orig, 0);
}
rect->y.computed = MIN(s[Geom::Y], opposite_y);
- rect->height.computed = MAX(h_orig - miny, 0);
+ rect->height.computed = MAX(h_orig - miny, 0);
}
rect->width._set = rect->height._set = rect->x._set = rect->y._set = true;
} else {
// move freely
- s = snap_knot_position(p);
- minx = s[Geom::X] - origin[Geom::X];
- miny = s[Geom::Y] - origin[Geom::Y];
+ s = snap_knot_position(p);
+ minx = s[Geom::X] - origin[Geom::X];
+ miny = s[Geom::Y] - origin[Geom::Y];
- rect->x.computed = MIN(s[Geom::X], opposite_x);
+ rect->x.computed = MIN(s[Geom::X], opposite_x);
rect->width.computed = MAX(w_orig - minx, 0);
rect->y.computed = MIN(s[Geom::Y], opposite_y);
rect->height.computed = MAX(h_orig - miny, 0);
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;
diff --git a/src/pencil-context.cpp b/src/pencil-context.cpp
index acdd4d6e5..5aa9efbd9 100644
--- a/src/pencil-context.cpp
+++ b/src/pencil-context.cpp
@@ -295,7 +295,7 @@ pencil_handle_button_press(SPPencilContext *const pc, GdkEventButton const &beve
static gint
pencil_handle_motion_notify(SPPencilContext *const pc, GdkEventMotion const &mevent)
{
- SPDesktop *const dt = pc->desktop;
+ SPDesktop *const dt = pc->desktop;
if ((mevent.state & GDK_CONTROL_MASK) && (mevent.state & GDK_BUTTON1_MASK)) {
// mouse was accidentally moved during Ctrl+click;
@@ -395,6 +395,11 @@ pencil_handle_motion_notify(SPPencilContext *const pc, GdkEventMotion const &mev
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;
}
diff --git a/src/rect-context.cpp b/src/rect-context.cpp
index dcc1f0aa1..9eab188dd 100644
--- a/src/rect-context.cpp
+++ b/src/rect-context.cpp
@@ -317,6 +317,13 @@ static gint sp_rect_context_root_handler(SPEventContext *event_context, GdkEvent
sp_rect_drag(*rc, motion_dt, event->motion.state); // this will also handle the snapping
gobble_motion_events(GDK_BUTTON1_MASK);
ret = TRUE;
+ } else if (sp_event_context_knot_mouseover(rc)) {
+ SnapManager &m = desktop->namedview->snap_manager;
+ m.setup(desktop);
+
+ Geom::Point const motion_w(event->motion.x, event->motion.y);
+ Geom::Point motion_dt(desktop->w2d(motion_w));
+ m.preSnap(Inkscape::SnapCandidatePoint(motion_dt, Inkscape::SNAPSOURCE_NODE_HANDLE));
}
break;
case GDK_BUTTON_RELEASE:
diff --git a/src/shape-editor.cpp b/src/shape-editor.cpp
index 7002c9723..e3b6d65c2 100644
--- a/src/shape-editor.cpp
+++ b/src/shape-editor.cpp
@@ -226,6 +226,16 @@ bool ShapeEditor::has_selection() {
return false; // so far, knotholder cannot have selection
}
+/**
+ * \brief Returns true if this ShapeEditor has a knot above which the mouse currently hovers
+ */
+bool ShapeEditor::knot_mouseover()
+{
+ if (this->knotholder) {
+ return knotholder->knot_mouseover();
+ }
+}
+
/*
Local Variables:
mode:c++
diff --git a/src/shape-editor.h b/src/shape-editor.h
index 2374d6ac6..f400244b3 100644
--- a/src/shape-editor.h
+++ b/src/shape-editor.h
@@ -62,6 +62,8 @@ public:
// this one is only public because it's called from non-C++ repr changed callback
void shapeeditor_event_attr_changed(gchar const *name);
+ bool knot_mouseover();
+
private:
bool has_knotholder ();
void reset_item (SubType type, bool keep_knotholder = true);
diff --git a/src/snap.cpp b/src/snap.cpp
index 4727c7b3e..9ee575e22 100644
--- a/src/snap.cpp
+++ b/src/snap.cpp
@@ -214,6 +214,22 @@ Inkscape::SnappedPoint SnapManager::freeSnap(Inkscape::SnapCandidatePoint const
return findBestSnap(p, sc, false);
}
+void SnapManager::preSnap(Inkscape::SnapCandidatePoint const &p)
+{
+ // setup() must have been called before calling this method!
+
+ if (_snapindicator) {
+ _snapindicator = false; // prevent other methods from drawing a snap indicator; we want to control this here
+ Inkscape::SnappedPoint s = freeSnap(p);
+ if (s.getSnapped()) {
+ _desktop->snapindicator->set_new_snaptarget(s, true);
+ } else {
+ _desktop->snapindicator->remove_snaptarget();
+ }
+ _snapindicator = true; // restore the original value
+ }
+}
+
/**
* \brief Snap to the closest multiple of a grid pitch
*
diff --git a/src/snap.h b/src/snap.h
index 24a60eaf0..613550376 100644
--- a/src/snap.h
+++ b/src/snap.h
@@ -105,6 +105,8 @@ public:
Inkscape::SnappedPoint freeSnap(Inkscape::SnapCandidatePoint const &p,
Geom::OptRect const &bbox_to_snap = Geom::OptRect() ) const;
+ void preSnap(Inkscape::SnapCandidatePoint const &p);
+
Geom::Point multipleOfGridPitch(Geom::Point const &t) const;
// constrainedSnapReturnByRef() is preferred over constrainedSnap(), because it only returns a
diff --git a/src/spiral-context.cpp b/src/spiral-context.cpp
index d751fae6d..f8a4bddfb 100644
--- a/src/spiral-context.cpp
+++ b/src/spiral-context.cpp
@@ -277,6 +277,13 @@ sp_spiral_context_root_handler(SPEventContext *event_context, GdkEvent *event)
gobble_motion_events(GDK_BUTTON1_MASK);
ret = TRUE;
+ } else if (sp_event_context_knot_mouseover(sc)) {
+ SnapManager &m = desktop->namedview->snap_manager;
+ m.setup(desktop);
+
+ Geom::Point const motion_w(event->motion.x, event->motion.y);
+ Geom::Point motion_dt(desktop->w2d(motion_w));
+ m.preSnap(Inkscape::SnapCandidatePoint(motion_dt, Inkscape::SNAPSOURCE_NODE_HANDLE));
}
break;
case GDK_BUTTON_RELEASE:
diff --git a/src/star-context.cpp b/src/star-context.cpp
index f67ca434d..693d51888 100644
--- a/src/star-context.cpp
+++ b/src/star-context.cpp
@@ -291,6 +291,13 @@ static gint sp_star_context_root_handler(SPEventContext *event_context, GdkEvent
gobble_motion_events(GDK_BUTTON1_MASK);
ret = TRUE;
+ } else if (sp_event_context_knot_mouseover(event_context)) {
+ SnapManager &m = desktop->namedview->snap_manager;
+ m.setup(desktop);
+
+ Geom::Point const motion_w(event->motion.x, event->motion.y);
+ Geom::Point motion_dt(desktop->w2d(motion_w));
+ m.preSnap(Inkscape::SnapCandidatePoint(motion_dt, Inkscape::SNAPSOURCE_NODE_HANDLE));
}
break;
case GDK_BUTTON_RELEASE:
@@ -472,13 +479,13 @@ sp_star_finish (SPStarContext * sc)
sc->_message_context->clear();
if (sc->item != NULL) {
- SPStar *star = SP_STAR(sc->item);
- if (star->r[1] == 0) {
- sp_star_cancel(sc); // Don't allow the creating of zero sized arc, for example when the start and and point snap to the snap grid point
- return;
- }
+ SPStar *star = SP_STAR(sc->item);
+ if (star->r[1] == 0) {
+ sp_star_cancel(sc); // Don't allow the creating of zero sized arc, for example when the start and and point snap to the snap grid point
+ return;
+ }
- SPDesktop *desktop = SP_EVENT_CONTEXT(sc)->desktop;
+ SPDesktop *desktop = SP_EVENT_CONTEXT(sc)->desktop;
SPObject *object = SP_OBJECT(sc->item);
sp_shape_set_shape(SP_SHAPE(sc->item));
@@ -497,14 +504,14 @@ sp_star_finish (SPStarContext * sc)
static void sp_star_cancel(SPStarContext *sc)
{
- SPDesktop *desktop = SP_EVENT_CONTEXT(sc)->desktop;
+ SPDesktop *desktop = SP_EVENT_CONTEXT(sc)->desktop;
- sp_desktop_selection(desktop)->clear();
- sp_canvas_item_ungrab(SP_CANVAS_ITEM(desktop->acetate), 0);
+ sp_desktop_selection(desktop)->clear();
+ sp_canvas_item_ungrab(SP_CANVAS_ITEM(desktop->acetate), 0);
if (sc->item != NULL) {
- SP_OBJECT(sc->item)->deleteObject();
- sc->item = NULL;
+ SP_OBJECT(sc->item)->deleteObject();
+ sc->item = NULL;
}
sc->within_tolerance = false;
diff --git a/src/star-context.h b/src/star-context.h
index 6db29ec42..024bf8d74 100644
--- a/src/star-context.h
+++ b/src/star-context.h
@@ -28,27 +28,27 @@ class SPStarContext;
class SPStarContextClass;
struct SPStarContext : public SPEventContext {
- SPItem *item;
- Geom::Point center;
-
- /* Number of corners */
- gint magnitude;
- /* Outer/inner radius ratio */
- gdouble proportion;
- /* flat sides or not? */
- bool isflatsided;
- /* rounded corners ratio */
- gdouble rounded;
- // randomization
- gdouble randomized;
+ SPItem *item;
+ Geom::Point center;
+
+ /* Number of corners */
+ gint magnitude;
+ /* Outer/inner radius ratio */
+ gdouble proportion;
+ /* flat sides or not? */
+ bool isflatsided;
+ /* rounded corners ratio */
+ gdouble rounded;
+ // randomization
+ gdouble randomized;
sigc::connection sel_changed_connection;
- Inkscape::MessageContext *_message_context;
+ Inkscape::MessageContext *_message_context;
};
struct SPStarContextClass {
- SPEventContextClass parent_class;
+ SPEventContextClass parent_class;
};
GtkType sp_star_context_get_type (void);