X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=src%2Fconnector-context.cpp;h=476b87bc633acea8dda52cbd0c523d5ea6536991;hb=9ba7eae5f79161f75414ec25341ccf26417b0e94;hp=f3296aebfd0a3459bfcf3ff90f30d5fbdede2bfc;hpb=e8325ddfe05ac8dd00fbf1e25a583ee33887c031;p=inkscape.git diff --git a/src/connector-context.cpp b/src/connector-context.cpp index f3296aebf..476b87bc6 100644 --- a/src/connector-context.cpp +++ b/src/connector-context.cpp @@ -9,7 +9,7 @@ * Released under GNU GPL, read the file 'COPYING' for more information * * TODO: - * o Have shapes avoid coonvex hulls of objects, rather than their + * o Have shapes avoid convex hulls of objects, rather than their * bounding box. Possibly implement the unfinished ConvexHull * class in libnr. * (HOWEVER, using the convex hull C of a shape S does the wrong thing if a @@ -17,15 +17,16 @@ * an object involves going inside C but without entering S.) * o Draw connectors to shape edges rather than bounding box. * o Show a visual indicator for objects with the 'avoid' property set. + * o Allow user to change a object between a path and connector through + * the interface. * o Create an interface for setting markers (arrow heads). * o Better distinguish between paths and connectors to prevent problems * in the node tool and paths accidently being turned into connectors * in the connector tool. Perhaps have a way to convert between. * o Only call libavoid's updateEndPoint as required. Currently we do it * for both endpoints, even if only one is moving. - * o Cleanup to remove unecessary borrowed DrawContext code. * o Allow user-placeable connection points. - * o Deal sanely with connectors with both endpoints attached to the + * o Deal sanely with connectors with both endpoints attached to the * same connection point, and drawing of connectors attaching * overlaping shapes (currently tries to adjust connector to be * outside both bounding boxes). @@ -34,7 +35,7 @@ * attached to each other. * e.g., detach connector when it is moved or transformed in * one of the other contexts. - * o Cope with shapes whose ids change when they have attached + * o Cope with shapes whose ids change when they have attached * connectors. * o gobble_motion_events(GDK_BUTTON1_MASK)?; * @@ -67,7 +68,9 @@ #include "conn-avoid-ref.h" #include "libavoid/vertices.h" #include "context-fns.h" - +#include "sp-namedview.h" +#include "sp-text.h" +#include "sp-flowtext.h" static void sp_connector_context_class_init(SPConnectorContextClass *klass); @@ -101,6 +104,8 @@ static void cc_clear_active_conn(SPConnectorContext *cc); static gchar *conn_pt_handle_test(SPConnectorContext *cc, NR::Point& w); static bool cc_item_is_shape(SPItem *item); static void cc_selection_changed(Inkscape::Selection *selection, gpointer data); +static void cc_connector_rerouting_finish(SPConnectorContext *const cc, + NR::Point *const p); static void shape_event_attr_deleted(Inkscape::XML::Node *repr, Inkscape::XML::Node *child, Inkscape::XML::Node *ref, gpointer data); @@ -183,12 +188,12 @@ sp_connector_context_init(SPConnectorContext *cc) ec->yp = 0; cc->red_color = 0xff00007f; - + cc->newconn = NULL; cc->newConnRef = NULL; - + cc->sel_changed_connection = sigc::connection(); - + cc->active_shape = NULL; cc->active_shape_repr = NULL; cc->active_shape_layer_repr = NULL; @@ -197,10 +202,10 @@ sp_connector_context_init(SPConnectorContext *cc) cc->active_conn_repr = NULL; cc->active_handle = NULL; - + cc->clickeditem = NULL; cc->clickedhandle = NULL; - + cc->connpthandle = NULL; for (int i = 0; i < 2; ++i) { cc->endpt_handle[i] = NULL; @@ -254,15 +259,15 @@ sp_connector_context_setup(SPEventContext *ec) ((SPEventContextClass *) parent_class)->setup(ec); } - cc->selection = SP_DT_SELECTION(dt); + cc->selection = sp_desktop_selection(dt); cc->sel_changed_connection.disconnect(); cc->sel_changed_connection = cc->selection->connectChanged( sigc::bind(sigc::ptr_fun(&cc_selection_changed), (gpointer) cc)); - + /* Create red bpath */ - cc->red_bpath = sp_canvas_bpath_new(SP_DT_SKETCH(ec->desktop), NULL); + cc->red_bpath = sp_canvas_bpath_new(sp_desktop_sketch(ec->desktop), NULL); sp_canvas_bpath_set_stroke(SP_CANVAS_BPATH(cc->red_bpath), cc->red_color, 1.0, SP_STROKE_LINEJOIN_MITER, SP_STROKE_LINECAP_BUTT); sp_canvas_bpath_set_fill(SP_CANVAS_BPATH(cc->red_bpath), 0x00000000, @@ -275,7 +280,7 @@ sp_connector_context_setup(SPEventContext *ec) // Notice the initial selection. cc_selection_changed(cc->selection, (gpointer) cc); - + if (prefs_get_int_attribute("tools.connector", "selcue", 0) != 0) { ec->enableSelectionCue(); } @@ -290,13 +295,13 @@ static void sp_connector_context_finish(SPEventContext *ec) { SPConnectorContext *cc = SP_CONNECTOR_CONTEXT(ec); - + spcc_connector_finish(cc); if (((SPEventContextClass *) parent_class)->finish) { ((SPEventContextClass *) parent_class)->finish(ec); } - + if (cc->selection) { cc->selection = NULL; } @@ -327,7 +332,7 @@ cc_clear_active_shape(SPConnectorContext *cc) sp_repr_remove_listener_by_data(cc->active_shape_repr, cc); Inkscape::GC::release(cc->active_shape_repr); cc->active_shape_repr = NULL; - + sp_repr_remove_listener_by_data(cc->active_shape_layer_repr, cc); Inkscape::GC::release(cc->active_shape_layer_repr); cc->active_shape_layer_repr = NULL; @@ -370,7 +375,7 @@ conn_pt_handle_test(SPConnectorContext *cc, NR::Point& p) { // TODO: this will need to change when there are more connection // points available for each shape. - + SPKnot *centerpt = cc->connpthandle; if (cc->active_handle && (cc->active_handle == centerpt)) { @@ -493,7 +498,7 @@ connector_handle_button_press(SPConnectorContext *const cc, GdkEventButton const if (Inkscape::have_viable_layer(desktop, cc->_message_context) == false) { return TRUE; } - + NR::Point const event_w(bevent.x, bevent.y); connector_drag_origin_w = event_w; @@ -508,35 +513,35 @@ connector_handle_button_press(SPConnectorContext *const cc, GdkEventButton const if ( cc->npoints == 0 ) { /* Set start anchor */ NR::Point p; - + cc_clear_active_conn(cc); SP_EVENT_CONTEXT_DESKTOP(cc)->messageStack()->flash(Inkscape::NORMAL_MESSAGE, _("Creating new connector")); /* Create green anchor */ p = event_dt; - + // Test whether we clicked on a connection point cc->sid = conn_pt_handle_test(cc, p); - + if (!cc->sid) { // This is the first point, so just snap it to the grid // as there's no other points to go off. - SnapManager const m(cc->desktop->namedview); + SnapManager const &m = cc->desktop->namedview->snap_manager; p = m.freeSnap(Inkscape::Snapper::SNAP_POINT | Inkscape::Snapper::BBOX_POINT, p, NULL).getPoint(); - } + } spcc_connector_set_initial_point(cc, p); - + } cc->state = SP_CONNECTOR_CONTEXT_DRAGGING; ret = TRUE; break; - } + } case SP_CONNECTOR_CONTEXT_DRAGGING: { // This is the second click of a connector creation. - + spcc_connector_set_subsequent_point(cc, p); spcc_connector_finish_segment(cc, p); // Test whether we clicked on a connection point @@ -558,7 +563,17 @@ connector_handle_button_press(SPConnectorContext *const cc, GdkEventButton const break; } } else if (bevent.button == 3) { - if (cc->npoints != 0) { + if (cc->state == SP_CONNECTOR_CONTEXT_REROUTING) { + // A context menu is going to be triggered here, + // so end the rerouting operation. + cc_connector_rerouting_finish(cc, &p); + + cc->state = SP_CONNECTOR_CONTEXT_IDLE; + + // Don't set ret to TRUE, so we drop through to the + // parent handler which will open the context menu. + } + else if (cc->npoints != 0) { spcc_connector_finish(cc); ret = TRUE; } @@ -600,7 +615,7 @@ connector_handle_motion_notify(SPConnectorContext *const cc, GdkEventMotion cons case SP_CONNECTOR_CONTEXT_DRAGGING: { // This is movement during a connector creation. - + if ( cc->npoints > 0 ) { cc->selection->clear(); spcc_connector_set_subsequent_point(cc, p); @@ -653,7 +668,7 @@ connector_handle_button_release(SPConnectorContext *const cc, GdkEventButton con if ( revent.button == 1 ) { SPDesktop *desktop = SP_EVENT_CONTEXT_DESKTOP(cc); - SPDocument *doc = SP_DT_DOCUMENT(desktop); + SPDocument *doc = sp_desktop_document(desktop); NR::Point const event_w(revent.x, revent.y); @@ -683,29 +698,8 @@ connector_handle_button_release(SPConnectorContext *const cc, GdkEventButton con } case SP_CONNECTOR_CONTEXT_REROUTING: { - // Clear the temporary path: - sp_curve_reset(cc->red_curve); - sp_canvas_bpath_set_bpath(SP_CANVAS_BPATH(cc->red_bpath), NULL); - - // Test whether we clicked on a connection point - gchar *shape_label = conn_pt_handle_test(cc, p); - - if (shape_label) { - if (cc->clickedhandle == cc->endpt_handle[0]) { - sp_object_setAttribute(cc->clickeditem, - "inkscape:connection-start",shape_label, false); - } - else { - sp_object_setAttribute(cc->clickeditem, - "inkscape:connection-end",shape_label, false); - } - g_free(shape_label); - } - cc->clickeditem->setHidden(false); - sp_conn_adjust_path(SP_PATH(cc->clickeditem)); - cc->clickeditem->updateRepr(); - sp_document_done(doc); - cc_set_active_conn(cc, cc->clickeditem); + cc_connector_rerouting_finish(cc, &p); + sp_document_ensure_up_to_date(doc); cc->state = SP_CONNECTOR_CONTEXT_IDLE; return TRUE; @@ -738,7 +732,21 @@ connector_handle_key_press(SPConnectorContext *const cc, guint const keyval) } break; case GDK_Escape: - if (cc->npoints != 0) { + if (cc->state == SP_CONNECTOR_CONTEXT_REROUTING) { + + SPDesktop *desktop = SP_EVENT_CONTEXT_DESKTOP(cc); + SPDocument *doc = sp_desktop_document(desktop); + + cc_connector_rerouting_finish(cc, NULL); + + sp_document_undo(doc); + + cc->state = SP_CONNECTOR_CONTEXT_IDLE; + desktop->messageStack()->flash( Inkscape::NORMAL_MESSAGE, + _("Connector endpoint drag canceled.")); + ret = TRUE; + } + else if (cc->npoints != 0) { // if drawing, cancel, otherwise pass it up for deselecting cc->state = SP_CONNECTOR_CONTEXT_STOP; spcc_reset_colors(cc); @@ -752,13 +760,49 @@ connector_handle_key_press(SPConnectorContext *const cc, guint const keyval) } +static void +cc_connector_rerouting_finish(SPConnectorContext *const cc, NR::Point *const p) +{ + SPDesktop *desktop = SP_EVENT_CONTEXT_DESKTOP(cc); + SPDocument *doc = sp_desktop_document(desktop); + + // Clear the temporary path: + sp_curve_reset(cc->red_curve); + sp_canvas_bpath_set_bpath(SP_CANVAS_BPATH(cc->red_bpath), NULL); + + if (p != NULL) + { + // Test whether we clicked on a connection point + gchar *shape_label = conn_pt_handle_test(cc, *p); + + if (shape_label) { + if (cc->clickedhandle == cc->endpt_handle[0]) { + sp_object_setAttribute(cc->clickeditem, + "inkscape:connection-start",shape_label, false); + } + else { + sp_object_setAttribute(cc->clickeditem, + "inkscape:connection-end",shape_label, false); + } + g_free(shape_label); + } + } + cc->clickeditem->setHidden(false); + sp_conn_adjust_path(SP_PATH(cc->clickeditem)); + cc->clickeditem->updateRepr(); + sp_document_done(doc, SP_VERB_CONTEXT_CONNECTOR, + _("Reroute connector")); + cc_set_active_conn(cc, cc->clickeditem); +} + + static void spcc_reset_colors(SPConnectorContext *cc) { /* Red */ sp_curve_reset(cc->red_curve); sp_canvas_bpath_set_bpath(SP_CANVAS_BPATH(cc->red_bpath), NULL); - + sp_curve_reset(cc->green_curve); cc->npoints = 0; } @@ -784,11 +828,11 @@ spcc_connector_set_subsequent_point(SPConnectorContext *const cc, NR::Point cons SPDesktop *dt = cc->desktop; NR::Point o = dt->dt2doc(cc->p[0]); NR::Point d = dt->dt2doc(p); - Avoid::Point src = { o[NR::X], o[NR::Y] }; - Avoid::Point dst = { d[NR::X], d[NR::Y] }; + Avoid::Point src(o[NR::X], o[NR::Y]); + Avoid::Point dst(d[NR::X], d[NR::Y]); if (!cc->newConnRef) { - Avoid::Router *router = SP_DT_DOCUMENT(dt)->router; + Avoid::Router *router = sp_desktop_document(dt)->router; cc->newConnRef = new Avoid::ConnRef(router, 0, src, dst); cc->newConnRef->updateEndPoint(Avoid::VertID::src, src); } @@ -863,12 +907,13 @@ spcc_flush_white(SPConnectorContext *cc, SPCurve *gc) sp_desktop_dt2root_affine(SP_EVENT_CONTEXT_DESKTOP(cc))); SPDesktop *desktop = SP_EVENT_CONTEXT_DESKTOP(cc); - SPDocument *doc = SP_DT_DOCUMENT(desktop); + SPDocument *doc = sp_desktop_document(desktop); + Inkscape::XML::Document *xml_doc = sp_document_repr_doc(doc); if ( c && !sp_curve_empty(c) ) { /* We actually have something to write */ - Inkscape::XML::Node *repr = sp_repr_new("svg:path"); + Inkscape::XML::Node *repr = xml_doc->createElement("svg:path"); /* Set style */ sp_desktop_apply_style_tool(desktop, repr, "tools.connector", false); @@ -911,7 +956,7 @@ spcc_flush_white(SPConnectorContext *cc, SPCurve *gc) sp_curve_unref(c); /* Flush pending updates */ - sp_document_done(doc); + sp_document_done(doc, SP_VERB_CONTEXT_CONNECTOR, _("Create connector")); sp_document_ensure_up_to_date(doc); } @@ -941,7 +986,7 @@ spcc_connector_finish(SPConnectorContext *const cc) spcc_concat_colors_and_flush(cc); cc->npoints = 0; - + if (cc->newConnRef) { cc->newConnRef->removeFromGraph(); delete cc->newConnRef; @@ -955,6 +1000,8 @@ static gboolean cc_generic_knot_handler(SPCanvasItem *, GdkEvent *event, SPKnot *knot) { g_assert (knot != NULL); + + g_object_ref(knot); SPConnectorContext *cc = SP_CONNECTOR_CONTEXT( knot->desktop->event_context); @@ -963,11 +1010,8 @@ cc_generic_knot_handler(SPCanvasItem *, GdkEvent *event, SPKnot *knot) switch (event->type) { case GDK_ENTER_NOTIFY: - gtk_object_set (GTK_OBJECT (knot->item), "fill_color", - knot->fill [SP_KNOT_STATE_MOUSEOVER], NULL); - gtk_object_set (GTK_OBJECT (knot->item), "stroke_color", - knot->stroke [SP_KNOT_STATE_MOUSEOVER], NULL); - + sp_knot_set_flag(knot, SP_KNOT_MOUSEOVER, TRUE); + cc->active_handle = knot; if (knot->tip) @@ -975,32 +1019,31 @@ cc_generic_knot_handler(SPCanvasItem *, GdkEvent *event, SPKnot *knot) knot->desktop->event_context->defaultMessageContext()->set( Inkscape::NORMAL_MESSAGE, knot->tip); } - + consumed = TRUE; break; case GDK_LEAVE_NOTIFY: - gtk_object_set (GTK_OBJECT (knot->item), "fill_color", - knot->fill [SP_KNOT_STATE_NORMAL], NULL); - gtk_object_set (GTK_OBJECT (knot->item), "stroke_color", - knot->stroke [SP_KNOT_STATE_NORMAL], NULL); - - cc->active_handle = NULL; + sp_knot_set_flag(knot, SP_KNOT_MOUSEOVER, FALSE); + cc->active_handle = NULL; + if (knot->tip) { knot->desktop->event_context->defaultMessageContext()->clear(); } - + consumed = TRUE; break; default: break; } + + g_object_unref(knot); return consumed; } -static gboolean +static gboolean endpt_handler(SPKnot *knot, GdkEvent *event, SPConnectorContext *cc) { g_assert( SP_IS_CONNECTOR_CONTEXT(cc) ); @@ -1016,11 +1059,11 @@ endpt_handler(SPKnot *knot, GdkEvent *event, SPConnectorContext *cc) cc->clickedhandle = cc->active_handle; cc_clear_active_conn(cc); cc->state = SP_CONNECTOR_CONTEXT_REROUTING; - + // Disconnect from attached shape unsigned ind = (cc->active_handle == cc->endpt_handle[0]) ? 0 : 1; sp_conn_end_detach(cc->clickeditem, ind); - + NR::Point origin; if (cc->clickedhandle == cc->endpt_handle[0]) { origin = cc->endpt_handle[1]->pos; @@ -1054,69 +1097,60 @@ endpt_handler(SPKnot *knot, GdkEvent *event, SPConnectorContext *cc) static void cc_set_active_shape(SPConnectorContext *cc, SPItem *item) { g_assert(item != NULL ); - + cc->active_shape = item; // Remove existing active shape listeners if (cc->active_shape_repr) { sp_repr_remove_listener_by_data(cc->active_shape_repr, cc); Inkscape::GC::release(cc->active_shape_repr); - + sp_repr_remove_listener_by_data(cc->active_shape_layer_repr, cc); Inkscape::GC::release(cc->active_shape_layer_repr); } - + // Listen in case the active shape changes - cc->active_shape_repr = SP_OBJECT_REPR(item); + cc->active_shape_repr = SP_OBJECT_REPR(item); if (cc->active_shape_repr) { Inkscape::GC::anchor(cc->active_shape_repr); sp_repr_add_listener(cc->active_shape_repr, &shape_repr_events, cc); - + cc->active_shape_layer_repr = cc->active_shape_repr->parent(); Inkscape::GC::anchor(cc->active_shape_layer_repr); sp_repr_add_listener(cc->active_shape_layer_repr, &layer_repr_events, cc); } - + // Set center connection point. if ( cc->connpthandle == NULL ) { - SPKnot * knot = (SPKnot*)g_object_new (SP_TYPE_KNOT, 0); - - knot->desktop = cc->desktop; - knot->flags = SP_KNOT_VISIBLE; - - knot->item = sp_canvas_item_new (SP_DT_CONTROLS(cc->desktop), - SP_TYPE_CTRL, - "anchor", GTK_ANCHOR_CENTER, - "filled", TRUE, - "stroked", TRUE, - "mode", SP_KNOT_MODE_XOR, - NULL); - - gtk_signal_connect (GTK_OBJECT (knot->item), "event", - GTK_SIGNAL_FUNC (cc_generic_knot_handler), knot); - - knot->fill [SP_KNOT_STATE_NORMAL] = 0xffffff00; - knot->fill [SP_KNOT_STATE_MOUSEOVER] = 0xff0000ff; - knot->stroke [SP_KNOT_STATE_NORMAL] = 0x01000000; - - g_object_set(G_OBJECT(knot), - "shape", SP_KNOT_SHAPE_SQUARE, - "size", 8, - "anchor", GTK_ANCHOR_CENTER, - "tip", _("Connection point: click or drag to create a new connector"), - NULL); - + SPKnot *knot = sp_knot_new(cc->desktop, + _("Connection point: click or drag to create a new connector")); + + knot->setShape(SP_KNOT_SHAPE_SQUARE); + knot->setSize(8); + knot->setAnchor(GTK_ANCHOR_CENTER); + knot->setFill(0xffffff00, 0xff0000ff, 0xff0000ff); + sp_knot_update_ctrl(knot); + + // We don't want to use the standard knot handler, + //since we don't want this knot to be draggable. + g_signal_handler_disconnect(G_OBJECT(knot->item), + knot->_event_handler_id); + knot->_event_handler_id = 0; + + gtk_signal_connect(GTK_OBJECT(knot->item), "event", + GTK_SIGNAL_FUNC(cc_generic_knot_handler), knot); + cc->connpthandle = knot; } - + NR::Rect bbox = sp_item_bbox_desktop(cc->active_shape); NR::Point center = bbox.midpoint(); sp_knot_set_position(cc->connpthandle, ¢er, 0); sp_knot_show(cc->connpthandle); - + } @@ -1127,19 +1161,19 @@ cc_set_active_conn(SPConnectorContext *cc, SPItem *item) SPCurve *curve = SP_SHAPE(SP_PATH(item))->curve; NR::Matrix i2d = sp_item_i2d_affine(item); - + if (cc->active_conn == item) { // Just adjust handle positions. NR::Point startpt = sp_curve_first_point(curve) * i2d; sp_knot_set_position(cc->endpt_handle[0], &startpt, 0); - + NR::Point endpt = sp_curve_last_point(curve) * i2d; sp_knot_set_position(cc->endpt_handle[1], &endpt, 0); - + return; } - + cc->active_conn = item; // Remove existing active conn listeners @@ -1148,9 +1182,9 @@ cc_set_active_conn(SPConnectorContext *cc, SPItem *item) Inkscape::GC::release(cc->active_conn_repr); cc->active_conn_repr = NULL; } - + // Listen in case the active conn changes - cc->active_conn_repr = SP_OBJECT_REPR(item); + cc->active_conn_repr = SP_OBJECT_REPR(item); if (cc->active_conn_repr) { Inkscape::GC::anchor(cc->active_conn_repr); sp_repr_add_listener(cc->active_conn_repr, &shape_repr_events, cc); @@ -1160,36 +1194,28 @@ cc_set_active_conn(SPConnectorContext *cc, SPItem *item) // Create the handle if it doesn't exist if ( cc->endpt_handle[i] == NULL ) { - SPKnot * knot = (SPKnot*) g_object_new (SP_TYPE_KNOT, 0); + SPKnot *knot = sp_knot_new(cc->desktop, + _("Connector endpoint: drag to reroute or connect to new shapes")); - knot->desktop = cc->desktop; - knot->flags = SP_KNOT_VISIBLE; + knot->setShape(SP_KNOT_SHAPE_SQUARE); + knot->setSize(7); + knot->setAnchor(GTK_ANCHOR_CENTER); + knot->setFill(0xffffff00, 0xff0000ff, 0xff0000ff); + knot->setStroke(0x000000ff, 0x000000ff, 0x000000ff); + sp_knot_update_ctrl(knot); - knot->item = sp_canvas_item_new (SP_DT_CONTROLS (cc->desktop), - SP_TYPE_CTRL, - "anchor", GTK_ANCHOR_CENTER, - "filled", TRUE, - "stroked", TRUE, - "mode", SP_KNOT_MODE_XOR, - NULL); + // We don't want to use the standard knot handler, + //since we don't want this knot to be draggable. + g_signal_handler_disconnect(G_OBJECT(knot->item), + knot->_event_handler_id); + knot->_event_handler_id = 0; - knot->fill [SP_KNOT_STATE_NORMAL] = 0xffffff00; - knot->stroke [SP_KNOT_STATE_NORMAL] = 0x000000ff; - knot->stroke [SP_KNOT_STATE_DRAGGING] = 0x000000ff; - knot->stroke [SP_KNOT_STATE_MOUSEOVER] = 0x000000ff; - - g_object_set(G_OBJECT(knot), - "shape", SP_KNOT_SHAPE_DIAMOND, - "size", 10, - "tip", _("Connector endpoint: drag to reroute or connect to new shapes"), - NULL); - - gtk_signal_connect (GTK_OBJECT (knot->item), "event", - GTK_SIGNAL_FUNC (cc_generic_knot_handler), knot); + gtk_signal_connect(GTK_OBJECT(knot->item), "event", + GTK_SIGNAL_FUNC(cc_generic_knot_handler), knot); cc->endpt_handle[i] = knot; } - + // Remove any existing handlers if (cc->endpt_handler_id[i]) { g_signal_handlers_disconnect_by_func( @@ -1198,20 +1224,20 @@ cc_set_active_conn(SPConnectorContext *cc, SPItem *item) cc->endpt_handler_id[i] = 0; } - // Setup handlers for connector endpoints, this is + // Setup handlers for connector endpoints, this is // is as 'after' so that cc_generic_knot_handler is // triggered first for any endpoint. cc->endpt_handler_id[i] = g_signal_connect_after( G_OBJECT(cc->endpt_handle[i]->item), "event", G_CALLBACK(endpt_handler), cc); } - + NR::Point startpt = sp_curve_first_point(curve) * i2d; sp_knot_set_position(cc->endpt_handle[0], &startpt, 0); - + NR::Point endpt = sp_curve_last_point(curve) * i2d; sp_knot_set_position(cc->endpt_handle[1], &endpt, 0); - + sp_knot_show(cc->endpt_handle[0]); sp_knot_show(cc->endpt_handle[1]); } @@ -1226,6 +1252,12 @@ static bool cc_item_is_shape(SPItem *item) return false; } } + else if (SP_IS_TEXT(item) || SP_IS_FLOWTEXT(item)) { + if (prefs_get_int_attribute("tools.connector", "ignoretext", 1) == 1) { + // Don't count text as a shape we can connect connector to. + return false; + } + } return true; } @@ -1241,7 +1273,7 @@ bool cc_item_is_connector(SPItem *item) return false; } - + void cc_selection_set_avoid(bool const set_avoid) { SPDesktop *desktop = inkscape_active_desktop(); @@ -1249,9 +1281,9 @@ void cc_selection_set_avoid(bool const set_avoid) return; } - SPDocument *document = SP_DT_DOCUMENT(desktop); + SPDocument *document = sp_desktop_document(desktop); - Inkscape::Selection *selection = SP_DT_SELECTION(desktop); + Inkscape::Selection *selection = sp_desktop_selection(desktop); GSList *l = (GSList *) selection->itemList(); @@ -1261,14 +1293,14 @@ void cc_selection_set_avoid(bool const set_avoid) SPItem *item = (SPItem *) l->data; char const *value = (set_avoid) ? "true" : NULL; - + if (cc_item_is_shape(item)) { sp_object_setAttribute(item, "inkscape:connector-avoid", value, false); item->avoidRef->handleSettingChange(); changes++; } - + l = l->next; } @@ -1278,9 +1310,12 @@ void cc_selection_set_avoid(bool const set_avoid) return; } - sp_document_done(document); + 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); } - + static void cc_selection_changed(Inkscape::Selection *selection, gpointer data) @@ -1289,7 +1324,7 @@ cc_selection_changed(Inkscape::Selection *selection, gpointer data) //SPEventContext *ec = SP_EVENT_CONTEXT(cc); SPItem *item = selection->singleItem(); - + if (cc->active_conn == item) { // Nothing to change. @@ -1300,7 +1335,7 @@ cc_selection_changed(Inkscape::Selection *selection, gpointer data) cc_clear_active_conn(cc); return; } - + if (cc_item_is_connector(item)) { cc_set_active_conn(cc, item); } @@ -1328,7 +1363,7 @@ shape_event_attr_changed(Inkscape::XML::Node *repr, gchar const *name, { g_assert(data); SPConnectorContext *cc = SP_CONNECTOR_CONTEXT(data); - + // Look for changes than result in onscreen movement. if (!strcmp(name, "d") || !strcmp(name, "x") || !strcmp(name, "y") || !strcmp(name, "width") || !strcmp(name, "height") ||