summaryrefslogtreecommitdiffstats
path: root/src/ui
diff options
context:
space:
mode:
authorLiam P. White <inkscapebrony@gmail.com>2014-10-05 23:24:27 +0000
committerLiam P. White <inkscapebrony@gmail.com>2014-10-05 23:24:27 +0000
commit156cf3323a936c7dfccd9e09458cd8b5d174b7fe (patch)
treebaeeae39954ed5aade824f0426d9bab5d677f5ce /src/ui
parentAttempt to fix build breakage reported by su_v (but not seen locally). (diff)
downloadinkscape-156cf3323a936c7dfccd9e09458cd8b5d174b7fe.tar.gz
inkscape-156cf3323a936c7dfccd9e09458cd8b5d174b7fe.zip
Move more UI code into ui/
(bzr r13341.1.253)
Diffstat (limited to 'src/ui')
-rw-r--r--src/ui/CMakeLists.txt8
-rw-r--r--src/ui/Makefile_insert9
-rw-r--r--src/ui/clipboard.cpp2
-rw-r--r--src/ui/dialog/align-and-distribute.cpp2
-rw-r--r--src/ui/dialog/document-properties.cpp4
-rw-r--r--src/ui/dialog/objects.cpp2
-rw-r--r--src/ui/dialog/spellcheck.cpp2
-rw-r--r--src/ui/draw-anchor.cpp105
-rw-r--r--src/ui/draw-anchor.h52
-rw-r--r--src/ui/object-edit.cpp1399
-rw-r--r--src/ui/object-edit.h84
-rw-r--r--src/ui/shape-editor.cpp177
-rw-r--r--src/ui/shape-editor.h71
-rw-r--r--src/ui/tool-factory.h40
-rw-r--r--src/ui/tool/node.cpp2
-rw-r--r--src/ui/tools-switch.cpp196
-rw-r--r--src/ui/tools-switch.h64
-rw-r--r--src/ui/tools/arc-tool.cpp4
-rw-r--r--src/ui/tools/box3d-tool.cpp4
-rw-r--r--src/ui/tools/calligraphic-tool.cpp2
-rw-r--r--src/ui/tools/connector-tool.cpp2
-rw-r--r--src/ui/tools/dropper-tool.cpp2
-rw-r--r--src/ui/tools/eraser-tool.cpp2
-rw-r--r--src/ui/tools/flood-tool.cpp4
-rw-r--r--src/ui/tools/freehand-base.cpp2
-rw-r--r--src/ui/tools/gradient-tool.cpp2
-rw-r--r--src/ui/tools/lpe-tool.cpp4
-rw-r--r--src/ui/tools/measure-tool.cpp2
-rw-r--r--src/ui/tools/mesh-tool.cpp2
-rw-r--r--src/ui/tools/node-tool.cpp4
-rw-r--r--src/ui/tools/pen-tool.cpp6
-rw-r--r--src/ui/tools/pencil-tool.cpp4
-rw-r--r--src/ui/tools/rect-tool.cpp4
-rw-r--r--src/ui/tools/select-tool.cpp4
-rw-r--r--src/ui/tools/spiral-tool.cpp4
-rw-r--r--src/ui/tools/spray-tool.cpp2
-rw-r--r--src/ui/tools/star-tool.cpp4
-rw-r--r--src/ui/tools/text-tool.cpp4
-rw-r--r--src/ui/tools/tool-base.cpp4
-rw-r--r--src/ui/tools/tool-base.h4
-rw-r--r--src/ui/tools/tweak-tool.cpp2
-rw-r--r--src/ui/tools/zoom-tool.cpp2
42 files changed, 2253 insertions, 46 deletions
diff --git a/src/ui/CMakeLists.txt b/src/ui/CMakeLists.txt
index 0f6e560d2..8bae15fa5 100644
--- a/src/ui/CMakeLists.txt
+++ b/src/ui/CMakeLists.txt
@@ -3,8 +3,12 @@ set(ui_SRC
clipboard.cpp
control-manager.cpp
dialog-events.cpp
+ draw-anchor.cpp
interface.cpp
+ object-edit.cpp
previewholder.cpp
+ shape-editor.cpp
+ tools-switch.cpp
uxmanager.cpp
cache/svg_preview_cache.cpp
@@ -159,11 +163,15 @@ set(ui_SRC
control-manager.h
control-types.h
dialog-events.h
+ draw-anchor.h
icon-names.h
interface.h
+ object-edit.h
previewable.h
previewfillable.h
previewholder.h
+ shape-editor.h
+ tools-switch.h
uxmanager.h
cache/svg_preview_cache.h
diff --git a/src/ui/Makefile_insert b/src/ui/Makefile_insert
index 4c6b49ed6..7aeb4a83d 100644
--- a/src/ui/Makefile_insert
+++ b/src/ui/Makefile_insert
@@ -8,12 +8,21 @@ ink_common_sources += \
ui/control-types.h \
ui/dialog-events.cpp \
ui/dialog-events.h \
+ ui/draw-anchor.cpp \
+ ui/draw-anchor.h \
ui/icon-names.h \
ui/interface.cpp \
ui/interface.h \
+ ui/object-edit.cpp \
+ ui/object-edit.h \
ui/previewable.h \
ui/previewfillable.h \
ui/previewholder.cpp \
ui/previewholder.h \
+ ui/shape-editor.cpp \
+ ui/shape-editor.h \
+ ui/tool-factory.h \
+ ui/tools-switch.cpp \
+ ui/tools-switch.h \
ui/uxmanager.cpp \
ui/uxmanager.h
diff --git a/src/ui/clipboard.cpp b/src/ui/clipboard.cpp
index 1209b19cd..40500cf15 100644
--- a/src/ui/clipboard.cpp
+++ b/src/ui/clipboard.cpp
@@ -76,7 +76,7 @@
#include "svg/css-ostringstream.h" // used in copy
#include "ui/tools/text-tool.h"
#include "text-editing.h"
-#include "tools-switch.h"
+#include "ui/tools-switch.h"
#include "path-chemistry.h"
#include "util/units.h"
#include "helper/png-write.h"
diff --git a/src/ui/dialog/align-and-distribute.cpp b/src/ui/dialog/align-and-distribute.cpp
index 8352de1e3..431da7ad1 100644
--- a/src/ui/dialog/align-and-distribute.cpp
+++ b/src/ui/dialog/align-and-distribute.cpp
@@ -38,7 +38,7 @@
#include "sp-item-transform.h"
#include "sp-text.h"
#include "text-editing.h"
-#include "tools-switch.h"
+#include "ui/tools-switch.h"
#include "ui/icon-names.h"
#include "ui/tools/node-tool.h"
#include "ui/tool/multi-path-manipulator.h"
diff --git a/src/ui/dialog/document-properties.cpp b/src/ui/dialog/document-properties.cpp
index 2a3a1dd86..071ac037f 100644
--- a/src/ui/dialog/document-properties.cpp
+++ b/src/ui/dialog/document-properties.cpp
@@ -31,13 +31,13 @@
#include "inkscape.h"
#include "io/sys.h"
#include "preferences.h"
-#include "shape-editor.h"
+#include "ui/shape-editor.h"
#include "sp-namedview.h"
#include "sp-root.h"
#include "sp-script.h"
#include "style.h"
#include "svg/stringstream.h"
-#include "tools-switch.h"
+#include "ui/tools-switch.h"
#include "ui/widget/color-picker.h"
#include "ui/widget/scalar-unit.h"
#include "ui/dialog/filedialog.h"
diff --git a/src/ui/dialog/objects.cpp b/src/ui/dialog/objects.cpp
index 07a27c96e..93d5dfbd5 100644
--- a/src/ui/dialog/objects.cpp
+++ b/src/ui/dialog/objects.cpp
@@ -43,7 +43,7 @@
#include "sp-root.h"
#include "sp-shape.h"
#include "style.h"
-#include "tools-switch.h"
+#include "ui/tools-switch.h"
#include "ui/icon-names.h"
#include "ui/widget/imagetoggler.h"
#include "ui/widget/layertypeicon.h"
diff --git a/src/ui/dialog/spellcheck.cpp b/src/ui/dialog/spellcheck.cpp
index b8436ebf1..9faa8a2cb 100644
--- a/src/ui/dialog/spellcheck.cpp
+++ b/src/ui/dialog/spellcheck.cpp
@@ -23,7 +23,7 @@
#include "selection.h"
#include "desktop.h"
#include "desktop-handles.h"
-#include "tools-switch.h"
+#include "ui/tools-switch.h"
#include "ui/tools/text-tool.h"
#include "ui/interface.h"
#include "preferences.h"
diff --git a/src/ui/draw-anchor.cpp b/src/ui/draw-anchor.cpp
new file mode 100644
index 000000000..84c919018
--- /dev/null
+++ b/src/ui/draw-anchor.cpp
@@ -0,0 +1,105 @@
+/** \file
+ * Anchors implementation.
+ */
+
+/*
+ * Authors:
+ * Copyright (C) 2000 Lauris Kaplinski
+ * Copyright (C) 2000-2001 Ximian, Inc.
+ * Copyright (C) 2002 Lauris Kaplinski
+ * Copyright (C) 2004 Monash University
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+
+#include "ui/draw-anchor.h"
+#include "desktop.h"
+#include "desktop-handles.h"
+#include "ui/tools/tool-base.h"
+#include "ui/tools/lpe-tool.h"
+#include "display/sodipodi-ctrl.h"
+#include "display/curve.h"
+#include "ui/control-manager.h"
+
+using Inkscape::ControlManager;
+
+#define FILL_COLOR_NORMAL 0xffffff7f
+#define FILL_COLOR_MOUSEOVER 0xff0000ff
+
+/**
+ * Creates an anchor object and initializes it.
+ */
+SPDrawAnchor *sp_draw_anchor_new(Inkscape::UI::Tools::FreehandBase *dc, SPCurve *curve, bool start, Geom::Point delta)
+{
+ if (SP_IS_LPETOOL_CONTEXT(dc)) {
+ // suppress all kinds of anchors in LPEToolContext
+ return NULL;
+ }
+
+ SPDrawAnchor *a = g_new(SPDrawAnchor, 1);
+
+ a->dc = dc;
+ a->curve = curve;
+ curve->ref();
+ a->start = start;
+ a->active = FALSE;
+ a->dp = delta;
+ a->ctrl = ControlManager::getManager().createControl(sp_desktop_controls(&dc->getDesktop()), Inkscape::CTRL_TYPE_ANCHOR);
+
+ SP_CTRL(a->ctrl)->moveto(delta);
+
+ ControlManager::getManager().track(a->ctrl);
+
+ return a;
+}
+
+/**
+ * Destroys the anchor's canvas item and frees the anchor object.
+ */
+SPDrawAnchor *sp_draw_anchor_destroy(SPDrawAnchor *anchor)
+{
+ if (anchor->curve) {
+ anchor->curve->unref();
+ }
+ if (anchor->ctrl) {
+ sp_canvas_item_destroy(anchor->ctrl);
+ }
+ g_free(anchor);
+ return NULL;
+}
+
+/**
+ * Test if point is near anchor, if so fill anchor on canvas and return
+ * pointer to it or NULL.
+ */
+SPDrawAnchor *sp_draw_anchor_test(SPDrawAnchor *anchor, Geom::Point w, bool activate)
+{
+ SPCtrl *ctrl = SP_CTRL(anchor->ctrl);
+
+ if ( activate && ( Geom::LInfty( w - anchor->dc->getDesktop().d2w(anchor->dp) ) <= (ctrl->box.width() / 2.0) ) ) {
+ if (!anchor->active) {
+ g_object_set(anchor->ctrl, "fill_color", FILL_COLOR_MOUSEOVER, NULL);
+ anchor->active = TRUE;
+ }
+ return anchor;
+ }
+
+ if (anchor->active) {
+ g_object_set(anchor->ctrl, "fill_color", FILL_COLOR_NORMAL, NULL);
+ anchor->active = FALSE;
+ }
+ return NULL;
+}
+
+
+/*
+ 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/ui/draw-anchor.h b/src/ui/draw-anchor.h
new file mode 100644
index 000000000..1f7b55920
--- /dev/null
+++ b/src/ui/draw-anchor.h
@@ -0,0 +1,52 @@
+#ifndef SEEN_DRAW_ANCHOR_H
+#define SEEN_DRAW_ANCHOR_H
+
+/** \file
+ * Drawing anchors.
+ */
+
+#include <2geom/point.h>
+
+namespace Inkscape {
+namespace UI {
+namespace Tools {
+
+class FreehandBase;
+
+}
+}
+}
+
+class SPCurve;
+struct SPCanvasItem;
+
+/// The drawing anchor.
+/// \todo Make this a regular knot, this will allow to set statusbar tips.
+struct SPDrawAnchor {
+ Inkscape::UI::Tools::FreehandBase *dc;
+ SPCurve *curve;
+ unsigned int start : 1;
+ unsigned int active : 1;
+ Geom::Point dp;
+ SPCanvasItem *ctrl;
+};
+
+
+SPDrawAnchor *sp_draw_anchor_new(Inkscape::UI::Tools::FreehandBase *dc, SPCurve *curve, bool start,
+ Geom::Point delta);
+SPDrawAnchor *sp_draw_anchor_destroy(SPDrawAnchor *anchor);
+SPDrawAnchor *sp_draw_anchor_test(SPDrawAnchor *anchor, Geom::Point w, bool activate);
+
+
+#endif /* !SEEN_DRAW_ANCHOR_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/ui/object-edit.cpp b/src/ui/object-edit.cpp
new file mode 100644
index 000000000..cc96727f8
--- /dev/null
+++ b/src/ui/object-edit.cpp
@@ -0,0 +1,1399 @@
+/*
+ * Node editing extension to objects
+ *
+ * Authors:
+ * Lauris Kaplinski <lauris@kaplinski.com>
+ * Mitsuru Oka
+ * Maximilian Albert <maximilian.albert@gmail.com>
+ * Abhishek Sharma
+ *
+ * Licensed under GNU GPL
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+
+
+#include "sp-item.h"
+#include "sp-rect.h"
+#include "box3d.h"
+#include "sp-ellipse.h"
+#include "sp-star.h"
+#include "sp-spiral.h"
+#include "sp-offset.h"
+#include "sp-flowtext.h"
+#include "preferences.h"
+#include "style.h"
+#include "desktop.h"
+#include "desktop-handles.h"
+#include "sp-namedview.h"
+#include "live_effects/effect.h"
+#include "sp-pattern.h"
+#include "sp-path.h"
+#include <glibmm/i18n.h>
+#include "ui/object-edit.h"
+#include "xml/repr.h"
+#include <2geom/math-utils.h>
+#include "knot-holder-entity.h"
+
+#define sp_round(v,m) (((v) < 0.0) ? ((ceil((v) / (m) - 0.5)) * (m)) : ((floor((v) / (m) + 0.5)) * (m)))
+
+namespace {
+
+static KnotHolder *sp_lpe_knot_holder(SPItem *item, SPDesktop *desktop)
+{
+ KnotHolder *knot_holder = new KnotHolder(desktop, item, NULL);
+
+ Inkscape::LivePathEffect::Effect *effect = SP_LPE_ITEM(item)->getCurrentLPE();
+ effect->addHandles(knot_holder, desktop, item);
+
+ return knot_holder;
+}
+
+} // namespace
+
+namespace Inkscape {
+namespace UI {
+
+KnotHolder *createKnotHolder(SPItem *item, SPDesktop *desktop)
+{
+ KnotHolder *knotholder = NULL;
+
+ if (SP_IS_LPE_ITEM(item) &&
+ SP_LPE_ITEM(item)->getCurrentLPE() &&
+ SP_LPE_ITEM(item)->getCurrentLPE()->isVisible() &&
+ SP_LPE_ITEM(item)->getCurrentLPE()->providesKnotholder()) {
+ knotholder = sp_lpe_knot_holder(item, desktop);
+ } else if (SP_IS_RECT(item)) {
+ knotholder = new RectKnotHolder(desktop, item, NULL);
+ } else if (SP_IS_BOX3D(item)) {
+ knotholder = new Box3DKnotHolder(desktop, item, NULL);
+ } else if (SP_IS_GENERICELLIPSE(item)) {
+ knotholder = new ArcKnotHolder(desktop, item, NULL);
+ } else if (SP_IS_STAR(item)) {
+ knotholder = new StarKnotHolder(desktop, item, NULL);
+ } else if (SP_IS_SPIRAL(item)) {
+ knotholder = new SpiralKnotHolder(desktop, item, NULL);
+ } else if (SP_IS_OFFSET(item)) {
+ knotholder = new OffsetKnotHolder(desktop, item, NULL);
+ } else if (SP_IS_FLOWTEXT(item) && SP_FLOWTEXT(item)->has_internal_frame()) {
+ knotholder = new FlowtextKnotHolder(desktop, SP_FLOWTEXT(item)->get_frame(NULL), NULL);
+ } else if ((item->style->fill.isPaintserver() && SP_IS_PATTERN(item->style->getFillPaintServer())) ||
+ (item->style->stroke.isPaintserver() && SP_IS_PATTERN(item->style->getStrokePaintServer()))) {
+ knotholder = new KnotHolder(desktop, item, NULL);
+ knotholder->add_pattern_knotholder();
+ }
+
+ return knotholder;
+}
+
+}
+} // namespace Inkscape
+
+/* SPRect */
+
+/* handle for horizontal rounding radius */
+class RectKnotHolderEntityRX : public KnotHolderEntity {
+public:
+ virtual Geom::Point knot_get() const;
+ virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, unsigned int state);
+ virtual void knot_click(unsigned int state);
+};
+
+/* handle for vertical rounding radius */
+class RectKnotHolderEntityRY : public KnotHolderEntity {
+public:
+ virtual Geom::Point knot_get() const;
+ virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, unsigned int state);
+ virtual void knot_click(unsigned int state);
+};
+
+/* handle for width/height adjustment */
+class RectKnotHolderEntityWH : public KnotHolderEntity {
+public:
+ virtual Geom::Point knot_get() const;
+ virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, unsigned int state);
+
+protected:
+ void set_internal(Geom::Point const &p, Geom::Point const &origin, unsigned int state);
+};
+
+/* handle for x/y adjustment */
+class RectKnotHolderEntityXY : public KnotHolderEntity {
+public:
+ virtual Geom::Point knot_get() const;
+ virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, unsigned int state);
+};
+
+Geom::Point
+RectKnotHolderEntityRX::knot_get() const
+{
+ SPRect *rect = SP_RECT(item);
+
+ return Geom::Point(rect->x.computed + rect->width.computed - rect->rx.computed, rect->y.computed);
+}
+
+void
+RectKnotHolderEntityRX::knot_set(Geom::Point const &p, Geom::Point const &/*origin*/, unsigned int state)
+{
+ SPRect *rect = SP_RECT(item);
+
+ //In general we cannot just snap this radius to an arbitrary point, as we have only a single
+ //degree of freedom. For snapping to an arbitrary point we need two DOF. If we're going to snap
+ //the radius then we should have a constrained snap. snap_knot_position() is unconstrained
+ Geom::Point const s = snap_knot_position_constrained(p, Inkscape::Snapper::SnapConstraint(Geom::Point(rect->x.computed + rect->width.computed, rect->y.computed), Geom::Point(-1, 0)), state);
+
+ if (state & GDK_CONTROL_MASK) {
+ gdouble temp = MIN(rect->height.computed, rect->width.computed) / 2.0;
+ rect->rx.computed = rect->ry.computed = CLAMP(rect->x.computed + rect->width.computed - s[Geom::X], 0.0, temp);
+ rect->rx._set = rect->ry._set = true;
+
+ } else {
+ rect->rx.computed = CLAMP(rect->x.computed + rect->width.computed - s[Geom::X], 0.0, rect->width.computed / 2.0);
+ rect->rx._set = true;
+ }
+
+ update_knot();
+
+ (static_cast<SPObject*>(rect))->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
+}
+
+void
+RectKnotHolderEntityRX::knot_click(unsigned int state)
+{
+ SPRect *rect = SP_RECT(item);
+
+ if (state & GDK_SHIFT_MASK) {
+ /* remove rounding from rectangle */
+ rect->getRepr()->setAttribute("rx", NULL);
+ rect->getRepr()->setAttribute("ry", NULL);
+ } else if (state & GDK_CONTROL_MASK) {
+ /* Ctrl-click sets the vertical rounding to be the same as the horizontal */
+ rect->getRepr()->setAttribute("ry", rect->getRepr()->attribute("rx"));
+ }
+
+}
+
+Geom::Point
+RectKnotHolderEntityRY::knot_get() const
+{
+ SPRect *rect = SP_RECT(item);
+
+ return Geom::Point(rect->x.computed + rect->width.computed, rect->y.computed + rect->ry.computed);
+}
+
+void
+RectKnotHolderEntityRY::knot_set(Geom::Point const &p, Geom::Point const &/*origin*/, unsigned int state)
+{
+ SPRect *rect = SP_RECT(item);
+
+ //In general we cannot just snap this radius to an arbitrary point, as we have only a single
+ //degree of freedom. For snapping to an arbitrary point we need two DOF. If we're going to snap
+ //the radius then we should have a constrained snap. snap_knot_position() is unconstrained
+ Geom::Point const s = snap_knot_position_constrained(p, Inkscape::Snapper::SnapConstraint(Geom::Point(rect->x.computed + rect->width.computed, rect->y.computed), Geom::Point(0, 1)), state);
+
+ if (state & GDK_CONTROL_MASK) { // When holding control then rx will be kept equal to ry,
+ // resulting in a perfect circle (and not an ellipse)
+ gdouble temp = MIN(rect->height.computed, rect->width.computed) / 2.0;
+ rect->rx.computed = rect->ry.computed = CLAMP(s[Geom::Y] - rect->y.computed, 0.0, temp);
+ rect->ry._set = rect->rx._set = true;
+ } else {
+ if (!rect->rx._set || rect->rx.computed == 0) {
+ rect->ry.computed = CLAMP(s[Geom::Y] - rect->y.computed,
+ 0.0,
+ MIN(rect->height.computed / 2.0, rect->width.computed / 2.0));
+ } else {
+ rect->ry.computed = CLAMP(s[Geom::Y] - rect->y.computed,
+ 0.0,
+ rect->height.computed / 2.0);
+ }
+
+ rect->ry._set = true;
+ }
+
+ update_knot();
+
+ (static_cast<SPObject *>(rect))->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
+}
+
+void
+RectKnotHolderEntityRY::knot_click(unsigned int state)
+{
+ SPRect *rect = SP_RECT(item);
+
+ if (state & GDK_SHIFT_MASK) {
+ /* remove rounding */
+ rect->getRepr()->setAttribute("rx", NULL);
+ rect->getRepr()->setAttribute("ry", NULL);
+ } else if (state & GDK_CONTROL_MASK) {
+ /* Ctrl-click sets the vertical rounding to be the same as the horizontal */
+ rect->getRepr()->setAttribute("rx", rect->getRepr()->attribute("ry"));
+ }
+}
+
+#define SGN(x) ((x)>0?1:((x)<0?-1:0))
+
+static void sp_rect_clamp_radii(SPRect *rect)
+{
+ // clamp rounding radii so that they do not exceed width/height
+ if (2 * rect->rx.computed > rect->width.computed) {
+ rect->rx.computed = 0.5 * rect->width.computed;
+ rect->rx._set = true;
+ }
+ if (2 * rect->ry.computed > rect->height.computed) {
+ rect->ry.computed = 0.5 * rect->height.computed;
+ rect->ry._set = true;
+ }
+}
+
+Geom::Point
+RectKnotHolderEntityWH::knot_get() const
+{
+ SPRect *rect = SP_RECT(item);
+
+ return Geom::Point(rect->x.computed + rect->width.computed, rect->y.computed + rect->height.computed);
+}
+
+void
+RectKnotHolderEntityWH::set_internal(Geom::Point const &p, Geom::Point const &origin, unsigned int state)
+{
+ SPRect *rect = SP_RECT(item);
+
+ Geom::Point s = p;
+
+ if (state & GDK_CONTROL_MASK) {
+ // original width/height when drag started
+ gdouble const w_orig = (origin[Geom::X] - rect->x.computed);
+ gdouble const h_orig = (origin[Geom::Y] - rect->y.computed);
+
+ //original ratio
+ gdouble ratio = (w_orig / h_orig);
+
+ // mouse displacement since drag started
+ gdouble minx = p[Geom::X] - origin[Geom::X];
+ gdouble miny = p[Geom::Y] - origin[Geom::Y];
+
+ Geom::Point p_handle(rect->x.computed + rect->width.computed, rect->y.computed + rect->height.computed);
+
+ if (fabs(minx) > fabs(miny)) {
+ // snap to horizontal or diagonal
+ if (minx != 0 && fabs(miny/minx) > 0.5 * 1/ratio && (SGN(minx) == SGN(miny))) {
+ // closer to the diagonal and in same-sign quarters, change both using ratio
+ s = snap_knot_position_constrained(p, Inkscape::Snapper::SnapConstraint(p_handle, Geom::Point(-ratio, -1)), state);
+ minx = s[Geom::X] - origin[Geom::X];
+ miny = s[Geom::Y] - origin[Geom::Y];
+ rect->height.computed = MAX(h_orig + minx / ratio, 0);
+ } else {
+ // closer to the horizontal, change only width, height is h_orig
+ s = snap_knot_position_constrained(p, Inkscape::Snapper::SnapConstraint(p_handle, Geom::Point(-1, 0)), state);
+ minx = s[Geom::X] - origin[Geom::X];
+ miny = s[Geom::Y] - origin[Geom::Y];
+ rect->height.computed = MAX(h_orig, 0);
+ }
+ rect->width.computed = MAX(w_orig + minx, 0);
+
+ } else {
+ // snap to vertical or diagonal
+ if (miny != 0 && fabs(minx/miny) > 0.5 * ratio && (SGN(minx) == SGN(miny))) {
+ // closer to the diagonal and in same-sign quarters, change both using ratio
+ s = snap_knot_position_constrained(p, Inkscape::Snapper::SnapConstraint(p_handle, Geom::Point(-ratio, -1)), state);
+ minx = s[Geom::X] - origin[Geom::X];
+ miny = s[Geom::Y] - origin[Geom::Y];
+ rect->width.computed = MAX(w_orig + miny * ratio, 0);
+ } else {
+ // closer to the vertical, change only height, width is w_orig
+ s = snap_knot_position_constrained(p, Inkscape::Snapper::SnapConstraint(p_handle, Geom::Point(0, -1)), state);
+ minx = s[Geom::X] - origin[Geom::X];
+ miny = s[Geom::Y] - origin[Geom::Y];
+ rect->width.computed = MAX(w_orig, 0);
+ }
+ rect->height.computed = MAX(h_orig + miny, 0);
+
+ }
+
+ rect->width._set = rect->height._set = true;
+
+ } else {
+ // move freely
+ s = snap_knot_position(p, state);
+ rect->width.computed = MAX(s[Geom::X] - rect->x.computed, 0);
+ rect->height.computed = MAX(s[Geom::Y] - rect->y.computed, 0);
+ rect->width._set = rect->height._set = true;
+ }
+
+ sp_rect_clamp_radii(rect);
+
+ (static_cast<SPObject *>(rect))->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
+}
+
+void
+RectKnotHolderEntityWH::knot_set(Geom::Point const &p, Geom::Point const &origin, unsigned int state)
+{
+ set_internal(p, origin, state);
+ update_knot();
+}
+
+Geom::Point
+RectKnotHolderEntityXY::knot_get() const
+{
+ SPRect *rect = SP_RECT(item);
+
+ return Geom::Point(rect->x.computed, rect->y.computed);
+}
+
+void
+RectKnotHolderEntityXY::knot_set(Geom::Point const &p, Geom::Point const &origin, unsigned int state)
+{
+ SPRect *rect = SP_RECT(item);
+
+ // opposite corner (unmoved)
+ gdouble opposite_x = (rect->x.computed + rect->width.computed);
+ gdouble opposite_y = (rect->y.computed + rect->height.computed);
+
+ // original width/height when drag started
+ gdouble w_orig = opposite_x - origin[Geom::X];
+ gdouble h_orig = opposite_y - origin[Geom::Y];
+
+ Geom::Point s = p;
+ Geom::Point p_handle(rect->x.computed, rect->y.computed);
+
+ // mouse displacement since drag started
+ gdouble minx = p[Geom::X] - origin[Geom::X];
+ gdouble miny = p[Geom::Y] - origin[Geom::Y];
+
+ if (state & GDK_CONTROL_MASK) {
+ //original ratio
+ gdouble ratio = (w_orig / h_orig);
+
+ if (fabs(minx) > fabs(miny)) {
+ // snap to horizontal or diagonal
+ if (minx != 0 && fabs(miny/minx) > 0.5 * 1/ratio && (SGN(minx) == SGN(miny))) {
+ // closer to the diagonal and in same-sign quarters, change both using ratio
+ s = snap_knot_position_constrained(p, Inkscape::Snapper::SnapConstraint(p_handle, Geom::Point(-ratio, -1)), state);
+ minx = s[Geom::X] - origin[Geom::X];
+ miny = s[Geom::Y] - origin[Geom::Y];
+ rect->y.computed = MIN(origin[Geom::Y] + minx / ratio, opposite_y);
+ rect->height.computed = MAX(h_orig - minx / ratio, 0);
+ } else {
+ // closer to the horizontal, change only width, height is h_orig
+ s = snap_knot_position_constrained(p, Inkscape::Snapper::SnapConstraint(p_handle, Geom::Point(-1, 0)), state);
+ minx = s[Geom::X] - origin[Geom::X];
+ miny = s[Geom::Y] - origin[Geom::Y];
+ rect->y.computed = MIN(origin[Geom::Y], opposite_y);
+ rect->height.computed = MAX(h_orig, 0);
+ }
+ rect->x.computed = MIN(s[Geom::X], opposite_x);
+ rect->width.computed = MAX(w_orig - minx, 0);
+ } else {
+ // snap to vertical or diagonal
+ if (miny != 0 && fabs(minx/miny) > 0.5 *ratio && (SGN(minx) == SGN(miny))) {
+ // closer to the diagonal and in same-sign quarters, change both using ratio
+ s = snap_knot_position_constrained(p, Inkscape::Snapper::SnapConstraint(p_handle, Geom::Point(-ratio, -1)), state);
+ minx = s[Geom::X] - origin[Geom::X];
+ miny = s[Geom::Y] - origin[Geom::Y];
+ rect->x.computed = MIN(origin[Geom::X] + miny * ratio, opposite_x);
+ rect->width.computed = MAX(w_orig - miny * ratio, 0);
+ } else {
+ // closer to the vertical, change only height, width is w_orig
+ s = snap_knot_position_constrained(p, Inkscape::Snapper::SnapConstraint(p_handle, Geom::Point(0, -1)), state);
+ minx = s[Geom::X] - origin[Geom::X];
+ miny = s[Geom::Y] - origin[Geom::Y];
+ rect->x.computed = MIN(origin[Geom::X], opposite_x);
+ rect->width.computed = MAX(w_orig, 0);
+ }
+ rect->y.computed = MIN(s[Geom::Y], opposite_y);
+ rect->height.computed = MAX(h_orig - miny, 0);
+ }
+
+ rect->width._set = rect->height._set = rect->x._set = rect->y._set = true;
+
+ } else {
+ // move freely
+ s = snap_knot_position(p, state);
+ minx = s[Geom::X] - origin[Geom::X];
+ miny = s[Geom::Y] - origin[Geom::Y];
+
+ rect->x.computed = MIN(s[Geom::X], opposite_x);
+ rect->width.computed = MAX(w_orig - minx, 0);
+ rect->y.computed = MIN(s[Geom::Y], opposite_y);
+ rect->height.computed = MAX(h_orig - miny, 0);
+ rect->width._set = rect->height._set = rect->x._set = rect->y._set = true;
+ }
+
+ sp_rect_clamp_radii(rect);
+
+ update_knot();
+
+ (static_cast<SPObject *>(rect))->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
+}
+
+RectKnotHolder::RectKnotHolder(SPDesktop *desktop, SPItem *item, SPKnotHolderReleasedFunc relhandler) :
+ KnotHolder(desktop, item, relhandler)
+{
+ RectKnotHolderEntityRX *entity_rx = new RectKnotHolderEntityRX();
+ RectKnotHolderEntityRY *entity_ry = new RectKnotHolderEntityRY();
+ RectKnotHolderEntityWH *entity_wh = new RectKnotHolderEntityWH();
+ RectKnotHolderEntityXY *entity_xy = new RectKnotHolderEntityXY();
+
+ entity_rx->create(desktop, item, this, Inkscape::CTRL_TYPE_ROTATE,
+ _("Adjust the <b>horizontal rounding</b> radius; with <b>Ctrl</b> "
+ "to make the vertical radius the same"),
+ SP_KNOT_SHAPE_CIRCLE, SP_KNOT_MODE_XOR);
+
+ entity_ry->create(desktop, item, this, Inkscape::CTRL_TYPE_ROTATE,
+ _("Adjust the <b>vertical rounding</b> radius; with <b>Ctrl</b> "
+ "to make the horizontal radius the same"),
+ SP_KNOT_SHAPE_CIRCLE, SP_KNOT_MODE_XOR);
+
+ entity_wh->create(desktop, item, this, Inkscape::CTRL_TYPE_SIZER,
+ _("Adjust the <b>width and height</b> of the rectangle; with <b>Ctrl</b> "
+ "to lock ratio or stretch in one dimension only"),
+ SP_KNOT_SHAPE_SQUARE, SP_KNOT_MODE_XOR);
+
+ entity_xy->create(desktop, item, this, Inkscape::CTRL_TYPE_SIZER,
+ _("Adjust the <b>width and height</b> of the rectangle; with <b>Ctrl</b> "
+ "to lock ratio or stretch in one dimension only"),
+ SP_KNOT_SHAPE_SQUARE, SP_KNOT_MODE_XOR);
+
+ entity.push_back(entity_rx);
+ entity.push_back(entity_ry);
+ entity.push_back(entity_wh);
+ entity.push_back(entity_xy);
+
+ add_pattern_knotholder();
+}
+
+/* Box3D (= the new 3D box structure) */
+
+class Box3DKnotHolderEntity : public KnotHolderEntity {
+public:
+ virtual Geom::Point knot_get() const = 0;
+ virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, unsigned int state) = 0;
+
+ Geom::Point knot_get_generic(SPItem *item, unsigned int knot_id) const;
+ void knot_set_generic(SPItem *item, unsigned int knot_id, Geom::Point const &p, unsigned int state);
+};
+
+Geom::Point
+Box3DKnotHolderEntity::knot_get_generic(SPItem *item, unsigned int knot_id) const
+{
+ return box3d_get_corner_screen(SP_BOX3D(item), knot_id);
+}
+
+void
+Box3DKnotHolderEntity::knot_set_generic(SPItem *item, unsigned int knot_id, Geom::Point const &new_pos, unsigned int state)
+{
+ Geom::Point const s = snap_knot_position(new_pos, state);
+
+ g_assert(item != NULL);
+ SPBox3D *box = SP_BOX3D(item);
+ Geom::Affine const i2dt (item->i2dt_affine ());
+
+ Box3D::Axis movement;
+ if ((knot_id < 4) != (state & GDK_SHIFT_MASK)) {
+ movement = Box3D::XY;
+ } else {
+ movement = Box3D::Z;
+ }
+
+ box3d_set_corner (box, knot_id, s * i2dt, movement, (state & GDK_CONTROL_MASK));
+ box3d_set_z_orders(box);
+ box3d_position_set(box);
+}
+
+class Box3DKnotHolderEntity0 : public Box3DKnotHolderEntity {
+public:
+ virtual Geom::Point knot_get() const;
+ virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, unsigned int state);
+};
+
+class Box3DKnotHolderEntity1 : public Box3DKnotHolderEntity {
+public:
+ virtual Geom::Point knot_get() const;
+ virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, unsigned int state);
+};
+
+class Box3DKnotHolderEntity2 : public Box3DKnotHolderEntity {
+public:
+ virtual Geom::Point knot_get() const;
+ virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, unsigned int state);
+};
+
+class Box3DKnotHolderEntity3 : public Box3DKnotHolderEntity {
+public:
+ virtual Geom::Point knot_get() const;
+ virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, unsigned int state);
+};
+
+class Box3DKnotHolderEntity4 : public Box3DKnotHolderEntity {
+public:
+ virtual Geom::Point knot_get() const;
+ virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, unsigned int state);
+};
+
+class Box3DKnotHolderEntity5 : public Box3DKnotHolderEntity {
+public:
+ virtual Geom::Point knot_get() const;
+ virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, unsigned int state);
+};
+
+class Box3DKnotHolderEntity6 : public Box3DKnotHolderEntity {
+public:
+ virtual Geom::Point knot_get() const;
+ virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, unsigned int state);
+};
+
+class Box3DKnotHolderEntity7 : public Box3DKnotHolderEntity {
+public:
+ virtual Geom::Point knot_get() const;
+ virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, unsigned int state);
+};
+
+class Box3DKnotHolderEntityCenter : public KnotHolderEntity {
+public:
+ virtual Geom::Point knot_get() const;
+ virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, unsigned int state);
+};
+
+Geom::Point
+Box3DKnotHolderEntity0::knot_get() const
+{
+ return knot_get_generic(item, 0);
+}
+
+Geom::Point
+Box3DKnotHolderEntity1::knot_get() const
+{
+ return knot_get_generic(item, 1);
+}
+
+Geom::Point
+Box3DKnotHolderEntity2::knot_get() const
+{
+ return knot_get_generic(item, 2);
+}
+
+Geom::Point
+Box3DKnotHolderEntity3::knot_get() const
+{
+ return knot_get_generic(item, 3);
+}
+
+Geom::Point
+Box3DKnotHolderEntity4::knot_get() const
+{
+ return knot_get_generic(item, 4);
+}
+
+Geom::Point
+Box3DKnotHolderEntity5::knot_get() const
+{
+ return knot_get_generic(item, 5);
+}
+
+Geom::Point
+Box3DKnotHolderEntity6::knot_get() const
+{
+ return knot_get_generic(item, 6);
+}
+
+Geom::Point
+Box3DKnotHolderEntity7::knot_get() const
+{
+ return knot_get_generic(item, 7);
+}
+
+Geom::Point
+Box3DKnotHolderEntityCenter::knot_get() const
+{
+ return box3d_get_center_screen(SP_BOX3D(item));
+}
+
+void
+Box3DKnotHolderEntity0::knot_set(Geom::Point const &new_pos, Geom::Point const &/*origin*/, unsigned int state)
+{
+ knot_set_generic(item, 0, new_pos, state);
+}
+
+void
+Box3DKnotHolderEntity1::knot_set(Geom::Point const &new_pos, Geom::Point const &/*origin*/, unsigned int state)
+{
+ knot_set_generic(item, 1, new_pos, state);
+}
+
+void
+Box3DKnotHolderEntity2::knot_set(Geom::Point const &new_pos, Geom::Point const &/*origin*/, unsigned int state)
+{
+ knot_set_generic(item, 2, new_pos, state);
+}
+
+void
+Box3DKnotHolderEntity3::knot_set(Geom::Point const &new_pos, Geom::Point const &/*origin*/, unsigned int state)
+{
+ knot_set_generic(item, 3, new_pos, state);
+}
+
+void
+Box3DKnotHolderEntity4::knot_set(Geom::Point const &new_pos, Geom::Point const &/*origin*/, unsigned int state)
+{
+ knot_set_generic(item, 4, new_pos, state);
+}
+
+void
+Box3DKnotHolderEntity5::knot_set(Geom::Point const &new_pos, Geom::Point const &/*origin*/, unsigned int state)
+{
+ knot_set_generic(item, 5, new_pos, state);
+}
+
+void
+Box3DKnotHolderEntity6::knot_set(Geom::Point const &new_pos, Geom::Point const &/*origin*/, unsigned int state)
+{
+ knot_set_generic(item, 6, new_pos, state);
+}
+
+void
+Box3DKnotHolderEntity7::knot_set(Geom::Point const &new_pos, Geom::Point const &/*origin*/, unsigned int state)
+{
+ knot_set_generic(item, 7, new_pos, state);
+}
+
+void
+Box3DKnotHolderEntityCenter::knot_set(Geom::Point const &new_pos, Geom::Point const &origin, unsigned int state)
+{
+ Geom::Point const s = snap_knot_position(new_pos, state);
+
+ SPBox3D *box = SP_BOX3D(item);
+ Geom::Affine const i2dt (item->i2dt_affine ());
+
+ box3d_set_center (SP_BOX3D(item), s * i2dt, origin * i2dt, !(state & GDK_SHIFT_MASK) ? Box3D::XY : Box3D::Z,
+ state & GDK_CONTROL_MASK);
+
+ box3d_set_z_orders(box);
+ box3d_position_set(box);
+}
+
+Box3DKnotHolder::Box3DKnotHolder(SPDesktop *desktop, SPItem *item, SPKnotHolderReleasedFunc relhandler) :
+ KnotHolder(desktop, item, relhandler)
+{
+ Box3DKnotHolderEntity0 *entity_corner0 = new Box3DKnotHolderEntity0();
+ Box3DKnotHolderEntity1 *entity_corner1 = new Box3DKnotHolderEntity1();
+ Box3DKnotHolderEntity2 *entity_corner2 = new Box3DKnotHolderEntity2();
+ Box3DKnotHolderEntity3 *entity_corner3 = new Box3DKnotHolderEntity3();
+ Box3DKnotHolderEntity4 *entity_corner4 = new Box3DKnotHolderEntity4();
+ Box3DKnotHolderEntity5 *entity_corner5 = new Box3DKnotHolderEntity5();
+ Box3DKnotHolderEntity6 *entity_corner6 = new Box3DKnotHolderEntity6();
+ Box3DKnotHolderEntity7 *entity_corner7 = new Box3DKnotHolderEntity7();
+ Box3DKnotHolderEntityCenter *entity_center = new Box3DKnotHolderEntityCenter();
+
+ entity_corner0->create(desktop, item, this, Inkscape::CTRL_TYPE_SHAPER,
+ _("Resize box in X/Y direction; with <b>Shift</b> along the Z axis; "
+ "with <b>Ctrl</b> to constrain to the directions of edges or diagonals"));
+
+ entity_corner1->create(desktop, item, this, Inkscape::CTRL_TYPE_SHAPER,
+ _("Resize box in X/Y direction; with <b>Shift</b> along the Z axis; "
+ "with <b>Ctrl</b> to constrain to the directions of edges or diagonals"));
+
+ entity_corner2->create(desktop, item, this, Inkscape::CTRL_TYPE_SHAPER,
+ _("Resize box in X/Y direction; with <b>Shift</b> along the Z axis; "
+ "with <b>Ctrl</b> to constrain to the directions of edges or diagonals"));
+
+ entity_corner3->create(desktop, item, this, Inkscape::CTRL_TYPE_SHAPER,
+ _("Resize box in X/Y direction; with <b>Shift</b> along the Z axis; "
+ "with <b>Ctrl</b> to constrain to the directions of edges or diagonals"));
+
+ entity_corner4->create(desktop, item, this, Inkscape::CTRL_TYPE_SHAPER,
+ _("Resize box along the Z axis; with <b>Shift</b> in X/Y direction; "
+ "with <b>Ctrl</b> to constrain to the directions of edges or diagonals"));
+
+ entity_corner5->create(desktop, item, this, Inkscape::CTRL_TYPE_SHAPER,
+ _("Resize box along the Z axis; with <b>Shift</b> in X/Y direction; "
+ "with <b>Ctrl</b> to constrain to the directions of edges or diagonals"));
+
+ entity_corner6->create(desktop, item, this, Inkscape::CTRL_TYPE_SHAPER,
+ _("Resize box along the Z axis; with <b>Shift</b> in X/Y direction; "
+ "with <b>Ctrl</b> to constrain to the directions of edges or diagonals"));
+
+ entity_corner7->create(desktop, item, this, Inkscape::CTRL_TYPE_SHAPER,
+ _("Resize box along the Z axis; with <b>Shift</b> in X/Y direction; "
+ "with <b>Ctrl</b> to constrain to the directions of edges or diagonals"));
+
+ entity_center->create(desktop, item, this, Inkscape::CTRL_TYPE_POINT,
+ _("Move the box in perspective"),
+ SP_KNOT_SHAPE_CROSS);
+
+ entity.push_back(entity_corner0);
+ entity.push_back(entity_corner1);
+ entity.push_back(entity_corner2);
+ entity.push_back(entity_corner3);
+ entity.push_back(entity_corner4);
+ entity.push_back(entity_corner5);
+ entity.push_back(entity_corner6);
+ entity.push_back(entity_corner7);
+ entity.push_back(entity_center);
+
+ add_pattern_knotholder();
+}
+
+/* SPArc */
+
+class ArcKnotHolderEntityStart : public KnotHolderEntity {
+public:
+ virtual Geom::Point knot_get() const;
+ virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, unsigned int state);
+ virtual void knot_click(unsigned int state);
+};
+
+class ArcKnotHolderEntityEnd : public KnotHolderEntity {
+public:
+ virtual Geom::Point knot_get() const;
+ virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, unsigned int state);
+ virtual void knot_click(unsigned int state);
+};
+
+class ArcKnotHolderEntityRX : public KnotHolderEntity {
+public:
+ virtual Geom::Point knot_get() const;
+ virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, unsigned int state);
+ virtual void knot_click(unsigned int state);
+};
+
+class ArcKnotHolderEntityRY : public KnotHolderEntity {
+public:
+ virtual Geom::Point knot_get() const;
+ virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, unsigned int state);
+ virtual void knot_click(unsigned int state);
+};
+
+/*
+ * return values:
+ * 1 : inside
+ * 0 : on the curves
+ * -1 : outside
+ */
+static gint
+sp_genericellipse_side(SPGenericEllipse *ellipse, Geom::Point const &p)
+{
+ gdouble dx = (p[Geom::X] - ellipse->cx.computed) / ellipse->rx.computed;
+ gdouble dy = (p[Geom::Y] - ellipse->cy.computed) / ellipse->ry.computed;
+
+ gdouble s = dx * dx + dy * dy;
+ if (s < 1.0) return 1;
+ if (s > 1.0) return -1;
+ return 0;
+}
+
+void
+ArcKnotHolderEntityStart::knot_set(Geom::Point const &p, Geom::Point const &/*origin*/, unsigned int state)
+{
+ int snaps = Inkscape::Preferences::get()->getInt("/options/rotationsnapsperpi/value", 12);
+
+ SPGenericEllipse *arc = SP_GENERICELLIPSE(item);
+
+ arc->setClosed(sp_genericellipse_side(arc, p) == -1);
+
+ Geom::Point delta = p - Geom::Point(arc->cx.computed, arc->cy.computed);
+ Geom::Scale sc(arc->rx.computed, arc->ry.computed);
+
+ arc->start = atan2(delta * sc.inverse());
+
+ if ((state & GDK_CONTROL_MASK) && snaps) {
+ arc->start = sp_round(arc->start, M_PI / snaps);
+ }
+
+ arc->normalize();
+ arc->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
+}
+
+Geom::Point
+ArcKnotHolderEntityStart::knot_get() const
+{
+ SPGenericEllipse const *ge = SP_GENERICELLIPSE(item);
+
+ return ge->getPointAtAngle(ge->start);
+}
+
+void
+ArcKnotHolderEntityStart::knot_click(unsigned int state)
+{
+ SPGenericEllipse *ge = SP_GENERICELLIPSE(item);
+
+ if (state & GDK_SHIFT_MASK) {
+ ge->end = ge->start = 0;
+ (static_cast<SPObject *>(ge))->updateRepr();
+ }
+}
+
+void
+ArcKnotHolderEntityEnd::knot_set(Geom::Point const &p, Geom::Point const &/*origin*/, unsigned int state)
+{
+ int snaps = Inkscape::Preferences::get()->getInt("/options/rotationsnapsperpi/value", 12);
+
+ SPGenericEllipse *arc = SP_GENERICELLIPSE(item);
+
+ arc->setClosed(sp_genericellipse_side(arc, p) == -1);
+
+ Geom::Point delta = p - Geom::Point(arc->cx.computed, arc->cy.computed);
+ Geom::Scale sc(arc->rx.computed, arc->ry.computed);
+
+ arc->end = atan2(delta * sc.inverse());
+
+ if ((state & GDK_CONTROL_MASK) && snaps) {
+ arc->end = sp_round(arc->end, M_PI/snaps);
+ }
+
+ arc->normalize();
+ arc->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
+}
+
+Geom::Point
+ArcKnotHolderEntityEnd::knot_get() const
+{
+ SPGenericEllipse const *ge = SP_GENERICELLIPSE(item);
+
+ return ge->getPointAtAngle(ge->end);
+}
+
+
+void
+ArcKnotHolderEntityEnd::knot_click(unsigned int state)
+{
+ SPGenericEllipse *ge = SP_GENERICELLIPSE(item);
+
+ if (state & GDK_SHIFT_MASK) {
+ ge->end = ge->start = 0;
+ (static_cast<SPObject *>(ge))->updateRepr();
+ }
+}
+
+
+void
+ArcKnotHolderEntityRX::knot_set(Geom::Point const &p, Geom::Point const &/*origin*/, unsigned int state)
+{
+ SPGenericEllipse *ge = SP_GENERICELLIPSE(item);
+
+ Geom::Point const s = snap_knot_position(p, state);
+
+ ge->rx.computed = fabs( ge->cx.computed - s[Geom::X] );
+
+ if ( state & GDK_CONTROL_MASK ) {
+ ge->ry.computed = ge->rx.computed;
+ }
+
+ (static_cast<SPObject *>(item))->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
+}
+
+Geom::Point
+ArcKnotHolderEntityRX::knot_get() const
+{
+ SPGenericEllipse const *ge = SP_GENERICELLIPSE(item);
+
+ return (Geom::Point(ge->cx.computed, ge->cy.computed) - Geom::Point(ge->rx.computed, 0));
+}
+
+void
+ArcKnotHolderEntityRX::knot_click(unsigned int state)
+{
+ SPGenericEllipse *ge = SP_GENERICELLIPSE(item);
+
+ if (state & GDK_CONTROL_MASK) {
+ ge->ry.computed = ge->rx.computed;
+ (static_cast<SPObject *>(ge))->updateRepr();
+ }
+}
+
+void
+ArcKnotHolderEntityRY::knot_set(Geom::Point const &p, Geom::Point const &/*origin*/, unsigned int state)
+{
+ SPGenericEllipse *ge = SP_GENERICELLIPSE(item);
+
+ Geom::Point const s = snap_knot_position(p, state);
+
+ ge->ry.computed = fabs( ge->cy.computed - s[Geom::Y] );
+
+ if ( state & GDK_CONTROL_MASK ) {
+ ge->rx.computed = ge->ry.computed;
+ }
+
+ (static_cast<SPObject *>(item))->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
+}
+
+Geom::Point
+ArcKnotHolderEntityRY::knot_get() const
+{
+ SPGenericEllipse const *ge = SP_GENERICELLIPSE(item);
+
+ return (Geom::Point(ge->cx.computed, ge->cy.computed) - Geom::Point(0, ge->ry.computed));
+}
+
+void
+ArcKnotHolderEntityRY::knot_click(unsigned int state)
+{
+ SPGenericEllipse *ge = SP_GENERICELLIPSE(item);
+
+ if (state & GDK_CONTROL_MASK) {
+ ge->rx.computed = ge->ry.computed;
+ (static_cast<SPObject *>(ge))->updateRepr();
+ }
+}
+
+ArcKnotHolder::ArcKnotHolder(SPDesktop *desktop, SPItem *item, SPKnotHolderReleasedFunc relhandler) :
+ KnotHolder(desktop, item, relhandler)
+{
+ ArcKnotHolderEntityRX *entity_rx = new ArcKnotHolderEntityRX();
+ ArcKnotHolderEntityRY *entity_ry = new ArcKnotHolderEntityRY();
+ ArcKnotHolderEntityStart *entity_start = new ArcKnotHolderEntityStart();
+ ArcKnotHolderEntityEnd *entity_end = new ArcKnotHolderEntityEnd();
+
+ entity_rx->create(desktop, item, this, Inkscape::CTRL_TYPE_SIZER,
+ _("Adjust ellipse <b>width</b>, with <b>Ctrl</b> to make circle"),
+ SP_KNOT_SHAPE_SQUARE, SP_KNOT_MODE_XOR);
+
+ entity_ry->create(desktop, item, this, Inkscape::CTRL_TYPE_SIZER,
+ _("Adjust ellipse <b>height</b>, with <b>Ctrl</b> to make circle"),
+ SP_KNOT_SHAPE_SQUARE, SP_KNOT_MODE_XOR);
+
+ entity_start->create(desktop, item, this, Inkscape::CTRL_TYPE_ROTATE,
+ _("Position the <b>start point</b> of the arc or segment; with <b>Ctrl</b> "
+ "to snap angle; drag <b>inside</b> the ellipse for arc, <b>outside</b> for segment"),
+ SP_KNOT_SHAPE_CIRCLE, SP_KNOT_MODE_XOR);
+
+ entity_end->create(desktop, item, this, Inkscape::CTRL_TYPE_ROTATE,
+ _("Position the <b>end point</b> of the arc or segment; with <b>Ctrl</b> to snap angle; "
+ "drag <b>inside</b> the ellipse for arc, <b>outside</b> for segment"),
+ SP_KNOT_SHAPE_CIRCLE, SP_KNOT_MODE_XOR);
+
+ entity.push_back(entity_rx);
+ entity.push_back(entity_ry);
+ entity.push_back(entity_start);
+ entity.push_back(entity_end);
+
+ add_pattern_knotholder();
+}
+
+/* SPStar */
+
+class StarKnotHolderEntity1 : public KnotHolderEntity {
+public:
+ virtual Geom::Point knot_get() const;
+ virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, unsigned int state);
+ virtual void knot_click(unsigned int state);
+};
+
+class StarKnotHolderEntity2 : public KnotHolderEntity {
+public:
+ virtual Geom::Point knot_get() const;
+ virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, unsigned int state);
+ virtual void knot_click(unsigned int state);
+};
+
+void
+StarKnotHolderEntity1::knot_set(Geom::Point const &p, Geom::Point const &/*origin*/, unsigned int state)
+{
+ SPStar *star = SP_STAR(item);
+
+ Geom::Point const s = snap_knot_position(p, state);
+
+ Geom::Point d = s - star->center;
+
+ double arg1 = atan2(d);
+ double darg1 = arg1 - star->arg[0];
+
+ if (state & GDK_MOD1_MASK) {
+ star->randomized = darg1/(star->arg[0] - star->arg[1]);
+ } else if (state & GDK_SHIFT_MASK) {
+ star->rounded = darg1/(star->arg[0] - star->arg[1]);
+ } else if (state & GDK_CONTROL_MASK) {
+ star->r[0] = L2(d);
+ } else {
+ star->r[0] = L2(d);
+ star->arg[0] = arg1;
+ star->arg[1] += darg1;
+ }
+ (static_cast<SPObject *>(star))->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
+}
+
+void
+StarKnotHolderEntity2::knot_set(Geom::Point const &p, Geom::Point const &/*origin*/, unsigned int state)
+{
+ SPStar *star = SP_STAR(item);
+
+ Geom::Point const s = snap_knot_position(p, state);
+
+ if (star->flatsided == false) {
+ Geom::Point d = s - star->center;
+
+ double arg1 = atan2(d);
+ double darg1 = arg1 - star->arg[1];
+
+ if (state & GDK_MOD1_MASK) {
+ star->randomized = darg1/(star->arg[0] - star->arg[1]);
+ } else if (state & GDK_SHIFT_MASK) {
+ star->rounded = fabs(darg1/(star->arg[0] - star->arg[1]));
+ } else if (state & GDK_CONTROL_MASK) {
+ star->r[1] = L2(d);
+ star->arg[1] = star->arg[0] + M_PI / star->sides;
+ }
+ else {
+ star->r[1] = L2(d);
+ star->arg[1] = atan2(d);
+ }
+ (static_cast<SPObject *>(star))->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
+ }
+}
+
+Geom::Point
+StarKnotHolderEntity1::knot_get() const
+{
+ g_assert(item != NULL);
+
+ SPStar const *star = SP_STAR(item);
+
+ return sp_star_get_xy(star, SP_STAR_POINT_KNOT1, 0);
+
+}
+
+Geom::Point
+StarKnotHolderEntity2::knot_get() const
+{
+ g_assert(item != NULL);
+
+ SPStar const *star = SP_STAR(item);
+
+ return sp_star_get_xy(star, SP_STAR_POINT_KNOT2, 0);
+}
+
+static void
+sp_star_knot_click(SPItem *item, unsigned int state)
+{
+ SPStar *star = SP_STAR(item);
+
+ if (state & GDK_MOD1_MASK) {
+ star->randomized = 0;
+ (static_cast<SPObject *>(star))->updateRepr();
+ } else if (state & GDK_SHIFT_MASK) {
+ star->rounded = 0;
+ (static_cast<SPObject *>(star))->updateRepr();
+ } else if (state & GDK_CONTROL_MASK) {
+ star->arg[1] = star->arg[0] + M_PI / star->sides;
+ (static_cast<SPObject *>(star))->updateRepr();
+ }
+}
+
+void
+StarKnotHolderEntity1::knot_click(unsigned int state)
+{
+ sp_star_knot_click(item, state);
+}
+
+void
+StarKnotHolderEntity2::knot_click(unsigned int state)
+{
+ sp_star_knot_click(item, state);
+}
+
+StarKnotHolder::StarKnotHolder(SPDesktop *desktop, SPItem *item, SPKnotHolderReleasedFunc relhandler) :
+ KnotHolder(desktop, item, relhandler)
+{
+ SPStar *star = SP_STAR(item);
+
+ StarKnotHolderEntity1 *entity1 = new StarKnotHolderEntity1();
+ entity1->create(desktop, item, this, Inkscape::CTRL_TYPE_SHAPER,
+ _("Adjust the <b>tip radius</b> of the star or polygon; "
+ "with <b>Shift</b> to round; with <b>Alt</b> to randomize"));
+
+ entity.push_back(entity1);
+
+ if (star->flatsided == false) {
+ StarKnotHolderEntity2 *entity2 = new StarKnotHolderEntity2();
+ entity2->create(desktop, item, this, Inkscape::CTRL_TYPE_SHAPER,
+ _("Adjust the <b>base radius</b> of the star; with <b>Ctrl</b> to keep star rays "
+ "radial (no skew); with <b>Shift</b> to round; with <b>Alt</b> to randomize"));
+ entity.push_back(entity2);
+ }
+
+ add_pattern_knotholder();
+}
+
+/* SPSpiral */
+
+class SpiralKnotHolderEntityInner : public KnotHolderEntity {
+public:
+ virtual Geom::Point knot_get() const;
+ virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, unsigned int state);
+ virtual void knot_click(unsigned int state);
+};
+
+class SpiralKnotHolderEntityOuter : public KnotHolderEntity {
+public:
+ virtual Geom::Point knot_get() const;
+ virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, unsigned int state);
+};
+
+
+/*
+ * set attributes via inner (t=t0) knot point:
+ * [default] increase/decrease inner point
+ * [shift] increase/decrease inner and outer arg synchronizely
+ * [control] constrain inner arg to round per PI/4
+ */
+void
+SpiralKnotHolderEntityInner::knot_set(Geom::Point const &p, Geom::Point const &origin, unsigned int state)
+{
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ int snaps = prefs->getInt("/options/rotationsnapsperpi/value", 12);
+
+ SPSpiral *spiral = SP_SPIRAL(item);
+
+ gdouble dx = p[Geom::X] - spiral->cx;
+ gdouble dy = p[Geom::Y] - spiral->cy;
+
+ gdouble moved_y = p[Geom::Y] - origin[Geom::Y];
+
+ if (state & GDK_MOD1_MASK) {
+ // adjust divergence by vertical drag, relative to rad
+ if (spiral->rad > 0) {
+ double exp_delta = 0.1*moved_y/(spiral->rad); // arbitrary multiplier to slow it down
+ spiral->exp += exp_delta;
+ if (spiral->exp < 1e-3)
+ spiral->exp = 1e-3;
+ }
+ } else {
+ // roll/unroll from inside
+ gdouble arg_t0;
+ spiral->getPolar(spiral->t0, NULL, &arg_t0);
+
+ gdouble arg_tmp = atan2(dy, dx) - arg_t0;
+ gdouble arg_t0_new = arg_tmp - floor((arg_tmp+M_PI)/(2.0*M_PI))*2.0*M_PI + arg_t0;
+ spiral->t0 = (arg_t0_new - spiral->arg) / (2.0*M_PI*spiral->revo);
+
+ /* round inner arg per PI/snaps, if CTRL is pressed */
+ if ( ( state & GDK_CONTROL_MASK )
+ && ( fabs(spiral->revo) > SP_EPSILON_2 )
+ && ( snaps != 0 ) ) {
+ gdouble arg = 2.0*M_PI*spiral->revo*spiral->t0 + spiral->arg;
+ spiral->t0 = (sp_round(arg, M_PI/snaps) - spiral->arg)/(2.0*M_PI*spiral->revo);
+ }
+
+ spiral->t0 = CLAMP(spiral->t0, 0.0, 0.999);
+ }
+
+ (static_cast<SPObject *>(spiral))->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
+}
+
+/*
+ * set attributes via outer (t=1) knot point:
+ * [default] increase/decrease revolution factor
+ * [control] constrain inner arg to round per PI/4
+ */
+void
+SpiralKnotHolderEntityOuter::knot_set(Geom::Point const &p, Geom::Point const &/*origin*/, unsigned int state)
+{
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ int snaps = prefs->getInt("/options/rotationsnapsperpi/value", 12);
+
+ SPSpiral *spiral = SP_SPIRAL(item);
+
+ gdouble dx = p[Geom::X] - spiral->cx;
+ gdouble dy = p[Geom::Y] - spiral->cy;
+
+ if (state & GDK_SHIFT_MASK) { // rotate without roll/unroll
+ spiral->arg = atan2(dy, dx) - 2.0*M_PI*spiral->revo;
+ if (!(state & GDK_MOD1_MASK)) {
+ // if alt not pressed, change also rad; otherwise it is locked
+ spiral->rad = MAX(hypot(dx, dy), 0.001);
+ }
+ if ( ( state & GDK_CONTROL_MASK )
+ && snaps ) {
+ spiral->arg = sp_round(spiral->arg, M_PI/snaps);
+ }
+ } else { // roll/unroll
+ // arg of the spiral outer end
+ double arg_1;
+ spiral->getPolar(1, NULL, &arg_1);
+
+ // its fractional part after the whole turns are subtracted
+ double arg_r = arg_1 - sp_round(arg_1, 2.0*M_PI);
+
+ // arg of the mouse point relative to spiral center
+ double mouse_angle = atan2(dy, dx);
+ if (mouse_angle < 0)
+ mouse_angle += 2*M_PI;
+
+ // snap if ctrl
+ if ( ( state & GDK_CONTROL_MASK ) && snaps ) {
+ mouse_angle = sp_round(mouse_angle, M_PI/snaps);
+ }
+
+ // by how much we want to rotate the outer point
+ double diff = mouse_angle - arg_r;
+ if (diff > M_PI)
+ diff -= 2*M_PI;
+ else if (diff < -M_PI)
+ diff += 2*M_PI;
+
+ // calculate the new rad;
+ // the value of t corresponding to the angle arg_1 + diff:
+ double t_temp = ((arg_1 + diff) - spiral->arg)/(2*M_PI*spiral->revo);
+ // the rad at that t:
+ double rad_new = 0;
+ if (t_temp > spiral->t0)
+ spiral->getPolar(t_temp, &rad_new, NULL);
+
+ // change the revo (converting diff from radians to the number of turns)
+ spiral->revo += diff/(2*M_PI);
+ if (spiral->revo < 1e-3)
+ spiral->revo = 1e-3;
+
+ // if alt not pressed and the values are sane, change the rad
+ if (!(state & GDK_MOD1_MASK) && rad_new > 1e-3 && rad_new/spiral->rad < 2) {
+ // adjust t0 too so that the inner point stays unmoved
+ double r0;
+ spiral->getPolar(spiral->t0, &r0, NULL);
+ spiral->rad = rad_new;
+ spiral->t0 = pow(r0 / spiral->rad, 1.0/spiral->exp);
+ }
+ if (!IS_FINITE(spiral->t0)) spiral->t0 = 0.0;
+ spiral->t0 = CLAMP(spiral->t0, 0.0, 0.999);
+ }
+
+ (static_cast<SPObject *>(spiral))->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
+}
+
+Geom::Point
+SpiralKnotHolderEntityInner::knot_get() const
+{
+ SPSpiral const *spiral = SP_SPIRAL(item);
+
+ return spiral->getXY(spiral->t0);
+}
+
+Geom::Point
+SpiralKnotHolderEntityOuter::knot_get() const
+{
+ SPSpiral const *spiral = SP_SPIRAL(item);
+
+ return spiral->getXY(1.0);
+}
+
+void
+SpiralKnotHolderEntityInner::knot_click(unsigned int state)
+{
+ SPSpiral *spiral = SP_SPIRAL(item);
+
+ if (state & GDK_MOD1_MASK) {
+ spiral->exp = 1;
+ (static_cast<SPObject *>(spiral))->updateRepr();
+ } else if (state & GDK_SHIFT_MASK) {
+ spiral->t0 = 0;
+ (static_cast<SPObject *>(spiral))->updateRepr();
+ }
+}
+
+SpiralKnotHolder::SpiralKnotHolder(SPDesktop *desktop, SPItem *item, SPKnotHolderReleasedFunc relhandler) :
+ KnotHolder(desktop, item, relhandler)
+{
+ SpiralKnotHolderEntityInner *entity_inner = new SpiralKnotHolderEntityInner();
+ SpiralKnotHolderEntityOuter *entity_outer = new SpiralKnotHolderEntityOuter();
+
+ entity_inner->create(desktop, item, this, Inkscape::CTRL_TYPE_SHAPER,
+ _("Roll/unroll the spiral from <b>inside</b>; with <b>Ctrl</b> to snap angle; "
+ "with <b>Alt</b> to converge/diverge"));
+
+ entity_outer->create(desktop, item, this, Inkscape::CTRL_TYPE_SHAPER,
+ _("Roll/unroll the spiral from <b>outside</b>; with <b>Ctrl</b> to snap angle; "
+ "with <b>Shift</b> to scale/rotate; with <b>Alt</b> to lock radius"));
+
+ entity.push_back(entity_inner);
+ entity.push_back(entity_outer);
+
+ add_pattern_knotholder();
+}
+
+/* SPOffset */
+
+class OffsetKnotHolderEntity : public KnotHolderEntity {
+public:
+ virtual Geom::Point knot_get() const;
+ virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, unsigned int state);
+};
+
+void
+OffsetKnotHolderEntity::knot_set(Geom::Point const &p, Geom::Point const &/*origin*/, unsigned int /*state*/)
+{
+ SPOffset *offset = SP_OFFSET(item);
+
+ offset->rad = sp_offset_distance_to_original(offset, p);
+ offset->knot = p;
+ offset->knotSet = true;
+
+ (static_cast<SPObject *>(offset))->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
+}
+
+
+Geom::Point
+OffsetKnotHolderEntity::knot_get() const
+{
+ SPOffset const *offset = SP_OFFSET(item);
+
+ Geom::Point np;
+ sp_offset_top_point(offset,&np);
+ return np;
+}
+
+OffsetKnotHolder::OffsetKnotHolder(SPDesktop *desktop, SPItem *item, SPKnotHolderReleasedFunc relhandler) :
+ KnotHolder(desktop, item, relhandler)
+{
+ OffsetKnotHolderEntity *entity_offset = new OffsetKnotHolderEntity();
+ entity_offset->create(desktop, item, this, Inkscape::CTRL_TYPE_SHAPER,
+ _("Adjust the <b>offset distance</b>"));
+ entity.push_back(entity_offset);
+
+ add_pattern_knotholder();
+}
+
+// TODO: this is derived from RectKnotHolderEntityWH because it used the same static function
+// set_internal as the latter before KnotHolderEntity was C++ified. Check whether this also makes
+// sense logically.
+class FlowtextKnotHolderEntity : public RectKnotHolderEntityWH {
+public:
+ virtual Geom::Point knot_get() const;
+ virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, unsigned int state);
+};
+
+Geom::Point
+FlowtextKnotHolderEntity::knot_get() const
+{
+ SPRect const *rect = SP_RECT(item);
+
+ return Geom::Point(rect->x.computed + rect->width.computed, rect->y.computed + rect->height.computed);
+}
+
+void
+FlowtextKnotHolderEntity::knot_set(Geom::Point const &p, Geom::Point const &origin, unsigned int state)
+{
+ set_internal(p, origin, state);
+}
+
+FlowtextKnotHolder::FlowtextKnotHolder(SPDesktop *desktop, SPItem *item, SPKnotHolderReleasedFunc relhandler) :
+ KnotHolder(desktop, item, relhandler)
+{
+ g_assert(item != NULL);
+
+ FlowtextKnotHolderEntity *entity_flowtext = new FlowtextKnotHolderEntity();
+ entity_flowtext->create(desktop, item, this, Inkscape::CTRL_TYPE_SHAPER,
+ _("Drag to resize the <b>flowed text frame</b>"));
+ entity.push_back(entity_flowtext);
+}
+
+/*
+ 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/ui/object-edit.h b/src/ui/object-edit.h
new file mode 100644
index 000000000..75f3ce12b
--- /dev/null
+++ b/src/ui/object-edit.h
@@ -0,0 +1,84 @@
+#ifndef OBJECT_EDIT_H_SEEN
+#define OBJECT_EDIT_H_SEEN
+
+/*
+ * Node editing extension to objects
+ *
+ * Authors:
+ * Lauris Kaplinski <lauris@kaplinski.com>
+ * Mitsuru Oka
+ * Jon A. Cruz <jon@joncruz.org>
+ *
+ * Licensed under GNU GPL
+ */
+
+#include "knotholder.h"
+
+namespace Inkscape {
+namespace UI {
+
+KnotHolder *createKnotHolder(SPItem *item, SPDesktop *desktop);
+
+}
+}
+
+class RectKnotHolder : public KnotHolder {
+public:
+ RectKnotHolder(SPDesktop *desktop, SPItem *item, SPKnotHolderReleasedFunc relhandler);
+ virtual ~RectKnotHolder() {};
+};
+
+class Box3DKnotHolder : public KnotHolder {
+public:
+ Box3DKnotHolder(SPDesktop *desktop, SPItem *item, SPKnotHolderReleasedFunc relhandler);
+ virtual ~Box3DKnotHolder() {};
+};
+
+class ArcKnotHolder : public KnotHolder {
+public:
+ ArcKnotHolder(SPDesktop *desktop, SPItem *item, SPKnotHolderReleasedFunc relhandler);
+ virtual ~ArcKnotHolder() {};
+};
+
+class StarKnotHolder : public KnotHolder {
+public:
+ StarKnotHolder(SPDesktop *desktop, SPItem *item, SPKnotHolderReleasedFunc relhandler);
+ virtual ~StarKnotHolder() {};
+};
+
+class SpiralKnotHolder : public KnotHolder {
+public:
+ SpiralKnotHolder(SPDesktop *desktop, SPItem *item, SPKnotHolderReleasedFunc relhandler);
+ virtual ~SpiralKnotHolder() {};
+};
+
+class OffsetKnotHolder : public KnotHolder {
+public:
+ OffsetKnotHolder(SPDesktop *desktop, SPItem *item, SPKnotHolderReleasedFunc relhandler);
+ virtual ~OffsetKnotHolder() {};
+};
+
+class FlowtextKnotHolder : public KnotHolder {
+public:
+ FlowtextKnotHolder(SPDesktop *desktop, SPItem *item, SPKnotHolderReleasedFunc relhandler);
+ virtual ~FlowtextKnotHolder() {};
+};
+
+class MiscKnotHolder : public KnotHolder {
+public:
+ MiscKnotHolder(SPDesktop *desktop, SPItem *item, SPKnotHolderReleasedFunc relhandler);
+ virtual ~MiscKnotHolder() {};
+};
+
+#endif // OBJECT_EDIT_H_SEEN
+
+/*
+ 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/ui/shape-editor.cpp b/src/ui/shape-editor.cpp
new file mode 100644
index 000000000..0b9fc24c5
--- /dev/null
+++ b/src/ui/shape-editor.cpp
@@ -0,0 +1,177 @@
+/*
+ * Inkscape::ShapeEditor
+ *
+ * Authors:
+ * bulia byak <buliabyak@users.sf.net>
+ * Krzysztof KosiƄski <tweenk.pl@gmail.com>
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+#include <glibmm/i18n.h>
+
+#include "desktop-handles.h"
+#include "document.h"
+#include "gc-anchored.h"
+#include "knotholder.h"
+#include "ui/object-edit.h"
+#include "sp-item.h"
+#include "sp-object.h"
+#include "ui/shape-editor.h"
+#include "xml/node-event-vector.h"
+
+//using Inkscape::createKnotHolder;
+
+namespace Inkscape {
+namespace UI {
+
+bool ShapeEditor::_blockSetItem = false;
+
+ShapeEditor::ShapeEditor(SPDesktop *dt) {
+ this->desktop = dt;
+ this->knotholder = NULL;
+ this->knotholder_listener_attached_for = NULL;
+}
+
+ShapeEditor::~ShapeEditor() {
+ unset_item();
+}
+
+void ShapeEditor::unset_item(bool keep_knotholder) {
+ if (this->knotholder) {
+ Inkscape::XML::Node *old_repr = this->knotholder->repr;
+ if (old_repr && old_repr == knotholder_listener_attached_for) {
+ sp_repr_remove_listener_by_data(old_repr, this);
+ Inkscape::GC::release(old_repr);
+ knotholder_listener_attached_for = NULL;
+ }
+
+ if (!keep_knotholder) {
+ delete this->knotholder;
+ this->knotholder = NULL;
+ }
+ }
+}
+
+bool ShapeEditor::has_knotholder() {
+ return this->knotholder != NULL;
+}
+
+void ShapeEditor::update_knotholder() {
+ if (this->knotholder)
+ this->knotholder->update_knots();
+}
+
+bool ShapeEditor::has_local_change() {
+ return (this->knotholder && this->knotholder->local_change != 0);
+}
+
+void ShapeEditor::decrement_local_change() {
+ if (this->knotholder) {
+ this->knotholder->local_change = FALSE;
+ }
+}
+
+const SPItem *ShapeEditor::get_item() {
+ const SPItem *item = NULL;
+ if (this->has_knotholder()) {
+ item = this->knotholder->getItem();
+ }
+ return item;
+}
+
+void ShapeEditor::event_attr_changed(Inkscape::XML::Node *, gchar const *name, gchar const *, gchar const *, bool, void *data)
+{
+ g_assert(data);
+ ShapeEditor *sh = static_cast<ShapeEditor *>(data);
+ bool changed_kh = false;
+
+ if (sh->has_knotholder())
+ {
+ changed_kh = !sh->has_local_change();
+ sh->decrement_local_change();
+ if (changed_kh) {
+ // this can happen if an LPEItem's knotholder handle was dragged, in which case we want
+ // to keep the knotholder; in all other cases (e.g., if the LPE itself changes) we delete it
+ sh->reset_item(!strcmp(name, "d"));
+ }
+ }
+}
+
+static Inkscape::XML::NodeEventVector shapeeditor_repr_events = {
+ NULL, /* child_added */
+ NULL, /* child_removed */
+ ShapeEditor::event_attr_changed,
+ NULL, /* content_changed */
+ NULL /* order_changed */
+};
+
+
+void ShapeEditor::set_item(SPItem *item, bool keep_knotholder) {
+ if (_blockSetItem) {
+ return;
+ }
+
+ // this happens (and should only happen) when for an LPEItem having both knotholder and
+ // nodepath the knotholder is adapted; in this case we don't want to delete the knotholder
+ // since this freezes the handles
+ unset_item(keep_knotholder);
+
+ if (item) {
+ Inkscape::XML::Node *repr;
+ if (!this->knotholder) {
+ // only recreate knotholder if none is present
+ this->knotholder = createKnotHolder(item, desktop);
+ }
+ if (this->knotholder) {
+ this->knotholder->update_knots();
+ // setting new listener
+ repr = this->knotholder->repr;
+ if (repr != knotholder_listener_attached_for) {
+ Inkscape::GC::anchor(repr);
+ sp_repr_add_listener(repr, &shapeeditor_repr_events, this);
+ knotholder_listener_attached_for = repr;
+ }
+ }
+ }
+}
+
+
+/** FIXME: This thing is only called when the item needs to be updated in response to repr change.
+ Why not make a reload function in KnotHolder? */
+void ShapeEditor::reset_item(bool keep_knotholder)
+{
+ if (knotholder) {
+ SPObject *obj = sp_desktop_document(desktop)->getObjectByRepr(knotholder_listener_attached_for); /// note that it is not certain that this is an SPItem; it could be a LivePathEffectObject.
+ set_item(SP_ITEM(obj), keep_knotholder);
+ }
+}
+
+/**
+ * Returns true if this ShapeEditor has a knot above which the mouse currently hovers.
+ */
+bool ShapeEditor::knot_mouseover() const {
+ if (this->knotholder) {
+ return knotholder->knot_mouseover();
+ }
+
+ return false;
+}
+
+} // namespace UI
+} // namespace Inkscape
+
+/*
+ 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 :
diff --git a/src/ui/shape-editor.h b/src/ui/shape-editor.h
new file mode 100644
index 000000000..142a2493b
--- /dev/null
+++ b/src/ui/shape-editor.h
@@ -0,0 +1,71 @@
+#ifndef SEEN_SHAPE_EDITOR_H
+#define SEEN_SHAPE_EDITOR_H
+
+/*
+ * Inkscape::ShapeEditor
+ *
+ * This is a container class which contains a knotholder for shapes.
+ * It is attached to a single item.
+ *
+ * Authors:
+ * bulia byak <buliabyak@users.sf.net>
+ *
+ */
+
+class KnotHolder;
+class LivePathEffectObject;
+class SPDesktop;
+class SPItem;
+
+namespace Inkscape { namespace XML { class Node; }
+namespace UI {
+
+class ShapeEditor {
+public:
+
+ ShapeEditor(SPDesktop *desktop);
+ ~ShapeEditor();
+
+ void set_item(SPItem *item, bool keep_knotholder = false);
+ void unset_item(bool keep_knotholder = false);
+
+ void update_knotholder(); //((deprecated))
+
+ bool has_local_change();
+ void decrement_local_change();
+
+ bool knot_mouseover() const;
+
+ static void blockSetItem(bool b) { _blockSetItem = b; } // kludge
+
+ static void event_attr_changed(Inkscape::XML::Node * /*repr*/, char const *name, char const * /*old_value*/,
+ char const * /*new_value*/, bool /*is_interactive*/, void *data);
+private:
+ bool has_knotholder();
+ void reset_item (bool keep_knotholder = true);
+ const SPItem *get_item();
+
+ static bool _blockSetItem;
+
+ SPDesktop *desktop;
+ KnotHolder *knotholder;
+ Inkscape::XML::Node *knotholder_listener_attached_for;
+};
+
+} // namespace UI
+} // namespace Inkscape
+
+#endif // SEEN_SHAPE_EDITOR_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 :
+
diff --git a/src/ui/tool-factory.h b/src/ui/tool-factory.h
new file mode 100644
index 000000000..726706732
--- /dev/null
+++ b/src/ui/tool-factory.h
@@ -0,0 +1,40 @@
+/** @file
+ * Factory for ToolBase tree
+ *//*
+ * Authors:
+ * Markus Engel
+ *
+ * Copyright (C) 2013 Authors
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#ifndef TOOL_FACTORY_SEEN
+#define TOOL_FACTORY_SEEN
+
+#include "factory.h"
+
+namespace Inkscape {
+namespace UI {
+namespace Tools {
+
+class ToolBase;
+
+}
+}
+}
+
+typedef Singleton< Factory<Inkscape::UI::Tools::ToolBase> > ToolFactory;
+
+
+#endif
+
+/*
+ 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/ui/tool/node.cpp b/src/ui/tool/node.cpp
index 5d6e96588..4abc901d2 100644
--- a/src/ui/tool/node.cpp
+++ b/src/ui/tool/node.cpp
@@ -28,7 +28,7 @@
#include "ui/tool/node.h"
#include "ui/tool/path-manipulator.h"
#include "ui/tools/node-tool.h"
-#include "tools-switch.h"
+#include "ui/tools-switch.h"
#include <gdk/gdkkeysyms.h>
#include <cmath>
diff --git a/src/ui/tools-switch.cpp b/src/ui/tools-switch.cpp
new file mode 100644
index 000000000..048252788
--- /dev/null
+++ b/src/ui/tools-switch.cpp
@@ -0,0 +1,196 @@
+/*
+ * Utility functions for switching tools (= contexts)
+ *
+ * Authors:
+ * bulia byak <buliabyak@users.sf.net>
+ * Josh Andler <scislac@users.sf.net>
+ *
+ * Copyright (C) 2003-2007 authors
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include <gtkmm.h> // prevents deprecation warnings
+
+#include <cstring>
+#include <string>
+
+#include "inkscape-private.h"
+#include "desktop.h"
+#include "desktop-handles.h"
+#include <glibmm/i18n.h>
+
+#include <xml/repr.h>
+
+#include "ui/tools-switch.h"
+
+#include "box3d.h"
+#include "sp-ellipse.h"
+#include "sp-flowtext.h"
+#include "sp-offset.h"
+#include "sp-path.h"
+#include "sp-rect.h"
+#include "sp-star.h"
+#include "sp-spiral.h"
+#include "sp-text.h"
+
+// TODO: How many of these are actually needed?
+#include "ui/tools/arc-tool.h"
+#include "ui/tools/box3d-tool.h"
+#include "ui/tools/calligraphic-tool.h"
+#include "ui/tools/connector-tool.h"
+#include "ui/tools/dropper-tool.h"
+#include "ui/tools/eraser-tool.h"
+#include "ui/tools/flood-tool.h"
+#include "ui/tools/gradient-tool.h"
+#include "ui/tools/lpe-tool.h"
+#include "ui/tools/measure-tool.h"
+#include "ui/tools/mesh-tool.h"
+#include "ui/tools/node-tool.h"
+#include "ui/tools/pen-tool.h"
+#include "ui/tools/pencil-tool.h"
+#include "ui/tools/rect-tool.h"
+#include "ui/tools/select-tool.h"
+#include "ui/tools/spiral-tool.h"
+#include "ui/tools/spray-tool.h"
+#include "ui/tools/text-tool.h"
+#include "ui/tools/tweak-tool.h"
+#include "ui/tools/zoom-tool.h"
+
+#include "message-context.h"
+
+static char const *const tool_names[] = {
+ NULL,
+ "/tools/select",
+ "/tools/nodes",
+ "/tools/tweak",
+ "/tools/spray",
+ "/tools/shapes/rect",
+ "/tools/shapes/3dbox",
+ "/tools/shapes/arc",
+ "/tools/shapes/star",
+ "/tools/shapes/spiral",
+ "/tools/freehand/pencil",
+ "/tools/freehand/pen",
+ "/tools/calligraphic",
+ "/tools/text",
+ "/tools/gradient",
+ "/tools/mesh",
+ "/tools/zoom",
+ "/tools/measure",
+ "/tools/dropper",
+ "/tools/connector",
+ "/tools/paintbucket",
+ "/tools/eraser",
+ "/tools/lpetool",
+ NULL
+};
+
+// TODO: HEY! these belong to the tools themselves!
+static char const *const tool_msg[] = {
+ NULL,
+ N_("<b>Click</b> to Select and Transform objects, <b>Drag</b> to select many objects."),
+ N_("Modify selected path points (nodes) directly."),
+ N_("To tweak a path by pushing, select it and drag over it."),
+ N_("<b>Drag</b>, <b>click</b> or <b>click and scroll</b> to spray the selected objects."),
+ N_("<b>Drag</b> to create a rectangle. <b>Drag controls</b> to round corners and resize. <b>Click</b> to select."),
+ N_("<b>Drag</b> to create a 3D box. <b>Drag controls</b> to resize in perspective. <b>Click</b> to select (with <b>Ctrl+Alt</b> for single faces)."),
+ N_("<b>Drag</b> to create an ellipse. <b>Drag controls</b> to make an arc or segment. <b>Click</b> to select."),
+ N_("<b>Drag</b> to create a star. <b>Drag controls</b> to edit the star shape. <b>Click</b> to select."),
+ N_("<b>Drag</b> to create a spiral. <b>Drag controls</b> to edit the spiral shape. <b>Click</b> to select."),
+ N_("<b>Drag</b> to create a freehand line. <b>Shift</b> appends to selected path, <b>Alt</b> activates sketch mode."),
+ N_("<b>Click</b> or <b>click and drag</b> to start a path; with <b>Shift</b> to append to selected path. <b>Ctrl+click</b> to create single dots (straight line modes only)."),
+ N_("<b>Drag</b> to draw a calligraphic stroke; with <b>Ctrl</b> to track a guide path. <b>Arrow keys</b> adjust width (left/right) and angle (up/down)."),
+ N_("<b>Click</b> to select or create text, <b>drag</b> to create flowed text; then type."),
+ N_("<b>Drag</b> or <b>double click</b> to create a gradient on selected objects, <b>drag handles</b> to adjust gradients."),
+ N_("<b>Drag</b> or <b>double click</b> to create a mesh on selected objects, <b>drag handles</b> to adjust meshes."),
+ N_("<b>Click</b> or <b>drag around an area</b> to zoom in, <b>Shift+click</b> to zoom out."),
+ N_("<b>Drag</b> to measure the dimensions of objects."),
+ N_("<b>Click</b> to set fill, <b>Shift+click</b> to set stroke; <b>drag</b> to average color in area; with <b>Alt</b> to pick inverse color; <b>Ctrl+C</b> to copy the color under mouse to clipboard"),
+ N_("<b>Click and drag</b> between shapes to create a connector."),
+ N_("<b>Click</b> to paint a bounded area, <b>Shift+click</b> to union the new fill with the current selection, <b>Ctrl+click</b> to change the clicked object's fill and stroke to the current setting."),
+ N_("<b>Drag</b> to erase."),
+ N_("Choose a subtool from the toolbar"),
+};
+
+static int
+tools_prefpath2num(char const *id)
+{
+ int i = 1;
+ while (tool_names[i]) {
+ if (strcmp(tool_names[i], id) == 0)
+ return i;
+ else i++;
+ }
+ g_assert( 0 == TOOLS_INVALID );
+ return 0; //nothing found
+}
+
+int
+tools_isactive(SPDesktop *dt, unsigned num)
+{
+ g_assert( num < G_N_ELEMENTS(tool_names) );
+ if (SP_IS_EVENT_CONTEXT(dt->event_context))
+ return dt->event_context->pref_observer->observed_path == tool_names[num];
+ else return FALSE;
+}
+
+int
+tools_active(SPDesktop *dt)
+{
+ return tools_prefpath2num(dt->event_context->pref_observer->observed_path.data());
+}
+
+void
+tools_switch(SPDesktop *dt, int num)
+{
+ dt->tipsMessageContext()->set(Inkscape::NORMAL_MESSAGE, gettext( tool_msg[num] ) );
+ if (dt) {
+ // This event may change the above message
+ dt->_tool_changed.emit(num);
+ }
+
+ dt->set_event_context2(tool_names[num]);
+ /* fixme: This is really ugly hack. We should bind and unbind class methods */
+ /* First 4 tools use guides, first is undefined but we don't care */
+ dt->activate_guides(num < 5);
+ inkscape_eventcontext_set(dt->getEventContext());
+}
+
+void tools_switch_by_item(SPDesktop *dt, SPItem *item, Geom::Point const p)
+{
+ if (SP_IS_RECT(item)) {
+ tools_switch(dt, TOOLS_SHAPES_RECT);
+ } else if (SP_IS_BOX3D(item)) {
+ tools_switch(dt, TOOLS_SHAPES_3DBOX);
+ } else if (SP_IS_GENERICELLIPSE(item)) {
+ tools_switch(dt, TOOLS_SHAPES_ARC);
+ } else if (SP_IS_STAR(item)) {
+ tools_switch(dt, TOOLS_SHAPES_STAR);
+ } else if (SP_IS_SPIRAL(item)) {
+ tools_switch(dt, TOOLS_SHAPES_SPIRAL);
+ } else if (SP_IS_PATH(item)) {
+ if (Inkscape::UI::Tools::cc_item_is_connector(item)) {
+ tools_switch(dt, TOOLS_CONNECTOR);
+ }
+ else {
+ tools_switch(dt, TOOLS_NODES);
+ }
+ } else if (SP_IS_TEXT(item) || SP_IS_FLOWTEXT(item)) {
+ tools_switch(dt, TOOLS_TEXT);
+ sp_text_context_place_cursor_at (SP_TEXT_CONTEXT(dt->event_context), SP_OBJECT(item), p);
+ } else if (SP_IS_OFFSET(item)) {
+ tools_switch(dt, TOOLS_NODES);
+ }
+}
+
+/*
+ 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/ui/tools-switch.h b/src/ui/tools-switch.h
new file mode 100644
index 000000000..280837e87
--- /dev/null
+++ b/src/ui/tools-switch.h
@@ -0,0 +1,64 @@
+/*
+ * Utility functions for switching tools (= contexts)
+ *
+ * Authors:
+ * bulia byak <bulia@dr.com>
+ *
+ * Copyright (C) 2003 authors
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#ifndef SEEN_TOOLS_SWITCH_H
+#define SEEN_TOOLS_SWITCH_H
+
+class SPDesktop;
+class SPItem;
+namespace Geom {
+class Point;
+}
+
+
+enum {
+ TOOLS_INVALID,
+ TOOLS_SELECT,
+ TOOLS_NODES,
+ TOOLS_TWEAK,
+ TOOLS_SPRAY,
+ TOOLS_SHAPES_RECT,
+ TOOLS_SHAPES_3DBOX,
+ TOOLS_SHAPES_ARC,
+ TOOLS_SHAPES_STAR,
+ TOOLS_SHAPES_SPIRAL,
+ TOOLS_FREEHAND_PENCIL,
+ TOOLS_FREEHAND_PEN,
+ TOOLS_CALLIGRAPHIC,
+ TOOLS_TEXT,
+ TOOLS_GRADIENT,
+ TOOLS_MESH,
+ TOOLS_ZOOM,
+ TOOLS_MEASURE,
+ TOOLS_DROPPER,
+ TOOLS_CONNECTOR,
+ TOOLS_PAINTBUCKET,
+ TOOLS_ERASER,
+ TOOLS_LPETOOL
+};
+
+int tools_isactive(SPDesktop *dt, unsigned num);
+int tools_active(SPDesktop *dt);
+void tools_switch(SPDesktop *dt, int num);
+void tools_switch_by_item (SPDesktop *dt, SPItem *item, Geom::Point const p);
+
+#endif // !SEEN_TOOLS_SWITCH_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/ui/tools/arc-tool.cpp b/src/ui/tools/arc-tool.cpp
index 9fd68f1b9..4f64ade25 100644
--- a/src/ui/tools/arc-tool.cpp
+++ b/src/ui/tools/arc-tool.cpp
@@ -40,7 +40,7 @@
#include "desktop-style.h"
#include "context-fns.h"
#include "verbs.h"
-#include "shape-editor.h"
+#include "ui/shape-editor.h"
#include "ui/tools/tool-base.h"
#include "ui/tools/arc-tool.h"
@@ -48,7 +48,7 @@
using Inkscape::DocumentUndo;
-#include "tool-factory.h"
+#include "ui/tool-factory.h"
namespace Inkscape {
namespace UI {
diff --git a/src/ui/tools/box3d-tool.cpp b/src/ui/tools/box3d-tool.cpp
index b998267c2..0a20a0842 100644
--- a/src/ui/tools/box3d-tool.cpp
+++ b/src/ui/tools/box3d-tool.cpp
@@ -47,12 +47,12 @@
#include "box3d-side.h"
#include "document-private.h"
#include "line-geometry.h"
-#include "shape-editor.h"
+#include "ui/shape-editor.h"
#include "verbs.h"
using Inkscape::DocumentUndo;
-#include "tool-factory.h"
+#include "ui/tool-factory.h"
namespace Inkscape {
namespace UI {
diff --git a/src/ui/tools/calligraphic-tool.cpp b/src/ui/tools/calligraphic-tool.cpp
index 64097e834..d297fe5e1 100644
--- a/src/ui/tools/calligraphic-tool.cpp
+++ b/src/ui/tools/calligraphic-tool.cpp
@@ -82,7 +82,7 @@ using Inkscape::DocumentUndo;
#define DYNA_MIN_WIDTH 1.0e-6
-#include "tool-factory.h"
+#include "ui/tool-factory.h"
namespace Inkscape {
namespace UI {
diff --git a/src/ui/tools/connector-tool.cpp b/src/ui/tools/connector-tool.cpp
index d1355e807..7b5c84c16 100644
--- a/src/ui/tools/connector-tool.cpp
+++ b/src/ui/tools/connector-tool.cpp
@@ -109,7 +109,7 @@
using Inkscape::DocumentUndo;
-#include "tool-factory.h"
+#include "ui/tool-factory.h"
namespace Inkscape {
namespace UI {
diff --git a/src/ui/tools/dropper-tool.cpp b/src/ui/tools/dropper-tool.cpp
index 99d42a211..6c55f7484 100644
--- a/src/ui/tools/dropper-tool.cpp
+++ b/src/ui/tools/dropper-tool.cpp
@@ -52,7 +52,7 @@ using Inkscape::DocumentUndo;
static GdkCursor *cursor_dropper_fill = NULL;
static GdkCursor *cursor_dropper_stroke = NULL;
-#include "tool-factory.h"
+#include "ui/tool-factory.h"
namespace Inkscape {
namespace UI {
diff --git a/src/ui/tools/eraser-tool.cpp b/src/ui/tools/eraser-tool.cpp
index 4106785e7..bf4015b4c 100644
--- a/src/ui/tools/eraser-tool.cpp
+++ b/src/ui/tools/eraser-tool.cpp
@@ -84,7 +84,7 @@ using Inkscape::DocumentUndo;
#define DRAG_DEFAULT 1.0
#define DRAG_MAX 1.0
-#include "tool-factory.h"
+#include "ui/tool-factory.h"
namespace Inkscape {
namespace UI {
diff --git a/src/ui/tools/flood-tool.cpp b/src/ui/tools/flood-tool.cpp
index 3fb56b2ad..5745fc9cc 100644
--- a/src/ui/tools/flood-tool.cpp
+++ b/src/ui/tools/flood-tool.cpp
@@ -50,7 +50,7 @@
#include "preferences.h"
#include "rubberband.h"
#include "selection.h"
-#include "shape-editor.h"
+#include "ui/shape-editor.h"
#include "sp-defs.h"
#include "sp-item.h"
#include "splivarot.h"
@@ -74,7 +74,7 @@ using Inkscape::Display::ExtractARGB32;
using Inkscape::Display::ExtractRGB32;
using Inkscape::Display::AssembleARGB32;
-#include "tool-factory.h"
+#include "ui/tool-factory.h"
namespace Inkscape {
namespace UI {
diff --git a/src/ui/tools/freehand-base.cpp b/src/ui/tools/freehand-base.cpp
index 46ab53eef..6434c30d2 100644
--- a/src/ui/tools/freehand-base.cpp
+++ b/src/ui/tools/freehand-base.cpp
@@ -30,7 +30,7 @@
#include "desktop-handles.h"
#include "desktop-style.h"
#include "document.h"
-#include "draw-anchor.h"
+#include "ui/draw-anchor.h"
#include "macros.h"
#include "message-stack.h"
#include "ui/tools/pen-tool.h"
diff --git a/src/ui/tools/gradient-tool.cpp b/src/ui/tools/gradient-tool.cpp
index 4f9a7b59b..9c853917e 100644
--- a/src/ui/tools/gradient-tool.cpp
+++ b/src/ui/tools/gradient-tool.cpp
@@ -51,7 +51,7 @@
using Inkscape::DocumentUndo;
-#include "tool-factory.h"
+#include "ui/tool-factory.h"
namespace Inkscape {
namespace UI {
diff --git a/src/ui/tools/lpe-tool.cpp b/src/ui/tools/lpe-tool.cpp
index e9b9421f1..1fd1ebf8c 100644
--- a/src/ui/tools/lpe-tool.cpp
+++ b/src/ui/tools/lpe-tool.cpp
@@ -28,7 +28,7 @@
#include "desktop.h"
#include "message-context.h"
#include "preferences.h"
-#include "shape-editor.h"
+#include "ui/shape-editor.h"
#include "selection.h"
#include "desktop-handles.h"
#include "document.h"
@@ -59,7 +59,7 @@ SubtoolEntry lpesubtools[] = {
};
-#include "tool-factory.h"
+#include "ui/tool-factory.h"
namespace Inkscape {
namespace UI {
diff --git a/src/ui/tools/measure-tool.cpp b/src/ui/tools/measure-tool.cpp
index feeb68288..6b5cbeccd 100644
--- a/src/ui/tools/measure-tool.cpp
+++ b/src/ui/tools/measure-tool.cpp
@@ -49,7 +49,7 @@ using Inkscape::ControlManager;
using Inkscape::CTLINE_SECONDARY;
using Inkscape::Util::unit_table;
-#include "tool-factory.h"
+#include "ui/tool-factory.h"
namespace Inkscape {
namespace UI {
diff --git a/src/ui/tools/mesh-tool.cpp b/src/ui/tools/mesh-tool.cpp
index 7d6d3bc23..8a1fb7c72 100644
--- a/src/ui/tools/mesh-tool.cpp
+++ b/src/ui/tools/mesh-tool.cpp
@@ -53,7 +53,7 @@
using Inkscape::DocumentUndo;
-#include "tool-factory.h"
+#include "ui/tool-factory.h"
namespace Inkscape {
namespace UI {
diff --git a/src/ui/tools/node-tool.cpp b/src/ui/tools/node-tool.cpp
index 0b98bacc1..e2bb85d11 100644
--- a/src/ui/tools/node-tool.cpp
+++ b/src/ui/tools/node-tool.cpp
@@ -23,7 +23,7 @@
#include "live_effects/lpeobject.h"
#include "message-context.h"
#include "selection.h"
-#include "shape-editor.h" // temporary!
+#include "ui/shape-editor.h" // temporary!
#include "live_effects/effect.h"
#include "display/curve.h"
#include "sp-clippath.h"
@@ -107,7 +107,7 @@
using Inkscape::ControlManager;
-#include "tool-factory.h"
+#include "ui/tool-factory.h"
namespace Inkscape {
namespace UI {
diff --git a/src/ui/tools/pen-tool.cpp b/src/ui/tools/pen-tool.cpp
index 2c5ffc182..92937a135 100644
--- a/src/ui/tools/pen-tool.cpp
+++ b/src/ui/tools/pen-tool.cpp
@@ -26,7 +26,7 @@
#include "desktop-handles.h"
#include "selection.h"
#include "selection-chemistry.h"
-#include "draw-anchor.h"
+#include "ui/draw-anchor.h"
#include "message-stack.h"
#include "message-context.h"
#include "preferences.h"
@@ -40,7 +40,7 @@
#include <glibmm/i18n.h>
#include "macros.h"
#include "context-fns.h"
-#include "tools-switch.h"
+#include "ui/tools-switch.h"
#include "ui/control-manager.h"
// we include the necessary files for BSpline & Spiro
#include "live_effects/effect.h"
@@ -70,7 +70,7 @@
#include "live_effects/lpe-bspline.h"
#include <2geom/nearest-point.h>
-#include "tool-factory.h"
+#include "ui/tool-factory.h"
#include "live_effects/effect.h"
diff --git a/src/ui/tools/pencil-tool.cpp b/src/ui/tools/pencil-tool.cpp
index ca6dffc12..3ea2ae843 100644
--- a/src/ui/tools/pencil-tool.cpp
+++ b/src/ui/tools/pencil-tool.cpp
@@ -23,7 +23,7 @@
#include "desktop-handles.h"
#include "selection.h"
#include "selection-chemistry.h"
-#include "draw-anchor.h"
+#include "ui/draw-anchor.h"
#include "message-stack.h"
#include "message-context.h"
#include "sp-path.h"
@@ -43,7 +43,7 @@
#include "display/sp-canvas.h"
#include "display/curve.h"
#include "livarot/Path.h"
-#include "tool-factory.h"
+#include "ui/tool-factory.h"
#include "ui/tool/event-utils.h"
namespace Inkscape {
diff --git a/src/ui/tools/rect-tool.cpp b/src/ui/tools/rect-tool.cpp
index 819671dd6..de91dcff4 100644
--- a/src/ui/tools/rect-tool.cpp
+++ b/src/ui/tools/rect-tool.cpp
@@ -40,13 +40,13 @@
#include "xml/node-event-vector.h"
#include "preferences.h"
#include "context-fns.h"
-#include "shape-editor.h"
+#include "ui/shape-editor.h"
#include "verbs.h"
#include "display/sp-canvas-item.h"
using Inkscape::DocumentUndo;
-#include "tool-factory.h"
+#include "ui/tool-factory.h"
namespace Inkscape {
namespace UI {
diff --git a/src/ui/tools/select-tool.cpp b/src/ui/tools/select-tool.cpp
index 83bef17c9..394b0b369 100644
--- a/src/ui/tools/select-tool.cpp
+++ b/src/ui/tools/select-tool.cpp
@@ -41,7 +41,7 @@
#include "desktop-handles.h"
#include "sp-root.h"
#include "preferences.h"
-#include "tools-switch.h"
+#include "ui/tools-switch.h"
#include "message-stack.h"
#include "selection-describer.h"
#include "seltrans.h"
@@ -49,7 +49,7 @@
#include "display/sp-canvas.h"
#include "display/sp-canvas-item.h"
#include "display/drawing-item.h"
-#include "tool-factory.h"
+#include "ui/tool-factory.h"
using Inkscape::DocumentUndo;
diff --git a/src/ui/tools/spiral-tool.cpp b/src/ui/tools/spiral-tool.cpp
index 83712457a..18c3e4e2d 100644
--- a/src/ui/tools/spiral-tool.cpp
+++ b/src/ui/tools/spiral-tool.cpp
@@ -39,13 +39,13 @@
#include "xml/node-event-vector.h"
#include "preferences.h"
#include "context-fns.h"
-#include "shape-editor.h"
+#include "ui/shape-editor.h"
#include "verbs.h"
#include "display/sp-canvas-item.h"
using Inkscape::DocumentUndo;
-#include "tool-factory.h"
+#include "ui/tool-factory.h"
namespace Inkscape {
namespace UI {
diff --git a/src/ui/tools/spray-tool.cpp b/src/ui/tools/spray-tool.cpp
index 29f1b9a73..933da6fb1 100644
--- a/src/ui/tools/spray-tool.cpp
+++ b/src/ui/tools/spray-tool.cpp
@@ -84,7 +84,7 @@ using namespace std;
// Please enable again when working on 1.0
#define ENABLE_SPRAY_MODE_SINGLE_PATH
-#include "tool-factory.h"
+#include "ui/tool-factory.h"
namespace Inkscape {
namespace UI {
diff --git a/src/ui/tools/star-tool.cpp b/src/ui/tools/star-tool.cpp
index ed28c0a8d..7604ba04e 100644
--- a/src/ui/tools/star-tool.cpp
+++ b/src/ui/tools/star-tool.cpp
@@ -41,7 +41,7 @@
#include "xml/repr.h"
#include "xml/node-event-vector.h"
#include "context-fns.h"
-#include "shape-editor.h"
+#include "ui/shape-editor.h"
#include "verbs.h"
#include "display/sp-canvas-item.h"
@@ -49,7 +49,7 @@
using Inkscape::DocumentUndo;
-#include "tool-factory.h"
+#include "ui/tool-factory.h"
namespace Inkscape {
namespace UI {
diff --git a/src/ui/tools/text-tool.cpp b/src/ui/tools/text-tool.cpp
index b60a39e5d..a72748733 100644
--- a/src/ui/tools/text-tool.cpp
+++ b/src/ui/tools/text-tool.cpp
@@ -40,7 +40,7 @@
#include "rubberband.h"
#include "selection-chemistry.h"
#include "selection.h"
-#include "shape-editor.h"
+#include "ui/shape-editor.h"
#include "sp-flowtext.h"
#include "sp-namedview.h"
#include "sp-text.h"
@@ -52,7 +52,7 @@
#include "xml/node-event-vector.h"
#include "xml/repr.h"
#include <gtk/gtk.h>
-#include "tool-factory.h"
+#include "ui/tool-factory.h"
using Inkscape::ControlManager;
using Inkscape::DocumentUndo;
diff --git a/src/ui/tools/tool-base.cpp b/src/ui/tools/tool-base.cpp
index 150e899ce..37ca5eeea 100644
--- a/src/ui/tools/tool-base.cpp
+++ b/src/ui/tools/tool-base.cpp
@@ -46,7 +46,7 @@
#include "selection.h"
#include "ui/interface.h"
#include "macros.h"
-#include "tools-switch.h"
+#include "ui/tools-switch.h"
#include "preferences.h"
#include "message-context.h"
#include "gradient-drag.h"
@@ -55,7 +55,7 @@
#include "selcue.h"
#include "ui/tools/lpe-tool.h"
#include "ui/tool/control-point.h"
-#include "shape-editor.h"
+#include "ui/shape-editor.h"
#include "sp-guide.h"
#include "color.h"
#include "knot.h"
diff --git a/src/ui/tools/tool-base.h b/src/ui/tools/tool-base.h
index b27de9030..7a6ab83e7 100644
--- a/src/ui/tools/tool-base.h
+++ b/src/ui/tools/tool-base.h
@@ -30,7 +30,6 @@ namespace Glib {
class GrDrag;
class SPDesktop;
class SPItem;
-class ShapeEditor;
namespace Inkscape {
class MessageContext;
@@ -42,6 +41,9 @@ namespace Inkscape {
namespace Inkscape {
namespace UI {
+
+class ShapeEditor;
+
namespace Tools {
class ToolBase;
diff --git a/src/ui/tools/tweak-tool.cpp b/src/ui/tools/tweak-tool.cpp
index 75650d3af..340f64a0b 100644
--- a/src/ui/tools/tweak-tool.cpp
+++ b/src/ui/tools/tweak-tool.cpp
@@ -91,7 +91,7 @@ using Inkscape::DocumentUndo;
#define DYNA_MIN_WIDTH 1.0e-6
-#include "tool-factory.h"
+#include "ui/tool-factory.h"
namespace Inkscape {
namespace UI {
diff --git a/src/ui/tools/zoom-tool.cpp b/src/ui/tools/zoom-tool.cpp
index 9f99cfe2e..b3fb78c8f 100644
--- a/src/ui/tools/zoom-tool.cpp
+++ b/src/ui/tools/zoom-tool.cpp
@@ -25,7 +25,7 @@
#include "selection-chemistry.h"
#include "ui/tools/zoom-tool.h"
-#include "tool-factory.h"
+#include "ui/tool-factory.h"
namespace Inkscape {
namespace UI {