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