summaryrefslogtreecommitdiffstats
path: root/src/ui/tool/node.h
diff options
context:
space:
mode:
authorJon A. Cruz <jon@joncruz.org>2012-05-17 02:33:16 +0000
committerJon A. Cruz <jon@joncruz.org>2012-05-17 02:33:16 +0000
commite9412c187da3f62f01bc5acb6190af2d5a395ccb (patch)
tree4d6d98646a87c82dc1cc631d88875ca0d63c3fcf /src/ui/tool/node.h
parentFixed warning with printf format. Also corrected inproper type that resulted ... (diff)
downloadinkscape-e9412c187da3f62f01bc5acb6190af2d5a395ccb.tar.gz
inkscape-e9412c187da3f62f01bc5acb6190af2d5a395ccb.zip
Corrected protected type access (comments were incorrect).
Unified color set types; fixed uninitialized member; Switched colorsets to references; Added const correctness. (bzr r11373)
Diffstat (limited to 'src/ui/tool/node.h')
-rw-r--r--src/ui/tool/node.h158
1 files changed, 131 insertions, 27 deletions
diff --git a/src/ui/tool/node.h b/src/ui/tool/node.h
index f2e31e018..daab19cae 100644
--- a/src/ui/tool/node.h
+++ b/src/ui/tool/node.h
@@ -3,6 +3,7 @@
*/
/* Authors:
* Krzysztof KosiƄski <tweenk.pl@gmail.com>
+ * Jon A. Cruz <jon@joncruz.org>
*
* Copyright (C) 2009 Authors
* Released under GNU GPL, read the file 'COPYING' for more information
@@ -80,10 +81,11 @@ struct NodeSharedData {
class Handle : public ControlPoint {
public:
+
virtual ~Handle();
- inline Geom::Point relativePos();
- inline double length();
- bool isDegenerate() { return _degenerate; } // True if the handle is retracted, i.e. has zero length.
+ inline Geom::Point relativePos() const;
+ inline double length() const;
+ bool isDegenerate() const { return _degenerate; } // True if the handle is retracted, i.e. has zero length.
virtual void setVisible(bool);
virtual void move(Geom::Point const &p);
@@ -96,80 +98,160 @@ public:
void setDirection(Geom::Point const &dir);
Node *parent() { return _parent; }
Handle *other();
+ Handle const *other() const;
static char const *handle_type_to_localized_string(NodeType type);
+
protected:
+
Handle(NodeSharedData const &data, Geom::Point const &initial_pos, Node *parent);
virtual bool _eventHandler(SPEventContext *event_context, GdkEvent *event);
- virtual void dragged(Geom::Point &, GdkEventMotion *);
- virtual bool grabbed(GdkEventMotion *);
- virtual void ungrabbed(GdkEventButton *);
- virtual bool clicked(GdkEventButton *);
-
- virtual Glib::ustring _getTip(unsigned state);
- virtual Glib::ustring _getDragTip(GdkEventMotion *event);
- virtual bool _hasDragTips() { return true; }
+ virtual void dragged(Geom::Point &new_pos, GdkEventMotion *event);
+ virtual bool grabbed(GdkEventMotion *event);
+ virtual void ungrabbed(GdkEventButton *event);
+ virtual bool clicked(GdkEventButton *event);
+
+ virtual Glib::ustring _getTip(unsigned state) const;
+ virtual Glib::ustring _getDragTip(GdkEventMotion *event) const;
+ virtual bool _hasDragTips() const { return true; }
+
private:
+
inline PathManipulator &_pm();
Node *_parent; // the handle's lifetime does not extend beyond that of the parent node,
// so a naked pointer is OK and allows setting it during Node's construction
SPCtrlLine *_handle_line;
bool _degenerate; // True if the handle is retracted, i.e. has zero length. This is used often internally so it makes sense to cache this
+ /**
+ * Control point of a cubic Bezier curve in a path.
+ *
+ * Handle keeps the node type invariant only for the opposite handle of the same node.
+ * Keeping the invariant on node moves is left to the %Node class.
+ */
static Geom::Point _saved_other_pos;
+
static double _saved_length;
static bool _drag_out;
+ static ColorSet _handle_colors;
friend class Node;
};
class Node : ListNode, public SelectableControlPoint {
public:
+
+ /**
+ * Curve endpoint in an editable path.
+ *
+ * The method move() keeps node type invariants during translations.
+ */
Node(NodeSharedData const &data, Geom::Point const &pos);
+
virtual void move(Geom::Point const &p);
virtual void transform(Geom::Affine const &m);
- virtual Geom::Rect bounds();
-
- NodeType type() { return _type; }
+ virtual Geom::Rect bounds() const;
+
+ NodeType type() const { return _type; }
+
+ /**
+ * Sets the node type and optionally restores the invariants associated with the given type.
+ * @param type The type to set.
+ * @param update_handles Whether to restore invariants associated with the given type.
+ * Passing false is useful e.g. wen initially creating the path,
+ * and when making cusp nodes during some node algorithms.
+ * Pass true when used in response to an UI node type button.
+ */
void setType(NodeType type, bool update_handles = true);
+
void showHandles(bool v);
+
+
+ /**
+ * Pick the best type for this node, based on the position of its handles.
+ * This is what assigns types to nodes created using the pen tool.
+ */
void pickBestType(); // automatically determine the type from handle positions
- bool isDegenerate() { return _front.isDegenerate() && _back.isDegenerate(); }
- bool isEndNode();
+
+ bool isDegenerate() const { return _front.isDegenerate() && _back.isDegenerate(); }
+ bool isEndNode() const;
Handle *front() { return &_front; }
Handle *back() { return &_back; }
+
+ /**
+ * Gets the handle that faces the given adjacent node.
+ * Will abort with error if the given node is not adjacent.
+ */
Handle *handleToward(Node *to);
+
+ /**
+ * Gets the node in the direction of the given handle.
+ * Will abort with error if the handle doesn't belong to this node.
+ */
Node *nodeToward(Handle *h);
+
+ /**
+ * Gets the handle that goes in the direction opposite to the given adjacent node.
+ * Will abort with error if the given node is not adjacent.
+ */
Handle *handleAwayFrom(Node *to);
+
+ /**
+ * Gets the node in the direction opposite to the given handle.
+ * Will abort with error if the handle doesn't belong to this node.
+ */
Node *nodeAwayFrom(Handle *h);
+
NodeList &nodeList() { return *(static_cast<ListNode*>(this)->ln_list); }
+
+ /**
+ * Move the node to the bottom of its canvas group.
+ * Useful for node break, to ensure that the selected nodes are above the unselected ones.
+ */
void sink();
static NodeType parse_nodetype(char x);
static char const *node_type_to_localized_string(NodeType type);
+
// temporarily public
+ /** Customized event handler to catch scroll events needed for selection grow/shrink. */
virtual bool _eventHandler(SPEventContext *event_context, GdkEvent *event);
+
Inkscape::SnapCandidatePoint snapCandidatePoint();
+
protected:
- virtual void dragged(Geom::Point &, GdkEventMotion *);
- virtual bool grabbed(GdkEventMotion *);
- virtual bool clicked(GdkEventButton *);
+
+ virtual void dragged(Geom::Point &new_pos, GdkEventMotion *event);
+ virtual bool grabbed(GdkEventMotion *event);
+ virtual bool clicked(GdkEventButton *event);
virtual void _setState(State state);
- virtual Glib::ustring _getTip(unsigned state);
- virtual Glib::ustring _getDragTip(GdkEventMotion *event);
- virtual bool _hasDragTips() { return true; }
+ virtual Glib::ustring _getTip(unsigned state) const;
+ virtual Glib::ustring _getDragTip(GdkEventMotion *event) const;
+ virtual bool _hasDragTips() const { return true; }
+
private:
+
Node(Node const &);
void _fixNeighbors(Geom::Point const &old_pos, Geom::Point const &new_pos);
void _updateAutoHandles();
+
+ /**
+ * Select or deselect a node in this node's subpath based on its path distance from this node.
+ * @param dir If negative, shrink selection by one node; if positive, grow by one node.
+ */
void _linearGrow(int dir);
+
Node *_next();
+ Node const *_next() const;
Node *_prev();
- Inkscape::SnapSourceType _snapSourceType();
- Inkscape::SnapTargetType _snapTargetType();
+ Node const *_prev() const;
+ Inkscape::SnapSourceType _snapSourceType() const;
+ Inkscape::SnapTargetType _snapTargetType() const;
inline PathManipulator &_pm();
static SPCtrlShapeType _node_type_to_shape(NodeType type);
+
+ /** Determine whether two nodes are joined by a linear segment. */
static bool _is_line_segment(Node *first, Node *second);
// Handles are always present, but are not visible if they coincide with the node
@@ -179,6 +261,8 @@ private:
Handle _back; ///< Node handle in the forward direction of the path
NodeType _type; ///< Type of node - cusp, smooth...
bool _handles_shown;
+ static ColorSet node_colors;
+
friend class Handle;
friend class NodeList;
friend class NodeIterator<Node>;
@@ -271,7 +355,15 @@ public:
typedef NodeIterator<value_type const> const_iterator;
// TODO Lame. Make this private and make SubpathList a factory
+ /**
+ * An editable list of nodes representing a subpath.
+ *
+ * It can optionally be cyclic to represent a closed path.
+ * The list has iterators that act like plain node iterators, but can also be used
+ * to obtain shared pointers to nodes.
+ */
NodeList(SubpathList &_list);
+
~NodeList();
// iterators
@@ -286,7 +378,13 @@ public:
// extra node-specific methods
bool closed();
+
+ /**
+ * A subpath is degenerate if it has no segments - either one node in an open path
+ * or no nodes in a closed path.
+ */
bool degenerate();
+
void setClosed(bool c) { _closed = c; }
iterator before(double t, double *fracpart = NULL);
const_iterator before(double t, double *fracpart = NULL) const {
@@ -294,7 +392,10 @@ public:
}
// list operations
+
+ /** insert a node before pos. */
iterator insert(iterator pos, Node *x);
+
template <class InputIterator>
void insert(iterator pos, InputIterator first, InputIterator last) {
for (; first != last; ++first) insert(pos, *first);
@@ -342,7 +443,10 @@ private:
friend class NodeIterator<Node const>;
};
-/** List of node lists. Represents an editable path. */
+/**
+ * List of node lists. Represents an editable path.
+ * Editable path composed of one or more subpaths.
+ */
class SubpathList : public std::list< boost::shared_ptr<NodeList> > {
public:
typedef std::list< boost::shared_ptr<NodeList> > list_type;
@@ -361,13 +465,13 @@ private:
// define inline Handle funcs after definition of Node
-inline Geom::Point Handle::relativePos() {
+inline Geom::Point Handle::relativePos() const {
return position() - _parent->position();
}
inline void Handle::setRelativePos(Geom::Point const &p) {
setPosition(_parent->position() + p);
}
-inline double Handle::length() {
+inline double Handle::length() const {
return relativePos().length();
}
inline PathManipulator &Handle::_pm() {