index 228c81d29e0bdc26365ebe694bf4600778f901f3..f4b202451156cc5e83133d55d3fe5dfda76075b1 100644 (file)
-/*
+/**
* Connector creation tool
*
* Authors:
* Michael Wybrow <mjwybrow@users.sourceforge.net>
+ * Abhishek Sharma
+ * Jon A. Cruz <jon@joncruz.org>
*
* Copyright (C) 2005-2008 Michael Wybrow
* Copyright (C) 2009 Monash University
+ * Copyright (C) 2010 authors
*
* Released under GNU GPL, read the file 'COPYING' for more information
*
* Gobbling away all duplicates after the current can occasionally result
* in the path lagging behind the mouse cursor if it is no longer being
* dragged.
- * o Fix up libavoid's representation after undo actions. It doesn't see
+ * o Fix up libavoid's representation after undo actions. It doesn't see
* any transform signals and hence doesn't know shapes have moved back to
* there earlier positions.
* o Decide whether drawing/editing mode should be an Inkscape preference
* ----------------------------------------------------------------------------
*
* mjwybrow's observations on acracan's Summer of Code connector work:
- *
+ *
* - GUI comments:
- *
+ *
* - Buttons for adding and removing user-specified connection
* points should probably have "+" and "-" symbols on them so they
* are consistent with the similar buttons for the node tool.
- * - Controls on the connector tool be should be reordered logically,
+ * - Controls on the connector tool be should be reordered logically,
* possibly as follows:
- *
- * *Connector*: [Polyline-radio-button] [Orthgonal-radio-button]
+ *
+ * *Connector*: [Polyline-radio-button] [Orthgonal-radio-button]
* [Curvature-control] | *Shape*: [Avoid-button] [Dont-avoid-button]
* [Spacing-control] | *Connection pts*: [Edit-mode] [Add-pt] [Rm-pt]
- *
- * I think that the network layout controls be moved to the
- * Align and Distribute dialog (there is already the layout button
+ *
+ * I think that the network layout controls be moved to the
+ * Align and Distribute dialog (there is already the layout button
* there, but no options are exposed).
- *
+ *
* I think that the style change between polyline and orthogonal
* would be much clearer with two buttons (radio behaviour -- just
* one is true).
- *
- * The other tools show a label change from "New:" to "Change:"
+ *
+ * The other tools show a label change from "New:" to "Change:"
* depending on whether an object is selected. We could consider
* this but there may not be space.
- *
+ *
* The Add-pt and Rm-pt buttons should be greyed out (inactive) if
* we are not in connection point editing mode. And probably also
* if there is no shape selected, i.e. at the times they have no
* effect when clicked.
- *
- * Likewise for the avoid/ignore shapes buttons. These should be
+ *
+ * Likewise for the avoid/ignore shapes buttons. These should be
* inactive when a shape is not selected in the connector context.
- *
+ *
* - When creating/editing connection points:
- *
+ *
* - Strange things can happen if you have connectors selected, or
- * try rerouting connectors by dragging their endpoints when in
+ * try rerouting connectors by dragging their endpoints when in
* connection point editing mode.
- *
+ *
* - Possibly the selected shape's connection points should always
* be shown (i.e., have knots) when in editing mode.
- *
+ *
* - It is a little strange to be able to place connection points
* competely outside shapes. Especially when you later can't draw
* connectors to them since the knots are only visible when you
* are over the shape. I think that you should only be able to
- * place connection points inside or on the boundary of the shape
+ * place connection points inside or on the boundary of the shape
* itself.
- *
- * - The intended ability to place a new point at the current cursor
+ *
+ * - The intended ability to place a new point at the current cursor
* position by pressing RETURN does not seem to work.
- *
+ *
* - The Status bar tooltip should change to reflect editing mode
* and tell the user about RETURN and how to use the tool.
- *
+ *
* - Connection points general:
- *
- * - Connection points that were inside the shape can end up outside
+ *
+ * - Connection points that were inside the shape can end up outside
* after a rotation is applied to the shape in the select tool.
* It doesn't seem like the correct transform is being applied to
* these, or it is being applied at the wrong time. I'd expect
* connection points to rotate with the shape, and stay at the
* same position "on the shape"
- *
+ *
* - I was able to make the connectors attached to a shape fall off
* the shape after scaling it. Not sure the exact cause, but may
* require more investigation/debugging.
- *
+ *
* - The user-defined connection points should be either absolute
* (as the current ones are) or defined as a percentage of the
* shape. These would be based on a toggle setting on the
* toolbar, and they would be placed in exactly the same way by
* the user. The only difference would be that they would be
* store as percentage positions in the SVG connection-points
- * property and that they would update/move automatically if the
+ * property and that they would update/move automatically if the
* object was resized or scaled.
- *
+ *
* - Thinking more, I think you always want to store and think about
* the positions of connection points to be pre-transform, but
* obviously the shape transform is applied to them. That way,
* the shape transform is altered. The Percentage version would
* compute their position from the pre-transform dimensions and
* then have the transform applied to them, for example.
- *
+ *
* - The connection points in the test_connection_points.svg file
* seem to follow the shape when it is moved, but connection
* points I add to new shapes, do not follow the shape, either
* when the shape is just moved or transformed. There is
- * something wrong here. What exactly should the behaviour be
+ * something wrong here. What exactly should the behaviour be
* currently?
- *
+ *
* - I see that connection points are specified at absolute canvas
* positions. I really think that they should be specified in
* shape coordinated relative to the shapes. There may be
#include "connector-context.h"
#include "pixmaps/cursor-connector.xpm"
#include "pixmaps/cursor-node.xpm"
-#include "pixmaps/cursor-node-m.xpm"
-#include "pixmaps/cursor-node-d.xpm"
+//#include "pixmaps/cursor-node-m.xpm"
+//#include "pixmaps/cursor-node-d.xpm"
#include "xml/node-event-vector.h"
#include "xml/repr.h"
#include "svg/svg.h"
#include "inkscape.h"
#include "preferences.h"
#include "sp-path.h"
+#include "display/sp-canvas.h"
#include "display/canvas-bpath.h"
#include "display/sodipodi-ctrl.h"
#include <glibmm/i18n.h>
#include "sp-flowtext.h"
#include "display/curve.h"
+using Inkscape::DocumentUndo;
+
static void sp_connector_context_class_init(SPConnectorContextClass *klass);
static void sp_connector_context_init(SPConnectorContext *conn_context);
static void sp_connector_context_dispose(GObject *object);
static void cc_clear_active_shape(SPConnectorContext *cc);
static void cc_set_active_conn(SPConnectorContext *cc, SPItem *item);
static void cc_clear_active_conn(SPConnectorContext *cc);
-static gchar *conn_pt_handle_test(SPConnectorContext *cc, Geom::Point& w);
+static bool conn_pt_handle_test(SPConnectorContext *cc, Geom::Point& p, gchar **href, gchar **cpid);
static void cc_select_handle(SPKnot* knot);
static void cc_deselect_handle(SPKnot* knot);
static bool cc_item_is_shape(SPItem *item);
@@ -233,6 +239,9 @@ static void shape_event_attr_changed(Inkscape::XML::Node *repr, gchar const *nam
gpointer data);
+static char* cc_knot_tips[] = { _("<b>Connection point</b>: click or drag to create a new connector"),
+ _("<b>Connection point</b>: click to select, drag to move") };
+
/*static Geom::Point connector_drag_origin_w(0, 0);
static bool connector_within_tolerance = false;*/
static SPEventContextClass *parent_class;
cc->clickedhandle = NULL;
new (&cc->connpthandles) ConnectionPointMap();
-
+
for (int i = 0; i < 2; ++i) {
cc->endpt_handle[i] = NULL;
cc->endpt_handler_id[i] = 0;
}
- cc->sid = NULL;
- cc->eid = NULL;
+ cc->shref = NULL;
+ cc->scpid = NULL;
+ cc->ehref = NULL;
+ cc->ecpid = NULL;
cc->npoints = 0;
cc->state = SP_CONNECTOR_CONTEXT_IDLE;
}
cc->sel_changed_connection.disconnect();
if (!cc->connpthandles.empty()) {
- for (ConnectionPointMap::iterator it = cc->connpthandles.begin();
+ for (ConnectionPointMap::iterator it = cc->connpthandles.begin();
it != cc->connpthandles.end(); ++it) {
g_object_unref(it->first);
}
cc->endpt_handle[i] = NULL;
}
}
- if (cc->sid) {
- g_free(cc->sid);
- cc->sid = NULL;
+ if (cc->shref) {
+ g_free(cc->shref);
+ cc->shref = NULL;
+ }
+ if (cc->scpid) {
+ g_free(cc->scpid);
+ cc->scpid = NULL;
+ }
+ if (cc->ehref) {
+ g_free(cc->shref);
+ cc->shref = NULL;
}
- if (cc->eid) {
- g_free(cc->eid);
- cc->eid = NULL;
+ if (cc->ecpid) {
+ g_free(cc->scpid);
+ cc->scpid = NULL;
}
g_assert( cc->newConnRef == NULL );
cc_selection_changed(cc->selection, (gpointer) cc);
cc->within_tolerance = false;
-
+
sp_event_context_read(ec, "curvature");
sp_event_context_read(ec, "orthogonal");
sp_event_context_read(ec, "mode");
{
cc->selection->set( SP_OBJECT( cc->active_shape ) );
}
- else
+ else
{
SPItem* item = cc->selection->singleItem();
if ( item )
// Hide the connection points if they exist.
if (cc->connpthandles.size()) {
- for (ConnectionPointMap::iterator it = cc->connpthandles.begin();
+ for (ConnectionPointMap::iterator it = cc->connpthandles.begin();
it != cc->connpthandles.end(); ++it) {
sp_knot_hide(it->first);
}
}
-static gchar *
-conn_pt_handle_test(SPConnectorContext *cc, Geom::Point& p)
+static bool
+conn_pt_handle_test(SPConnectorContext *cc, Geom::Point& p, gchar **href, gchar **cpid)
{
// TODO: this will need to change when there are more connection
// points available for each shape.
{
p = cc->active_handle->pos;
const ConnectionPoint& cp = cc->connpthandles[cc->active_handle];
- return g_strdup_printf("#%s_%c_%d", SP_OBJECT_ID(cc->active_shape),
- cp.type == ConnPointDefault ? 'd' : 'u' , cp.id);
+ *href = g_strdup_printf("#%s", cc->active_shape->getId());
+ *cpid = g_strdup_printf("%c%d", cp.type == ConnPointDefault ? 'd' : 'u' , cp.id);
+ return true;
}
- return NULL;
+ *href = NULL;
+ *cpid = NULL;
+ return false;
}
static void
@@ -616,7 +638,7 @@ sp_connector_context_item_handler(SPEventContext *event_context, SPItem *item, G
SPConnectorContext *cc = SP_CONNECTOR_CONTEXT(event_context);
Geom::Point p(event->button.x, event->button.y);
-
+
switch (event->type) {
case GDK_BUTTON_RELEASE:
if (event->button.button == 1 && !event_context->space_panning) {
@@ -625,7 +647,6 @@ sp_connector_context_item_handler(SPEventContext *event_context, SPItem *item, G
{
spcc_reset_colors(cc);
cc->state = SP_CONNECTOR_CONTEXT_IDLE;
-// sp_event_context_snap_window_closed(event_context);
}
if (cc->state != SP_CONNECTOR_CONTEXT_IDLE) {
// Doing something else like rerouting.
@@ -660,11 +681,11 @@ sp_connector_context_item_handler(SPEventContext *event_context, SPItem *item, G
if (cc->mode == SP_CONNECTOR_CONTEXT_DRAWING_MODE || (cc->mode == SP_CONNECTOR_CONTEXT_EDITING_MODE && !cc->selected_handle))
{
if (cc_item_is_shape(item)) {
-
+
// I don't really understand what the above does,
// so I commented it.
// This is a shape, so show connection point(s).
- /* if (!(cc->active_shape)
+ /* if (!(cc->active_shape)
// Don't show handle for another handle.
// || (cc->connpthandles.find((SPKnot*) item) != cc->connpthandles.end())
)
@@ -753,11 +774,10 @@ connector_handle_button_press(SPConnectorContext *const cc, GdkEventButton const
Geom::Point const event_dt = cc->desktop->w2d(event_w);
SnapManager &m = cc->desktop->namedview->snap_manager;
- m.setup(cc->desktop);
switch (cc->state) {
case SP_CONNECTOR_CONTEXT_STOP:
- /* This is allowed, if we just cancelled curve */
+ /* This is allowed, if we just canceled curve */
case SP_CONNECTOR_CONTEXT_IDLE:
{
if ( cc->npoints == 0 ) {
@@ -770,14 +790,14 @@ connector_handle_button_press(SPConnectorContext *const cc, GdkEventButton const
Geom::Point p = event_dt;
// Test whether we clicked on a connection point
- cc->sid = conn_pt_handle_test(cc, p);
+ bool found = conn_pt_handle_test(cc, p, &cc->shref, &cc->scpid);
-// sp_event_context_snap_window_open(event_context);
-
- if (!cc->sid) {
+ if (!found) {
// This is the first point, so just snap it to the grid
// as there's no other points to go off.
- m.freeSnapReturnByRef(Inkscape::SnapPreferences::SNAPPOINT_NODE, p, Inkscape::SNAPSOURCE_HANDLE);
+ m.setup(cc->desktop);
+ m.freeSnapReturnByRef(p, Inkscape::SNAPSOURCE_OTHER_HANDLE);
+ m.unSetup();
}
spcc_connector_set_initial_point(cc, p);
@@ -789,18 +809,19 @@ connector_handle_button_press(SPConnectorContext *const cc, GdkEventButton const
case SP_CONNECTOR_CONTEXT_DRAGGING:
{
// This is the second click of a connector creation.
- m.freeSnapReturnByRef(Inkscape::SnapPreferences::SNAPPOINT_NODE, p, Inkscape::SNAPSOURCE_HANDLE);
+ m.setup(cc->desktop);
+ m.freeSnapReturnByRef(p, Inkscape::SNAPSOURCE_OTHER_HANDLE);
+ m.unSetup();
spcc_connector_set_subsequent_point(cc, p);
spcc_connector_finish_segment(cc, p);
// Test whether we clicked on a connection point
- cc->eid = conn_pt_handle_test(cc, p);
+ /*bool found = */conn_pt_handle_test(cc, p, &cc->ehref, &cc->ecpid);
if (cc->npoints != 0) {
spcc_connector_finish(cc);
}
cc_set_active_conn(cc, cc->newconn);
cc->state = SP_CONNECTOR_CONTEXT_IDLE;
-// sp_event_context_snap_window_closed(event_context);
ret = TRUE;
break;
}
@@ -819,7 +840,6 @@ connector_handle_button_press(SPConnectorContext *const cc, GdkEventButton const
cc_connector_rerouting_finish(cc, &p);
cc->state = SP_CONNECTOR_CONTEXT_IDLE;
-// sp_event_context_snap_window_closed(event_context);
// Don't set ret to TRUE, so we drop through to the
// parent handler which will open the context menu.
@@ -827,7 +847,6 @@ connector_handle_button_press(SPConnectorContext *const cc, GdkEventButton const
else if (cc->npoints != 0) {
spcc_connector_finish(cc);
cc->state = SP_CONNECTOR_CONTEXT_IDLE;
-// sp_event_context_snap_window_closed(event_context);
ret = TRUE;
}
}
@@ -847,7 +866,7 @@ connector_handle_button_press(SPConnectorContext *const cc, GdkEventButton const
cc->xp = bevent.x;
cc->yp = bevent.y;
cc->within_tolerance = true;
-
+
ConnectionPointMap::iterator const& active_knot_it = cc->connpthandles.find( cc->active_handle );
switch (cc->state)
@@ -879,7 +898,6 @@ connector_handle_button_press(SPConnectorContext *const cc, GdkEventButton const
if ( cc->selected_handle )
{
-// sp_event_context_snap_window_open(event_context);
cc->state = SP_CONNECTOR_CONTEXT_DRAGGING;
cc->selection->set( SP_OBJECT( cc->active_shape ) );
}
@@ -933,16 +951,16 @@ connector_handle_motion_notify(SPConnectorContext *const cc, GdkEventMotion cons
if ( cc->mode == SP_CONNECTOR_CONTEXT_DRAWING_MODE )
{
SnapManager &m = dt->namedview->snap_manager;
- m.setup(dt);
-
+
switch (cc->state) {
case SP_CONNECTOR_CONTEXT_DRAGGING:
{
gobble_motion_events(mevent.state);
// This is movement during a connector creation.
if ( cc->npoints > 0 ) {
- m.freeSnapReturnByRef(Inkscape::SnapPreferences::SNAPPOINT_NODE, p,
- Inkscape::SNAPSOURCE_HANDLE);
+ m.setup(dt);
+ m.freeSnapReturnByRef(p, Inkscape::SNAPSOURCE_OTHER_HANDLE);
+ m.unSetup();
cc->selection->clear();
spcc_connector_set_subsequent_point(cc, p);
ret = TRUE;
@@ -954,11 +972,12 @@ connector_handle_motion_notify(SPConnectorContext *const cc, GdkEventMotion cons
gobble_motion_events(GDK_BUTTON1_MASK);
g_assert( SP_IS_PATH(cc->clickeditem));
- m.freeSnapReturnByRef(Inkscape::SnapPreferences::SNAPPOINT_NODE, p,
- Inkscape::SNAPSOURCE_HANDLE);
+ m.setup(dt);
+ m.freeSnapReturnByRef(p, Inkscape::SNAPSOURCE_OTHER_HANDLE);
+ m.unSetup();
// Update the hidden path
- Geom::Matrix i2d = sp_item_i2d_affine(cc->clickeditem);
+ Geom::Matrix i2d = (cc->clickeditem)->i2d_affine();
Geom::Matrix d2i = i2d.inverse();
SPPath *path = SP_PATH(cc->clickeditem);
SPCurve *curve = path->original_curve ? path->original_curve : path->curve;
@@ -985,6 +1004,11 @@ connector_handle_motion_notify(SPConnectorContext *const cc, GdkEventMotion cons
/* This is perfectly valid */
break;
default:
+ if (!sp_event_context_knot_mouseover(cc)) {
+ m.setup(dt);
+ m.preSnap(Inkscape::SnapCandidatePoint(p, Inkscape::SNAPSOURCE_OTHER_HANDLE));
+ m.unSetup();
+ }
break;
}
}
@@ -1018,7 +1042,6 @@ connector_handle_button_release(SPConnectorContext *const cc, GdkEventButton con
SPDocument *doc = sp_desktop_document(desktop);
SnapManager &m = desktop->namedview->snap_manager;
- m.setup(desktop);
Geom::Point const event_w(revent.x, revent.y);
@@ -1030,7 +1053,9 @@ connector_handle_button_release(SPConnectorContext *const cc, GdkEventButton con
//case SP_CONNECTOR_CONTEXT_POINT:
case SP_CONNECTOR_CONTEXT_DRAGGING:
{
- m.freeSnapReturnByRef(Inkscape::SnapPreferences::SNAPPOINT_NODE, p, Inkscape::SNAPSOURCE_HANDLE);
+ m.setup(desktop);
+ m.freeSnapReturnByRef(p, Inkscape::SNAPSOURCE_OTHER_HANDLE);
+ m.unSetup();
if (cc->within_tolerance)
{
@@ -1041,23 +1066,23 @@ connector_handle_button_release(SPConnectorContext *const cc, GdkEventButton con
spcc_connector_set_subsequent_point(cc, p);
spcc_connector_finish_segment(cc, p);
// Test whether we clicked on a connection point
- cc->eid = conn_pt_handle_test(cc, p);
+ /*bool found = */conn_pt_handle_test(cc, p, &cc->ehref, &cc->ecpid);
if (cc->npoints != 0) {
spcc_connector_finish(cc);
}
cc_set_active_conn(cc, cc->newconn);
cc->state = SP_CONNECTOR_CONTEXT_IDLE;
-// sp_event_context_snap_window_closed(event_context);
break;
}
case SP_CONNECTOR_CONTEXT_REROUTING:
{
- m.freeSnapReturnByRef(Inkscape::SnapPreferences::SNAPPOINT_NODE, p, Inkscape::SNAPSOURCE_HANDLE);
+ m.setup(desktop);
+ m.freeSnapReturnByRef(p, Inkscape::SNAPSOURCE_OTHER_HANDLE);
+ m.unSetup();
cc_connector_rerouting_finish(cc, &p);
- sp_document_ensure_up_to_date(doc);
+ doc->ensureUpToDate();
cc->state = SP_CONNECTOR_CONTEXT_IDLE;
-// sp_event_context_snap_window_closed(event_context);
return TRUE;
break;
}
@@ -1074,15 +1099,15 @@ connector_handle_button_release(SPConnectorContext *const cc, GdkEventButton con
switch ( cc->state )
{
case SP_CONNECTOR_CONTEXT_DRAGGING:
-
+
if (!cc->within_tolerance)
{
-// sp_event_context_snap_window_open(event_context);
- m.freeSnapReturnByRef(Inkscape::SnapPreferences::SNAPPOINT_NODE, p, Inkscape::SNAPSOURCE_HANDLE);
+ m.setup(desktop);
+ m.freeSnapReturnByRef(p, Inkscape::SNAPSOURCE_OTHER_HANDLE);
+ m.unSetup();
sp_knot_set_position(cc->selected_handle, p, 0);
-// sp_event_context_snap_window_closed(event_context);
ConnectionPoint& cp = cc->connpthandles[cc->selected_handle];
- cp.pos = p * sp_item_dt2i_affine(cc->active_shape);
+ cp.pos = p * (cc->active_shape)->dt2i_affine();
cc->active_shape->avoidRef->updateConnectionPoint(cp);
}
@@ -1092,19 +1117,19 @@ connector_handle_button_release(SPConnectorContext *const cc, GdkEventButton con
case SP_CONNECTOR_CONTEXT_NEWCONNPOINT:
-// sp_event_context_snap_window_open( event_context );
- m.freeSnapReturnByRef(Inkscape::SnapPreferences::SNAPPOINT_NODE, p, Inkscape::SNAPSOURCE_HANDLE);
-
+ m.setup(desktop);
+ m.freeSnapReturnByRef(p, Inkscape::SNAPSOURCE_OTHER_HANDLE);
+ m.unSetup();
+
sp_knot_set_position(cc->selected_handle, p, 0);
-// sp_event_context_snap_window_closed(event_context);
ConnectionPoint cp;
cp.type = ConnPointUserDefined;
- cp.pos = p * sp_item_dt2i_affine(cc->active_shape);
+ cp.pos = p * (cc->active_shape)->dt2i_affine();
cp.dir = Avoid::ConnDirAll;
g_object_unref(cc->selected_handle);
cc->active_shape->avoidRef->addConnectionPoint(cp);
- sp_document_ensure_up_to_date(doc);
+ doc->ensureUpToDate();
for (ConnectionPointMap::iterator it = cc->connpthandles.begin(); it != cc->connpthandles.end(); ++it)
if (it->second.type == ConnPointUserDefined && it->second.id == cp.id)
{
@@ -1118,7 +1143,7 @@ connector_handle_button_release(SPConnectorContext *const cc, GdkEventButton con
}
}
}
-
+
return ret;
}
if (cc->npoints != 0) {
spcc_connector_finish(cc);
cc->state = SP_CONNECTOR_CONTEXT_IDLE;
-// sp_event_context_snap_window_closed(SP_EVENT_CONTEXT(cc));
ret = TRUE;
}
break;
cc_connector_rerouting_finish(cc, NULL);
- sp_document_undo(doc);
+ DocumentUndo::undo(doc);
cc->state = SP_CONNECTOR_CONTEXT_IDLE;
-// sp_event_context_snap_window_closed(SP_EVENT_CONTEXT(cc));
desktop->messageStack()->flash( Inkscape::NORMAL_MESSAGE,
_("Connector endpoint drag cancelled."));
ret = TRUE;
else if (cc->npoints != 0) {
// if drawing, cancel, otherwise pass it up for deselecting
cc->state = SP_CONNECTOR_CONTEXT_STOP;
-// sp_event_context_snap_window_closed(SP_EVENT_CONTEXT(cc));
spcc_reset_colors(cc);
ret = TRUE;
}
// Obtain original position
ConnectionPoint const& cp = cc->connpthandles[cc->selected_handle];
SPDesktop *desktop = SP_EVENT_CONTEXT_DESKTOP(cc);
- const Geom::Matrix& i2doc = sp_item_i2doc_affine(cc->active_shape);
+ const Geom::Matrix& i2doc = (cc->active_shape)->i2doc_affine();
sp_knot_set_position(cc->selected_handle, cp.pos * i2doc * desktop->doc2dt(), 0);
cc->state = SP_CONNECTOR_CONTEXT_IDLE;
desktop->messageStack()->flash( Inkscape::NORMAL_MESSAGE,
@@ -1192,20 +1214,18 @@ connector_handle_key_press(SPConnectorContext *const cc, guint const keyval)
{
// Put connection point at current position
- SPDesktop *desktop = SP_EVENT_CONTEXT_DESKTOP(cc);
- SnapManager &m = desktop->namedview->snap_manager;
- m.setup(desktop);
Geom::Point p = cc->selected_handle->pos;
- SPEventContext* event_context = SP_EVENT_CONTEXT( cc );
-
+
if (!cc->within_tolerance)
{
-// sp_event_context_snap_window_open(event_context);
- m.freeSnapReturnByRef(Inkscape::SnapPreferences::SNAPPOINT_NODE, p, Inkscape::SNAPSOURCE_HANDLE);
+ SPDesktop *desktop = SP_EVENT_CONTEXT_DESKTOP(cc);
+ SnapManager &m = desktop->namedview->snap_manager;
+ m.setup(desktop);
+ m.freeSnapReturnByRef(p, Inkscape::SNAPSOURCE_OTHER_HANDLE);
+ m.unSetup();
sp_knot_set_position(cc->selected_handle, p, 0);
-// sp_event_context_snap_window_closed(event_context);
ConnectionPoint& cp = cc->connpthandles[cc->selected_handle];
- cp.pos = p * sp_item_dt2i_affine(cc->active_shape);
+ cp.pos = p * (cc->active_shape)->dt2i_affine();
cc->active_shape->avoidRef->updateConnectionPoint(cp);
}
@@ -1229,21 +1249,17 @@ connector_handle_key_press(SPConnectorContext *const cc, guint const keyval)
SnapManager &m = desktop->namedview->snap_manager;
m.setup(desktop);
Geom::Point p = cc->selected_handle->pos;
- SPEventContext* event_context = SP_EVENT_CONTEXT( cc );
-
-// sp_event_context_snap_window_open( event_context );
- m.freeSnapReturnByRef(Inkscape::SnapPreferences::SNAPPOINT_NODE, p, Inkscape::SNAPSOURCE_HANDLE);
-
+ m.freeSnapReturnByRef(p, Inkscape::SNAPSOURCE_OTHER_HANDLE);
+ m.unSetup();
sp_knot_set_position(cc->selected_handle, p, 0);
-// sp_event_context_snap_window_closed(event_context);
ConnectionPoint cp;
cp.type = ConnPointUserDefined;
- cp.pos = p * sp_item_dt2i_affine(cc->active_shape);
+ cp.pos = p * (cc->active_shape)->dt2i_affine();
cp.dir = Avoid::ConnDirAll;
g_object_unref(cc->selected_handle);
cc->active_shape->avoidRef->addConnectionPoint(cp);
- sp_document_ensure_up_to_date(doc);
+ doc->ensureUpToDate();
for (ConnectionPointMap::iterator it = cc->connpthandles.begin(); it != cc->connpthandles.end(); ++it)
if (it->second.type == ConnPointUserDefined && it->second.id == cp.id)
{
cc->selected_handle = NULL;
ret = TRUE;
}
-
+
break;
}
}
@@ -1285,16 +1301,17 @@ cc_connector_rerouting_finish(SPConnectorContext *const cc, Geom::Point *const p
if (p != NULL)
{
// Test whether we clicked on a connection point
- gchar *shape_label = conn_pt_handle_test(cc, *p);
+ gchar *shape_label, *cpid;
+ bool found = conn_pt_handle_test(cc, *p, &shape_label, &cpid);
- if (shape_label) {
+ if (found) {
if (cc->clickedhandle == cc->endpt_handle[0]) {
- sp_object_setAttribute(cc->clickeditem,
- "inkscape:connection-start",shape_label, false);
+ cc->clickeditem->setAttribute("inkscape:connection-start", shape_label, false);
+ cc->clickeditem->setAttribute("inkscape:connection-start-point", cpid, false);
}
else {
- sp_object_setAttribute(cc->clickeditem,
- "inkscape:connection-end",shape_label, false);
+ cc->clickeditem->setAttribute("inkscape:connection-end", shape_label, false);
+ cc->clickeditem->setAttribute("inkscape:connection-end-point", cpid, false);
}
g_free(shape_label);
}
@@ -1302,7 +1319,7 @@ cc_connector_rerouting_finish(SPConnectorContext *const cc, Geom::Point *const p
cc->clickeditem->setHidden(false);
sp_conn_reroute_path_immediate(SP_PATH(cc->clickeditem));
cc->clickeditem->updateRepr();
- sp_document_done(doc, SP_VERB_CONTEXT_CONNECTOR,
+ DocumentUndo::done(doc, SP_VERB_CONTEXT_CONNECTOR,
_("Reroute connector"));
cc_set_active_conn(cc, cc->clickeditem);
}
SPDesktop *desktop = SP_EVENT_CONTEXT_DESKTOP(cc);
SPDocument *doc = sp_desktop_document(desktop);
- Inkscape::XML::Document *xml_doc = sp_document_repr_doc(doc);
+ Inkscape::XML::Document *xml_doc = doc->getReprDoc();
if ( c && !c->is_empty() ) {
/* We actually have something to write */
/* Attach repr */
cc->newconn = SP_ITEM(desktop->currentLayer()->appendChildRepr(repr));
- cc->newconn->transform = sp_item_i2doc_affine(SP_ITEM(desktop->currentLayer())).inverse();
+ cc->newconn->transform = SP_ITEM(desktop->currentLayer())->i2doc_affine().inverse();
bool connection = false;
- sp_object_setAttribute(cc->newconn, "inkscape:connector-type",
- cc->isOrthogonal ? "orthogonal" : "polyline", false);
- sp_object_setAttribute(cc->newconn, "inkscape:connector-curvature",
- Glib::Ascii::dtostr(cc->curvature).c_str(), false);
- if (cc->sid)
+ cc->newconn->setAttribute( "inkscape:connector-type",
+ cc->isOrthogonal ? "orthogonal" : "polyline", false );
+ cc->newconn->setAttribute( "inkscape:connector-curvature",
+ Glib::Ascii::dtostr(cc->curvature).c_str(), false );
+ if (cc->shref)
{
- sp_object_setAttribute(cc->newconn, "inkscape:connection-start",
- cc->sid, false);
+ cc->newconn->setAttribute( "inkscape:connection-start", cc->shref, false);
+ if (cc->scpid) {
+ cc->newconn->setAttribute( "inkscape:connection-start-point", cc->scpid, false);
+ }
connection = true;
}
- if (cc->eid)
+ if (cc->ehref)
{
- sp_object_setAttribute(cc->newconn, "inkscape:connection-end",
- cc->eid, false);
+ cc->newconn->setAttribute( "inkscape:connection-end", cc->ehref, false);
+ if (cc->ecpid) {
+ cc->newconn->setAttribute( "inkscape:connection-end-point", cc->ecpid, false);
+ }
connection = true;
}
// Process pending updates.
cc->newconn->updateRepr();
- sp_document_ensure_up_to_date(doc);
-
+ doc->ensureUpToDate();
+
if (connection) {
// Adjust endpoints to shape edge.
sp_conn_reroute_path_immediate(SP_PATH(cc->newconn));
}
// Only set the selection after we are finished with creating the attributes of
- // the connector. Otherwise, the selection change may alter the defaults for
+ // the connector. Otherwise, the selection change may alter the defaults for
// values like curvature in the connector context, preventing subsequent lookup
// of their original values.
cc->selection->set(repr);
c->unref();
- sp_document_done(doc, SP_VERB_CONTEXT_CONNECTOR, _("Create connector"));
+ DocumentUndo::done(doc, SP_VERB_CONTEXT_CONNECTOR, _("Create connector"));
}
cc->clickedhandle = cc->active_handle;
cc_clear_active_conn(cc);
cc->state = SP_CONNECTOR_CONTEXT_REROUTING;
-// sp_event_context_snap_window_open(SP_EVENT_CONTEXT(cc));
// Disconnect from attached shape
unsigned ind = (cc->active_handle == cc->endpt_handle[0]) ? 0 : 1;
// Show the red path for dragging.
cc->red_curve = SP_PATH(cc->clickeditem)->original_curve ? SP_PATH(cc->clickeditem)->original_curve->copy() : SP_PATH(cc->clickeditem)->curve->copy();
- Geom::Matrix i2d = sp_item_i2d_affine(cc->clickeditem);
+ Geom::Matrix i2d = (cc->clickeditem)->i2d_affine();
cc->red_curve->transform(i2d);
sp_canvas_bpath_set_bpath(SP_CANVAS_BPATH(cc->red_bpath), cc->red_curve);
@@ -1630,7 +1650,7 @@ static void cc_active_shape_add_knot(SPDesktop* desktop, SPItem* item, Connectio
static void cc_set_active_shape(SPConnectorContext *cc, SPItem *item)
{
g_assert(item != NULL );
-
+
std::map<int, ConnectionPoint>* connpts = &item->avoidRef->connection_points;
if (cc->active_shape != item)
if ( connpts->size() )
for (std::map<int, ConnectionPoint>::iterator it = connpts->begin(); it != connpts->end(); ++it)
cc_active_shape_add_knot(cc->desktop, item, cc->connpthandles, it->second);
-
+
// Also add default connection points
// For now, only centre default connection point will
// be available
// Ensure the item's connection_points map
// has been updated
- sp_document_ensure_up_to_date(SP_OBJECT_DOCUMENT(item));
+ item->document->ensureUpToDate();
std::set<int> seen;
for ( ConnectionPointMap::iterator it = cc->connpthandles.begin(); it != cc->connpthandles.end() ;)
g_assert( SP_IS_PATH(item) );
SPCurve *curve = SP_PATH(item)->original_curve ? SP_PATH(item)->original_curve : SP_PATH(item)->curve;
- Geom::Matrix i2d = sp_item_i2d_affine(item);
+ Geom::Matrix i2d = item->i2d_affine();
if (cc->active_conn == item)
{
- // Just adjust handle positions.
- Geom::Point startpt = *(curve->first_point()) * i2d;
- sp_knot_set_position(cc->endpt_handle[0], startpt, 0);
+ if (curve->is_empty())
+ {
+ // Connector is invisible because it is clipped to the boundary of
+ // two overlpapping shapes.
+ sp_knot_hide(cc->endpt_handle[0]);
+ sp_knot_hide(cc->endpt_handle[1]);
+ }
+ else
+ {
+ // Just adjust handle positions.
+ Geom::Point startpt = *(curve->first_point()) * i2d;
+ sp_knot_set_position(cc->endpt_handle[0], startpt, 0);
- Geom::Point endpt = *(curve->last_point()) * i2d;
- sp_knot_set_position(cc->endpt_handle[1], endpt, 0);
+ Geom::Point endpt = *(curve->last_point()) * i2d;
+ sp_knot_set_position(cc->endpt_handle[1], endpt, 0);
+ }
return;
}
G_CALLBACK(endpt_handler), cc);
}
+ if (curve->is_empty())
+ {
+ // Connector is invisible because it is clipped to the boundary
+ // of two overlpapping shapes. So, it doesn't need endpoints.
+ return;
+ }
+
Geom::Point startpt = *(curve->first_point()) * i2d;
sp_knot_set_position(cc->endpt_handle[0], startpt, 0);
bool cc_item_is_connector(SPItem *item)
{
if (SP_IS_PATH(item)) {
- if (SP_PATH(item)->connEndPair.isAutoRoutingConn()) {
- g_assert( SP_PATH(item)->original_curve ? !(SP_PATH(item)->original_curve->is_closed()) : !(SP_PATH(item)->curve->is_closed()) );
+ bool closed = SP_PATH(item)->original_curve ? SP_PATH(item)->original_curve->is_closed() : SP_PATH(item)->curve->is_closed();
+ if (SP_PATH(item)->connEndPair.isAutoRoutingConn() && !closed) {
+ // To be considered a connector, an object must be a non-closed
+ // path that is marked with a "inkscape:connector-type" attribute.
return true;
}
}
char const *value = (set_avoid) ? "true" : NULL;
if (cc_item_is_shape(item)) {
- sp_object_setAttribute(item, "inkscape:connector-avoid",
- value, false);
+ item->setAttribute("inkscape:connector-avoid", value, false);
item->avoidRef->handleSettingChange();
changes++;
}
char *event_desc = (set_avoid) ?
_("Make connectors avoid selected objects") :
_("Make connectors ignore selected objects");
- sp_document_done(document, SP_VERB_CONTEXT_CONNECTOR, event_desc);
+ DocumentUndo::done(document, SP_VERB_CONTEXT_CONNECTOR, event_desc);
}
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 :