diff options
| author | Jabier Arraiza Cenoz <jabier.arraiza@marker.es> | 2015-10-12 10:37:15 +0000 |
|---|---|---|
| committer | Jabiertxof <jtx@jtx.marker.es> | 2015-10-12 10:37:15 +0000 |
| commit | 2653fd7c3a138f91181f7bb64e1fd342c943ee7b (patch) | |
| tree | 208c04e67468b39db595cdb539ed3914a7c9d7af /src | |
| parent | update to trunk (diff) | |
| download | inkscape-2653fd7c3a138f91181f7bb64e1fd342c943ee7b.tar.gz inkscape-2653fd7c3a138f91181f7bb64e1fd342c943ee7b.zip | |
Convert Measure to Item done
(bzr r14393.1.17)
Diffstat (limited to 'src')
| -rw-r--r-- | src/ui/tools/measure-tool.cpp | 905 | ||||
| -rw-r--r-- | src/ui/tools/measure-tool.h | 21 | ||||
| -rw-r--r-- | src/widgets/measure-toolbar.cpp | 17 | ||||
| -rw-r--r-- | src/widgets/toolbox.cpp | 1 |
4 files changed, 638 insertions, 306 deletions
diff --git a/src/ui/tools/measure-tool.cpp b/src/ui/tools/measure-tool.cpp index 585128135..76b8e931e 100644 --- a/src/ui/tools/measure-tool.cpp +++ b/src/ui/tools/measure-tool.cpp @@ -4,6 +4,7 @@ * Authors: * Felipe Correa da Silva Sanches <juca@members.fsf.org> * Jon A. Cruz <jon@joncruz.org> + * Jabiertxo Arraiza <jabier.arraiza@marker.es> * * Copyright (C) 2011 Authors * @@ -14,42 +15,44 @@ #include <gdk/gdkkeysyms.h> #include <boost/none_t.hpp> #include "util/units.h" -#include "macros.h" -#include "rubberband.h" +#include "display/canvas-text.h" #include "display/curve.h" -#include "text-editing.h" -#include "display/sp-ctrlline.h" #include "display/sodipodi-ctrl.h" +#include "display/sp-ctrlline.h" +#include "display/sp-canvas.h" #include "display/sp-canvas-item.h" #include "display/sp-canvas-util.h" -#include "desktop.h" #include "svg/svg.h" -#include "document.h" -#include "document-undo.h" -#include <viewbox.h> -#include "pixmaps/cursor-measure.xpm" -#include "preferences.h" -#include "inkscape.h" -#include "knot.h" +#include "svg/svg-color.h" #include "ui/tools/measure-tool.h" #include "ui/tools/freehand-base.h" -#include "display/canvas-text.h" -#include "path-chemistry.h" -#include "2geom/line.h" +#include "ui/control-manager.h" +#include <2geom/line.h> #include <2geom/path-intersection.h> #include <2geom/pathvector.h> #include <2geom/crossing.h> #include <2geom/angle.h> #include <2geom/transforms.h> -#include "snap.h" #include "sp-namedview.h" #include "sp-shape.h" #include "sp-text.h" #include "sp-flowtext.h" #include "sp-defs.h" #include "sp-item.h" +#include "macros.h" +#include "rubberband.h" +#include "path-chemistry.h" +#include "desktop.h" +#include "document.h" +#include "document-undo.h" +#include "viewbox.h" +#include "snap.h" +#include "text-editing.h" +#include "pixmaps/cursor-measure.xpm" +#include "preferences.h" +#include "inkscape.h" +#include "knot.h" #include "enums.h" -#include "ui/control-manager.h" #include "knot-enums.h" #include "desktop-style.h" #include "verbs.h" @@ -63,20 +66,21 @@ using Inkscape::DocumentUndo; #define MT_KNOT_COLOR_NORMAL 0xffffff00 #define MT_KNOT_COLOR_MOUSEOVER 0xff000000 + namespace Inkscape { namespace UI { namespace Tools { std::vector<Inkscape::Display::TemporaryItem*> measure_tmp_items; -const std::string& MeasureTool::getPrefsPath() { +const std::string& MeasureTool::getPrefsPath() +{ return MeasureTool::prefsPath; } const std::string MeasureTool::prefsPath = "/tools/measure"; -namespace -{ +namespace { gint dimension_offset = 35; @@ -196,8 +200,9 @@ Geom::Point calcAngleDisplayAnchor(SPDesktop *desktop, double angle, double base * @param end the point that ends at the edge of the arc segment. * @param anchor the anchor point for displaying the text label. * @param angle the angle of the arc segment to draw. + * @param measure_rpr the container of the curve if converted to items. */ -void createAngleDisplayCurve(SPDesktop *desktop, Geom::Point const ¢er, Geom::Point const &end, Geom::Point const &anchor, double angle) +void createAngleDisplayCurve(SPDesktop *desktop, Geom::Point const ¢er, Geom::Point const &end, Geom::Point const &anchor, double angle, Inkscape::XML::Node *measure_repr = NULL) { // Given that we have a point on the arc's edge and the angle of the arc, we need to get the two endpoints. @@ -205,7 +210,7 @@ void createAngleDisplayCurve(SPDesktop *desktop, Geom::Point const ¢er, Geom double sideLen = std::abs((end - center).length()); if (sideLen > 0.0) { double factor = std::min(1.0, textLen / sideLen); - + // arc start Geom::Point p1 = end * (Geom::Affine(Geom::Translate(-center)) * Geom::Affine(Geom::Scale(factor)) @@ -235,9 +240,47 @@ void createAngleDisplayCurve(SPDesktop *desktop, Geom::Point const ¢er, Geom SPCtrlCurve *curve = ControlManager::getManager().createControlCurve(desktop->getTempGroup(), p1, p2, p3, p4, CTLINE_SECONDARY); measure_tmp_items.push_back(desktop->add_temporary_canvasitem(SP_CANVAS_ITEM(curve), 0, true)); + if(measure_repr) { + Geom::PathVector c; + Geom::Path p; + p.start(desktop->doc2dt(p1)); + p.appendNew<Geom::CubicBezier>(desktop->doc2dt(p2),desktop->doc2dt(p3),desktop->doc2dt(p4)); + c.push_back(p); + c *= SP_ITEM(desktop->currentLayer())->i2doc_affine().inverse(); + SPDocument *doc = desktop->getDocument(); + Inkscape::XML::Document *xml_doc = doc->getReprDoc(); + if (c.size() == 1) { + Inkscape::XML::Node *repr; + repr = xml_doc->createElement("svg:path"); + gchar const *str = sp_svg_write_path(c); + Geom::Point strokewidth = Geom::Point(1,1) * SP_ITEM(desktop->currentLayer())->i2doc_affine().inverse(); + SPCSSAttr *css = sp_repr_css_attr_new(); + std::stringstream stroke_width; + stroke_width.imbue(std::locale::classic()); + stroke_width << strokewidth[Geom::X] / desktop->current_zoom(); + sp_repr_css_set_property (css, "stroke-width", stroke_width.str().c_str()); + sp_repr_css_set_property (css, "fill", "none"); + guint32 line_color_secondary = 0xff00007f; + gchar c[64]; + sp_svg_write_color (c, sizeof(c), line_color_secondary); + sp_repr_css_set_property (css, "stroke", c); + sp_repr_css_set_property (css, "stroke-linecap", "butt"); + sp_repr_css_set_property (css, "stroke-linejoin", "miter"); + sp_repr_css_set_property (css, "stroke-miterlimit", "4"); + sp_repr_css_set_property (css, "stroke-dasharray", "none"); + sp_repr_css_set_property (css, "stroke-opacity", "0.5"); + Glib::ustring css_str; + sp_repr_css_write_string(css,css_str); + repr->setAttribute("style", css_str.c_str()); + sp_repr_css_attr_unref (css); + g_assert( str != NULL ); + repr->setAttribute("d", str); + measure_repr->addChild(repr, NULL); + Inkscape::GC::release(repr); + } + } } } - } // namespace Geom::Point const MAGIC_POINT = Geom::Point(-0.0003432532004303,-0.006745034004304); @@ -249,7 +292,7 @@ MeasureTool::MeasureTool() , grabbed(NULL) { SPDesktop *desktop = SP_ACTIVE_DESKTOP; - // create the knot + // create the knots this->knot_start = new SPKnot(desktop, N_("Measure start")); this->knot_start->setMode(SP_KNOT_MODE_XOR); this->knot_start->setFill(MT_KNOT_COLOR_NORMAL, MT_KNOT_COLOR_MOUSEOVER, MT_KNOT_COLOR_MOUSEOVER); @@ -262,12 +305,13 @@ MeasureTool::MeasureTool() this->knot_end->setStroke(0x0000007f, 0x0000007f, 0x0000007f); this->knot_end->setShape(SP_KNOT_SHAPE_CIRCLE); this->knot_end->updateCtrl(); - if(end_p != MAGIC_POINT){ + Geom::Rect display_area = desktop->get_display_area () ; + if(display_area.interiorContains(start_p) && display_area.interiorContains(end_p) && end_p != MAGIC_POINT) { this->knot_start->moveto(start_p); this->knot_start->show(); this->knot_end->moveto(end_p); this->knot_end->show(); - this->showCanvasItems(); + showCanvasItems(); } this->_knot_start_moved_connection = this->knot_start->moved_signal.connect(sigc::mem_fun(*this, &MeasureTool::knotStartMovedHandler)); this->_knot_start_ungrabbed_connection = this->knot_start->ungrabbed_signal.connect(sigc::mem_fun(*this, &MeasureTool::knotUngrabbedHandler)); @@ -276,7 +320,8 @@ MeasureTool::MeasureTool() } -MeasureTool::~MeasureTool() { +MeasureTool::~MeasureTool() +{ this->_knot_start_moved_connection.disconnect(); this->_knot_start_ungrabbed_connection.disconnect(); this->_knot_end_moved_connection.disconnect(); @@ -291,7 +336,8 @@ MeasureTool::~MeasureTool() { measure_tmp_items.clear(); } -void MeasureTool::reverseKnots(){ +void MeasureTool::reverseKnots() +{ Geom::Point start = start_p; Geom::Point end = end_p; this->knot_start->moveto(end); @@ -301,45 +347,59 @@ void MeasureTool::reverseKnots(){ this->showCanvasItems(end, start); } -void MeasureTool::knotStartMovedHandler(SPKnot */*knot*/, Geom::Point const &ppointer, guint state){ - if (!(state & GDK_SHIFT_MASK)) { +void MeasureTool::knotStartMovedHandler(SPKnot */*knot*/, Geom::Point const &ppointer, guint state) +{ + Geom::Point point = this->knot_start->position(); + if (state & GDK_CONTROL_MASK) { + spdc_endpoint_snap_rotation(this, point, end_p, state); + } else if (!(state & GDK_SHIFT_MASK)) { SnapManager &m = desktop->namedview->snap_manager; m.setup(desktop); - Inkscape::SnapCandidatePoint scp(this->knot_start->position(), Inkscape::SNAPSOURCE_OTHER_HANDLE); + Inkscape::SnapCandidatePoint scp(point, Inkscape::SNAPSOURCE_OTHER_HANDLE); scp.addOrigin(this->knot_end->position()); Inkscape::SnappedPoint sp = m.freeSnap(scp); - if(start_p != sp.getPoint()){ - start_p = sp.getPoint(); - this->knot_start->moveto(start_p); - } + point = sp.getPoint(); m.unSetup(); } - showCanvasItems(start_p, this->knot_end->position()); + if(start_p != point) { + start_p = point; + this->knot_start->moveto(start_p); + } + showCanvasItems(start_p, end_p); } -void MeasureTool::knotEndMovedHandler(SPKnot */*knot*/, Geom::Point const &ppointer, guint state){ - if (!(state & GDK_SHIFT_MASK)) { +void MeasureTool::knotEndMovedHandler(SPKnot */*knot*/, Geom::Point const &ppointer, guint state) +{ + Geom::Point point = this->knot_end->position(); + if (state & GDK_CONTROL_MASK) { + spdc_endpoint_snap_rotation(this, point, start_p, state); + } else if (!(state & GDK_SHIFT_MASK)) { SnapManager &m = desktop->namedview->snap_manager; m.setup(desktop); - Inkscape::SnapCandidatePoint scp(this->knot_end->position(), Inkscape::SNAPSOURCE_OTHER_HANDLE); + Inkscape::SnapCandidatePoint scp(point, Inkscape::SNAPSOURCE_OTHER_HANDLE); scp.addOrigin(this->knot_start->position()); Inkscape::SnappedPoint sp = m.freeSnap(scp); - if(end_p != sp.getPoint()){ - end_p = sp.getPoint(); - this->knot_end->moveto(end_p); - } + point = sp.getPoint(); m.unSetup(); } - showCanvasItems(this->knot_start->position(), end_p); + if(end_p != point) { + end_p = point; + this->knot_end->moveto(end_p); + } + showCanvasItems(start_p, end_p); } -void MeasureTool::knotUngrabbedHandler(SPKnot */*knot*/, unsigned int state){ - showCanvasItems(this->knot_start->position(), this->knot_end->position()); +void MeasureTool::knotUngrabbedHandler(SPKnot */*knot*/, unsigned int state) +{ + this->knot_start->moveto(start_p); + this->knot_end->moveto(end_p); + showCanvasItems(start_p, end_p); } -void MeasureTool::finish() { +void MeasureTool::finish() +{ this->enableGrDrag(false); if (this->grabbed) { @@ -386,9 +446,9 @@ static void calculate_intersections(SPDesktop * /*desktop*/, SPItem* item, Geom: double eps = 0.0001; SPDocument* doc = desktop->getDocument(); if (((*m).ta > eps && - item == doc->getItemAtPoint(desktop->dkey, lineseg[0].pointAt((*m).ta - eps), false, NULL)) || - ((*m).ta + eps < 1 && - item == doc->getItemAtPoint(desktop->dkey, lineseg[0].pointAt((*m).ta + eps), false, NULL)) ) { + item == doc->getItemAtPoint(desktop->dkey, lineseg[0].pointAt((*m).ta - eps), false, NULL)) || + ((*m).ta + eps < 1 && + item == doc->getItemAtPoint(desktop->dkey, lineseg[0].pointAt((*m).ta + eps), false, NULL)) ) { intersections.push_back((*m).ta); } #else @@ -398,106 +458,83 @@ static void calculate_intersections(SPDesktop * /*desktop*/, SPItem* item, Geom: } } -bool MeasureTool::root_handler(GdkEvent* event) { +bool MeasureTool::root_handler(GdkEvent* event) +{ gint ret = FALSE; switch (event->type) { - case GDK_BUTTON_PRESS: { - this->knot_start->hide(); - this->knot_end->hide(); - Geom::Point const button_w(event->button.x, event->button.y); - explicitBase = boost::none; - last_end = boost::none; - start_point = desktop->w2d(button_w); - - if (event->button.button == 1 && !this->space_panning) { - // save drag origin - start_point = desktop->w2d(Geom::Point(event->button.x, event->button.y)); - within_tolerance = true; - - ret = TRUE; - } + case GDK_BUTTON_PRESS: { + this->knot_start->hide(); + this->knot_end->hide(); + Geom::Point const button_w(event->button.x, event->button.y); + explicitBase = boost::none; + last_end = boost::none; + start_point = desktop->w2d(button_w); + + if (event->button.button == 1 && !this->space_panning) { + // save drag origin + start_point = desktop->w2d(Geom::Point(event->button.x, event->button.y)); + within_tolerance = true; + + ret = TRUE; + } - SnapManager &m = desktop->namedview->snap_manager; - m.setup(desktop); - m.freeSnapReturnByRef(start_point, Inkscape::SNAPSOURCE_OTHER_HANDLE); - m.unSetup(); + SnapManager &m = desktop->namedview->snap_manager; + m.setup(desktop); + m.freeSnapReturnByRef(start_point, Inkscape::SNAPSOURCE_OTHER_HANDLE); + m.unSetup(); - sp_canvas_item_grab(SP_CANVAS_ITEM(desktop->acetate), - GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK, - NULL, event->button.time); - this->grabbed = SP_CANVAS_ITEM(desktop->acetate); - break; - } - case GDK_KEY_PRESS: { - if ((event->key.keyval == GDK_KEY_Shift_L) || (event->key.keyval == GDK_KEY_Shift_R)) { - if (last_end) { - explicitBase = last_end; - } + sp_canvas_item_grab(SP_CANVAS_ITEM(desktop->acetate), + GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK, + NULL, event->button.time); + this->grabbed = SP_CANVAS_ITEM(desktop->acetate); + break; + } + case GDK_KEY_PRESS: { + if ((event->key.keyval == GDK_KEY_Shift_L) || (event->key.keyval == GDK_KEY_Shift_R)) { + if (last_end) { + explicitBase = last_end; } - break; } - case GDK_MOTION_NOTIFY: { - if (!(event->motion.state & GDK_BUTTON1_MASK)){ - if(!(event->motion.state & GDK_SHIFT_MASK)) { - Geom::Point const motion_w(event->motion.x, event->motion.y); - Geom::Point const motion_dt(desktop->w2d(motion_w)); + break; + } + case GDK_MOTION_NOTIFY: { + if (!(event->motion.state & GDK_BUTTON1_MASK)) { + if(!(event->motion.state & GDK_SHIFT_MASK)) { + Geom::Point const motion_w(event->motion.x, event->motion.y); + Geom::Point const motion_dt(desktop->w2d(motion_w)); - SnapManager &m = desktop->namedview->snap_manager; - m.setup(desktop); + SnapManager &m = desktop->namedview->snap_manager; + m.setup(desktop); - Inkscape::SnapCandidatePoint scp(motion_dt, Inkscape::SNAPSOURCE_OTHER_HANDLE); - scp.addOrigin(start_point); + Inkscape::SnapCandidatePoint scp(motion_dt, Inkscape::SNAPSOURCE_OTHER_HANDLE); + scp.addOrigin(start_point); - m.preSnap(scp); - m.unSetup(); - } - } else { - ret = TRUE; - Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - tolerance = prefs->getIntLimited("/options/dragtolerance/value", 0, 0, 100); - Geom::Point const motion_w(event->motion.x, event->motion.y); - if ( within_tolerance){ - if ( Geom::LInfty( motion_w - start_point ) < tolerance) { - return FALSE; // Do not drag if we're within tolerance from origin. - } - } - // Once the user has moved farther than tolerance from the original location - // (indicating they intend to move the object, not click), then always process the - // motion notify coordinates as given (no snapping back to origin) - within_tolerance = false; - if(event->motion.time == 0 || !last_end || Geom::LInfty( motion_w - *last_end ) > (tolerance/2)){ - Geom::Point const motion_w(event->motion.x, event->motion.y); - Geom::Point const motion_dt(desktop->w2d(motion_w)); - Geom::Point end_point = motion_dt; - - if (event->motion.state & GDK_CONTROL_MASK) { - spdc_endpoint_snap_rotation(this, end_point, start_point, event->motion.state); - } else if (!(event->motion.state & GDK_SHIFT_MASK)) { - SnapManager &m = desktop->namedview->snap_manager; - m.setup(desktop); - Inkscape::SnapCandidatePoint scp(end_point, Inkscape::SNAPSOURCE_OTHER_HANDLE); - scp.addOrigin(start_point); - Inkscape::SnappedPoint sp = m.freeSnap(scp); - end_point = sp.getPoint(); - m.unSetup(); - } - showCanvasItems(start_point, end_point); - last_end = motion_w ; + m.preSnap(scp); + m.unSetup(); + } + } else { + ret = TRUE; + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + tolerance = prefs->getIntLimited("/options/dragtolerance/value", 0, 0, 100); + Geom::Point const motion_w(event->motion.x, event->motion.y); + if ( within_tolerance) { + if ( Geom::LInfty( motion_w - start_point ) < tolerance) { + return FALSE; // Do not drag if we're within tolerance from origin. } - gobble_motion_events(GDK_BUTTON1_MASK); } - break; - } - case GDK_BUTTON_RELEASE: { - this->knot_start->moveto(start_point); - this->knot_start->show(); - Geom::Point end_point = end_p; - if(last_end){ - end_point = desktop->w2d(*last_end); - if (event->button.state & GDK_CONTROL_MASK) { + // Once the user has moved farther than tolerance from the original location + // (indicating they intend to move the object, not click), then always process the + // motion notify coordinates as given (no snapping back to origin) + within_tolerance = false; + if(event->motion.time == 0 || !last_end || Geom::LInfty( motion_w - *last_end ) > (tolerance/4.0)) { + Geom::Point const motion_w(event->motion.x, event->motion.y); + Geom::Point const motion_dt(desktop->w2d(motion_w)); + Geom::Point end_point = motion_dt; + + if (event->motion.state & GDK_CONTROL_MASK) { spdc_endpoint_snap_rotation(this, end_point, start_point, event->motion.state); - } else if (!(event->button.state & GDK_SHIFT_MASK)) { + } else if (!(event->motion.state & GDK_SHIFT_MASK)) { SnapManager &m = desktop->namedview->snap_manager; m.setup(desktop); Inkscape::SnapCandidatePoint scp(end_point, Inkscape::SNAPSOURCE_OTHER_HANDLE); @@ -506,153 +543,317 @@ bool MeasureTool::root_handler(GdkEvent* event) { end_point = sp.getPoint(); m.unSetup(); } + showCanvasItems(start_point, end_point); + last_end = motion_w ; } - this->knot_end->moveto(end_point); - this->knot_end->show(); - showCanvasItems(start_point, end_point); - if (this->grabbed) { - sp_canvas_item_ungrab(this->grabbed, event->button.time); - this->grabbed = NULL; + gobble_motion_events(GDK_BUTTON1_MASK); + } + break; + } + case GDK_BUTTON_RELEASE: { + this->knot_start->moveto(start_point); + this->knot_start->show(); + Geom::Point end_point = end_p; + if(last_end) { + end_point = desktop->w2d(*last_end); + if (event->button.state & GDK_CONTROL_MASK) { + spdc_endpoint_snap_rotation(this, end_point, start_point, event->motion.state); + } else if (!(event->button.state & GDK_SHIFT_MASK)) { + SnapManager &m = desktop->namedview->snap_manager; + m.setup(desktop); + Inkscape::SnapCandidatePoint scp(end_point, Inkscape::SNAPSOURCE_OTHER_HANDLE); + scp.addOrigin(start_point); + Inkscape::SnappedPoint sp = m.freeSnap(scp); + end_point = sp.getPoint(); + m.unSetup(); } - break; } - default: - break; + this->knot_end->moveto(end_point); + this->knot_end->show(); + showCanvasItems(start_point, end_point); + if (this->grabbed) { + sp_canvas_item_ungrab(this->grabbed, event->button.time); + this->grabbed = NULL; + } + break; + } + default: + break; } if (!ret) { ret = ToolBase::root_handler(event); } - + return ret; } -void MeasureTool::setMarkers(){ - SPDesktop *desktop = this->desktop; +void MeasureTool::setMarkers() +{ + SPDesktop *desktop = SP_ACTIVE_DESKTOP; SPDocument *doc = desktop->getDocument(); SPObject *arrowStart = doc->getObjectById("Arrow2Sstart"); SPObject *arrowEnd = doc->getObjectById("Arrow2Send"); if (!arrowStart) { setMarker(true); } - if(!arrowEnd){ + if(!arrowEnd) { setMarker(false); } } -void MeasureTool::setMarker(bool isStart){ - SPDesktop *desktop = this->desktop; +void MeasureTool::setMarker(bool isStart) +{ + SPDesktop *desktop = SP_ACTIVE_DESKTOP; SPDocument *doc = desktop->getDocument(); SPDefs *defs = doc->getDefs(); - Inkscape::XML::Node *repr; + Inkscape::XML::Node *rmarker; Inkscape::XML::Document *xml_doc = doc->getReprDoc(); - repr = xml_doc->createElement("svg:marker"); - if(isStart){ - repr->setAttribute("id", "Arrow2Sstart"); + rmarker = xml_doc->createElement("svg:marker"); + if(isStart) { + rmarker->setAttribute("id", "Arrow2Sstart"); } else { - repr->setAttribute("id", "Arrow2Send"); + rmarker->setAttribute("id", "Arrow2Send"); } - repr->setAttribute("inkscape:isstock", "true"); - if(isStart){ - repr->setAttribute("inkscape:stockid", "Arrow2Sstart"); + rmarker->setAttribute("inkscape:isstock", "true"); + if(isStart) { + rmarker->setAttribute("inkscape:stockid", "Arrow2Sstart"); } else { - repr->setAttribute("inkscape:stockid", "Arrow2Send"); + rmarker->setAttribute("inkscape:stockid", "Arrow2Send"); } - repr->setAttribute("orient", "auto"); - repr->setAttribute("refX", "0.0"); - repr->setAttribute("refY", "0.0"); - repr->setAttribute("style", "overflow:visible;"); - SPItem *item = SP_ITEM(defs->appendChildRepr(repr)); - Inkscape::GC::release(repr); - item->updateRepr(); - Inkscape::XML::Node *repr2; - repr2 = xml_doc->createElement("svg:path"); - repr2->setAttribute("d", "M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z"); - if(isStart){ - repr2->setAttribute("id", "Arrow2SstartPath"); + rmarker->setAttribute("orient", "auto"); + rmarker->setAttribute("refX", "0.0"); + rmarker->setAttribute("refY", "0.0"); + rmarker->setAttribute("style", "overflow:visible;"); + SPItem *marker = SP_ITEM(defs->appendChildRepr(rmarker)); + Inkscape::GC::release(rmarker); + marker->updateRepr(); + Inkscape::XML::Node *rpath; + rpath = xml_doc->createElement("svg:path"); + rpath->setAttribute("d", "M 8.72,4.03 L -2.21,0.02 L 8.72,-4.00 C 6.97,-1.63 6.98,1.62 8.72,4.03 z"); + if(isStart) { + rpath->setAttribute("id", "Arrow2SstartPath"); } else { - repr2->setAttribute("id", "Arrow2SendPath"); + rpath->setAttribute("id", "Arrow2SendPath"); } - repr2->setAttribute("style", "stroke:#000000;stroke-opacity:1;fill:#000000;fill-opacity:1"); - if(isStart){ - repr2->setAttribute("transform", "scale(0.3) translate(-2.3,0)"); + SPCSSAttr *css = sp_repr_css_attr_new(); + sp_repr_css_set_property (css, "stroke", "none"); + sp_repr_css_set_property (css, "fill", "#000000"); + sp_repr_css_set_property (css, "fill-opacity", "1"); + Glib::ustring css_str; + sp_repr_css_write_string(css,css_str); + rpath->setAttribute("style", css_str.c_str()); + sp_repr_css_attr_unref (css); + if(isStart) { + rpath->setAttribute("transform", "scale(0.3) translate(-2.3,0)"); } else { - repr2->setAttribute("transform", "scale(0.3) rotate(180) translate(-2.3,0)"); + rpath->setAttribute("transform", "scale(0.3) rotate(180) translate(-2.3,0)"); } - SPItem *item2 = SP_ITEM(item->appendChildRepr(repr2)); - Inkscape::GC::release(repr2); - item2->updateRepr(); + SPItem *path = SP_ITEM(marker->appendChildRepr(rpath)); + Inkscape::GC::release(rpath); + path->updateRepr(); +} + +void MeasureTool::toItem() +{ + SPDesktop *desktop = SP_ACTIVE_DESKTOP; + SPDocument *doc = desktop->getDocument(); + Geom::Ray ray(start_p,end_p); + guint32 line_color_primary = 0x0000ff7f; + Inkscape::XML::Document *xml_doc = desktop->doc()->getReprDoc(); + Inkscape::XML::Node *rgroup = xml_doc->createElement("svg:g"); + showCanvasItems(start_p, end_p, true, rgroup); + setLine(start_p,end_p, false, &line_color_primary, rgroup); + SPItem *measure_item = SP_ITEM(desktop->currentLayer()->appendChildRepr(rgroup)); + Inkscape::GC::release(rgroup); + measure_item->updateRepr(); + doc->ensureUpToDate(); + DocumentUndo::done(desktop->getDocument(), SP_VERB_CONTEXT_MEASURE,_("Convert measure to items")); + reset(); } -void MeasureTool::toMarkDimension(){ +void MeasureTool::toMarkDimension() +{ + SPDesktop *desktop = SP_ACTIVE_DESKTOP; + SPDocument *doc = desktop->getDocument(); setMarkers(); - Geom::PathVector c; - Geom::Path p; Geom::Ray ray(start_p,end_p); Geom::Point start = start_p + Geom::Point::polar(ray.angle(), 5); - start = desktop->doc2dt(start + Geom::Point::polar(ray.angle() + Geom::deg_to_rad(90), -(dimension_offset / 4.0))); + start = start + Geom::Point::polar(ray.angle() + Geom::deg_to_rad(90), -(dimension_offset / 4.0)); Geom::Point end = end_p + Geom::Point::polar(ray.angle(), -5); - end = desktop->doc2dt(end+ Geom::Point::polar(ray.angle() + Geom::deg_to_rad(90), -(dimension_offset / 4.0))); - p.start(start); - p.appendNew<Geom::LineSegment>(end); + end = end+ Geom::Point::polar(ray.angle() + Geom::deg_to_rad(90), -(dimension_offset / 4.0)); + guint32 color = 0x000000ff; + setLine(start, end, true, &color); + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + Glib::ustring unit_name = prefs->getString("/tools/measure/unit"); + if (!unit_name.compare("")) { + unit_name = "px"; + } + double fontsize = prefs->getInt("/tools/measure/fontsize") * (96/72); + Geom::Point middle = Geom::middle_point(start, end); + double totallengthval = (end_p - start_p).length(); + totallengthval = Inkscape::Util::Quantity::convert(totallengthval, "px", unit_name); + gchar *totallength_str = g_strdup_printf("%.2f %s", totallengthval, unit_name.c_str()); + setLabelText(totallength_str, middle, fontsize, Geom::deg_to_rad(180) - ray.angle()); + doc->ensureUpToDate(); + DocumentUndo::done(desktop->getDocument(), SP_VERB_CONTEXT_MEASURE,_("Add global meassure line")); +} + +void MeasureTool::setLine(Geom::Point start_point,Geom::Point end_point, bool markers, guint32 *color, Inkscape::XML::Node *measure_repr) +{ + SPDesktop *desktop = SP_ACTIVE_DESKTOP; + if(!desktop || !start_point.isFinite() || !end_point.isFinite()) { + return; + } + Geom::PathVector c; + Geom::Path p; + p.start(desktop->doc2dt(start_point)); + p.appendNew<Geom::LineSegment>(desktop->doc2dt(end_point)); c.push_back(p); c *= SP_ITEM(desktop->currentLayer())->i2doc_affine().inverse(); - SPDesktop *desktop = this->desktop; SPDocument *doc = desktop->getDocument(); Inkscape::XML::Document *xml_doc = doc->getReprDoc(); if (c.size() == 1) { Inkscape::XML::Node *repr; repr = xml_doc->createElement("svg:path"); gchar const *str = sp_svg_write_path(c); - Geom::Point stroke_width = Geom::Point(1,1) * SP_ITEM(desktop->currentLayer())->i2doc_affine().inverse(); - std::stringstream style_str; - style_str.imbue(std::locale::classic()); - style_str << "fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:" << stroke_width[Geom::X] << ";stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-start:url(#Arrow2Sstart);marker-end:url(#Arrow2Send)"; + Geom::Point strokewidth = Geom::Point(1,1) * SP_ITEM(desktop->currentLayer())->i2doc_affine().inverse(); + SPCSSAttr *css = sp_repr_css_attr_new(); + std::stringstream stroke_width; + stroke_width.imbue(std::locale::classic()); + if(measure_repr) { + stroke_width << strokewidth[Geom::X] / desktop->current_zoom(); + } else { + stroke_width << strokewidth[Geom::X]; + } + sp_repr_css_set_property (css, "stroke-width", stroke_width.str().c_str()); + sp_repr_css_set_property (css, "fill", "none"); + if(color) { + gchar c[64]; + sp_svg_write_color (c, sizeof(c), *color); + sp_repr_css_set_property (css, "stroke", c); + } else { + sp_repr_css_set_property (css, "stroke", "#000000"); + } + sp_repr_css_set_property (css, "stroke-linecap", "butt"); + sp_repr_css_set_property (css, "stroke-linejoin", "miter"); + sp_repr_css_set_property (css, "stroke-miterlimit", "4"); + sp_repr_css_set_property (css, "stroke-dasharray", "none"); + if(measure_repr) { + sp_repr_css_set_property (css, "stroke-opacity", "0.5"); + } else { + sp_repr_css_set_property (css, "stroke-opacity", "1"); + } + if(markers) { + sp_repr_css_set_property (css, "marker-start", "url(#Arrow2Sstart)"); + sp_repr_css_set_property (css, "marker-end", "url(#Arrow2Send)"); + } + Glib::ustring css_str; + sp_repr_css_write_string(css,css_str); + repr->setAttribute("style", css_str.c_str()); + sp_repr_css_attr_unref (css); g_assert( str != NULL ); repr->setAttribute("d", str); - repr->setAttribute("style", style_str.str().c_str()); - SPItem *item = SP_ITEM(desktop->currentLayer()->appendChildRepr(repr)); - Inkscape::GC::release(repr); - item->updateRepr(); + if(measure_repr) { + measure_repr->addChild(repr, NULL); + Inkscape::GC::release(repr); + } else { + SPItem *item = SP_ITEM(desktop->currentLayer()->appendChildRepr(repr)); + Inkscape::GC::release(repr); + item->updateRepr(); + } } +} - Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - Glib::ustring unit_name = prefs->getString("/tools/measure/unit"); - if (!unit_name.compare("")) { - unit_name = "px"; +void MeasureTool::setPoint(Geom::Point origin, Inkscape::XML::Node *measure_repr) +{ + SPDesktop *desktop = SP_ACTIVE_DESKTOP; + if(!desktop || !origin.isFinite()) { + return; + } + char const * svgd; + svgd = "m -3.55,-3.55 7.11,7.11 m 0,-7.11 -7.11,7.11"; + Geom::PathVector c = sp_svg_read_pathv(svgd); + Geom::Scale scale = Geom::Scale(desktop->current_zoom()).inverse(); + c *= scale; + Geom::Point strokewidth = (Geom::Point(1,1) * SP_ITEM(desktop->currentLayer())->i2doc_affine().inverse())/ desktop->current_zoom(); + c *= Geom::Translate(Geom::Point(strokewidth/2.0) - (scale.vector() * 0.5)); + c *= Geom::Translate(desktop->doc2dt(origin)); + c *= SP_ITEM(desktop->currentLayer())->i2doc_affine().inverse(); + SPDocument *doc = desktop->getDocument(); + Inkscape::XML::Document *xml_doc = doc->getReprDoc(); + if (c.size() == 2) { + Inkscape::XML::Node *repr; + repr = xml_doc->createElement("svg:path"); + gchar const *str = sp_svg_write_path(c); + SPCSSAttr *css = sp_repr_css_attr_new(); + std::stringstream stroke_width; + stroke_width.imbue(std::locale::classic()); + stroke_width << strokewidth[Geom::X]; + sp_repr_css_set_property (css, "stroke-width", stroke_width.str().c_str()); + sp_repr_css_set_property (css, "fill", "none"); + guint32 line_color_secondary = 0xff0000ff; + gchar c[64]; + sp_svg_write_color (c, sizeof(c), line_color_secondary); + sp_repr_css_set_property (css, "stroke", c); + sp_repr_css_set_property (css, "stroke-linecap", "butt"); + sp_repr_css_set_property (css, "stroke-linejoin", "miter"); + sp_repr_css_set_property (css, "stroke-miterlimit", "4"); + sp_repr_css_set_property (css, "stroke-dasharray", "none"); + sp_repr_css_set_property (css, "stroke-opacity", "0.5"); + Glib::ustring css_str; + sp_repr_css_write_string(css,css_str); + repr->setAttribute("style", css_str.c_str()); + sp_repr_css_attr_unref (css); + g_assert( str != NULL ); + repr->setAttribute("d", str); + measure_repr->addChild(repr, NULL); + Inkscape::GC::release(repr); } - double fontsize = prefs->getInt("/tools/measure/fontsize") * (96/72); - Geom::Point middle = Geom::middle_point(start, end); - double totallengthval = (end_p - start_p).length(); - totallengthval = Inkscape::Util::Quantity::convert(totallengthval, "px", unit_name); - gchar *totallength_str = g_strdup_printf("%.2f %s", totallengthval, unit_name.c_str()); - setLabelText(totallength_str, middle, fontsize, Geom::deg_to_rad(180) - ray.angle()); - // Flush pending updates - doc->ensureUpToDate(); - DocumentUndo::done(desktop->getDocument(), SP_VERB_CONTEXT_MEASURE, - _("Add global meassure line")); - //reset(); } -void MeasureTool::setLabelText(const char *value, Geom::Point pos, double fontsize, Geom::Coord angle) +void MeasureTool::setLabelText(const char *value, Geom::Point pos, double fontsize, Geom::Coord angle, guint32 *background, Inkscape::XML::Node *measure_repr, CanvasTextAnchorPositionEnum text_anchor) { - /* Create <text> */ + SPDesktop *desktop = SP_ACTIVE_DESKTOP; Inkscape::XML::Document *xml_doc = desktop->doc()->getReprDoc(); + /* Create <text> */ + pos = desktop->doc2dt(pos); Inkscape::XML::Node *rtext = xml_doc->createElement("svg:text"); rtext->setAttribute("xml:space", "preserve"); /* Set style */ sp_desktop_apply_style_tool(desktop, rtext, "/tools/text", true); - - sp_repr_set_svg_double(rtext, "x", 0); - sp_repr_set_svg_double(rtext, "y", 0); + if(measure_repr) { + sp_repr_set_svg_double(rtext, "x", 2); + sp_repr_set_svg_double(rtext, "y", 2); + } else { + sp_repr_set_svg_double(rtext, "x", 0); + sp_repr_set_svg_double(rtext, "y", 0); + } /* Create <tspan> */ Inkscape::XML::Node *rtspan = xml_doc->createElement("svg:tspan"); rtspan->setAttribute("sodipodi:role", "line"); // otherwise, why bother creating the tspan? - std::stringstream text_style; - text_style.imbue(std::locale::classic()); - text_style << "font-style:normal;font-weight:normal;font-size:" << fontsize << "px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"; - rtspan->setAttribute("style", text_style.str().c_str()); + SPCSSAttr *css = sp_repr_css_attr_new(); + std::stringstream font_size; + font_size.imbue(std::locale::classic()); + font_size << fontsize ; + sp_repr_css_set_property (css, "font-size", font_size.str().c_str()); + sp_repr_css_set_property (css, "font-style", "normal"); + sp_repr_css_set_property (css, "font-weight", "normal"); + sp_repr_css_set_property (css, "line-height", "125%"); + sp_repr_css_set_property (css, "letter-spacing", "0px"); + sp_repr_css_set_property (css, "word-spacing", "0px"); + if(measure_repr) { + sp_repr_css_set_property (css, "fill", "#FFFFFF"); + } else { + sp_repr_css_set_property (css, "fill", "#000000"); + } + sp_repr_css_set_property (css, "fill-opacity", "1"); + sp_repr_css_set_property (css, "stroke", "none"); + Glib::ustring css_str; + sp_repr_css_write_string(css,css_str); + rtspan->setAttribute("style", css_str.c_str()); + sp_repr_css_attr_unref (css); rtext->addChild(rtspan, NULL); Inkscape::GC::release(rtspan); /* Create TEXT */ @@ -663,19 +864,63 @@ void MeasureTool::setLabelText(const char *value, Geom::Point pos, double fontsi Inkscape::GC::release(rtext); text_item->updateRepr(); Geom::OptRect bbox = text_item->geometricBounds(); - if (bbox) { - Geom::Coord posX = Geom::middle_point(Geom::Point(bbox->left(), bbox->top()), Geom::Point(bbox->right(), bbox->top()))[Geom::X]; - Geom::Coord posY = Geom::middle_point(Geom::Point(bbox->left(), bbox->top()), Geom::Point(bbox->left(), bbox->bottom()))[Geom::Y]; - text_item->transform *= Geom::Translate(Geom::Point(posX, posY)).inverse(); - pos = pos + Geom::Point::polar(angle + Geom::deg_to_rad(90), -Geom::distance(Geom::Point(bbox->left(), bbox->top()), Geom::Point(bbox->left(), bbox->bottom()))); + if (!measure_repr && bbox) { + Geom::Point center = bbox->midpoint(); + text_item->transform *= Geom::Translate(center).inverse(); + pos = pos + Geom::Point::polar(angle+ Geom::deg_to_rad(90), -bbox->height()); + } + if(measure_repr) { + /* Create <group> */ + Inkscape::XML::Node *rgroup = xml_doc->createElement("svg:g"); + /* Create <rect> */ + Inkscape::XML::Node *rrect = xml_doc->createElement("svg:rect"); + SPCSSAttr *css = sp_repr_css_attr_new (); + gchar c[64]; + sp_svg_write_color (c, sizeof(c), *background); + sp_repr_css_set_property (css, "fill", c); + sp_repr_css_set_property (css, "fill-opacity", "0.5"); + sp_repr_css_set_property (css, "stroke-width", "0"); + Glib::ustring css_str; + sp_repr_css_write_string(css,css_str); + rrect->setAttribute("style", css_str.c_str()); + sp_repr_css_attr_unref (css); + sp_repr_set_svg_double(rgroup, "x", 0); + sp_repr_set_svg_double(rgroup, "y", 0); + sp_repr_set_svg_double(rrect, "x", 0); + sp_repr_set_svg_double(rrect, "y", -bbox->height()); + sp_repr_set_svg_double(rrect, "width", (bbox->width()) + 6); + sp_repr_set_svg_double(rrect, "height", (bbox->height()) + 6); + Inkscape::XML::Node *rtextitem = text_item->getRepr(); + text_item->deleteObject(); + rgroup->addChild(rtextitem, NULL); + Inkscape::GC::release(rtextitem); + rgroup->addChild(rrect, NULL); + Inkscape::GC::release(rrect); + SPItem *text_item_box = SP_ITEM(desktop->currentLayer()->appendChildRepr(rgroup)); + Geom::Scale scale = Geom::Scale(desktop->current_zoom()).inverse(); + if(bbox && text_anchor == TEXT_ANCHOR_CENTER) { + text_item_box->transform *= Geom::Translate(bbox->midpoint() - Geom::Point(1.0,1.0)).inverse(); + } + text_item_box->transform *= scale; + text_item_box->transform *= Geom::Translate(Geom::Point() - (scale.vector() * 0.5)); + text_item_box->transform *= Geom::Translate(pos); + text_item_box->transform *= SP_ITEM(desktop->currentLayer())->i2doc_affine().inverse(); + text_item_box->updateRepr(); + text_item_box->doWriteTransform(text_item_box->getRepr(), text_item_box->transform, NULL, true); + Inkscape::XML::Node *rlabel = text_item_box->getRepr(); + text_item_box->deleteObject(); + measure_repr->addChild(rlabel, NULL); + Inkscape::GC::release(rlabel); + } else { + text_item->transform *= Geom::Rotate(angle); + text_item->transform *= Geom::Translate(pos); + text_item->transform *= SP_ITEM(desktop->currentLayer())->i2doc_affine().inverse(); + text_item->doWriteTransform(text_item->getRepr(), text_item->transform, NULL, true); } - text_item->transform *= Geom::Rotate(angle); - text_item->transform *= Geom::Translate(pos); - text_item->transform *= SP_ITEM(desktop->currentLayer())->i2doc_affine().inverse(); - text_item->doWriteTransform(text_item->getRepr(), text_item->transform, NULL, true); } -void MeasureTool::reset(){ +void MeasureTool::reset() +{ this->knot_start->hide(); this->knot_end->hide(); for (size_t idx = 0; idx < measure_tmp_items.size(); ++idx) { @@ -684,15 +929,19 @@ void MeasureTool::reset(){ measure_tmp_items.clear(); } -void MeasureTool::showCanvasItems(){ +void MeasureTool::showCanvasItems() +{ showCanvasItems(start_p, end_p); } -void MeasureTool::showCanvasItems(Geom::Point start_point, Geom::Point end_point){ +void MeasureTool::showCanvasItems(Geom::Point start_point, Geom::Point end_point, bool to_item, Inkscape::XML::Node *measure_repr) +{ SPDesktop *desktop = SP_ACTIVE_DESKTOP; - if(!desktop || !start_point.isFinite() || !end_point.isFinite() || end_point == MAGIC_POINT){ + if(!desktop || !start_point.isFinite() || !end_point.isFinite() || end_point == MAGIC_POINT) { return; } + guint32 line_color_primary = 0x0000ff7f; + guint32 line_color_secondary = 0xff00007f; start_p = start_point; end_p = end_point; //clear previous temporary canvas items, we'll draw new ones @@ -731,7 +980,7 @@ void MeasureTool::showCanvasItems(Geom::Point start_point, Geom::Point end_point std::vector<SPItem*> items; Inkscape::Rubberband *r = Inkscape::Rubberband::get(desktop); r->setMode(RUBBERBAND_MODE_TOUCHPATH); - if(!show_in_between){ + if(!show_in_between) { r->start(desktop,start_p); r->move(end_p); items = desktop->getDocument()->getItemsAtPoints(desktop->dkey, r->getPoints(), all_layers, 2); @@ -741,10 +990,10 @@ void MeasureTool::showCanvasItems(Geom::Point start_point, Geom::Point end_point r->move(start_p); std::vector<SPItem*> items_reverse = desktop->getDocument()->getItemsAtPoints(desktop->dkey, r->getPoints(), all_layers, 2); r->stop(); - if(items_reverse.size() == 2 && items_reverse[1] != items[0] && items_reverse[1] != items[1]){ + if(items_reverse.size() == 2 && items_reverse[1] != items[0] && items_reverse[1] != items[1]) { items.push_back(items_reverse[1]); } - if(items_reverse.size() >= 1 && items_reverse[0] != items[1]){ + if(items_reverse.size() >= 1 && items_reverse[0] != items[1]) { items.push_back(items_reverse[0]); } } else { @@ -754,10 +1003,10 @@ void MeasureTool::showCanvasItems(Geom::Point start_point, Geom::Point end_point r->stop(); } std::vector<double> intersection_times; - for (std::vector<SPItem*>::const_iterator i=items.begin();i!=items.end();i++) { + for (std::vector<SPItem*>::const_iterator i=items.begin(); i!=items.end(); i++) { SPItem *item = *i; if (SP_IS_SHAPE(item)) { - calculate_intersections(desktop, item, lineseg, SP_SHAPE(item)->getCurve(), intersection_times); + calculate_intersections(desktop, item, lineseg, SP_SHAPE(item)->getCurve(), intersection_times); } else { if (SP_IS_TEXT(item) || SP_IS_FLOWTEXT(item)) { Inkscape::Text::Layout::iterator iter = te_get_layout(item)->begin(); @@ -802,11 +1051,11 @@ void MeasureTool::showCanvasItems(Geom::Point start_point, Geom::Point end_point std::vector<Geom::Point> intersections; std::sort(intersection_times.begin(), intersection_times.end()); for (std::vector<double>::iterator iter_t = intersection_times.begin(); iter_t != intersection_times.end(); iter_t++) { - if(show_in_between){ + if(show_in_between) { intersections.push_back(lineseg[0].pointAt(*iter_t)); } } - if(!show_in_between && intersection_times.size() > 1){ + if(!show_in_between && intersection_times.size() > 1) { intersections.push_back(lineseg[0].pointAt(intersection_times[0])); intersections.push_back(lineseg[0].pointAt(intersection_times[intersection_times.size()-1])); } @@ -828,47 +1077,52 @@ void MeasureTool::showCanvasItems(Geom::Point start_point, Geom::Point end_point // Adjust positions repositionOverlappingLabels(placements, desktop, windowNormal, fontsize); - for (std::vector<LabelPlacement>::iterator it = placements.begin(); it != placements.end(); ++it) - { + for (std::vector<LabelPlacement>::iterator it = placements.begin(); it != placements.end(); ++it) { LabelPlacement &place = *it; // TODO cleanup memory, Glib::ustring, etc.: gchar *measure_str = g_strdup_printf("%.2f %s", place.lengthVal, unit_name.c_str()); SPCanvasText *canvas_tooltip = sp_canvastext_new(desktop->getTempGroup(), - desktop, - place.end, - measure_str); + desktop, + place.end, + measure_str); sp_canvastext_set_fontsize(canvas_tooltip, fontsize); canvas_tooltip->rgba = 0xffffffff; canvas_tooltip->rgba_background = 0x0000007f; canvas_tooltip->outline = false; canvas_tooltip->background = true; canvas_tooltip->anchor_position = TEXT_ANCHOR_CENTER; - measure_tmp_items.push_back(desktop->add_temporary_canvasitem(canvas_tooltip, 0)); + if(to_item) { + guint32 background = canvas_tooltip->rgba_background; + setLabelText(measure_str, place.end, fontsize, 0, &background, measure_repr); + } g_free(measure_str); } Geom::Point angleDisplayPt = calcAngleDisplayAnchor(desktop, angle, baseAngle, - start_point, end_point, - fontsize); + start_point, end_point, + fontsize); { // TODO cleanup memory, Glib::ustring, etc.: gchar *angle_str = g_strdup_printf("%.2f °", angle * 180/M_PI); SPCanvasText *canvas_tooltip = sp_canvastext_new(desktop->getTempGroup(), - desktop, - angleDisplayPt, - angle_str); + desktop, + angleDisplayPt, + angle_str); sp_canvastext_set_fontsize(canvas_tooltip, fontsize); canvas_tooltip->rgba = 0xffffffff; canvas_tooltip->rgba_background = 0x337f337f; canvas_tooltip->outline = false; canvas_tooltip->background = true; canvas_tooltip->anchor_position = TEXT_ANCHOR_CENTER; - measure_tmp_items.push_back(desktop->add_temporary_canvasitem(canvas_tooltip, 0)); + if(to_item) { + guint32 background = canvas_tooltip->rgba_background; + setLabelText(angle_str, angleDisplayPt, fontsize, 0, &background, measure_repr); + } g_free(angle_str); } @@ -879,17 +1133,20 @@ void MeasureTool::showCanvasItems(Geom::Point start_point, Geom::Point end_point // TODO cleanup memory, Glib::ustring, etc.: gchar *totallength_str = g_strdup_printf("%.2f %s", totallengthval, unit_name.c_str()); SPCanvasText *canvas_tooltip = sp_canvastext_new(desktop->getTempGroup(), - desktop, - end_point + desktop->w2d(Geom::Point(3*fontsize, -fontsize)), - totallength_str); + desktop, + end_point + desktop->w2d(Geom::Point(3*fontsize, -fontsize)), + totallength_str); sp_canvastext_set_fontsize(canvas_tooltip, fontsize); canvas_tooltip->rgba = 0xffffffff; canvas_tooltip->rgba_background = 0x3333337f; canvas_tooltip->outline = false; canvas_tooltip->background = true; canvas_tooltip->anchor_position = TEXT_ANCHOR_LEFT; - measure_tmp_items.push_back(desktop->add_temporary_canvasitem(canvas_tooltip, 0)); + if(to_item) { + guint32 background = canvas_tooltip->rgba_background; + setLabelText(totallength_str, end_point + desktop->w2d(Geom::Point(3*fontsize, -fontsize)), fontsize, 0, &background, measure_repr, TEXT_ANCHOR_LEFT); + } g_free(totallength_str); } @@ -900,44 +1157,68 @@ void MeasureTool::showCanvasItems(Geom::Point start_point, Geom::Point end_point // TODO cleanup memory, Glib::ustring, etc.: gchar *total_str = g_strdup_printf("%.2f %s", totallengthval, unit_name.c_str()); SPCanvasText *canvas_tooltip = sp_canvastext_new(desktop->getTempGroup(), - desktop, - desktop->doc2dt((intersections[0] + intersections[intersections.size()-1])/2) + normal * (dimension_offset * 2), - total_str); + desktop, + desktop->doc2dt((intersections[0] + intersections[intersections.size()-1])/2) + normal * (dimension_offset * 2), + total_str); sp_canvastext_set_fontsize(canvas_tooltip, fontsize); canvas_tooltip->rgba = 0xffffffff; canvas_tooltip->rgba_background = 0x33337f7f; canvas_tooltip->outline = false; canvas_tooltip->background = true; canvas_tooltip->anchor_position = TEXT_ANCHOR_CENTER; - measure_tmp_items.push_back(desktop->add_temporary_canvasitem(canvas_tooltip, 0)); + if(to_item) { + guint32 background = canvas_tooltip->rgba_background; + setLabelText(total_str, desktop->doc2dt((intersections[0] + intersections[intersections.size()-1])/2) + normal * (dimension_offset * 2), fontsize, 0, &background, measure_repr); + } g_free(total_str); } + // Initial point + { + SPCanvasItem * canvasitem = sp_canvas_item_new(desktop->getTempGroup(), + SP_TYPE_CTRL, + "anchor", SP_ANCHOR_CENTER, + "size", 8.0, + "stroked", TRUE, + "stroke_color", 0xff0000ff, + "mode", SP_KNOT_MODE_XOR, + "shape", SP_KNOT_SHAPE_CROSS, + NULL ); + + SP_CTRL(canvasitem)->moveto(start_point); + measure_tmp_items.push_back(desktop->add_temporary_canvasitem(canvasitem, 0)); + if(to_item) { + setPoint(start_point, measure_repr); + } + } + // Now that text has been added, we can add lines and controls so that they go underneath for (size_t idx = 0; idx < intersections.size(); ++idx) { // Display the intersection indicator (i.e. the cross) SPCanvasItem * canvasitem = sp_canvas_item_new(desktop->getTempGroup(), - SP_TYPE_CTRL, - "anchor", SP_ANCHOR_CENTER, - "size", 8.0, - "stroked", TRUE, - "stroke_color", 0xff0000ff, - "mode", SP_KNOT_MODE_XOR, - "shape", SP_KNOT_SHAPE_CROSS, - NULL ); + SP_TYPE_CTRL, + "anchor", SP_ANCHOR_CENTER, + "size", 8.0, + "stroked", TRUE, + "stroke_color", 0xff0000ff, + "mode", SP_KNOT_MODE_XOR, + "shape", SP_KNOT_SHAPE_CROSS, + NULL ); SP_CTRL(canvasitem)->moveto(desktop->doc2dt(intersections[idx])); measure_tmp_items.push_back(desktop->add_temporary_canvasitem(canvasitem, 0)); + if(to_item) { + setPoint(desktop->doc2dt(intersections[idx]), measure_repr); + } } - // Since adding goes to the bottom, do all lines last. // draw main control line { SPCtrlLine *control_line = ControlManager::getManager().createControlLine(desktop->getTempGroup(), - start_point, - end_point); + start_point, + end_point); measure_tmp_items.push_back(desktop->add_temporary_canvasitem(control_line, 0)); if ((end_point[Geom::X] != start_point[Geom::X]) && (end_point[Geom::Y] != start_point[Geom::Y])) { @@ -951,12 +1232,18 @@ void MeasureTool::showCanvasItems(Geom::Point start_point, Geom::Point end_point } SPCtrlLine *control_line = ControlManager::getManager().createControlLine(desktop->getTempGroup(), - start_point, - anchorEnd, - CTLINE_SECONDARY); + start_point, + anchorEnd, + CTLINE_SECONDARY); measure_tmp_items.push_back(desktop->add_temporary_canvasitem(control_line, 0)); - - createAngleDisplayCurve(desktop, start_point, end_point, angleDisplayPt, angle); + if(to_item) { + setLine(start_point, + anchorEnd, + false, + &line_color_secondary, + measure_repr); + } + createAngleDisplayCurve(desktop, start_point, end_point, angleDisplayPt, angle, measure_repr); } } @@ -967,29 +1254,50 @@ void MeasureTool::showCanvasItems(Geom::Point start_point, Geom::Point end_point desktop->doc2dt(intersections[0]) + normal * (dimension_offset * 2), desktop->doc2dt(intersections[intersections.size() - 1]) + normal * (dimension_offset * 2)); measure_tmp_items.push_back(desktop->add_temporary_canvasitem(control_line, 0)); - + if(to_item) { + setLine(desktop->doc2dt(intersections[0]) + normal * (dimension_offset * 2), + desktop->doc2dt(intersections[intersections.size() - 1]) + normal * (dimension_offset * 2), + false, + &line_color_primary, + measure_repr); + } control_line = mgr.createControlLine(desktop->getTempGroup(), desktop->doc2dt(intersections[0]), desktop->doc2dt(intersections[0]) + normal * (dimension_offset * 2)); measure_tmp_items.push_back(desktop->add_temporary_canvasitem(control_line, 0)); - + if(to_item) { + setLine(desktop->doc2dt(intersections[0]), + desktop->doc2dt(intersections[0]) + normal * (dimension_offset * 2), + false, + &line_color_primary, + measure_repr); + } control_line = mgr.createControlLine(desktop->getTempGroup(), desktop->doc2dt(intersections[intersections.size() - 1]), desktop->doc2dt(intersections[intersections.size() - 1]) + normal * (dimension_offset * 2)); measure_tmp_items.push_back(desktop->add_temporary_canvasitem(control_line, 0)); + if(to_item) { + setLine(desktop->doc2dt(intersections[intersections.size() - 1]), + desktop->doc2dt(intersections[intersections.size() - 1]) + normal * (dimension_offset * 2), + false, + &line_color_primary, + measure_repr); + } } // call-out lines - for (std::vector<LabelPlacement>::iterator it = placements.begin(); it != placements.end(); ++it) - { + for (std::vector<LabelPlacement>::iterator it = placements.begin(); it != placements.end(); ++it) { LabelPlacement &place = *it; ControlManager &mgr = ControlManager::getManager(); SPCtrlLine *control_line = mgr.createControlLine(desktop->getTempGroup(), - place.start, - place.end, - CTLINE_SECONDARY); + place.start, + place.end, + CTLINE_SECONDARY); measure_tmp_items.push_back(desktop->add_temporary_canvasitem(control_line, 0)); + if(to_item) { + setLine(place.start,place.end, false, &line_color_secondary, measure_repr); + } } { @@ -998,28 +1306,19 @@ void MeasureTool::showCanvasItems(Geom::Point start_point, Geom::Point end_point ControlManager &mgr = ControlManager::getManager(); SPCtrlLine *control_line = mgr.createControlLine(desktop->getTempGroup(), - desktop->doc2dt(measure_text_pos), - desktop->doc2dt(measure_text_pos) - (normal * dimension_offset), - CTLINE_SECONDARY); + desktop->doc2dt(measure_text_pos), + desktop->doc2dt(measure_text_pos) - (normal * dimension_offset), + CTLINE_SECONDARY); measure_tmp_items.push_back(desktop->add_temporary_canvasitem(control_line, 0)); + if(to_item) { + setLine(desktop->doc2dt(measure_text_pos), + desktop->doc2dt(measure_text_pos) - (normal * dimension_offset), + false, + &line_color_secondary, + measure_repr); + } } } - - // Initial point - { - SPCanvasItem * canvasitem = sp_canvas_item_new(desktop->getTempGroup(), - SP_TYPE_CTRL, - "anchor", SP_ANCHOR_CENTER, - "size", 8.0, - "stroked", TRUE, - "stroke_color", 0xff0000ff, - "mode", SP_KNOT_MODE_XOR, - "shape", SP_KNOT_SHAPE_CROSS, - NULL ); - - SP_CTRL(canvasitem)->moveto(start_point); - measure_tmp_items.push_back(desktop->add_temporary_canvasitem(canvasitem, 0)); - } } } } diff --git a/src/ui/tools/measure-tool.h b/src/ui/tools/measure-tool.h index 0670fb9f7..ee45c18e5 100644 --- a/src/ui/tools/measure-tool.h +++ b/src/ui/tools/measure-tool.h @@ -6,7 +6,7 @@ * * Authors: * Felipe Correa da Silva Sanches <juca@members.fsf.org> - * + * Jabiertxo Arraiza <jabier.arraiza@marker.es> * Copyright (C) 2011 Authors * * Released under GNU GPL, read the file 'COPYING' for more information @@ -15,6 +15,7 @@ #include <sigc++/sigc++.h> #include "ui/tools/tool-base.h" #include <2geom/point.h> +#include "display/canvas-text.h" #include <boost/optional.hpp> #define SP_MEASURE_CONTEXT(obj) (dynamic_cast<Inkscape::UI::Tools::MeasureTool*>((Inkscape::UI::Tools::ToolBase*)obj)) @@ -36,14 +37,17 @@ public: virtual void finish(); virtual bool root_handler(GdkEvent* event); virtual void showCanvasItems(); - virtual void showCanvasItems(Geom::Point start_point, Geom::Point end_point); + virtual void showCanvasItems(Geom::Point start_point, Geom::Point end_point, bool to_item = false, Inkscape::XML::Node *measure_repr = NULL); virtual void reverseKnots(); virtual void toMarkDimension(); + virtual void toItem(); virtual void reset(); virtual void setMarkers(); virtual void setMarker(bool isStart); virtual const std::string& getPrefsPath(); - void setLabelText(const char *value, Geom::Point pos, double fontsize, Geom::Coord angle); + void setPoint(Geom::Point origin, Inkscape::XML::Node *measure_repr); + void setLine(Geom::Point start_point,Geom::Point end_point, bool markers = false, guint32 *color = NULL, Inkscape::XML::Node *measure_repr = NULL); + void setLabelText(const char *value, Geom::Point pos, double fontsize, Geom::Coord angle, guint32 *background = NULL, Inkscape::XML::Node *measure_repr = NULL, CanvasTextAnchorPositionEnum text_anchor = TEXT_ANCHOR_CENTER ); void knotStartMovedHandler(SPKnot */*knot*/, Geom::Point const &ppointer, guint state); void knotEndMovedHandler(SPKnot */*knot*/, Geom::Point const &ppointer, guint state); void knotUngrabbedHandler(SPKnot */*knot*/, unsigned int /*state*/); @@ -66,3 +70,14 @@ private: } #endif // SEEN_SP_MEASURING_CONTEXT_H + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/widgets/measure-toolbar.cpp b/src/widgets/measure-toolbar.cpp index 9c782b4b6..48c781fb3 100644 --- a/src/widgets/measure-toolbar.cpp +++ b/src/widgets/measure-toolbar.cpp @@ -178,6 +178,13 @@ static void sp_to_mark_dimension(void){ } } +static void sp_to_item(void){ + MeasureTool *mt = get_measure_tool(); + if (mt) { + mt->toItem(); + } +} + void sp_measure_toolbox_prep(SPDesktop * desktop, GtkActionGroup* mainActions, GObject* holder) { UnitTracker* tracker = new UnitTracker(Inkscape::Util::UNIT_TYPE_LINEAR); @@ -283,6 +290,16 @@ void sp_measure_toolbox_prep(SPDesktop * desktop, GtkActionGroup* mainActions, G g_signal_connect_after( G_OBJECT(act), "activate", G_CALLBACK(sp_to_mark_dimension), 0 ); gtk_action_group_add_action( mainActions, GTK_ACTION(act) ); } + //to item + { + InkAction* act = ink_action_new( "MeasureToItem", + _("Convert to item"), + _("Convert to item"), + INKSCAPE_ICON("path-reverse"), + secondarySize ); + g_signal_connect_after( G_OBJECT(act), "activate", G_CALLBACK(sp_to_item), 0 ); + gtk_action_group_add_action( mainActions, GTK_ACTION(act) ); + } } // end of sp_measure_toolbox_prep() diff --git a/src/widgets/toolbox.cpp b/src/widgets/toolbox.cpp index 3daa3c467..665502745 100644 --- a/src/widgets/toolbox.cpp +++ b/src/widgets/toolbox.cpp @@ -348,6 +348,7 @@ static gchar const * ui_descr = " <toolitem action='MeasureAllLayers' />" " <toolitem action='MeasureReverse' />" " <toolitem action='MeasureMarkDimension' />" + " <toolitem action='MeasureToItem' />" " </toolbar>" " <toolbar name='StarToolbar'>" |
