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