summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJabier Arraiza Cenoz <jabier.arraiza@marker.es>2015-10-04 01:31:27 +0000
committerjabiertxof <jabier.arraiza@marker.es>2015-10-04 01:31:27 +0000
commit6b61296109001d15cd1e2a43c38385b5fdba81c7 (patch)
tree3bbe592b4c5dd4ec4570de70df53709def6db9c2 /src
parentCrash. Fix for Bug #1404934 (Crash when opening files (Glib::ConvertError exc... (diff)
downloadinkscape-6b61296109001d15cd1e2a43c38385b5fdba81c7.tar.gz
inkscape-6b61296109001d15cd1e2a43c38385b5fdba81c7.zip
Add improvements to measure tool:
more responsive add option to handle only active layer or all add a option to hide/show first and last segment add a option to compute only one global sice (bzr r14393.1.1)
Diffstat (limited to 'src')
-rw-r--r--src/document.cpp20
-rw-r--r--src/document.h2
-rw-r--r--src/ui/tools/measure-tool.cpp731
-rw-r--r--src/ui/tools/measure-tool.h4
-rw-r--r--src/widgets/measure-toolbar.cpp36
-rw-r--r--src/widgets/toolbox.cpp3
6 files changed, 426 insertions, 370 deletions
diff --git a/src/document.cpp b/src/document.cpp
index c64bf3ed5..97113cb25 100644
--- a/src/document.cpp
+++ b/src/document.cpp
@@ -1450,7 +1450,7 @@ std::vector<SPItem*> SPDocument::getItemsPartiallyInBox(unsigned int dkey, Geom:
return find_items_in_area(x, SP_GROUP(this->root), dkey, box, overlaps);
}
-std::vector<SPItem*> SPDocument::getItemsAtPoints(unsigned const key, std::vector<Geom::Point> points) const
+std::vector<SPItem*> SPDocument::getItemsAtPoints(unsigned const key, std::vector<Geom::Point> points, bool all_layers, size_t limit) const
{
std::vector<SPItem*> items;
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
@@ -1464,11 +1464,25 @@ std::vector<SPItem*> SPDocument::getItemsAtPoints(unsigned const key, std::vecto
// Cache a flattened SVG DOM to speed up selection.
std::deque<SPItem*> nodes;
build_flat_item_list(&nodes, key, SP_GROUP(this->root), true, false, NULL);
-
+ SPObject *current_layer = SP_ACTIVE_DESKTOP->currentLayer();
+ SPDesktop *desktop = SP_ACTIVE_DESKTOP;
+ Inkscape::LayerModel *layer_model = NULL;
+ if(desktop){
+ layer_model = desktop->layers;
+ }
+ size_t h = 0;
for(int i = points.size()-1;i>=0; i--) {
SPItem *item = find_item_at_point(&nodes, key, points[i]);
if (item && items.end()==find(items.begin(),items.end(), item))
- items.push_back(item);
+ if(all_layers || (layer_model && layer_model->layerForObject(item) == current_layer)){
+ items.push_back(item);
+ h++;
+ //limit 0 = no limit
+ if(h == limit){
+ prefs->setDouble("/options/cursortolerance/value", saved_delta);
+ return items;
+ }
+ }
}
// and now we restore it back
diff --git a/src/document.h b/src/document.h
index dd1e295a2..be3f106d8 100644
--- a/src/document.h
+++ b/src/document.h
@@ -262,7 +262,7 @@ public:
std::vector<SPItem*> getItemsInBox(unsigned int dkey, Geom::Rect const &box) const;
std::vector<SPItem*> getItemsPartiallyInBox(unsigned int dkey, Geom::Rect const &box) const;
SPItem *getItemAtPoint(unsigned int key, Geom::Point const &p, bool into_groups, SPItem *upto = NULL) const;
- std::vector<SPItem*> getItemsAtPoints(unsigned const key, std::vector<Geom::Point> points) const;
+ std::vector<SPItem*> getItemsAtPoints(unsigned const key, std::vector<Geom::Point> points, bool all_layers = true, size_t limit = 0) const;
SPItem *getGroupAtPoint(unsigned int key, Geom::Point const &p) const;
void changeUriAndHrefs(char const *uri);
diff --git a/src/ui/tools/measure-tool.cpp b/src/ui/tools/measure-tool.cpp
index 570f3e796..aadc8790a 100644
--- a/src/ui/tools/measure-tool.cpp
+++ b/src/ui/tools/measure-tool.cpp
@@ -15,6 +15,7 @@
#include <boost/none_t.hpp>
#include "util/units.h"
#include "macros.h"
+#include "rubberband.h"
#include "display/curve.h"
#include "sp-shape.h"
#include "sp-text.h"
@@ -296,22 +297,18 @@ static void calculate_intersections(SPDesktop * /*desktop*/, SPItem* item, Geom:
}
bool MeasureTool::root_handler(GdkEvent* event) {
- Inkscape::Preferences *prefs = Inkscape::Preferences::get();
- tolerance = prefs->getIntLimited("/options/dragtolerance/value", 0, 0, 100);
-
gint ret = FALSE;
switch (event->type) {
case GDK_BUTTON_PRESS: {
Geom::Point const button_w(event->button.x, event->button.y);
explicitBase = boost::none;
- lastEnd = boost::none;
+ last_end = boost::none;
start_point = desktop->w2d(button_w);
if (event->button.button == 1 && !this->space_panning) {
// save drag origin
- xp = static_cast<gint>(event->button.x);
- yp = static_cast<gint>(event->button.y);
+ start_point = desktop->w2d(Geom::Point(event->button.x, event->button.y));
within_tolerance = true;
ret = TRUE;
@@ -330,417 +327,423 @@ bool MeasureTool::root_handler(GdkEvent* event) {
}
case GDK_KEY_PRESS: {
if ((event->key.keyval == GDK_KEY_Shift_L) || (event->key.keyval == GDK_KEY_Shift_R)) {
- if (lastEnd) {
- explicitBase = lastEnd;
+ if (last_end) {
+ explicitBase = last_end;
}
}
break;
}
case GDK_MOTION_NOTIFY: {
- if (!((event->motion.state & GDK_BUTTON1_MASK) && !this->space_panning)) {
- 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));
+ if (!(event->motion.state & GDK_BUTTON1_MASK) && !(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();
- }
+ m.preSnap(scp);
+ m.unSetup();
} else {
ret = TRUE;
-
- if ( within_tolerance
- && ( abs( static_cast<gint>(event->motion.x) - xp ) < tolerance )
- && ( abs( static_cast<gint>(event->motion.y) - yp ) < tolerance ) ) {
- break; // do not drag if we're within tolerance from origin
+ 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;
-
- //clear previous temporary canvas items, we'll draw new ones
- for (size_t idx = 0; idx < measure_tmp_items.size(); ++idx) {
- desktop->remove_temporary_canvasitem(measure_tmp_items[idx]);
- }
-
- measure_tmp_items.clear();
-
- 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();
- }
+ if(event->motion.time == 0 || !last_end || Geom::LInfty( motion_w - *last_end ) > (tolerance/2)){
+ showCanvasItems(event->motion);
+ last_end = motion_w ;
}
+ gobble_motion_events(GDK_BUTTON1_MASK);
+ }
+ break;
+ }
+ case GDK_BUTTON_RELEASE: {
+ sp_event_context_discard_delayed_snap_event(this);
+ explicitBase = boost::none;
+ last_end = boost::none;
- Geom::PathVector lineseg;
- Geom::Path p;
- p.start(desktop->dt2doc(start_point));
- p.appendNew<Geom::LineSegment>(desktop->dt2doc(end_point));
- lineseg.push_back(p);
-
- double deltax = end_point[Geom::X] - start_point[Geom::X];
- double deltay = end_point[Geom::Y] - start_point[Geom::Y];
- double angle = atan2(deltay, deltax);
- double baseAngle = 0;
+ //clear all temporary canvas items related to the measurement tool.
+ for (size_t idx = 0; idx < measure_tmp_items.size(); ++idx) {
+ desktop->remove_temporary_canvasitem(measure_tmp_items[idx]);
+ }
- if (explicitBase) {
- double deltax2 = explicitBase.get()[Geom::X] - start_point[Geom::X];
- double deltay2 = explicitBase.get()[Geom::Y] - start_point[Geom::Y];
+ measure_tmp_items.clear();
- baseAngle = atan2(deltay2, deltax2);
- angle -= baseAngle;
+ if (this->grabbed) {
+ sp_canvas_item_ungrab(this->grabbed, event->button.time);
+ this->grabbed = NULL;
+ }
- if (angle < -M_PI) {
- angle += 2 * M_PI;
- } else if (angle > M_PI) {
- angle -= 2 * M_PI;
- }
- }
+ start_point = Geom::Point();
+ break;
+ }
+ default:
+ break;
+ }
+ if (!ret) {
+ ret = ToolBase::root_handler(event);
+ }
+
+ return ret;
+}
-//TODO: calculate NPOINTS
-//800 seems to be a good value for 800x600 resolution
-#define NPOINTS 800
+void MeasureTool::showCanvasItems(GdkEventMotion const &mevent){
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ Geom::Point const motion_w(mevent.x, mevent.y);
+ bool show_in_between = prefs->getBool("/tools/measure/show_in_between");
+ bool all_layers = prefs->getBool("/tools/measure/all_layers");
+ //clear previous temporary canvas items, we'll draw new ones
+ for (size_t idx = 0; idx < measure_tmp_items.size(); ++idx) {
+ desktop->remove_temporary_canvasitem(measure_tmp_items[idx]);
+ }
- std::vector<Geom::Point> points;
+ measure_tmp_items.clear();
+ Geom::Point const motion_dt(desktop->w2d(motion_w));
+ Geom::Point end_point = motion_dt;
- for (double i = 0; i < NPOINTS; i++) {
- points.push_back(desktop->d2w(start_point + (i / NPOINTS) * (end_point - start_point)));
- }
+ if (mevent.state & GDK_CONTROL_MASK) {
+ spdc_endpoint_snap_rotation(this, end_point, start_point, mevent.state);
+ } else {
+ if (!(mevent.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();
+ }
+ }
- // TODO: Felipe, why don't you simply iterate over all items, and test whether their bounding boxes intersect
- // with the measurement line, instead of interpolating over 800 points? E.g. bbox_of_measurement_line.intersects(*bbox_of_item).
- // That's also how the object-snapper works, see _findCandidates() in object-snapper.cpp.
-
- // TODO switch to a different variable name. The single letter 'l' is easy to misread.
-
- //select elements crossed by line segment:
- std::vector<SPItem*> items = desktop->getDocument()->getItemsAtPoints(desktop->dkey, points);
- std::vector<double> intersection_times;
- 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);
- } else {
- if (SP_IS_TEXT(item) || SP_IS_FLOWTEXT(item)) {
- Inkscape::Text::Layout::iterator iter = te_get_layout(item)->begin();
- do {
- Inkscape::Text::Layout::iterator iter_next = iter;
- iter_next.nextGlyph(); // iter_next is one glyph ahead from iter
- if (iter == iter_next) {
- break;
- }
-
- // get path from iter to iter_next:
- SPCurve *curve = te_get_layout(item)->convertToCurves(iter, iter_next);
- iter = iter_next; // shift to next glyph
- if (!curve) {
- continue; // error converting this glyph
- }
- if (curve->is_empty()) { // whitespace glyph?
- curve->unref();
- continue;
- }
-
- curve->transform(item->i2doc_affine());
-
- calculate_intersections(desktop, item, lineseg, curve, intersection_times);
-
- if (iter == te_get_layout(item)->end()) {
- break;
- }
- } while (true);
- }
- }
- }
+ Geom::PathVector lineseg;
+ Geom::Path p;
+ p.start(desktop->dt2doc(start_point));
+ p.appendNew<Geom::LineSegment>(desktop->dt2doc(end_point));
+ lineseg.push_back(p);
- Inkscape::Preferences *prefs = Inkscape::Preferences::get();
- if (!prefs->getBool("/tools/measure/ignore_1st_and_last", true)) {
- intersection_times.push_back(0);
- intersection_times.push_back(1);
- }
+ double deltax = end_point[Geom::X] - start_point[Geom::X];
+ double deltay = end_point[Geom::Y] - start_point[Geom::Y];
+ double angle = atan2(deltay, deltax);
+ double baseAngle = 0;
- Glib::ustring unit_name = prefs->getString("/tools/measure/unit");
- if (!unit_name.compare("")) {
- unit_name = "px";
- }
+ if (explicitBase) {
+ double deltax2 = explicitBase.get()[Geom::X] - start_point[Geom::X];
+ double deltay2 = explicitBase.get()[Geom::Y] - start_point[Geom::Y];
- double fontsize = prefs->getInt("/tools/measure/fontsize");
+ baseAngle = atan2(deltay2, deltax2);
+ angle -= baseAngle;
- // Normal will be used for lines and text
- Geom::Point windowNormal = Geom::unit_vector(Geom::rot90(desktop->d2w(end_point - start_point)));
- Geom::Point normal = desktop->w2d(windowNormal);
+ if (angle < -M_PI) {
+ angle += 2 * M_PI;
+ } else if (angle > M_PI) {
+ angle -= 2 * M_PI;
+ }
+ }
+ std::vector<SPItem*> items;
+ Inkscape::Rubberband *r = Inkscape::Rubberband::get(desktop);
+ r->setMode(RUBBERBAND_MODE_TOUCHPATH);
+ if(!show_in_between){
+ r->start(desktop,start_point);
+ r->move(end_point);
+ items = desktop->getDocument()->getItemsAtPoints(desktop->dkey, r->getPoints(), all_layers, 2);
+ r->stop();
+ r->setMode(RUBBERBAND_MODE_TOUCHPATH);
+ r->start(desktop,end_point);
+ r->move(start_point);
+ std::vector<SPItem*> items_reverse = desktop->getDocument()->getItemsAtPoints(desktop->dkey, r->getPoints(), all_layers, 2);
+ r->stop();
+ if(items_reverse.size() == 2){
+ items.push_back(items_reverse[1]);
+ }
+ if(items_reverse.size() >= 1){
+ items.push_back(items_reverse[0]);
+ }
+ } else {
+ r->start(desktop,start_point);
+ r->move(end_point);
+ items = desktop->getDocument()->getItemsAtPoints(desktop->dkey, r->getPoints(), all_layers);
+ r->stop();
+ }
+ std::vector<double> intersection_times;
+ 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);
+ } else {
+ if (SP_IS_TEXT(item) || SP_IS_FLOWTEXT(item)) {
+ Inkscape::Text::Layout::iterator iter = te_get_layout(item)->begin();
+ do {
+ Inkscape::Text::Layout::iterator iter_next = iter;
+ iter_next.nextGlyph(); // iter_next is one glyph ahead from iter
+ if (iter == iter_next) {
+ break;
+ }
- 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++) {
- intersections.push_back(lineseg[0].pointAt(*iter_t));
- }
+ // get path from iter to iter_next:
+ SPCurve *curve = te_get_layout(item)->convertToCurves(iter, iter_next);
+ iter = iter_next; // shift to next glyph
+ if (!curve) {
+ continue; // error converting this glyph
+ }
+ if (curve->is_empty()) { // whitespace glyph?
+ curve->unref();
+ continue;
+ }
- std::vector<LabelPlacement> placements;
- for (size_t idx = 1; idx < intersections.size(); ++idx) {
- LabelPlacement placement;
- placement.lengthVal = (intersections[idx] - intersections[idx - 1]).length();
- placement.lengthVal = Inkscape::Util::Quantity::convert(placement.lengthVal, "px", unit_name);
- placement.offset = DIMENSION_OFFSET;
- placement.start = desktop->doc2dt( (intersections[idx - 1] + intersections[idx]) / 2 );
- placement.end = placement.start - (normal * placement.offset);
+ curve->transform(item->i2doc_affine());
- placements.push_back(placement);
- }
+ calculate_intersections(desktop, item, lineseg, curve, intersection_times);
+ if (iter == te_get_layout(item)->end()) {
+ break;
+ }
+ } while (true);
+ }
+ }
+ }
+ Glib::ustring unit_name = prefs->getString("/tools/measure/unit");
+ if (!unit_name.compare("")) {
+ unit_name = "px";
+ }
- // Adjust positions
- repositionOverlappingLabels(placements, desktop, windowNormal, fontsize);
-
- 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);
- 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));
- g_free(measure_str);
- }
+ double fontsize = prefs->getInt("/tools/measure/fontsize");
- Geom::Point angleDisplayPt = calcAngleDisplayAnchor(desktop, angle, baseAngle,
- 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);
- 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));
- g_free(angle_str);
- }
+ // Normal will be used for lines and text
+ Geom::Point windowNormal = Geom::unit_vector(Geom::rot90(desktop->d2w(end_point - start_point)));
+ Geom::Point normal = desktop->w2d(windowNormal);
- {
- double totallengthval = (end_point - start_point).length();
- totallengthval = Inkscape::Util::Quantity::convert(totallengthval, "px", unit_name);
-
- // 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);
- 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));
- g_free(totallength_str);
- }
+ 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){
+ intersections.push_back(lineseg[0].pointAt(*iter_t));
+ }
+ }
+ 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]));
+ }
+ if (!prefs->getBool("/tools/measure/ignore_1st_and_last", true)) {
+ intersections.insert(intersections.begin(),lineseg[0].pointAt(0));
+ intersections.push_back(lineseg[0].pointAt(1));
+ }
+ std::vector<LabelPlacement> placements;
+ for (size_t idx = 1; idx < intersections.size(); ++idx) {
+ LabelPlacement placement;
+ placement.lengthVal = (intersections[idx] - intersections[idx - 1]).length();
+ placement.lengthVal = Inkscape::Util::Quantity::convert(placement.lengthVal, "px", unit_name);
+ placement.offset = DIMENSION_OFFSET;
+ placement.start = desktop->doc2dt( (intersections[idx - 1] + intersections[idx]) / 2 );
+ placement.end = placement.start - (normal * placement.offset);
+
+ placements.push_back(placement);
+ }
- if (intersections.size() > 2) {
- double totallengthval = (intersections[intersections.size()-1] - intersections[0]).length();
- totallengthval = Inkscape::Util::Quantity::convert(totallengthval, "px", unit_name);
-
- // 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 * 60,
- 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));
- g_free(total_str);
- }
+ // Adjust positions
+ repositionOverlappingLabels(placements, desktop, windowNormal, fontsize);
+ 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);
+ 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));
+ g_free(measure_str);
+ }
- // 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_CTRL(canvasitem)->moveto(desktop->doc2dt(intersections[idx]));
- measure_tmp_items.push_back(desktop->add_temporary_canvasitem(canvasitem, 0));
- }
+ Geom::Point angleDisplayPt = calcAngleDisplayAnchor(desktop, angle, baseAngle,
+ start_point, end_point,
+ fontsize);
- // 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);
- 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])) {
- double length = std::abs((end_point - start_point).length());
- Geom::Point anchorEnd = start_point;
- anchorEnd[Geom::X] += length;
- if (explicitBase) {
- anchorEnd *= (Geom::Affine(Geom::Translate(-start_point))
- * Geom::Affine(Geom::Rotate(baseAngle))
- * Geom::Affine(Geom::Translate(start_point)));
- }
-
- SPCtrlLine *control_line = ControlManager::getManager().createControlLine(desktop->getTempGroup(),
- 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);
- }
- }
+ {
+ // 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);
+ 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));
+ g_free(angle_str);
+ }
- if (intersections.size() > 2) {
- ControlManager &mgr = ControlManager::getManager();
- SPCtrlLine *control_line = 0;
- control_line = mgr.createControlLine(desktop->getTempGroup(),
- desktop->doc2dt(intersections[0]) + normal * 60,
- desktop->doc2dt(intersections[intersections.size() - 1]) + normal * 60);
- measure_tmp_items.push_back(desktop->add_temporary_canvasitem(control_line, 0));
-
- control_line = mgr.createControlLine(desktop->getTempGroup(),
- desktop->doc2dt(intersections[0]),
- desktop->doc2dt(intersections[0]) + normal * 65);
- measure_tmp_items.push_back(desktop->add_temporary_canvasitem(control_line, 0));
-
- control_line = mgr.createControlLine(desktop->getTempGroup(),
- desktop->doc2dt(intersections[intersections.size() - 1]),
- desktop->doc2dt(intersections[intersections.size() - 1]) + normal * 65);
- measure_tmp_items.push_back(desktop->add_temporary_canvasitem(control_line, 0));
- }
+ {
+ double totallengthval = (end_point - start_point).length();
+ totallengthval = Inkscape::Util::Quantity::convert(totallengthval, "px", unit_name);
+
+ // 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);
+ 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));
+ g_free(totallength_str);
+ }
- // call-out lines
- 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);
- measure_tmp_items.push_back(desktop->add_temporary_canvasitem(control_line, 0));
- }
+ if (intersections.size() > 2) {
+ double totallengthval = (intersections[intersections.size()-1] - intersections[0]).length();
+ totallengthval = Inkscape::Util::Quantity::convert(totallengthval, "px", unit_name);
+
+ // 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 * 60,
+ 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));
+ g_free(total_str);
+ }
- {
- for (size_t idx = 1; idx < intersections.size(); ++idx) {
- Geom::Point measure_text_pos = (intersections[idx - 1] + intersections[idx]) / 2;
+ // 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_CTRL(canvasitem)->moveto(desktop->doc2dt(intersections[idx]));
+ measure_tmp_items.push_back(desktop->add_temporary_canvasitem(canvasitem, 0));
+ }
- 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);
- measure_tmp_items.push_back(desktop->add_temporary_canvasitem(control_line, 0));
- }
- }
+ // Since adding goes to the bottom, do all lines last.
- // 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));
- }
+ // draw main control line
+ {
+ SPCtrlLine *control_line = ControlManager::getManager().createControlLine(desktop->getTempGroup(),
+ 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])) {
+ double length = std::abs((end_point - start_point).length());
+ Geom::Point anchorEnd = start_point;
+ anchorEnd[Geom::X] += length;
+ if (explicitBase) {
+ anchorEnd *= (Geom::Affine(Geom::Translate(-start_point))
+ * Geom::Affine(Geom::Rotate(baseAngle))
+ * Geom::Affine(Geom::Translate(start_point)));
+ }
- lastEnd = end_point; // track in case we get a anchoring key-press later
+ SPCtrlLine *control_line = ControlManager::getManager().createControlLine(desktop->getTempGroup(),
+ start_point,
+ anchorEnd,
+ CTLINE_SECONDARY);
+ measure_tmp_items.push_back(desktop->add_temporary_canvasitem(control_line, 0));
- gobble_motion_events(GDK_BUTTON1_MASK);
- }
- break;
+ createAngleDisplayCurve(desktop, start_point, end_point, angleDisplayPt, angle);
}
- case GDK_BUTTON_RELEASE: {
- sp_event_context_discard_delayed_snap_event(this);
- explicitBase = boost::none;
- lastEnd = boost::none;
-
- //clear all temporary canvas items related to the measurement tool.
- for (size_t idx = 0; idx < measure_tmp_items.size(); ++idx) {
- desktop->remove_temporary_canvasitem(measure_tmp_items[idx]);
- }
+ }
- measure_tmp_items.clear();
+ if (intersections.size() > 2) {
+ ControlManager &mgr = ControlManager::getManager();
+ SPCtrlLine *control_line = 0;
+ control_line = mgr.createControlLine(desktop->getTempGroup(),
+ desktop->doc2dt(intersections[0]) + normal * 60,
+ desktop->doc2dt(intersections[intersections.size() - 1]) + normal * 60);
+ measure_tmp_items.push_back(desktop->add_temporary_canvasitem(control_line, 0));
+
+ control_line = mgr.createControlLine(desktop->getTempGroup(),
+ desktop->doc2dt(intersections[0]),
+ desktop->doc2dt(intersections[0]) + normal * 65);
+ measure_tmp_items.push_back(desktop->add_temporary_canvasitem(control_line, 0));
+
+ control_line = mgr.createControlLine(desktop->getTempGroup(),
+ desktop->doc2dt(intersections[intersections.size() - 1]),
+ desktop->doc2dt(intersections[intersections.size() - 1]) + normal * 65);
+ measure_tmp_items.push_back(desktop->add_temporary_canvasitem(control_line, 0));
+ }
- if (this->grabbed) {
- sp_canvas_item_ungrab(this->grabbed, event->button.time);
- this->grabbed = NULL;
- }
+ // call-out lines
+ 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);
+ measure_tmp_items.push_back(desktop->add_temporary_canvasitem(control_line, 0));
+ }
- xp = 0;
- yp = 0;
- break;
+ {
+ for (size_t idx = 1; idx < intersections.size(); ++idx) {
+ Geom::Point measure_text_pos = (intersections[idx - 1] + intersections[idx]) / 2;
+
+ 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);
+ measure_tmp_items.push_back(desktop->add_temporary_canvasitem(control_line, 0));
}
- default:
- break;
}
- if (!ret) {
- ret = ToolBase::root_handler(event);
+ // 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));
}
-
- return ret;
}
-
}
}
}
diff --git a/src/ui/tools/measure-tool.h b/src/ui/tools/measure-tool.h
index 9701ba6ea..4673e0f0a 100644
--- a/src/ui/tools/measure-tool.h
+++ b/src/ui/tools/measure-tool.h
@@ -32,15 +32,15 @@ public:
virtual void finish();
virtual bool root_handler(GdkEvent* event);
+ virtual void showCanvasItems(GdkEventMotion const &event);
virtual const std::string& getPrefsPath();
private:
SPCanvasItem* grabbed;
-
Geom::Point start_point;
boost::optional<Geom::Point> explicitBase;
- boost::optional<Geom::Point> lastEnd;
+ boost::optional<Geom::Point> last_end;
};
}
diff --git a/src/widgets/measure-toolbar.cpp b/src/widgets/measure-toolbar.cpp
index 5a4785b1f..ca79b5792 100644
--- a/src/widgets/measure-toolbar.cpp
+++ b/src/widgets/measure-toolbar.cpp
@@ -38,6 +38,8 @@
#include "widgets/ege-output-action.h"
#include "preferences.h"
#include "toolbox.h"
+#include "widgets/ink-action.h"
+#include "ui/icon-names.h"
#include "ui/widget/unit-tracker.h"
using Inkscape::UI::Widget::UnitTracker;
@@ -79,6 +81,7 @@ void sp_measure_toolbox_prep(SPDesktop * desktop, GtkActionGroup* mainActions, G
g_object_set_data( holder, "tracker", tracker );
EgeAdjustmentAction *eact = 0;
+ Inkscape::IconSize secondarySize = ToolboxFactory::prefToSize("/toolbox/secondary", 1);
/* Font Size */
{
@@ -108,6 +111,39 @@ void sp_measure_toolbox_prep(SPDesktop * desktop, GtkActionGroup* mainActions, G
g_signal_connect_after( G_OBJECT(act), "changed", G_CALLBACK(measure_unit_changed), holder );
gtk_action_group_add_action( mainActions, act );
}
+ // ignore_1st_and_last
+ {
+ InkToggleAction* act = ink_toggle_action_new( "MeasureIgnore1stAndLast",
+ _("Ignore first and last"),
+ _("Ignore first and last"),
+ INKSCAPE_ICON("draw-geometry-line-segment"),
+ secondarySize );
+ gtk_action_group_add_action( mainActions, GTK_ACTION( act ) );
+ PrefPusher *pusher = new PrefPusher(GTK_TOGGLE_ACTION(act), "/tools/measure/ignore_1st_and_last");
+ g_signal_connect( holder, "destroy", G_CALLBACK(delete_prefspusher), pusher);
+ }
+ // measure imbetweens
+ {
+ InkToggleAction* act = ink_toggle_action_new( "MeasureInBettween",
+ _("Show meassures between items"),
+ _("Show meassures between items"),
+ INKSCAPE_ICON("distribute-randomize"),
+ secondarySize );
+ gtk_action_group_add_action( mainActions, GTK_ACTION( act ) );
+ PrefPusher *pusher = new PrefPusher(GTK_TOGGLE_ACTION(act), "/tools/measure/show_in_between");
+ g_signal_connect( holder, "destroy", G_CALLBACK(delete_prefspusher), pusher);
+ }
+ // measure only current layer
+ {
+ InkToggleAction* act = ink_toggle_action_new( "MeasureAllLayers",
+ _("Measure all layers"),
+ _("Measure all layers"),
+ INKSCAPE_ICON("dialog-layers"),
+ secondarySize );
+ gtk_action_group_add_action( mainActions, GTK_ACTION( act ) );
+ PrefPusher *pusher = new PrefPusher(GTK_TOGGLE_ACTION(act), "/tools/measure/all_layers");
+ g_signal_connect( holder, "destroy", G_CALLBACK(delete_prefspusher), pusher);
+ }
} // end of sp_measure_toolbox_prep()
diff --git a/src/widgets/toolbox.cpp b/src/widgets/toolbox.cpp
index cdf39e9ef..ba02adb92 100644
--- a/src/widgets/toolbox.cpp
+++ b/src/widgets/toolbox.cpp
@@ -341,6 +341,9 @@ static gchar const * ui_descr =
" <separator />"
" <toolitem action='measure_units_label' />"
" <toolitem action='MeasureUnitsAction' />"
+ " <toolitem action='MeasureIgnore1stAndLast' />"
+ " <toolitem action='MeasureInBettween' />"
+ " <toolitem action='MeasureAllLayers' />"
" </toolbar>"
" <toolbar name='StarToolbar'>"