1 /* === S Y N F I G ========================================================= */
2 /*!	\file action.h
3 **	\brief Template File
4 **
5 **	$Id$
6 **
7 **	\legal
8 **	Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
9 **	Copyright (c) 2008 Chris Moore
10 **
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.
15 **
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.
20 **	\endlegal
21 */
22 /* ========================================================================= */
23 
24 /* === S T A R T =========================================================== */
25 
26 #ifndef __SYNFIG_APP_ACTION_H
27 #define __SYNFIG_APP_ACTION_H
28 
29 /* === H E A D E R S ======================================================= */
30 
31 #include "action_param.h"
32 
33 /* === M A C R O S ========================================================= */
34 
35 #define ACTION_MODULE_EXT public: \
36 	static const char name__[], local_name__[], version__[], cvs_id__[], task__[]; \
37 	static const Category category__; \
38 	static const int priority__; \
39 	static Action::Base *create(); \
40 	virtual synfig::String get_name()const;	\
41 	virtual synfig::String get_local_name()const;
42 
43 
44 #define ACTION_SET_NAME(class,x) const char class::name__[]=x
45 
46 #define ACTION_SET_CATEGORY(class,x) const Category class::category__(x)
47 
48 #define ACTION_SET_TASK(class,x) const char class::task__[]=x
49 
50 #define ACTION_SET_PRIORITY(class,x) const int class::priority__=x
51 
52 #define ACTION_SET_LOCAL_NAME(class,x) const char class::local_name__[]=x
53 
54 #define ACTION_SET_VERSION(class,x) const char class::version__[]=x
55 
56 #define ACTION_SET_CVS_ID(class,x) const char class::cvs_id__[]=x
57 
58 //! don't define get_local_name() - allow the action code to define its own
59 #define ACTION_INIT_NO_GET_LOCAL_NAME(class)			  \
60 	Action::Base* class::create() { return new class(); } \
61 	synfig::String class::get_name()const { return name__; }
62 
63 //#define ACTION_INIT(class)				 \
64 //	ACTION_INIT_NO_GET_LOCAL_NAME(class) \
65 //	synfig::String class::get_local_name()const { return dgettext("synfigstudio",local_name__); }
66 
67 #define ACTION_INIT(class)				 \
68 	ACTION_INIT_NO_GET_LOCAL_NAME(class) \
69 	synfig::String class::get_local_name()const { return synfiggui_localize(local_name__); }
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 synfig {
76 class ProgressCallback;
77 class Canvas;
78 }; // END of namespace synfig
79 
80 namespace synfigapp {
81 
82 class Instance;
83 class Main;
84 
85 namespace Action {
86 
87 class System;
88 
89 
90 //! Exception class, thrown when redoing or undoing an action
91 class Error
92 {
93 public:
94 	enum Type
95 	{
96 		TYPE_UNKNOWN,
97 		TYPE_UNABLE,
98 		TYPE_BADPARAM,
99 		TYPE_CRITICAL,
100 		TYPE_NOTREADY,
101 		TYPE_BUG,
102 
103 		TYPE_END
104 	};
105 private:
106 
107 	Type type_;
108 	synfig::String desc_;
109 
110 public:
111 
Error(Type type,const char * format,...)112 	Error(Type type, const char *format, ...):
113 		type_(type)
114 	{
115 		va_list args;
116 		va_start(args,format);
117 		desc_=etl::vstrprintf(format,args);
118 		va_end(args);
119 	}
120 
Error(const char * format,...)121 	Error(const char *format, ...):
122 		type_(TYPE_UNKNOWN)
123 	{
124 		va_list args;
125 		va_start(args,format);
126 		desc_=etl::vstrprintf(format,args);
127 		va_end(args);
128 	}
129 
130 	Error(Type type=TYPE_UNABLE):
type_(type)131 		type_(type)
132 	{
133 	}
134 
get_type()135 	Type get_type()const { return type_; }
get_desc()136 	synfig::String get_desc()const { return desc_; }
137 
138 }; // END of class Action::Error
139 
140 class Param;
141 class ParamList;
142 class ParamDesc;
143 class ParamVocab;
144 
145 // Action Category
146 enum Category
147 {
148 	CATEGORY_NONE			=0,
149 	CATEGORY_LAYER			=(1<<0),
150 	CATEGORY_CANVAS			=(1<<1),
151 	CATEGORY_WAYPOINT		=(1<<2),
152 	CATEGORY_ACTIVEPOINT	=(1<<3),
153 	CATEGORY_VALUEDESC		=(1<<4),
154 	CATEGORY_VALUENODE		=(1<<5),
155 	CATEGORY_KEYFRAME		=(1<<6),
156 	CATEGORY_GROUP			=(1<<7),
157 	CATEGORY_BEZIER			=(1<<8),
158 
159 	CATEGORY_OTHER			=(1<<12),
160 
161 	CATEGORY_DRAG			=(1<<24),
162 
163 	CATEGORY_HIDDEN			=(1<<31),
164 	CATEGORY_ALL			=(~0)-(1<<31)		//!< All categories (EXCEPT HIDDEN)
165 }; // END of enum Category
166 
167 inline Category operator|(Category lhs, Category rhs)
168 { return static_cast<Category>(int(lhs)|int(rhs)); }
169 
170 
171 
172 //! Top-level base class for all actions
173 /*!	An action should implement the following functions:
174 **	- static bool is_candidate(const ParamList &x);
175 **		- 	Checks the ParamList to see if this action could be performed.
176 **	- static ParamVocab get_param_vocab();
177 **		-	Yields the ParamVocab object which describes what
178 **			this action needs before it can perform the act.
179 **	- static Action::Base* create();
180 **		-	Factory for creating this action from a ParamList
181 **
182 */
183 class Base : public etl::shared_object
184 {
185 protected:
Base()186 	Base() { }
187 
188 public:
~Base()189 	virtual ~Base() { };
190 
191 	//! This function will throw an Action::Error() on failure
192 	virtual void perform()=0;
193 
set_param(const synfig::String &,const Param &)194 	virtual bool set_param(const synfig::String& /*name*/, const Param &) { return false; }
get_param(const synfig::String &,Param &)195 	virtual bool get_param(const synfig::String& /*name*/, Param &) { return false; }
196 	virtual bool is_ready()const=0;
197 
198 	virtual synfig::String get_name()const =0;
get_local_name()199 	virtual synfig::String get_local_name()const { return get_name(); }
200 
201 	void set_param_list(const ParamList &);
202 
203 	static synfig::String get_layer_descriptions(const std::list<synfig::Layer::Handle> layers, synfig::String singular_prefix = "", synfig::String plural_prefix = "");
204 	static synfig::String get_layer_descriptions(const std::list<std::pair<synfig::Layer::Handle,int> > layers, synfig::String singular_prefix = "", synfig::String plural_prefix = "");
205 }; // END of class Action::Base
206 
207 typedef Action::Base* (*Factory)();
208 typedef bool (*CandidateChecker)(const ParamList &x);
209 typedef ParamVocab (*GetParamVocab)();
210 
211 typedef etl::handle<Base> Handle;
212 
213 //! Undoable Action Base Class
214 class Undoable : public Base
215 {
216 	friend class System;
217 	bool active_;
218 
219 protected:
220 	Undoable();
221 
222 #ifdef _DEBUG
223 	~Undoable();
224 #endif
225 
226 private:
set_active(bool x)227 	void set_active(bool x) { active_=x; }
228 
229 public:
230 
231 	//! This function will throw an Action::Error() on failure
232 	virtual void undo()=0;
233 
is_active()234 	bool is_active()const { return active_; }
235 
236 #ifdef _DEBUG
237 	virtual void ref()const;
238 	virtual bool unref()const;
239 #endif
240 }; // END of class Action::Undoable
241 
242 //! Action base class for canvas-specific actions
243 class CanvasSpecific
244 {
245 private:
246 	bool is_dirty_;
247 	EditMode	mode_;
248 
249 	etl::loose_handle<synfigapp::CanvasInterface> canvas_interface_;
250 	synfig::Canvas::Handle canvas_;
251 
252 protected:
CanvasSpecific(const synfig::Canvas::Handle & canvas)253 	CanvasSpecific(const synfig::Canvas::Handle &canvas):is_dirty_(true),mode_(MODE_UNDEFINED),canvas_(canvas) { }
CanvasSpecific()254 	CanvasSpecific():is_dirty_(true), mode_(MODE_UNDEFINED) { }
255 
~CanvasSpecific()256 	virtual ~CanvasSpecific() { };
257 
258 
259 public:
260 
set_canvas(synfig::Canvas::Handle x)261 	void set_canvas(synfig::Canvas::Handle x) { canvas_=x; }
set_canvas_interface(etl::loose_handle<synfigapp::CanvasInterface> x)262 	void set_canvas_interface(etl::loose_handle<synfigapp::CanvasInterface> x) { canvas_interface_=x; }
263 
get_canvas()264 	synfig::Canvas::Handle get_canvas()const { return canvas_; }
get_canvas_interface()265 	etl::loose_handle<synfigapp::CanvasInterface> get_canvas_interface()const { return canvas_interface_; }
266 
267 	static ParamVocab get_param_vocab();
268 	virtual bool set_param(const synfig::String& name, const Param &);
get_param(const synfig::String &,Param &)269 	virtual bool get_param(const synfig::String& /*name*/, Param &) { return false; }
270 	virtual bool is_ready()const;
271 
272 	EditMode get_edit_mode()const;
273 
set_edit_mode(EditMode x)274 	void set_edit_mode(EditMode x) { mode_=x; }
275 
is_dirty()276 	bool is_dirty()const { return is_dirty_; }
277 	void set_dirty(bool x=true) { is_dirty_=x; }
278 
279 }; // END of class Action::CanvasSpecific
280 
281 typedef std::list< etl::handle<Action::Undoable> > ActionList;
282 
283 /*!	\class synfigapp::Action::Super
284 **	\brief Super-Action base class for actions composed of several other actions.
285 **
286 **	Actions deriving from this class should only implement prepare(), and
287 **	NOT implement perform() or undo().
288 */
289 class Super : public Undoable, public CanvasSpecific
290 {
291 	ActionList action_list_;
292 
293 public:
294 
action_list()295 	ActionList &action_list() { return action_list_; }
action_list()296 	const ActionList &action_list()const { return action_list_; }
297 
298 	virtual void prepare()=0;
299 
clear()300 	void clear() { action_list().clear(); }
301 
first_time()302 	bool first_time()const { return action_list_.empty(); }
303 
304 	void add_action(etl::handle<Undoable> action);
305 	void add_action_front(etl::handle<Undoable> action);
306 
add_action(etl::handle<Base> action)307 	void add_action(etl::handle<Base> action)
308 	{
309 		etl::handle<Undoable> undoable = etl::handle<Undoable>::cast_dynamic(action);
310 		assert(undoable);
311 		add_action(undoable);
312 	}
313 
add_action_front(etl::handle<Base> action)314 	void add_action_front(etl::handle<Base> action)
315 	{
316 		etl::handle<Undoable> undoable = etl::handle<Undoable>::cast_dynamic(action);
317 		assert(undoable);
318 		add_action_front(undoable);
319 	}
320 
321 	virtual void perform();
322 	virtual void undo();
323 
324 }; // END of class Action::Super
325 
326 
327 class Group : public Super
328 {
329 	synfig::String name_;
330 
331 	ActionList action_list_;
332 protected:
333 	bool ready_;
334 public:
335 	Group(const synfig::String &str="Group");
336 	virtual ~Group();
337 
get_name()338 	virtual synfig::String get_name()const { return name_; }
339 
prepare()340 	virtual void prepare() { };
341 
set_param(const synfig::String &,const Param &)342 	virtual bool set_param(const synfig::String& /*name*/, const Param &)const { return false; }
is_ready()343 	virtual bool is_ready()const { return ready_; }
344 
set_name(std::string & x)345 	void set_name(std::string&x) { name_=x; }
346 }; // END of class Action::Group
347 
348 
349 
350 
351 
352 struct BookEntry
353 {
354 	synfig::String 	name;
355 	synfig::String 	local_name;
356 	synfig::String 	version;
357 	synfig::String 	task;
358 	int 			priority;
359 	Category		category;
360 	Factory 		factory;
361 	CandidateChecker	is_candidate;
362 	GetParamVocab	get_param_vocab;
363 
364 	bool operator<(const BookEntry &rhs)const { return priority<rhs.priority; }
365 }; // END of struct BookEntry
366 
367 typedef std::map<synfig::String,BookEntry> Book;
368 
369 class CandidateList : public std::list<BookEntry>
370 {
371 public:
372 	iterator find(const synfig::String& x);
find(const synfig::String & x)373 	const_iterator find(const synfig::String& x)const { return const_cast<CandidateList*>(this)->find(x); }
374 };
375 
376 Book& book();
377 
378 Handle create(const synfig::String &name);
379 
380 //! Compiles a list of potential candidate actions with the given \a param_list and \a category
381 CandidateList compile_candidate_list(const ParamList& param_list, Category category=CATEGORY_ALL);
382 
383 /*!	\class synfigapp::Action::Main
384 **	\brief \writeme
385 **
386 **	\writeme
387 */
388 class Main
389 {
390 	friend class synfigapp::Main;
391 
392 	Main();
393 
394 public:
395 	~Main();
396 
397 }; // END of class Action::Main
398 
399 }; // END of namespace Action
400 
401 }; // END of namespace synfigapp
402 
403 /* === E N D =============================================================== */
404 
405 #endif
406