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