diff options
Diffstat (limited to 'src/ui/tools/pen-tool.h')
-rw-r--r-- | src/ui/tools/pen-tool.h | 175 |
1 files changed, 175 insertions, 0 deletions
diff --git a/src/ui/tools/pen-tool.h b/src/ui/tools/pen-tool.h new file mode 100644 index 0000000..a7053e8 --- /dev/null +++ b/src/ui/tools/pen-tool.h @@ -0,0 +1,175 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/** \file + * PenTool: a context for pen tool events. + *//* + * Authors: see git history + * + * Copyright (C) 2018 Authors + * Released under GNU GPL v2+, read the file 'COPYING' for more information. + */ +#ifndef SEEN_PEN_CONTEXT_H +#define SEEN_PEN_CONTEXT_H + +#include <array> +#include <sigc++/sigc++.h> + +#include "display/control/canvas-item-enums.h" +#include "live_effects/effect.h" +#include "ui/tools/freehand-base.h" +#include "util/action-accel.h" + +#define SP_PEN_CONTEXT(obj) (dynamic_cast<Inkscape::UI::Tools::PenTool*>((Inkscape::UI::Tools::ToolBase*)obj)) +#define SP_IS_PEN_CONTEXT(obj) (dynamic_cast<const Inkscape::UI::Tools::PenTool*>((const Inkscape::UI::Tools::ToolBase*)obj) != NULL) + +namespace Inkscape { + +class CanvasItemCtrl; +class CanvasItemCurve; + +namespace UI { +namespace Tools { + +/** + * PenTool: a context for pen tool events. + */ +class PenTool : public FreehandBase { +public: + PenTool(SPDesktop *desktop, + std::string prefs_path = "/tools/freehand/pen", + const std::string& cursor_filename = "pen.svg"); + ~PenTool() override; + + enum Mode { + MODE_CLICK, + MODE_DRAG + }; + + enum State { + POINT, + CONTROL, + CLOSE, + STOP, + DEAD + }; + + Geom::Point p[5]; + Geom::Point previous; + /** \invar npoints in {0, 2, 5}. */ + // npoints somehow determines the type of the node (what does it mean, exactly? the number of Bezier handles?) + gint npoints = 0; + + Mode mode = MODE_CLICK; + State state = POINT; + bool polylines_only = false; + bool polylines_paraxial = false; + Geom::Point paraxial_angle; + + bool spiro = false; // Spiro mode active? + bool bspline = false; // BSpline mode active? + + unsigned int expecting_clicks_for_LPE = 0; // if positive, finish the path after this many clicks + Inkscape::LivePathEffect::Effect *waiting_LPE = nullptr; // if NULL, waiting_LPE_type in SPDrawContext is taken into account + SPLPEItem *waiting_item = nullptr; + + CanvasItemPtr<CanvasItemCtrl> ctrl[4]; // Origin, Start, Center, End point of path. + static constexpr std::array<CanvasItemCtrlType, 4> ctrl_types = { + CANVAS_ITEM_CTRL_TYPE_NODE_SMOOTH, CANVAS_ITEM_CTRL_TYPE_ROTATE, + CANVAS_ITEM_CTRL_TYPE_ROTATE, CANVAS_ITEM_CTRL_TYPE_NODE_SMOOTH}; + + CanvasItemPtr<CanvasItemCurve> cl0; + CanvasItemPtr<CanvasItemCurve> cl1; + + bool events_disabled = false; + + void nextParaxialDirection(Geom::Point const &pt, Geom::Point const &origin, guint state); + void setPolylineMode(); + bool hasWaitingLPE(); + void waitForLPEMouseClicks(Inkscape::LivePathEffect::EffectType effect_type, unsigned int num_clicks, bool use_polylines = true); + +protected: + void set(const Inkscape::Preferences::Entry& val) override; + bool root_handler(GdkEvent* event) override; + bool item_handler(SPItem* item, GdkEvent* event) override; + +private: + bool _handleButtonPress(GdkEventButton const &bevent); + bool _handleMotionNotify(GdkEventMotion const &mevent); + bool _handleButtonRelease(GdkEventButton const &revent); + bool _handle2ButtonPress(GdkEventButton const &bevent); + bool _handleKeyPress(GdkEvent *event); + //this function changes the colors red, green and blue making them transparent or not depending on if the function uses spiro + void _bsplineSpiroColor(); + //creates a node in bspline or spiro modes + void _bsplineSpiro(bool shift); + //creates a node in bspline or spiro modes + void _bsplineSpiroOn(); + //creates a CUSP node + void _bsplineSpiroOff(); + //continues the existing curve in bspline or spiro mode + void _bsplineSpiroStartAnchor(bool shift); + //continues the existing curve with the union node in bspline or spiro modes + void _bsplineSpiroStartAnchorOn(); + //continues an existing curve with the union node in CUSP mode + void _bsplineSpiroStartAnchorOff(); + //modifies the "red_curve" when it detects movement + void _bsplineSpiroMotion(guint const state); + //closes the curve with the last node in bspline or spiro mode + void _bsplineSpiroEndAnchorOn(); + //closes the curve with the last node in CUSP mode + void _bsplineSpiroEndAnchorOff(); + //apply the effect + void _bsplineSpiroBuild(); + + void _setInitialPoint(Geom::Point const p); + void _setSubsequentPoint(Geom::Point const p, bool statusbar, guint status = 0); + void _setCtrl(Geom::Point const p, guint state); + void _finishSegment(Geom::Point p, guint state); + bool _undoLastPoint(bool user_undo = false); + bool _redoLastPoint(); + + void _finish(gboolean closed); + + void _resetColors(); + + void _disableEvents(); + void _enableEvents(); + + void _setToNearestHorizVert(Geom::Point &pt, guint const state) const; + + void _setAngleDistanceStatusMessage(Geom::Point const p, int pc_point_to_compare, gchar const *message); + + void _lastpointToLine(); + void _lastpointToCurve(); + void _lastpointMoveScreen(gdouble x, gdouble y); + void _lastpointMove(gdouble x, gdouble y); + void _redrawAll(); + + void _endpointSnapHandle(Geom::Point &p, guint const state); + void _endpointSnap(Geom::Point &p, guint const state); + + void _cancel(); + + sigc::connection _desktop_destroy; + Util::ActionAccel _undo, _redo; ///< Keep track of Undo and Redo keybindings + // NOTE: undoing work in progress always deletes the last added point, + // so there's no need for an undo stack. + std::vector<Geom::PathVector> _redo_stack; ///< History of undone events + bool _did_redo = false; +}; + +} +} +} + +#endif /* !SEEN_PEN_CONTEXT_H */ + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : |