1 /* === S Y N F I G ========================================================= */
3 ** \brief Template Header
8 ** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
9 ** Copyright (c) 2007, 2008 Chris Moore
11 ** This package is free software; you can redistribute it and/or
12 ** modify it under the terms of the GNU General Public License as
13 ** published by the Free Software Foundation; either version 2 of
14 ** the License, or (at your option) any later version.
16 ** This package is distributed in the hope that it will be useful,
17 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
18 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 ** General Public License for more details.
22 /* ========================================================================= */
24 /* === S T A R T =========================================================== */
26 #ifndef __SYNFIG_STUDIO_DUCKMATIC_H
27 #define __SYNFIG_STUDIO_DUCKMATIC_H
29 /* === H E A D E R S ======================================================= */
35 #include <ETL/smart_ptr>
38 #include <synfig/vector.h>
39 #include <synfig/string.h>
40 #include <synfig/real.h>
41 #include <sigc++/signal.h>
42 #include <sigc++/object.h>
43 #include <synfig/time.h>
44 #include <synfig/color.h>
45 #include <ETL/smart_ptr>
48 #include <synfig/color.h>
49 #include <synfig/guidset.h>
51 /* === M A C R O S ========================================================= */
57 #ifndef __STRING_HASH__
58 #define __STRING_HASH__
61 # ifdef FUNCTIONAL_HASH_ON_STRING
62 HASH_MAP_NAMESPACE::hash<synfig::String> hasher_;
63 # else // FUNCTIONAL_HASH_ON_STRING
64 HASH_MAP_NAMESPACE::hash<const char*> hasher_;
65 # endif // FUNCTIONAL_HASH_ON_STRING
67 size_t operator()(const synfig::String& x)const
69 # ifdef FUNCTIONAL_HASH_ON_STRING
71 # else // FUNCTIONAL_HASH_ON_STRING
72 return hasher_(x.c_str());
73 # endif // FUNCTIONAL_HASH_ON_STRING
81 /* === T Y P E D E F S ===================================================== */
83 /* === C L A S S E S & S T R U C T S ======================================= */
85 namespace synfigapp { class ValueDesc; class CanvasInterface; }
86 namespace synfig { class ParamDesc; }
94 class DuckDrag_Base : public etl::shared_object
97 virtual void begin_duck_drag(Duckmatic* duckmatic, const synfig::Vector& begin)=0;
98 virtual bool end_duck_drag(Duckmatic* duckmatic)=0;
99 virtual void duck_drag(Duckmatic* duckmatic, const synfig::Vector& vector)=0;
102 class DuckDrag_Translate : public DuckDrag_Base
104 synfig::Vector last_translate_;
105 synfig::Vector drag_offset_;
107 std::vector<synfig::Vector> positions;
110 void begin_duck_drag(Duckmatic* duckmatic, const synfig::Vector& begin);
111 bool end_duck_drag(Duckmatic* duckmatic);
112 void duck_drag(Duckmatic* duckmatic, const synfig::Vector& vector);
117 ** This class helps organize any of the devices displayed in
118 ** the work area that the user may want to interact with.
119 ** This includes ducks, beziers, and strokes
124 friend class DuckDrag_Base;
125 friend class DuckDrag_Translate;
128 -- ** -- P U B L I C T Y P E S ---------------------------------------------
134 typedef HASH_MAP_CLASS<synfig::GUID,etl::smart_ptr<synfig::Point>,synfig::GUIDHash> DuckDataMap;
136 typedef std::map<synfig::GUID,etl::smart_ptr<synfig::Point> > DuckDataMap;
139 typedef studio::DuckMap DuckMap;
141 typedef studio::Duck Duck;
151 typedef Duck::Type Type;
153 typedef std::list<float> GuideList;
156 -- ** -- P R I V A T E D A T A ---------------------------------------------
161 etl::loose_handle<synfigapp::CanvasInterface> canvas_interface;
167 DuckDataMap duck_data_share_map;
169 std::list<etl::handle<Stroke> > stroke_list_;
171 std::list<etl::handle<Stroke> > persistent_stroke_list_;
173 synfig::GUIDSet selected_ducks;
175 synfig::GUID last_duck_guid;
177 std::list<etl::handle<Bezier> > bezier_list_;
179 //! I cannot recall what this is for
180 //synfig::Vector snap;
182 etl::handle<DuckDrag_Base> duck_dragger_;
184 sigc::signal<void> signal_duck_selection_changed_;
186 sigc::signal<void> signal_strokes_changed_;
188 sigc::signal<void> signal_grid_changed_;
190 mutable sigc::signal<void> signal_sketch_saved_;
192 GuideList guide_list_x_;
193 GuideList guide_list_y_;
195 mutable synfig::String sketch_filename_;
198 -- ** -- P R O T E C T E D D A T A -----------------------------------------
203 etl::handle<Bezier> selected_bezier;
205 synfig::Time cur_time;
207 //! This flag is set if operations should snap to the grid
208 /*! \todo perhaps there should be two of these flags, one for each axis?
209 ** \see show_grid, grid_size */
214 //! This vector describes the grid size.
215 /*! \see grid_snap, show_grid */
216 synfig::Vector grid_size;
218 bool show_persistent_strokes;
223 -- ** -- P R I V A T E M E T H O D S ---------------------------------------
228 synfig::Vector last_translate_;
229 synfig::Vector drag_offset_;
231 //etl::handle<Duck> selected_duck;
235 -- ** -- P U B L I C M E T H O D S -----------------------------------------
240 Duckmatic(etl::loose_handle<synfigapp::CanvasInterface> canvas_interface);
241 virtual ~Duckmatic();
243 sigc::signal<void>& signal_duck_selection_changed() { return signal_duck_selection_changed_; }
244 sigc::signal<void>& signal_strokes_changed() { return signal_strokes_changed_; }
245 sigc::signal<void>& signal_grid_changed() { return signal_grid_changed_; }
246 sigc::signal<void>& signal_sketch_saved() { return signal_sketch_saved_; }
248 GuideList& get_guide_list_x() { return guide_list_x_; }
249 GuideList& get_guide_list_y() { return guide_list_y_; }
250 const GuideList& get_guide_list_x()const { return guide_list_x_; }
251 const GuideList& get_guide_list_y()const { return guide_list_y_; }
253 void set_guide_snap(bool x=true);
254 bool get_guide_snap()const { return guide_snap; }
255 void toggle_guide_snap() { set_guide_snap(!get_guide_snap()); }
257 //! Sets the state of the grid snap flag
258 void set_grid_snap(bool x=true);
260 //! Gets the state of the grid snap flag
261 bool get_grid_snap()const { return grid_snap; }
263 void enable_grid_snap() { set_grid_snap(true); }
265 void disable_grid_snap() { set_grid_snap(false); }
267 void toggle_grid_snap() { set_grid_snap(!grid_snap); }
269 synfig::Point snap_point_to_grid(const synfig::Point& x, float radius=0.1)const;
271 bool get_show_persistent_strokes()const { return show_persistent_strokes; }
272 void set_show_persistent_strokes(bool x);
274 //! Sets the size of the grid
275 void set_grid_size(const synfig::Vector &s);
277 //! Returns the size of the grid
278 const synfig::Vector &get_grid_size()const { return grid_size; }
281 const synfig::Time &get_time()const { return cur_time; }
283 bool get_axis_lock()const { return axis_lock; }
284 void set_axis_lock(bool x) { axis_lock=x; }
286 void set_time(synfig::Time x) { cur_time=x; }
288 bool is_duck_group_selectable(const etl::handle<Duck>& x)const;
290 //const DuckMap& duck_map()const { return duck_map; }
291 DuckList get_duck_list()const;
293 const std::list<etl::handle<Bezier> >& bezier_list()const { return bezier_list_; }
295 const std::list<etl::handle<Stroke> >& stroke_list()const { return stroke_list_; }
297 const std::list<etl::handle<Stroke> >& persistent_stroke_list()const { return persistent_stroke_list_; }
299 std::list<etl::handle<Stroke> >& persistent_stroke_list() { return persistent_stroke_list_; }
301 //! \todo We should modify this to support multiple selections
302 etl::handle<Duck> get_selected_duck()const;
304 DuckList get_selected_ducks()const;
306 //! Returns \a true if the given duck is currently selected
307 bool duck_is_selected(const etl::handle<Duck> &duck)const;
310 void refresh_selected_ducks();
312 void clear_selected_ducks();
314 int count_selected_ducks()const;
316 void toggle_select_duck(const etl::handle<Duck> &duck);
318 void select_duck(const etl::handle<Duck> &duck);
320 void toggle_select_ducks_in_box(const synfig::Vector& tl,const synfig::Vector& br);
322 void select_ducks_in_box(const synfig::Vector& tl,const synfig::Vector& br);
324 void unselect_duck(const etl::handle<Duck> &duck);
326 //! Begin dragging ducks
327 /*! \param offset Canvas coordinates of the mouse when the drag began */
328 void start_duck_drag(const synfig::Vector& offset);
330 //! Continue dragging the selected ducks
331 /*! The overall vector of the drag is vector-offset
332 * (where offset was given in start_duck_drag)
333 * \param vector Canvas coordinates of the mouse at this moment */
334 void translate_selected_ducks(const synfig::Vector& vector);
336 //! Update the coordinates of tangents and linked-to-bline ducks
339 //! Ends the duck drag
340 bool end_duck_drag();
342 //! Signals to each selected duck that it has been clicked
343 void signal_user_click_selected_ducks(int button);
345 //! Calls all of the ducks' edited signals
346 /*! Updates corresponding valuenodes after a drag */
347 void signal_edited_selected_ducks();
349 bool on_duck_changed(const synfig::Point &value,const synfigapp::ValueDesc& value_desc);
350 bool on_duck_angle_changed(const synfig::Angle &rotation,const synfigapp::ValueDesc& value_desc);
352 etl::handle<Duck> find_similar_duck(etl::handle<Duck> duck);
353 etl::handle<Duck> add_similar_duck(etl::handle<Duck> duck);
355 void add_stroke(etl::smart_ptr<std::list<synfig::Point> > stroke_point_list, const synfig::Color& color=synfig::Color(0,0,0));
357 void add_persistent_stroke(etl::smart_ptr<std::list<synfig::Point> > stroke_point_list, const synfig::Color& color=synfig::Color(0,0,0));
359 void clear_persistent_strokes();
361 void add_duck(const etl::handle<Duck> &duck);
363 void add_bezier(const etl::handle<Bezier> &bezier);
365 void erase_duck(const etl::handle<Duck> &duck);
367 void erase_bezier(const etl::handle<Bezier> &bezier);
369 //! Returns the last duck added
370 etl::handle<Duck> last_duck()const;
372 etl::handle<Bezier> last_bezier()const;
374 //! \note parameter is in canvas coordinates
375 /*! A radius of "zero" will have an unlimited radius */
376 etl::handle<Duck> find_duck(synfig::Point pos, synfig::Real radius=0, Duck::Type type=Duck::TYPE_DEFAULT);
378 GuideList::iterator find_guide_x(synfig::Point pos, float radius=0.1);
379 GuideList::iterator find_guide_y(synfig::Point pos, float radius=0.1);
380 GuideList::const_iterator find_guide_x(synfig::Point pos, float radius=0.1)const { return const_cast<Duckmatic*>(this)->find_guide_x(pos,radius); }
381 GuideList::const_iterator find_guide_y(synfig::Point pos, float radius=0.1)const { return const_cast<Duckmatic*>(this)->find_guide_y(pos,radius); }
383 //! \note parameter is in canvas coordinates
384 /*! A radius of "zero" will have an unlimited radius */
385 //etl::handle<Bezier> find_bezier(synfig::Point pos, synfig::Real radius=0);
387 //! \note parameter is in canvas coordinates
388 /*! A radius of "zero" will have an unlimited radius */
389 etl::handle<Bezier> find_bezier(synfig::Point pos, synfig::Real radius=0, float* location=0);
391 etl::handle<Bezier> find_bezier(synfig::Point pos, synfig::Real scale, synfig::Real radius, float* location=0);
393 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);
395 //! Set the type mask, which determines what types of ducks are shown
396 void set_type_mask(Type x) { type_mask=x; }
398 //! Get the type mask, which determines what types of ducks are shown
399 Type get_type_mask()const { return type_mask; }
401 void select_all_ducks();
402 void unselect_all_ducks();
406 bool save_sketch(const synfig::String& filename)const;
407 bool load_sketch(const synfig::String& filename);
408 const synfig::String& get_sketch_filename()const { return sketch_filename_; }
410 void set_duck_dragger(etl::handle<DuckDrag_Base> x) { duck_dragger_=x; }
411 etl::handle<DuckDrag_Base> get_duck_dragger()const { return duck_dragger_; }
412 void clear_duck_dragger() { duck_dragger_=new DuckDrag_Translate(); }
413 }; // END of class Duckmatic
416 /*! \class Duckmatic::Push
418 class Duckmatic::Push
420 Duckmatic *duckmatic_;
422 std::list<etl::handle<Bezier> > bezier_list_;
423 std::list<etl::handle<Stroke> > stroke_list_;
424 DuckDataMap duck_data_share_map;
425 etl::handle<DuckDrag_Base> duck_dragger_;
430 Push(Duckmatic *duckmatic_);
433 }; // END of class Duckmatic::Push
435 /*! \struct Duckmatic::Bezier
437 struct Duckmatic::Bezier : public etl::shared_object
440 sigc::signal<void,float> signal_user_click_[5];
443 etl::handle<Duck> p1,p2,c1,c2;
444 bool is_valid()const { return p1 && p2 && c1 && c2; }
446 sigc::signal<void,float> &signal_user_click(int i=0) { assert(i>=0); assert(i<5); return signal_user_click_[i]; }
447 }; // END of struct Duckmatic::Bezier
449 /*! \struct Duckmatic::Stroke
451 struct Duckmatic::Stroke : public etl::shared_object
454 sigc::signal<void,float> signal_user_click_[5];
457 etl::smart_ptr<std::list<synfig::Point> > stroke_data;
461 bool is_valid()const { return (bool)stroke_data; }
463 sigc::signal<void,float> &signal_user_click(int i=0) { assert(i>=0); assert(i<5); return signal_user_click_[i]; }
464 }; // END of struct Duckmatic::Stroke
466 }; // END of namespace studio
468 /* === E N D =============================================================== */