799dad0d3cb6e754390fc0129e2d4fb80c0d6e7d
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() {}
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 }
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:encoding=utf-8:textwidth=99 :