Implements PXEGeek's http://wiki.synfig.com/Wish_list entry: "Optionally display...
[synfig.git] / synfig-studio / trunk / src / gtkmm / duckmatic.h
1 /* === S Y N F I G ========================================================= */
2 /*!     \file duckmatic.h
3 **      \brief Template Header
4 **
5 **      $Id$
6 **
7 **      \legal
8 **      Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
9 **
10 **      This package is free software; you can redistribute it and/or
11 **      modify it under the terms of the GNU General Public License as
12 **      published by the Free Software Foundation; either version 2 of
13 **      the License, or (at your option) any later version.
14 **
15 **      This package is distributed in the hope that it will be useful,
16 **      but WITHOUT ANY WARRANTY; without even the implied warranty of
17 **      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 **      General Public License for more details.
19 **      \endlegal
20 */
21 /* ========================================================================= */
22
23 /* === S T A R T =========================================================== */
24
25 #ifndef __SYNFIG_STUDIO_DUCKMATIC_H
26 #define __SYNFIG_STUDIO_DUCKMATIC_H
27
28 /* === H E A D E R S ======================================================= */
29
30 #include <list>
31 #include <map>
32 #include <set>
33
34 #include <ETL/smart_ptr>
35 #include <ETL/handle>
36
37 #include <synfig/vector.h>
38 #include <synfig/string.h>
39 #include <synfig/real.h>
40 #include <sigc++/signal.h>
41 #include <sigc++/object.h>
42 #include <synfig/time.h>
43 #include <synfig/color.h>
44 #include <ETL/smart_ptr>
45
46 #include "duck.h"
47 #include <synfig/color.h>
48 #include <synfig/guidset.h>
49
50 /* === M A C R O S ========================================================= */
51
52 #define HASH_MAP_H <ext/hash_map>
53
54 #ifdef HASH_MAP_H
55 #include HASH_MAP_H
56 #ifndef __STRING_HASH__
57 #define __STRING_HASH__
58 class StringHash
59 {
60         __gnu_cxx::hash<const char*> hasher_;
61 public:
62         size_t operator()(const synfig::String& x)const
63         {
64                 return hasher_(x.c_str());
65         }
66 };
67 #endif
68 #else
69 #include <map>
70 #endif
71
72 /* === T Y P E D E F S ===================================================== */
73
74 /* === C L A S S E S & S T R U C T S ======================================= */
75
76 namespace synfigapp { class ValueDesc; }
77 namespace synfig { class ParamDesc; }
78
79 namespace studio
80 {
81
82 class CanvasView;
83 class Duckmatic;
84
85 class DuckDrag_Base : public etl::shared_object
86 {
87 public:
88         virtual void begin_duck_drag(Duckmatic* duckmatic, const synfig::Vector& begin)=0;
89         virtual bool end_duck_drag(Duckmatic* duckmatic)=0;
90         virtual void duck_drag(Duckmatic* duckmatic, const synfig::Vector& vector)=0;
91 };
92
93 class DuckDrag_Translate : public DuckDrag_Base
94 {
95         synfig::Vector last_translate_;
96         synfig::Vector drag_offset_;
97         synfig::Vector snap;
98         std::vector<synfig::Vector> positions;
99
100 public:
101         void begin_duck_drag(Duckmatic* duckmatic, const synfig::Vector& begin);
102         bool end_duck_drag(Duckmatic* duckmatic);
103         void duck_drag(Duckmatic* duckmatic, const synfig::Vector& vector);
104 };
105
106 /*! \class Duckmatic
107 **
108 **      This class helps organize any of the devices displayed in
109 **      the work area that the user may want to interact with.
110 **      This includes ducks, beziers, and strokes
111 **
112 **      \note At some point I'll probably rename this class to "DuckOMatic".
113 */
114 class Duckmatic
115 {
116         friend class DuckDrag_Base;
117         friend class DuckDrag_Translate;
118
119         /*
120  -- ** -- P U B L I C   T Y P E S ---------------------------------------------
121         */
122
123 public:
124
125 #ifdef HASH_MAP_H
126 typedef __gnu_cxx::hash_map<synfig::GUID,etl::smart_ptr<synfig::Point>,synfig::GUIDHash> DuckDataMap;
127 #else
128 typedef std::map<synfig::GUID,etl::smart_ptr<synfig::Point> > DuckDataMap;
129 #endif
130
131         typedef studio::DuckMap DuckMap;
132
133         typedef studio::Duck Duck;
134
135         struct Stroke;
136
137         struct Bezier;
138
139         class Push;
140
141         friend class Push;
142
143         typedef Duck::Type Type;
144
145         typedef std::list<float> GuideList;
146
147         /*
148  -- ** -- P R I V A T E   D A T A ---------------------------------------------
149         */
150
151 private:
152
153         Type type_mask;
154
155         DuckMap duck_map;
156
157         DuckDataMap duck_data_share_map;
158
159         std::list<etl::handle<Stroke> > stroke_list_;
160
161         std::list<etl::handle<Stroke> > persistant_stroke_list_;
162
163         synfig::GUIDSet selected_ducks;
164
165         synfig::GUID last_duck_guid;
166
167         std::list<etl::handle<Bezier> > bezier_list_;
168
169         //! I cannot recall what this is for
170         //synfig::Vector snap;
171
172         etl::handle<DuckDrag_Base> duck_dragger_;
173
174         sigc::signal<void> signal_duck_selection_changed_;
175
176         sigc::signal<void> signal_strokes_changed_;
177
178         sigc::signal<void> signal_grid_changed_;
179
180         mutable sigc::signal<void> signal_sketch_saved_;
181
182         GuideList guide_list_x_;
183         GuideList guide_list_y_;
184
185         mutable synfig::String sketch_filename_;
186
187         /*
188  -- ** -- P R O T E C T E D   D A T A -----------------------------------------
189         */
190
191 protected:
192
193         etl::handle<Bezier> selected_bezier;
194
195         synfig::Time cur_time;
196
197         //! This flag is set if operations should snap to the grid
198         /*! \todo perhaps there should be two of these flags, one for each axis?
199         **      \see show_grid, grid_size */
200         bool grid_snap;
201
202         bool guide_snap;
203
204         //! This vector describes the grid size.
205         /*! \see grid_snap, show_grid */
206         synfig::Vector grid_size;
207
208         bool show_persistant_strokes;
209
210         bool axis_lock;
211
212         /*
213  -- ** -- P R I V A T E   M E T H O D S ---------------------------------------
214         */
215
216 private:
217
218         synfig::Vector last_translate_;
219         synfig::Vector drag_offset_;
220
221         //etl::handle<Duck> selected_duck;
222
223
224         /*
225  -- ** -- P U B L I C   M E T H O D S -----------------------------------------
226         */
227
228 public:
229
230         Duckmatic();
231         virtual ~Duckmatic();
232
233         sigc::signal<void>& signal_duck_selection_changed() { return signal_duck_selection_changed_; }
234         sigc::signal<void>& signal_strokes_changed() { return signal_strokes_changed_; }
235         sigc::signal<void>& signal_grid_changed() { return signal_grid_changed_; }
236         sigc::signal<void>& signal_sketch_saved() { return signal_sketch_saved_; }
237
238         GuideList& get_guide_list_x() { return guide_list_x_; }
239         GuideList& get_guide_list_y() { return guide_list_y_; }
240         const GuideList& get_guide_list_x()const { return guide_list_x_; }
241         const GuideList& get_guide_list_y()const { return guide_list_y_; }
242
243         void set_guide_snap(bool x=true);
244         bool get_guide_snap()const { return guide_snap; }
245         void toggle_guide_snap() { set_guide_snap(!get_guide_snap()); }
246
247         //! Sets the state of the grid snap flag
248         void set_grid_snap(bool x=true);
249
250         //! Gets the state of the grid snap flag
251         bool get_grid_snap()const { return grid_snap; }
252
253         void enable_grid_snap() { set_grid_snap(true); }
254
255         void disable_grid_snap() { set_grid_snap(false); }
256
257         void toggle_grid_snap() { set_grid_snap(!grid_snap); }
258
259         synfig::Point snap_point_to_grid(const synfig::Point& x, float radius=0.1)const;
260
261         bool get_show_persistant_strokes()const { return show_persistant_strokes; }
262         void set_show_persistant_strokes(bool x);
263
264         //! Sets the size of the grid
265         void set_grid_size(const synfig::Vector &s);
266
267         //! Returns the size of the grid
268         const synfig::Vector &get_grid_size()const { return grid_size; }
269
270
271         const synfig::Time &get_time()const { return cur_time; }
272
273         bool get_axis_lock()const { return axis_lock; }
274         void set_axis_lock(bool x) { axis_lock=x; }
275
276         void set_time(synfig::Time x) { cur_time=x; }
277
278         bool is_duck_group_selectable(const etl::handle<Duck>& x)const;
279
280         //const DuckMap& duck_map()const { return duck_map; }
281         DuckList get_duck_list()const;
282
283         const std::list<etl::handle<Bezier> >& bezier_list()const { return bezier_list_; }
284
285         const std::list<etl::handle<Stroke> >& stroke_list()const { return stroke_list_; }
286
287         const std::list<etl::handle<Stroke> >& persistant_stroke_list()const { return persistant_stroke_list_; }
288
289         std::list<etl::handle<Stroke> >& persistant_stroke_list() { return persistant_stroke_list_; }
290
291         //! \todo We should modify this to support multiple selections
292         etl::handle<Duck> get_selected_duck()const;
293
294         DuckList get_selected_ducks()const;
295
296         //! Returns \a true if the given duck is currently selected
297         bool duck_is_selected(const etl::handle<Duck> &duck)const;
298
299
300         void refresh_selected_ducks();
301
302         void clear_selected_ducks();
303
304         int count_selected_ducks()const;
305
306         void toggle_select_duck(const etl::handle<Duck> &duck);
307
308         void select_duck(const etl::handle<Duck> &duck);
309
310         void select_ducks_in_box(const synfig::Vector& tl,const synfig::Vector& br);
311
312         void unselect_duck(const etl::handle<Duck> &duck);
313
314         void start_duck_drag(const synfig::Vector& offset);
315         void translate_selected_ducks(const synfig::Vector& vector);
316         bool end_duck_drag();
317
318         void signal_edited_selected_ducks();
319
320         void signal_user_click_selected_ducks(int button);
321
322
323         etl::handle<Duck> find_similar_duck(etl::handle<Duck> duck);
324         etl::handle<Duck> add_similar_duck(etl::handle<Duck> duck);
325
326         void add_stroke(etl::smart_ptr<std::list<synfig::Point> > stroke_point_list, const synfig::Color& color=synfig::Color(0,0,0));
327
328         void add_persistant_stroke(etl::smart_ptr<std::list<synfig::Point> > stroke_point_list, const synfig::Color& color=synfig::Color(0,0,0));
329
330         void clear_persistant_strokes();
331
332         void add_duck(const etl::handle<Duck> &duck);
333
334         void add_bezier(const etl::handle<Bezier> &bezier);
335
336         void erase_duck(const etl::handle<Duck> &duck);
337
338         void erase_bezier(const etl::handle<Bezier> &bezier);
339
340         //! Returns the last duck added
341         etl::handle<Duck> last_duck()const;
342
343         etl::handle<Bezier> last_bezier()const;
344
345         //! \note parameter is in canvas coordinates
346         /*!     A radius of "zero" will have an unlimited radius */
347         etl::handle<Duck> find_duck(synfig::Point pos, synfig::Real radius=0, Duck::Type type=Duck::TYPE_DEFAULT);
348
349         GuideList::iterator find_guide_x(synfig::Point pos, float radius=0.1);
350         GuideList::iterator find_guide_y(synfig::Point pos, float radius=0.1);
351         GuideList::const_iterator find_guide_x(synfig::Point pos, float radius=0.1)const { return const_cast<Duckmatic*>(this)->find_guide_x(pos,radius); }
352         GuideList::const_iterator find_guide_y(synfig::Point pos, float radius=0.1)const { return const_cast<Duckmatic*>(this)->find_guide_y(pos,radius); }
353
354         //! \note parameter is in canvas coordinates
355         /*!     A radius of "zero" will have an unlimited radius */
356         //etl::handle<Bezier> find_bezier(synfig::Point pos, synfig::Real radius=0);
357
358         //! \note parameter is in canvas coordinates
359         /*!     A radius of "zero" will have an unlimited radius */
360         etl::handle<Bezier> find_bezier(synfig::Point pos, synfig::Real radius=0, float* location=0);
361
362         etl::handle<Bezier> find_bezier(synfig::Point pos, synfig::Real scale, synfig::Real radius, float* location=0);
363
364         bool add_to_ducks(const synfigapp::ValueDesc& value_desc,etl::handle<CanvasView> canvas_view, const synfig::TransformStack& transform_stack_, synfig::ParamDesc *param_desc=0, int multiple=0);
365
366         //! \writeme
367         void set_type_mask(Type x) { type_mask=x; }
368
369         //! \writeme
370         Type get_type_mask()const { return type_mask; }
371
372         void select_all_ducks();
373
374         void clear_ducks();
375
376         bool save_sketch(const synfig::String& filename)const;
377         bool load_sketch(const synfig::String& filename);
378         const synfig::String& get_sketch_filename()const { return sketch_filename_; }
379
380         void set_duck_dragger(etl::handle<DuckDrag_Base> x) { duck_dragger_=x; }
381         etl::handle<DuckDrag_Base> get_duck_dragger()const { return duck_dragger_; }
382         void clear_duck_dragger() { duck_dragger_=new DuckDrag_Translate(); }
383 }; // END of class Duckmatic
384
385
386 /*! \class Duckmatic::Push
387 **      \writeme */
388 class Duckmatic::Push
389 {
390         Duckmatic *duckmatic_;
391         DuckMap duck_map;
392         std::list<etl::handle<Bezier> > bezier_list_;
393         std::list<etl::handle<Stroke> > stroke_list_;
394         DuckDataMap duck_data_share_map;
395         etl::handle<DuckDrag_Base> duck_dragger_;
396
397         bool needs_restore;
398
399 public:
400         Push(Duckmatic *duckmatic_);
401         ~Push();
402         void restore();
403 }; // END of class Duckmatic::Push
404
405 /*! \struct Duckmatic::Bezier
406 **      \writeme */
407 struct Duckmatic::Bezier : public etl::shared_object
408 {
409 private:
410         sigc::signal<void,float> signal_user_click_[5];
411 public:
412
413         etl::handle<Duck> p1,p2,c1,c2;
414         bool is_valid()const { return p1 && p2 && c1 && c2; }
415
416         sigc::signal<void,float> &signal_user_click(int i=0) { assert(i>=0); assert(i<5); return signal_user_click_[i]; }
417 }; // END of struct Duckmatic::Bezier
418
419 /*! \struct Duckmatic::Stroke
420 **      \writeme */
421 struct Duckmatic::Stroke : public etl::shared_object
422 {
423 private:
424         sigc::signal<void,float> signal_user_click_[5];
425 public:
426
427         etl::smart_ptr<std::list<synfig::Point> > stroke_data;
428
429         synfig::Color color;
430
431         bool is_valid()const { return (bool)stroke_data; }
432
433         sigc::signal<void,float> &signal_user_click(int i=0) { assert(i>=0); assert(i<5); return signal_user_click_[i]; }
434 }; // END of struct Duckmatic::Bezier
435
436 }; // END of namespace studio
437
438 /* === E N D =============================================================== */
439
440 #endif