Code

Node tool: fix handle retraction with non-cusp nodes
[inkscape.git] / src / ui / tool / manipulator.h
1 /** @file
2  * Manipulator - edits something on-canvas
3  */
4 /* Authors:
5  *   Krzysztof KosiƄski <tweenk.pl@gmail.com>
6  *
7  * Copyright (C) 2009 Authors
8  * Released under GNU GPL, read the file 'COPYING' for more information
9  */
11 #ifndef SEEN_UI_TOOL_MANIPULATOR_H
12 #define SEEN_UI_TOOL_MANIPULATOR_H
14 #include <set>
15 #include <map>
16 #include <sigc++/sigc++.h>
17 #include <glib.h>
18 #include <gdk/gdk.h>
19 #include <boost/shared_ptr.hpp>
21 class SPDesktop;
22 namespace Inkscape {
23 namespace UI {
25 class ManipulatorGroup;
26 class ControlPointSelection;
28 /**
29  * @brief Tool component that processes events and does something in response to them.
30  * Note: this class is probably redundant.
31  */
32 class Manipulator {
33 friend class ManipulatorGroup;
34 public:
35     Manipulator(SPDesktop *d)
36         : _desktop(d)
37     {}
38     virtual ~Manipulator() {}
39     
40     /// Handle input event. Returns true if handled.
41     virtual bool event(GdkEvent *)=0;
42 protected:
43     SPDesktop *const _desktop;
44 };
46 /**
47  * @brief Tool component that edits something on the canvas using selectable control points.
48  * Note: this class is probably redundant.
49  */
50 class PointManipulator : public Manipulator, public sigc::trackable {
51 public:
52     PointManipulator(SPDesktop *d, ControlPointSelection &sel)
53         : Manipulator(d)
54         , _selection(sel)
55     {}
56 protected:
57     ControlPointSelection &_selection;
58 };
60 /** Manipulator that aggregates several manipulators of the same type.
61  * The order of invoking events on the member manipulators is undefined.
62  * To make this class more useful, derive from it and add actions that can be performed
63  * on all manipulators in the set.
64  *
65  * This is not used at the moment and is probably useless. */
66 template <typename T>
67 class MultiManipulator : public PointManipulator {
68 public:
69     //typedef typename T::ItemType ItemType;
70     typedef typename std::pair<void*, boost::shared_ptr<T> > MapPair;
71     typedef typename std::map<void*, boost::shared_ptr<T> > MapType;
73     MultiManipulator(SPDesktop *d, ControlPointSelection &sel)
74         : PointManipulator(d, sel)
75     {}
76     void addItem(void *item) {
77         boost::shared_ptr<T> m(_createManipulator(item));
78         _mmap.insert(MapPair(item, m));
79     }
80     void removeItem(void *item) {
81         _mmap.erase(item);
82     }
83     void clear() {
84         _mmap.clear();
85     }
86     bool contains(void *item) {
87         return _mmap.find(item) != _mmap.end();
88     }
89     bool empty() {
90         return _mmap.empty();
91     }
92     void setItems(GSList const *list) {
93         std::set<void*> to_remove;
94         for (typename MapType::iterator mi = _mmap.begin(); mi != _mmap.end(); ++mi) {
95             to_remove.insert(mi->first);
96         }
97         for (GSList *i = const_cast<GSList*>(list); i; i = i->next) {
98             if (_isItemType(i->data)) {
99                 // erase returns the number of items removed
100                 // if nothing was removed, it means this item did not have a manipulator - add it
101                 if (!to_remove.erase(i->data)) addItem(i->data);
102             }
103         }
104         typedef typename std::set<void*>::iterator RmIter;
105         for (RmIter ri = to_remove.begin(); ri != to_remove.end(); ++ri) {
106             removeItem(*ri);
107         }
108     }
110     /** Invoke a method on all managed manipulators.
111      * Example:
112      * @code m.invokeForAll(&SomeManipulator::someMethod); @endcode
113      */
114     template <typename R>
115     void invokeForAll(R (T::*method)()) {
116         for (typename MapType::iterator i = _mmap.begin(); i != _mmap.end(); ++i) {
117             ((i->second.get())->*method)();
118         }
119     }
120     template <typename R, typename A>
121     void invokeForAll(R (T::*method)(A), A a) {
122         for (typename MapType::iterator i = _mmap.begin(); i != _mmap.end(); ++i) {
123             ((i->second.get())->*method)(a);
124         }
125     }
126     template <typename R, typename A>
127     void invokeForAll(R (T::*method)(A const &), A const &a) {
128         for (typename MapType::iterator i = _mmap.begin(); i != _mmap.end(); ++i) {
129             ((i->second.get())->*method)(a);
130         }
131     }
132     template <typename R, typename A, typename B>
133     void invokeForAll(R (T::*method)(A,B), A a, B b) {
134         for (typename MapType::iterator i = _mmap.begin(); i != _mmap.end(); ++i) {
135             ((i->second.get())->*method)(a, b);
136         }
137     }
138     
139     virtual bool event(GdkEvent *event) {
140         for (typename MapType::iterator i = _mmap.begin(); i != _mmap.end(); ++i) {
141             if ((*i).second->event(event)) return true;
142         }
143         return false;
144     }
145 protected:
146     virtual T *_createManipulator(void *item) = 0;
147     virtual bool _isItemType(void *item) = 0;
148     MapType _mmap;
149 };
151 } // namespace UI
152 } // namespace Inkscape
154 #endif
156 /*
157   Local Variables:
158   mode:c++
159   c-file-style:"stroustrup"
160   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
161   indent-tabs-mode:nil
162   fill-column:99
163   End:
164 */
165 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :