measure-tool.cpp revision 057ccfd4aef2393aaf723dda8d0059cc82e76b6d
/*
* Our nice measuring tool
*
* 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
*
* Released under GNU GPL, read the file 'COPYING' for more information
*/
#include <gdk/gdkkeysyms.h>
#include <boost/none_t.hpp>
#include "display/canvas-text.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 "svg/svg-color.h"
#include "ui/tools/measure-tool.h"
#include "ui/tools/freehand-base.h"
#include "ui/control-manager.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 "knot-enums.h"
#include "desktop-style.h"
#include "verbs.h"
using Inkscape::ControlManager;
using Inkscape::CTLINE_SECONDARY;
using Inkscape::DocumentUndo;
#define MT_KNOT_COLOR_NORMAL 0xffffff00
#define MT_KNOT_COLOR_MOUSEOVER 0xff000000
namespace Inkscape {
namespace UI {
namespace Tools {
{
return MeasureTool::prefsPath;
}
namespace {
/**
* Simple class to use for removing label overlap.
*/
class LabelPlacement {
public:
double lengthVal;
double offset;
};
{
} else {
}
}
void repositionOverlappingLabels(std::vector<LabelPlacement> &placements, SPDesktop *desktop, Geom::Point const &normal, double fontsize)
{
double border = 3;
{
}
// Using index since vector may be re-ordered as we go.
// Starting at one, since the first item can't overlap itself
bool changed = false;
do {
changed = false;
bool overlaps = false;
overlaps = true;
}
}
if (overlaps) {
changed = true;
}
} while (changed);
}
}
/**
* Calculates where to place the anchor for the display text and arc.
*
* @param desktop the desktop that is being used.
* @param angle the angle to be displaying.
* @param baseAngle the angle of the initial baseline.
* @param startPoint the point that is the vertex of the selected angle.
* @param endPoint the point that is the end the user is manipulating for measurement.
* @param fontsize the size to display the text label at.
*/
double fontsize)
{
// Time for the trick work of figuring out where things should go, and how.
}
// Bring it in to "title safe" for the anchor point
return where;
}
/**
* Given an angle, the arc center and edge point, draw an arc segment centered around that edge point.
*
* @param desktop the desktop that is being used.
* @param center the center point for the arc.
* @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, 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.
if (sideLen > 0.0) {
// arc start
// arc end
// from Riskus
SPCtrlCurve *curve = ControlManager::getManager().createControlCurve(desktop->getTempGroup(), p1, p2, p3, p4, CTLINE_SECONDARY);
if(measure_repr) {
Geom::PathVector c;
c.push_back(p);
if (c.size() == 1) {
Geom::Point strokewidth = Geom::Point(1,1) * SP_ITEM(desktop->currentLayer())->i2doc_affine().inverse();
gchar c[64];
sp_svg_write_color (c, sizeof(c), line_color_secondary);
}
}
}
}
} // namespace
{
// create the knots
this->knot_start->updateCtrl();
this->knot_end->updateCtrl();
if(display_area.interiorContains(start_p) && display_area.interiorContains(end_p) && end_p != MAGIC_POINT) {
this->knot_start->show();
}
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));
this->_knot_end_moved_connection = this->knot_end->moved_signal.connect(sigc::mem_fun(*this, &MeasureTool::knotEndMovedHandler));
this->_knot_end_ungrabbed_connection = this->knot_end->ungrabbed_signal.connect(sigc::mem_fun(*this, &MeasureTool::knotUngrabbedHandler));
}
{
this->_knot_start_moved_connection.disconnect();
this->_knot_end_moved_connection.disconnect();
this->_knot_end_ungrabbed_connection.disconnect();
/* unref should call destroy */
knot_unref(this->knot_start);
knot_unref(this->knot_end);
}
}
void MeasureTool::reverseKnots()
{
this->knot_start->show();
this->showCanvasItems();
}
{
if (state & GDK_CONTROL_MASK) {
} else if (!(state & GDK_SHIFT_MASK)) {
m.unSetup();
}
}
}
{
if (state & GDK_CONTROL_MASK) {
} else if (!(state & GDK_SHIFT_MASK)) {
m.unSetup();
}
}
}
{
}
void MeasureTool::finish()
{
this->enableGrDrag(false);
if (this->grabbed) {
}
}
//void MeasureTool::setup() {
// ToolBase* ec = this;
//
//// if (SP_EVENT_CONTEXT_CLASS(sp_measure_context_parent_class)->setup) {
//// SP_EVENT_CONTEXT_CLASS(sp_measure_context_parent_class)->setup(ec);
//// }
// ToolBase::setup();
//}
//gint MeasureTool::item_handler(SPItem* item, GdkEvent* event) {
// gint ret = FALSE;
//
//// if (SP_EVENT_CONTEXT_CLASS(sp_measure_context_parent_class)->item_handler) {
//// ret = SP_EVENT_CONTEXT_CLASS(sp_measure_context_parent_class)->item_handler(event_context, item, event);
//// }
// ret = ToolBase::item_handler(item, event);
//
// return ret;
//}
static void calculate_intersections(SPDesktop * /*desktop*/, SPItem* item, Geom::PathVector const &lineseg, SPCurve *curve, std::vector<double> &intersections)
{
// Find all intersections of the control-line with this shape
// Reconstruct and store the points of intersection
#if 0
//TODO: consider only visible intersections
double eps = 0.0001;
}
#else
#endif
}
}
{
case GDK_BUTTON_PRESS: {
this->knot_start->hide();
// save drag origin
within_tolerance = true;
}
m.unSetup();
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,
break;
}
case GDK_KEY_PRESS: {
}
break;
}
case GDK_MOTION_NOTIFY: {
m.unSetup();
}
} else {
if ( within_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/4.0)) {
m.unSetup();
}
}
}
break;
}
case GDK_BUTTON_RELEASE: {
this->knot_start->show();
if(last_end) {
m.unSetup();
}
}
if (this->grabbed) {
}
break;
}
default:
break;
}
if (!ret) {
}
return ret;
}
void MeasureTool::setMarkers()
{
if (!arrowStart) {
setMarker(true);
}
if(!arrowEnd) {
setMarker(false);
}
}
{
if(isStart) {
} else {
}
if(isStart) {
} else {
}
marker->updateRepr();
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) {
} else {
}
if(isStart) {
} else {
}
path->updateRepr();
}
void MeasureTool::toItem()
{
showCanvasItems(true, rgroup);
doc->ensureUpToDate();
reset();
}
void MeasureTool::toMarkDimension()
{
setMarkers();
unit_name = "px";
}
doc->ensureUpToDate();
}
void MeasureTool::setLine(Geom::Point start_point,Geom::Point end_point, bool markers, guint32 *color, Inkscape::XML::Node *measure_repr)
{
return;
}
Geom::PathVector c;
c.push_back(p);
if (c.size() == 1) {
Geom::Point strokewidth = Geom::Point(1,1) * SP_ITEM(desktop->currentLayer())->i2doc_affine().inverse();
if(measure_repr) {
} else {
}
if(color) {
gchar c[64];
sp_svg_write_color (c, sizeof(c), *color);
} else {
}
if(measure_repr) {
} else {
}
if(markers) {
}
if(measure_repr) {
} else {
item->updateRepr();
}
}
}
{
return;
}
char const * svgd;
svgd = "m 0.707,0.707 6.586,6.586 m 0,-6.586 -6.586,6.586";
c *= scale;
if (c.size() == 2) {
Geom::Point strokewidth = (Geom::Point(1,1) * SP_ITEM(desktop->currentLayer())->i2doc_affine().inverse())/ desktop->current_zoom();
gchar c[64];
sp_svg_write_color (c, sizeof(c), line_color_secondary);
}
}
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> */
/* Set style */
if(measure_repr) {
} else {
}
/* Create <tspan> */
if(measure_repr) {
} else {
}
/* Create TEXT */
text_item->updateRepr();
if (!measure_repr && bbox) {
}
if(measure_repr) {
/* Create <group> */
/* Create <rect> */
gchar c[64];
sp_svg_write_color (c, sizeof(c), *background);
}
} else {
}
}
void MeasureTool::reset()
{
this->knot_start->hide();
}
}
{
return;
}
//clear previous temporary canvas items, we'll draw new ones
}
double baseAngle = 0;
if (explicitBase) {
}
}
if(!show_in_between) {
r->stop();
std::vector<SPItem*> items_reverse = desktop->getDocument()->getItemsAtPoints(desktop->dkey, r->getPoints(), all_layers, 2);
r->stop();
}
}
} else {
r->stop();
}
if (SP_IS_SHAPE(item)) {
} else {
do {
break;
}
// get path from iter to iter_next:
if (!curve) {
continue; // error converting this glyph
}
continue;
}
break;
}
} while (true);
}
}
}
unit_name = "px";
}
// Normal will be used for lines and text
for (std::vector<double>::iterator iter_t = intersection_times.begin(); iter_t != intersection_times.end(); iter_t++) {
if(show_in_between) {
}
}
}
}
}
// Adjust positions
// TODO cleanup memory, Glib::ustring, etc.:
canvas_tooltip->outline = false;
canvas_tooltip->background = true;
if(to_item) {
}
}
fontsize);
{
// TODO cleanup memory, Glib::ustring, etc.:
canvas_tooltip->outline = false;
canvas_tooltip->background = true;
if(to_item) {
}
}
{
// TODO cleanup memory, Glib::ustring, etc.:
canvas_tooltip->outline = false;
canvas_tooltip->background = true;
if(to_item) {
setLabelText(totallength_str, end_p + desktop->w2d(Geom::Point(3*fontsize, -fontsize)), fontsize, 0, &background, measure_repr, TEXT_ANCHOR_LEFT);
}
}
// TODO cleanup memory, Glib::ustring, etc.:
desktop->doc2dt((intersections[0] + intersections[intersections.size()-1])/2) + normal * (dimension_offset * 2),
canvas_tooltip->outline = false;
canvas_tooltip->background = true;
if(to_item) {
setLabelText(total_str, desktop->doc2dt((intersections[0] + intersections[intersections.size()-1])/2) + normal * (dimension_offset * 2), fontsize, 0, &background, measure_repr);
}
}
// Initial point
{
"anchor", SP_ANCHOR_CENTER,
"size", 8.0,
"stroked", TRUE,
"stroke_color", 0xff0000ff,
"mode", SP_KNOT_MODE_XOR,
"shape", SP_KNOT_SHAPE_CROSS,
NULL );
if(to_item) {
}
}
// Now that text has been added, we can add lines and controls so that they go underneath
// Display the intersection indicator (i.e. the cross)
"anchor", SP_ANCHOR_CENTER,
"size", 8.0,
"stroked", TRUE,
"stroke_color", 0xff0000ff,
"mode", SP_KNOT_MODE_XOR,
"shape", SP_KNOT_SHAPE_CROSS,
NULL );
if(to_item) {
}
}
// Since adding goes to the bottom, do all lines last.
// draw main control line
{
end_p);
if (explicitBase) {
}
if(to_item) {
false,
}
}
}
SPCtrlLine *control_line = 0;
if(to_item) {
false,
}
if(to_item) {
false,
}
if(to_item) {
false,
}
}
// call-out lines
if(to_item) {
}
}
{
if(to_item) {
false,
}
}
}
}
}
}
}
/*
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 :