X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=src%2Fsp-conn-end-pair.cpp;h=786209fdae0a4a859286a85aed84c59f45e55529;hb=8d358698ecbf192ba7c6dc05d4f7de7592753d9f;hp=ff1005a1636e474c130a08289008ef803c731cb0;hpb=6b15695578f07a3f72c4c9475c1a261a3021472a;p=inkscape.git diff --git a/src/sp-conn-end-pair.cpp b/src/sp-conn-end-pair.cpp index ff1005a16..786209fda 100644 --- a/src/sp-conn-end-pair.cpp +++ b/src/sp-conn-end-pair.cpp @@ -10,6 +10,9 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ +#include +#include + #include "attributes.h" #include "sp-conn-end.h" #include "uri.h" @@ -17,6 +20,9 @@ #include "xml/repr.h" #include "sp-path.h" #include "libavoid/vertices.h" +#include "libavoid/router.h" +#include "document.h" +#include "sp-item-group.h" SPConnEndPair::SPConnEndPair(SPPath *const owner) @@ -46,7 +52,7 @@ SPConnEndPair::~SPConnEndPair() delete _connRef; _connRef = NULL; } - + _invalid_path_connection.disconnect(); _transformed_connection.disconnect(); } @@ -73,12 +79,9 @@ sp_conn_end_pair_build(SPObject *object) } -static void -avoid_conn_move(NR::Matrix const *mp, SPItem *moved_item) +static void +avoid_conn_move(NR::Matrix const */*mp*/, SPItem *moved_item) { - // Detach from objects if attached. - sp_conn_end_detach(moved_item, 0); - sp_conn_end_detach(moved_item, 1); // Reroute connector SPPath *path = SP_PATH(moved_item); path->connEndPair.makePathInvalid(); @@ -92,9 +95,10 @@ SPConnEndPair::setAttr(unsigned const key, gchar const *const value) if (key == SP_ATTR_CONNECTOR_TYPE) { if (value && (strcmp(value, "polyline") == 0)) { _connType = SP_CONNECTOR_POLYLINE; - + + Avoid::Router *router = _path->document->router; GQuark itemID = g_quark_from_string(SP_OBJECT(_path)->id); - _connRef = new Avoid::ConnRef(itemID); + _connRef = new Avoid::ConnRef(router, itemID); _invalid_path_connection = connectInvalidPath( sigc::ptr_fun(&sp_conn_adjust_invalid_path)); _transformed_connection = _path->connectTransformed( @@ -102,7 +106,7 @@ SPConnEndPair::setAttr(unsigned const key, gchar const *const value) } else { _connType = SP_CONNECTOR_NOAVOID; - + if (_connRef) { _connRef->removeFromGraph(); delete _connRef; @@ -114,7 +118,7 @@ SPConnEndPair::setAttr(unsigned const key, gchar const *const value) return; } - + unsigned const handle_ix = key - SP_ATTR_CONNECTION_START; g_assert( handle_ix <= 1 ); this->_connEnd[handle_ix]->setAttacherHref(value); @@ -138,6 +142,20 @@ void SPConnEndPair::getAttachedItems(SPItem *h2attItem[2]) const { for (unsigned h = 0; h < 2; ++h) { h2attItem[h] = this->_connEnd[h]->ref.getObject(); + + // Deal with the case of the attached object being an empty group. + // A group containing no items does not have a valid bbox, so + // causes problems for the auto-routing code. Also, since such a + // group no longer has an onscreen representation and can only be + // selected through the XML editor, it makes sense just to detach + // connectors from them. + if (SP_IS_GROUP(h2attItem[h])) { + if (SP_GROUP(h2attItem[h])->group->getItemCount() == 0) { + // This group is empty, so detach. + sp_conn_end_detach(_path, h); + h2attItem[h] = NULL; + } + } } } @@ -146,19 +164,24 @@ SPConnEndPair::getEndpoints(NR::Point endPts[]) const { SPCurve *curve = _path->curve; SPItem *h2attItem[2]; getAttachedItems(h2attItem); - + for (unsigned h = 0; h < 2; ++h) { if ( h2attItem[h] ) { - NR::Rect const bbox = h2attItem[h]->invokeBbox(sp_item_i2doc_affine(h2attItem[h])); - endPts[h] = bbox.midpoint(); + NR::Maybe bbox = h2attItem[h]->getBounds(from_2geom(sp_item_i2doc_affine(h2attItem[h]))); + if (bbox) { + endPts[h] = bbox->midpoint(); + } else { + // FIXME + endPts[h] = NR::Point(0, 0); + } } - else + else { if (h == 0) { - endPts[h] = sp_curve_first_point(curve); + endPts[h] = curve->first_point(); } else { - endPts[h] = sp_curve_last_point(curve); + endPts[h] = curve->last_point(); } } } @@ -177,7 +200,7 @@ static void emitPathInvalidationNotification(void *ptr) // then all connectors (that require it) will be rerouted. Otherwise, // one connector could get rerouted several times as a result of // dragging a couple of shapes. - + SPPath *path = SP_PATH(ptr); path->connEndPair._invalid_path_signal.emit(path); } @@ -205,15 +228,40 @@ SPConnEndPair::update(void) NR::Point endPt[2]; getEndpoints(endPt); - Avoid::Point src = { endPt[0][NR::X], endPt[0][NR::Y] }; - Avoid::Point dst = { endPt[1][NR::X], endPt[1][NR::Y] }; + Avoid::Point src(endPt[0][NR::X], endPt[0][NR::Y]); + Avoid::Point dst(endPt[1][NR::X], endPt[1][NR::Y]); _connRef->lateSetup(src, dst); _connRef->setCallback(&emitPathInvalidationNotification, _path); } + // Store the ID of the objects attached to the connector. + storeIds(); } } - + + +void SPConnEndPair::storeIds(void) +{ + if (_connEnd[0]->href) { + // href begins with a '#' which we don't want. + const char *startId = _connEnd[0]->href + 1; + GQuark itemId = g_quark_from_string(startId); + _connRef->setEndPointId(Avoid::VertID::src, itemId); + } + else { + _connRef->setEndPointId(Avoid::VertID::src, 0); + } + if (_connEnd[1]->href) { + // href begins with a '#' which we don't want. + const char *endId = _connEnd[1]->href + 1; + GQuark itemId = g_quark_from_string(endId); + _connRef->setEndPointId(Avoid::VertID::tar, itemId); + } + else { + _connRef->setEndPointId(Avoid::VertID::tar, 0); + } +} + bool SPConnEndPair::isAutoRoutingConn(void) @@ -223,7 +271,7 @@ SPConnEndPair::isAutoRoutingConn(void) } return false; } - + void SPConnEndPair::makePathInvalid(void) { @@ -243,9 +291,9 @@ SPConnEndPair::reroutePath(void) NR::Point endPt[2]; getEndpoints(endPt); - Avoid::Point src = { endPt[0][NR::X], endPt[0][NR::Y] }; - Avoid::Point dst = { endPt[1][NR::X], endPt[1][NR::Y] }; - + Avoid::Point src(endPt[0][NR::X], endPt[0][NR::Y]); + Avoid::Point dst(endPt[1][NR::X], endPt[1][NR::Y]); + _connRef->updateEndPoint(Avoid::VertID::src, src); _connRef->updateEndPoint(Avoid::VertID::tar, dst); @@ -253,13 +301,13 @@ SPConnEndPair::reroutePath(void) Avoid::PolyLine route = _connRef->route(); _connRef->calcRouteDist(); - - sp_curve_reset(curve); - sp_curve_moveto(curve, endPt[0]); + + curve->reset(); + curve->moveto(endPt[0]); for (int i = 1; i < route.pn; ++i) { NR::Point p(route.ps[i].x, route.ps[i].y); - sp_curve_lineto(curve, p); + curve->lineto(p); } }