Merge branch 'genete_master'
[synfig.git] / synfig-core / src / synfig / value.h
1 /* === S Y N F I G ========================================================= */
2 /*!     \file value.h
3 **      \brief Template Header
4 **
5 **      $Id$
6 **
7 **      \legal
8 **      Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
9 **      Copyright (c) 2007, 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_VALUE_H
27 #define __SYNFIG_VALUE_H
28
29 /* === H E A D E R S ======================================================= */
30
31 //#include "vector.h"
32 //#include "time.h"
33 #include "segment.h"
34 //#include "color.h"
35 #include "string.h"
36 #include <list>
37 #include <vector>
38 #include <ETL/trivial>
39 #include <ETL/handle>
40 #include "general.h"
41 //#include "gradient.h"
42 #include "blinepoint.h"
43 #include "exception.h"
44
45 #ifdef USE_HALF_TYPE
46 #include <OpenEXR/half.h>
47 #endif
48
49 #ifndef SYNFIG_NO_ANGLE
50 #include "angle.h"
51 #endif
52
53 #include <ETL/ref_count>
54
55 /* === M A C R O S ========================================================= */
56
57 /* === T Y P E D E F S ===================================================== */
58
59 /* === C L A S S E S & S T R U C T S ======================================= */
60
61 namespace synfig {
62
63 class Canvas;
64 class Vector;
65 class Time;
66 class Segment;
67 class Gradient;
68 class BLinePoint;
69 class Color;
70
71 /*!     \class ValueBase
72 **      \todo writeme
73 */
74 class ValueBase
75 {
76         /*
77  --     ** -- T Y P E S -----------------------------------------------------------
78         */
79
80 public:
81
82         //! \writeme
83         enum Type
84         {
85                 TYPE_NIL=0,                     //!< Represents an empty value
86
87                 TYPE_BOOL,
88                 TYPE_INTEGER,
89                 TYPE_ANGLE,                     //!< Angle
90
91                 // All types after this point are larger than 32 bits
92
93                 TYPE_TIME,                      //!< Time
94                 TYPE_REAL,                      //!< Real
95
96                 // All types after this point are larger than 64 bits
97
98                 TYPE_VECTOR,            //!< Vector
99                 TYPE_COLOR,                     //!< Color
100                 TYPE_SEGMENT,           //!< Segment
101                 TYPE_BLINEPOINT,        //!< BLinePoint
102
103                 // All types after this point require construction/destruction
104
105                 TYPE_LIST,                      //!< List
106                 TYPE_CANVAS,            //!< Canvas
107                 TYPE_STRING,            //!< String
108                 TYPE_GRADIENT,          //!< Color Gradient
109
110                 TYPE_END                        //!< Not a valid type, used for sanity checks
111         };
112
113 private:
114
115         typedef std::vector<ValueBase> list_type;
116
117         /*
118  --     ** -- D A T A -------------------------------------------------------------
119         */
120
121 protected:
122
123         Type type;
124         void *data;
125         etl::reference_counter ref_count;
126         bool loop_;
127
128         /*
129  --     ** -- C O N S T R U C T O R S -----------------------------------
130         */
131
132 public:
133
134         //! \writeme
135         ValueBase();
136
137         //! \writeme
138         template <typename T>
139         ValueBase(const T &x, bool loop_=false):
140                 type(TYPE_NIL),data(0),ref_count(0),loop_(loop_)
141                 { set(x); }
142
143         //! \writeme
144         ValueBase(Type x);
145
146         //! \writeme
147         ~ValueBase();
148
149         /*
150  --     ** -- O P E R A T O R S ---------------------------------------------------
151         */
152
153 public:
154
155         //! \writeme
156         template <class T> ValueBase& operator=(const T& x)
157                 { set(x); return *this; }
158
159         //! \writeme
160         ValueBase& operator=(const ValueBase& x);
161
162         //! \writeme
163         bool operator==(const ValueBase& rhs)const;
164
165         //! \writeme
166         bool operator!=(const ValueBase& rhs)const { return !operator==(rhs); }
167
168         //!     Constant index operator for when value is of type TYPE_LIST
169         const ValueBase &operator[](int index)const
170                 { assert(type==TYPE_LIST); assert(index>0); return get_list()[index]; }
171
172         /*
173  --     ** -- M E M B E R   F U N C T I O N S -------------------------------------
174         */
175
176 public:
177
178         //! \writeme
179         void clear();
180
181         //! \writeme
182         bool get_loop()const { return loop_; }
183
184         //! \writeme
185         void set_loop(bool x) { loop_=x; }
186
187         //! \writeme
188         bool empty()const;
189
190         //! \writeme
191         Type get_contained_type()const;
192
193         //! Returns true if the contained value is defined and valid.
194         bool is_valid()const;
195
196         //!     Returns a string containing the name of the type
197         String type_name()const { return type_name(type); }
198
199         //! Returns the type of the contained value
200         const Type & get_type()const { return type; }
201
202         //! Checks the type of the parameter against itself. Returns true if they are of the same type.
203         template <class T> bool
204         same_type_as(const T &x)const
205         {
206                 const Type testtype(get_type(x));
207
208                 return same_type_as(type, testtype);
209         }
210
211         bool same_type_as(const Type testtype)const
212         {
213                 return same_type_as(type, testtype);
214         }
215
216         //! Compares two types.  Returns true if they are the same type.
217         static bool same_type_as(const Type type1, const Type type2)
218         {
219                 if (type1 == type2) return true;
220                 if ((type1 == TYPE_REAL || type1 == TYPE_TIME) &&
221                         (type2 == TYPE_REAL || type2 == TYPE_TIME))
222                         return true;
223                 return false;
224         }
225
226
227         // === GET MEMBERS ========================================================
228         template <typename T>
229         const T &get(const T& x __attribute__ ((unused)))const
230         {
231                 assert(is_valid() && same_type_as(x));
232                 return *static_cast<const T*>(data);
233         }
234         float get(const float &)const { return get(Real()); }
235         etl::loose_handle<Canvas> get(const etl::handle<Canvas>&)const
236                 { return get(etl::loose_handle<Canvas>()); }
237         etl::loose_handle<Canvas> get(Canvas*)const
238                 { return get(etl::loose_handle<Canvas>()); }
239         const char* get(const char*)const;
240         const list_type& get_list()const { return get(list_type()); }
241
242 #ifdef _DEBUG
243         String get_string() const;
244 #endif  // _DEBUG
245         // ========================================================================
246
247
248
249         // === PUT MEMBERS ========================================================
250         template <typename T>
251         void put(T* x)const
252         {
253                 assert(same_type_as(*x));
254                 *x=*static_cast<const T*>(data);
255         }
256         void put(float* x)const { *x=get(Real()); }
257         void put(char** x)const;
258         // ========================================================================
259
260
261
262         // === SET MEMBERS ========================================================
263         template <typename T> void set(const T& x) { _set(x); }
264         void set(const float &x) { _set(Real(x)); }
265         void set(const list_type &x);
266         void set(const char* x);
267         void set(char* x);
268         void set(Canvas*x);
269         void set(etl::loose_handle<Canvas> x);
270         void set(etl::handle<Canvas> x);
271         template <class T> void set(const std::vector<T> &x)
272                 { _set(list_type(x.begin(),x.end())); }
273         template <class T> void set(const std::list<T> &x)
274                 { _set(list_type(x.begin(),x.end())); }
275         // ========================================================================
276
277
278         /*
279  --     ** -- S T A T I C   F U N C T I O N S -------------------------------------
280         */
281
282 public:
283
284         //!     Returns a string containing the name of the given Type
285         static String type_name(Type id);
286
287         //!     Returns a string containing the translated name of the given Type
288         static String type_local_name(Type id);
289
290         //!     Returns a the corresponding Type of the described type
291         static Type ident_type(const String &str);
292
293
294         // === GET TYPE MEMBERS ===================================================
295         static Type get_type(bool) { return TYPE_BOOL; }
296         static Type get_type(int) { return TYPE_INTEGER; }
297         static Type get_type(const Time&) { return TYPE_TIME; }
298         static Type get_type(const Real&) { return TYPE_REAL; }
299         static Type get_type(const float&) { return TYPE_REAL; }
300         static Type get_type(const Vector&) { return TYPE_VECTOR; }
301         static Type get_type(const Color&) { return TYPE_COLOR; }
302         static Type get_type(const Segment&) { return TYPE_SEGMENT; }
303         static Type get_type(const BLinePoint&) { return TYPE_BLINEPOINT; }
304         static Type get_type(const String&) { return TYPE_STRING; }
305         static Type get_type(const Gradient&) { return TYPE_GRADIENT; }
306         static Type get_type(Canvas*) { return TYPE_CANVAS; }
307         static Type get_type(const etl::handle<Canvas>&)
308                 { return TYPE_CANVAS; }
309         static Type get_type(const etl::loose_handle<Canvas>&)
310                 { return TYPE_CANVAS; }
311         static Type get_type(const list_type&) { return TYPE_LIST; }
312         template <class T> static Type get_type(const std::vector<T> &/*x*/)
313                 { return TYPE_LIST; }
314         template <class T> static Type get_type(const std::list<T> &/*x*/)
315                 { return TYPE_LIST; }
316         // ========================================================================
317
318
319         /*
320  --     ** -- C A S T   O P E R A T O R S -----------------------------------------
321         */
322
323 public:
324
325         operator const list_type&()const { return get_list(); }
326         //operator const Color&()const { return get(Color()); }
327         operator const Real&()const { return get(Real()); }
328         //operator const Time&()const { return get(Time()); }
329
330         operator const Vector&()const {  return get(Vector()); }
331         operator const BLinePoint&()const {  return get(BLinePoint()); }
332         //operator const int&()const {  return get(int()); }
333         //operator const String&()const {  return get(String()); }
334         //operator const char *()const {  return get(String()).c_str(); }
335         operator const Segment&()const { return get(Segment()); }
336
337
338         /*
339  --     ** -- O T H E R -----------------------------------------------------------
340         */
341
342 public:
343
344 #ifdef USE_HALF_TYPE
345         half get(const half &)const { return get(Real()); }
346         void put(half*x)const { *x=get(Real()); }
347         void set(const half &x) { _set(Real(x)); }
348         static Type get_type(const half&) { return TYPE_REAL; }
349         operator half()const { return get(Real()); }
350 #endif
351
352 #ifndef SYNFIG_NO_ANGLE
353         operator const Angle&()const { return get(Angle()); }
354         static Type get_type(const Angle&) { return TYPE_ANGLE; }
355 #endif
356
357         template <class T>
358         operator std::list<T>()const
359         {
360                 assert(type==TYPE_LIST);
361                 std::list<T> ret(get_list().begin(),get_list().end());
362                 return ret;
363         }
364         template <class T>
365         operator std::vector<T>()const
366         {
367                 assert(type==TYPE_LIST);
368                 std::vector<T> ret(get_list().begin(),get_list().end());
369                 return ret;
370         }
371
372
373 private:
374
375         template <typename T> void
376         _set(const T& x)
377         {
378                 const Type newtype(get_type(x));
379
380                 assert(newtype!=TYPE_NIL);
381
382                 if(newtype==type)
383                 {
384                         if(ref_count.unique())
385                         {
386                                 *reinterpret_cast<T*>(data)=x;
387                                 return;
388                         }
389                 }
390
391                 clear();
392
393                 type=newtype;
394                 ref_count.reset();
395                 data=new T(x);
396         }
397 }; // END of class ValueBase
398
399
400 /*!     \class Value
401 **      \todo writeme
402 */
403 template <class T>
404 class Value : public ValueBase
405 {
406 public:
407         Value(const T &x):ValueBase(x)
408         {
409         }
410
411         Value(const ValueBase &x):ValueBase(x)
412         {
413                 if(!x.same_type_as(T()))
414                         throw Exception::BadType("Value<T>(ValueBase): Type Mismatch");
415         }
416
417         Value()
418         {
419         }
420
421         T get()const { return ValueBase::get(T()); }
422
423         void put(T* x)const     { ValueBase::put(x); }
424
425         void set(const T& x) { ValueBase::operator=(x); }
426
427         Value<T>& operator=(const T& x) { set(x); return *this; }
428
429         Value<T>& operator=(const Value<T>& x) { return ValueBase::operator=(x); }
430
431         Value<T>& operator=(const ValueBase& x)
432         {
433                 if(!x.same_type_as(T()))
434                         throw Exception::BadType("Value<T>(ValueBase): Type Mismatch");
435                 return ValueBase::operator=(x);
436         }
437
438 }; // END of class Value
439
440 /*
441 template <>
442 class Value< std::list<CT> > : public ValueBase
443 {
444 public:
445         Value(const T &x):ValueBase(x)
446         {
447         }
448         Value(const ValueBase &x):ValueBase(x)
449         {
450                 if(!x.same_type_as(T()))
451                         throw Exception::BadType("Value<T>(ValueBase): Type Mismatch");
452         }
453         Value()
454         {
455         }
456
457         T get()const { return ValueBase::get(T()); }
458
459         void put(T* x)const     { ValueBase::put(x); }
460
461         void set(const T& x) { ValueBase::operator=(x); }
462
463         Value<T>& operator=(const T& x) { set(x); return *this; }
464
465         Value<T>& operator=(const Value<T>& x) { return ValueBase::operator=(x); }
466
467         Value<T>& operator=(const ValueBase& x)
468         {
469                 if(!x.same_type_as(T()))
470                         throw Exception::BadType("Value<T>(ValueBase): Type Mismatch");
471                 return ValueBase::operator=(x);
472         }
473
474 }; // END of class Value
475 */
476
477 }; // END of namespace synfig
478
479 /* === E N D =============================================================== */
480
481 #endif