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