diff --git a/src/ui/tool/node.h b/src/ui/tool/node.h
index d822d854f100971a1eda0d697e527bf54a9d7e17..b5d4d88f2045c424edfa7882ba427386434cd1fa 100644 (file)
--- a/src/ui/tool/node.h
+++ b/src/ui/tool/node.h
#ifndef SEEN_UI_TOOL_NODE_H
#define SEEN_UI_TOOL_NODE_H
+#include <glib.h>
#include <iterator>
#include <iosfwd>
#include <stdexcept>
*/
struct ListNode {
- ListNode *next;
- ListNode *prev;
- NodeList *list;
+ ListNode *ln_next;
+ ListNode *ln_prev;
+ NodeList *ln_list;
};
struct NodeSharedData {
void setDirection(Geom::Point const &from, Geom::Point const &to);
void setDirection(Geom::Point const &dir);
Node *parent() { return _parent; }
+ Handle *other();
static char const *handle_type_to_localized_string(NodeType type);
- sigc::signal<void> signal_update;
protected:
Handle(NodeSharedData const &data, Geom::Point const &initial_pos, Node *parent);
+
+ virtual bool _eventHandler(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; }
private:
- void _grabbedHandler();
- void _draggedHandler(Geom::Point &, GdkEventMotion *);
- void _ungrabbedHandler();
+ 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
SPCanvasItem *_handle_line;
bool _degenerate; // this is used often internally so it makes sense to cache this
+ static Geom::Point _saved_other_pos;
static double _saved_length;
static bool _drag_out;
friend class Node;
bool isEndNode();
Handle *front() { return &_front; }
Handle *back() { return &_back; }
- static NodeType parse_nodetype(char x);
- NodeList *list() { return static_cast<ListNode*>(this)->list; }
+ Handle *handleToward(Node *to);
+ Node *nodeToward(Handle *h);
+ Handle *handleAwayFrom(Node *to);
+ Node *nodeAwayFrom(Handle *h);
+ NodeList &nodeList() { return *(static_cast<ListNode*>(this)->ln_list); }
void sink();
+ static NodeType parse_nodetype(char x);
static char const *node_type_to_localized_string(NodeType type);
// temporarily public
virtual bool _eventHandler(GdkEvent *event);
protected:
+ virtual void dragged(Geom::Point &, GdkEventMotion *);
+ virtual bool grabbed(GdkEventMotion *);
+ virtual bool clicked(GdkEventButton *);
+
virtual void _setState(State state);
virtual Glib::ustring _getTip(unsigned state);
virtual Glib::ustring _getDragTip(GdkEventMotion *event);
virtual bool _hasDragTips() { return true; }
private:
Node(Node const &);
- bool _grabbedHandler(GdkEventMotion *);
- void _draggedHandler(Geom::Point &, GdkEventMotion *);
void _fixNeighbors(Geom::Point const &old_pos, Geom::Point const &new_pos);
void _updateAutoHandles();
void _linearGrow(int dir);
Node *_prev();
Inkscape::SnapSourceType _snapSourceType();
Inkscape::SnapTargetType _snapTargetType();
+ inline PathManipulator &_pm();
static SPCtrlShapeType _node_type_to_shape(NodeType type);
static bool _is_line_segment(Node *first, Node *second);
/// Iterator for editable nodes
/** Use this class for all operations that require some knowledge about the node's
- * neighbors. It works like a bidirectional iterator.
+ * neighbors. It is a bidirectional iterator.
*
* Because paths can be cyclic, node iterators have two different ways to
- * increment and decrement them. Nodes can be iterated over either in the
- * sequence order, which always has a beginning and an end, or in the path order,
- * which can be cyclic (moving to the next node never yields the end iterator).
+ * increment and decrement them. When using ++/--, the end iterator will eventually
+ * be returned. Whent using advance()/retreat(), the end iterator will only be returned
+ * when the path is open. If it's closed, calling advance() will cycle indefinitely.
+ * This is particularly useful for cases where the adjacency of nodes is more important
+ * than their sequence order.
*
* When @a i is a node iterator, then:
* - <code>++i</code> moves the iterator to the next node in sequence order;
* - <code>--i</code> moves the iterator to the previous node in sequence order;
- * - <code>i.next()</code> returns the next node with wrap-around if the path is cyclic;
- * - <code>i.prev()</code> returns the previous node with wrap-around if the path is cyclic.
+ * - <code>i.next()</code> returns the next node with wrap-around;
+ * - <code>i.prev()</code> returns the previous node with wrap-around;
+ * - <code>i.advance()</code> moves the iterator to the next node with wrap-around;
+ * - <code>i.retreat()</code> moves the iterator to the previous node with wrap-around.
*
* next() and prev() do not change their iterator. They can return the end iterator
* if the path is open.
*
- * Unlike most other iterators, you can check whether a node iterator is invalid
- * (is an end iterator) without having access to the iterator's container.
+ * Unlike most other iterators, you can check whether you've reached the end of the list
+ * without having access to the iterator's container.
* Simply use <code>if (i) { ...</code>
* */
template <typename N>
// default copy, default assign
self &operator++() {
- _node = _node->next;
+ _node = _node->ln_next;
return *this;
}
self &operator--() {
- _node = _node->prev;
+ _node = _node->ln_prev;
return *this;
}
bool operator==(self const &other) const { return _node == other._node; }
/// @see get_pointer()
N *ptr() const { return static_cast<N*>(_node); }
- self next() const;
- self prev() const;
+ self next() const {
+ self r(*this);
+ r.advance();
+ return r;
+ }
+ self prev() const {
+ self r(*this);
+ r.retreat();
+ return r;
+ }
+ self &advance();
+ self &retreat();
private:
NodeIterator(ListNode const *n)
: _node(const_cast<ListNode*>(n))
{}
ListNode *_node;
friend class NodeList;
- friend class std::tr1::hash<self>;
};
class NodeList : ListNode, boost::noncopyable, public boost::enable_shared_from_this<NodeList> {
typedef Node value_type;
typedef NodeIterator<value_type> iterator;
typedef NodeIterator<value_type const> const_iterator;
- typedef std::reverse_iterator<iterator> reverse_iterator;
- typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
// TODO Lame. Make this private and make SubpathList a factory
NodeList(SubpathList &_list);
~NodeList();
// iterators
- iterator begin() { return iterator(next); }
+ iterator begin() { return iterator(ln_next); }
iterator end() { return iterator(this); }
- const_iterator begin() const { return const_iterator(next); }
+ const_iterator begin() const { return const_iterator(ln_next); }
const_iterator end() const { return const_iterator(this); }
- reverse_iterator rbegin() { return reverse_iterator(end()); }
- reverse_iterator rend() { return reverse_iterator(begin()); }
- const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); }
- const_reverse_iterator rend() const { return const_reverse_iterator(begin()); }
// size
bool empty();
}
// member access - undefined results when the list is empty
- Node &front() { return *static_cast<Node*>(next); }
- Node &back() { return *static_cast<Node*>(prev); }
+ Node &front() { return *static_cast<Node*>(ln_next); }
+ Node &back() { return *static_cast<Node*>(ln_prev); }
// HACK remove this subpath from its path. This will be removed later.
void kill();
+ SubpathList &subpathList() { return _list; }
static iterator get_iterator(Node *n) { return iterator(n); }
static const_iterator get_iterator(Node const *n) { return const_iterator(n); }
typedef std::list< boost::shared_ptr<NodeList> > list_type;
SubpathList(PathManipulator &pm) : _path_manipulator(pm) {}
+ PathManipulator &pm() { return _path_manipulator; }
- sigc::signal<void, Node *> signal_insert_node;
- sigc::signal<void, Node *> signal_remove_node;
private:
list_type _nodelists;
PathManipulator &_path_manipulator;
inline double Handle::length() {
return relativePos().length();
}
+inline PathManipulator &Handle::_pm() {
+ return _parent->_pm();
+}
+inline PathManipulator &Node::_pm() {
+ return nodeList().subpathList().pm();
+}
// definitions for node iterator
template <typename N>
NodeIterator<N>::operator bool() const {
- return _node && static_cast<ListNode*>(_node->list) != _node;
+ return _node && static_cast<ListNode*>(_node->ln_list) != _node;
}
template <typename N>
-NodeIterator<N> NodeIterator<N>::next() const {
- NodeIterator<N> ret(*this);
- ++ret;
- if (!ret && _node->list->closed()) ++ret;
- return ret;
+NodeIterator<N> &NodeIterator<N>::advance() {
+ ++(*this);
+ if (G_UNLIKELY(!*this) && _node->ln_list->closed()) ++(*this);
+ return *this;
}
template <typename N>
-NodeIterator<N> NodeIterator<N>::prev() const {
- NodeIterator<N> ret(*this);
- --ret;
- if (!ret && _node->list->closed()) --ret;
- return ret;
+NodeIterator<N> &NodeIterator<N>::retreat() {
+ --(*this);
+ if (G_UNLIKELY(!*this) && _node->ln_list->closed()) --(*this);
+ return *this;
}
} // namespace UI
} // namespace Inkscape
-namespace std {
-namespace tr1 {
-template <typename N>
-struct hash< Inkscape::UI::NodeIterator<N> > : public unary_function<Inkscape::UI::NodeIterator<N>, size_t> {
- size_t operator()(Inkscape::UI::NodeIterator<N> const &ni) const {
- return reinterpret_cast<size_t>(ni._node);
- }
-};
-}
-}
-
#endif
/*
@@ -395,4 +409,4 @@ struct hash< Inkscape::UI::NodeIterator<N> > : public unary_function<Inkscape::U
fill-column:99
End:
*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :