/*
* 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
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <gtkmm.h>
#include <gdk/gdkkeysyms.h>
#include <boost/none_t.hpp>
#include "display/sodipodi-ctrl.h"
#include "display/sp-ctrlline.h"
#include "display/sp-ctrlcurve.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/dialog/knot-properties.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 "sp-root.h"
#include "macros.h"
#include "svg/stringstream.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 "knot.h"
#include "text-editing.h"
#include "pixmaps/cursor-measure.xpm"
#include "preferences.h"
#include "inkscape.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;
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 {
}
}
//precision is for give the number of decimal positions
//of the label to calculate label width
void repositionOverlappingLabels(std::vector<LabelPlacement> &placements, SPDesktop *desktop, Geom::Point const &normal, double fontsize, int precision)
{
{
}
// 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;
}
/**
* Create a measure iten in current document.
*
* @param pathv the path to create.
* @param markers, if the path resuts get markers.
* @param color of the stroke.
* @param measure_repr container element.
*/
void setMeasureItem(Geom::PathVector pathv, bool is_curve, bool markers, guint32 color, Inkscape::XML::Node *measure_repr)
{
if(!desktop) {
return;
}
if(measure_repr) {
} else {
}
if(color) {
} else {
}
if(measure_repr) {
} else {
}
if(markers) {
}
if(measure_repr) {
} else {
item->updateRepr();
}
}
/**
* 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, bool to_phantom, std::vector<SPCanvasItem *> &measure_phantom_items , std::vector<SPCanvasItem *> &measure_tmp_items , 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(to_phantom){
} else {
}
if(measure_repr) {
}
}
}
}
} // namespace
{
start_p = readMeasurePoint(true);
end_p = readMeasurePoint(false);
dimension_offset = 35;
// create the knots
this->knot_start = new SPKnot(desktop, N_("Measure start, <b>Shift+Click</b> for position dialog"));
this->knot_start->updateCtrl();
this->knot_end->updateCtrl();
if(display_area.interiorContains(start_p) && display_area.interiorContains(end_p) && end_p != Geom::Point()) {
this->knot_start->show();
} else {
writeMeasurePoint(start_p, true);
writeMeasurePoint(end_p, false);
}
this->_knot_start_moved_connection = this->knot_start->moved_signal.connect(sigc::mem_fun(*this, &MeasureTool::knotStartMovedHandler));
this->_knot_start_click_connection = this->knot_start->click_signal.connect(sigc::mem_fun(*this, &MeasureTool::knotClickHandler));
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_click_connection = this->knot_end->click_signal.connect(sigc::mem_fun(*this, &MeasureTool::knotClickHandler));
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);
}
}
}
if(!namedview) {
}
if(!measure_point_data) {
measure_point_data = "0,0";
}
if (success == 2) {
return point_data;
}
}
if(!namedview) {
return;
}
}
//This function is used to reverse the Measure, I do it in two steps because when move the knot the
//start_ or the end_p are overwrite so I need the original values.
{
this->knot_start->show();
this->showCanvasItems();
}
{
if (state & GDK_SHIFT_MASK) {
}
}
{
if (state & GDK_CONTROL_MASK) {
} else if (!(state & GDK_SHIFT_MASK)) {
}
}
}
{
if (state & GDK_CONTROL_MASK) {
} else if (!(state & GDK_SHIFT_MASK)) {
}
}
}
{
}
//todo: we need this function?
{
this->enableGrDrag(false);
if (this->grabbed) {
}
}
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 (!show_hidden) {
item == desktop->getItemAtPoint(desktop->d2w(desktop->dt2doc(lineseg[0].pointAt((*m).ta - eps))), true, NULL)) ||
item == desktop->getItemAtPoint(desktop->d2w(desktop->dt2doc(lineseg[0].pointAt((*m).ta + eps))), true, NULL))) {
}
} else {
}
}
}
{
case GDK_BUTTON_PRESS: {
this->knot_start->hide();
// save drag origin
within_tolerance = true;
}
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: {
}
} 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)) {
}
}
}
break;
}
case GDK_BUTTON_RELEASE: {
this->knot_start->show();
if(last_end) {
}
}
if (this->grabbed) {
}
break;
}
default:
break;
}
if (!ret) {
}
return ret;
}
{
if (!arrowStart) {
setMarker(true);
}
if(!arrowEnd) {
setMarker(false);
}
}
{
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");
rpath->setAttribute("transform", isStart ? "scale(0.3) translate(-2.3,0)" : "scale(0.3) rotate(180) translate(-2.3,0)");
path->updateRepr();
}
{
return;
}
if(!namedview) {
return;
}
if(explicit_base) {
}
}
showCanvasItems(true);
doc->ensureUpToDate();
DocumentUndo::done(desktop->getDocument(), SP_VERB_CONTEXT_MEASURE,_("Add guides from measure tool"));
}
{
return;
}
}
}
showCanvasItems(false, false, true);
doc->ensureUpToDate();
DocumentUndo::done(desktop->getDocument(), SP_VERB_CONTEXT_MEASURE,_("Add Stored to measure tool"));
}
{
return;
}
showCanvasItems(false, true, false, rgroup);
doc->ensureUpToDate();
reset();
}
{
return;
}
setMarkers();
unit_name = "px";
}
gchar *totallength_str = g_strdup_printf(precision_str.str().c_str(), totallengthval * scale, unit_name.c_str());
doc->ensureUpToDate();
}
{
if(root) {
}
if(!namedview) {
return;
}
//measure angle
}
void MeasureTool::setLine(Geom::Point start_point,Geom::Point end_point, bool markers, guint32 color, Inkscape::XML::Node *measure_repr)
{
return;
}
}
}
{
return;
}
char const * svgd;
svgd = "m 0.707,0.707 6.586,6.586 m 0,-6.586 -6.586,6.586";
}
}
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 {
}
if(measure_repr) {
} else {
}
/* Create TEXT */
text_item->updateRepr();
if (!measure_repr && bbox) {
}
if(measure_repr) {
/* Create <group> */
/* Create <rect> */
}
} else {
}
}
{
this->knot_start->hide();
}
}
void MeasureTool::setMeasureCanvasText(bool is_angle, double precision, double amount, double fontsize, Glib::ustring unit_name, Geom::Point position, guint32 background, CanvasTextAnchorPositionEnum text_anchor, bool to_item, bool to_phantom, Inkscape::XML::Node *measure_repr)
{
if(is_angle){
} else {
}
canvas_tooltip->outline = false;
canvas_tooltip->background = true;
if(to_phantom){
} else {
}
if(to_item) {
}
}
void MeasureTool::setMeasureCanvasItem(Geom::Point position, bool to_item, bool to_phantom, Inkscape::XML::Node *measure_repr){
if(to_phantom){
color = 0x888888ff;
}
"anchor", SP_ANCHOR_CENTER,
"size", 8.0,
"stroked", TRUE,
"stroke_color", color,
"mode", SP_KNOT_MODE_XOR,
"shape", SP_KNOT_SHAPE_CROSS,
NULL );
if(to_phantom){
} else {
}
if(to_item) {
}
}
void MeasureTool::setMeasureCanvasControlLine(Geom::Point start, Geom::Point end, bool to_item, bool to_phantom, Inkscape::CtrlLineType ctrl_line_type, Inkscape::XML::Node *measure_repr){
if(to_phantom){
}
end,
if(to_phantom){
} else {
}
if(to_item) {
end,
false,
}
}
void MeasureTool::showCanvasItems(bool to_guides, bool to_item, bool to_phantom, Inkscape::XML::Node *measure_repr)
{
return;
}
writeMeasurePoint(start_p, true);
writeMeasurePoint(end_p, false);
//clear previous canvas items, we'll draw new ones
}
//TODO:Calculate the measure area for current lenght and origin
// and use canvas->requestRedraw. In the calculation need a gap for outside text
// maybe this remove the trash lines on measure use
dimension_offset = 70;
double baseAngle = 0;
if (explicit_base) {
}
if(desktop){
}
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) {
}
}
}
}
// Adjust positions
setMeasureCanvasText(false, precision, place.lengthVal * scale, fontsize, unit_name, place.end, 0x0000007f, TEXT_ANCHOR_CENTER, to_item, to_phantom, measure_repr);
}
fontsize);
{
setMeasureCanvasText(true, precision, Geom::deg_from_rad(angle), fontsize, unit_name, angleDisplayPt, 0x337f337f, TEXT_ANCHOR_CENTER, to_item, to_phantom, measure_repr);
}
{
setMeasureCanvasText(false, precision, totallengthval * scale, fontsize, unit_name, origin, 0x3333337f, TEXT_ANCHOR_LEFT, to_item, to_phantom, measure_repr);
}
Geom::Point origin = desktop->doc2dt((intersections[0] + intersections[intersections.size()-1])/2) + normal * dimension_offset;
setMeasureCanvasText(false, precision, totallengthval * scale, fontsize, unit_name, origin, 0x33337f7f, TEXT_ANCHOR_CENTER, to_item, to_phantom, measure_repr);
}
// Initial point
{
}
// Now that text has been added, we can add lines and controls so that they go underneath
if(to_guides) {
} else {
}
} else {
}
}
}
// Since adding goes to the bottom, do all lines last.
// draw main control line
{
if (explicit_base) {
}
setMeasureCanvasControlLine(start_p, anchorEnd, to_item, to_phantom, CTLINE_SECONDARY, measure_repr);
createAngleDisplayCurve(desktop, start_p, end_p, angleDisplayPt, angle, to_phantom, measure_phantom_items, measure_tmp_items, measure_repr);
}
setMeasureCanvasControlLine(desktop->doc2dt(intersections[0]) + normal * dimension_offset, desktop->doc2dt(intersections[intersections.size() - 1]) + normal * dimension_offset, to_item, to_phantom, CTLINE_PRIMARY , measure_repr);
setMeasureCanvasControlLine(desktop->doc2dt(intersections[0]), desktop->doc2dt(intersections[0]) + normal * dimension_offset, to_item, to_phantom, CTLINE_PRIMARY , measure_repr);
setMeasureCanvasControlLine(desktop->doc2dt(intersections[intersections.size() - 1]), desktop->doc2dt(intersections[intersections.size() - 1]) + normal * dimension_offset, to_item, to_phantom, CTLINE_PRIMARY , measure_repr);
}
// call-out lines
setMeasureCanvasControlLine(place.start, place.end, to_item, to_phantom, CTLINE_SECONDARY, measure_repr);
}
{
setMeasureCanvasControlLine(desktop->doc2dt(measure_text_pos), desktop->doc2dt(measure_text_pos) - (normal * dimension_offset / 2), to_item, to_phantom, CTLINE_SECONDARY, measure_repr);
}
}
}
}
}
}
/*
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 :