Use an enumeration type rather than unnamed integers to specify the different types...
[synfig.git] / synfig-core / trunk / src / synfig / value.cpp
1 /* === S Y N F I G ========================================================= */
2 /*!     \file value.cpp
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 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 /* === H E A D E R S ======================================================= */
25
26 #ifdef USING_PCH
27 #       include "pch.h"
28 #else
29 #ifdef HAVE_CONFIG_H
30 #       include <config.h>
31 #endif
32
33 #include "value.h"
34 #include "general.h"
35 #include <ETL/stringf>
36 #include "canvas.h"
37 #include "gradient.h"
38
39
40
41 #include "vector.h"
42 #include "time.h"
43 #include "segment.h"
44 #include "color.h"
45
46 #endif
47
48 using namespace synfig;
49 using namespace std;
50 using namespace etl;
51
52 /* === M A C R O S ========================================================= */
53
54 /* === G L O B A L S ======================================================= */
55
56 /* === P R O C E D U R E S ================================================= */
57
58 /* === M E T H O D S ======================================================= */
59
60 ValueBase::ValueBase():type(TYPE_NIL),data(0),ref_count(0),loop_(0)
61 {
62 }
63
64 ValueBase::ValueBase(Type x):
65         type(x),
66         data(0),
67         loop_(0)
68 {
69         switch(type)
70         {
71         case TYPE_BOOL:                 data=static_cast<void*>(new bool());                            break;
72         case TYPE_INTEGER:              data=static_cast<void*>(new int());                                     break;
73         case TYPE_ANGLE:                data=static_cast<void*>(new Angle());                           break;
74         case TYPE_VECTOR:               data=static_cast<void*>(new Vector());                          break;
75         case TYPE_TIME:                 data=static_cast<void*>(new Time());                            break;
76         case TYPE_REAL:                 data=static_cast<void*>(new Real());                            break;
77         case TYPE_COLOR:                data=static_cast<void*>(new Color());                           break;
78         case TYPE_SEGMENT:              data=static_cast<void*>(new Segment());                         break;
79         case TYPE_BLINEPOINT:   data=static_cast<void*>(new BLinePoint());                      break;
80         case TYPE_LIST:                 data=static_cast<void*>(new list_type());                       break;
81         case TYPE_STRING:               data=static_cast<void*>(new String());                          break;
82         case TYPE_GRADIENT:             data=static_cast<void*>(new Gradient());                        break;
83         case TYPE_CANVAS:               data=static_cast<void*>(new etl::handle<Canvas>());     break;
84         default:                                                                                                                                        break;
85         }
86 }
87
88 ValueBase::~ValueBase()
89 {
90         clear();
91 }
92
93 const char*
94 ValueBase::get(const char*)const
95 {
96         return get(String()).c_str();
97 }
98
99 void
100 ValueBase::set(Canvas* x)
101 {
102         clear();
103         if(x && x->is_inline())
104         {
105                 _set(etl::handle<Canvas>(x));
106         }
107         else
108         {
109                 _set(etl::loose_handle<Canvas>(x));
110         }
111         assert(get(x)==x);
112 }
113
114 void
115 ValueBase::set(etl::loose_handle<Canvas> x)
116 {
117         clear();
118         if(x && x->is_inline())
119                 _set(etl::handle<Canvas>(x));
120         else
121                 _set(etl::loose_handle<Canvas>(x));
122         assert(get(x)==x);
123 }
124
125 void
126 ValueBase::set(etl::handle<Canvas> x)
127 {
128         clear();
129         if(x && x->is_inline())
130                 _set(etl::handle<Canvas>(x));
131         else
132                 _set(etl::loose_handle<Canvas>(x));
133         assert(get(x)==x);
134 }
135
136 void
137 ValueBase::set(const list_type &x)
138 {
139         _set(x);
140 }
141
142 void
143 ValueBase::set(const char* x)
144 {
145         _set(String(x));
146 }
147
148 bool
149 ValueBase::is_valid()const
150 {
151         return type>TYPE_NIL && type<TYPE_END && ref_count;
152 }
153
154 bool
155 ValueBase::empty()const
156 {
157         return !is_valid() || ((type==TYPE_LIST)?get_list().empty():false);
158 }
159
160 ValueBase::Type
161 ValueBase::get_contained_type()const
162 {
163         if(type!=TYPE_LIST || empty())
164                 return TYPE_NIL;
165         return get_list().front().get_type();
166 }
167
168 ValueBase&
169 ValueBase::operator=(const ValueBase& x)
170 {
171         if(data!=x.data)
172         {
173                 clear();
174                 type=x.type;
175                 data=x.data;
176                 ref_count=x.ref_count;
177         }
178         loop_=x.loop_;
179         return *this;
180 }
181
182 void
183 ValueBase::clear()
184 {
185         if(ref_count.unique() && data)
186         {
187                 switch(type)
188                 {
189                 case TYPE_BOOL:                 delete static_cast<bool*>(data);                break;
190                 case TYPE_INTEGER:              delete static_cast<int*>(data);                 break;
191                 case TYPE_ANGLE:                delete static_cast<Angle*>(data);               break;
192                 case TYPE_VECTOR:               delete static_cast<Vector*>(data);              break;
193                 case TYPE_TIME:                 delete static_cast<Time*>(data);                break;
194                 case TYPE_REAL:                 delete static_cast<Real*>(data);                break;
195                 case TYPE_COLOR:                delete static_cast<Color*>(data);               break;
196                 case TYPE_SEGMENT:              delete static_cast<Segment*>(data);             break;
197                 case TYPE_BLINEPOINT:   delete static_cast<BLinePoint*>(data);  break;
198                 case TYPE_LIST:                 delete static_cast<list_type*>(data);   break;
199                 case TYPE_STRING:               delete static_cast<String*>(data);              break;
200                 case TYPE_GRADIENT:             delete static_cast<Gradient*>(data);    break;
201                 case TYPE_CANVAS:
202                 {
203                         etl::handle<Canvas> canvas(get(etl::loose_handle<Canvas>()));
204                         if(canvas && canvas->is_inline())
205                                 delete static_cast<etl::handle<Canvas>*>(data);
206                         else
207                                 delete static_cast<etl::loose_handle<Canvas>*>(data);
208                         break;
209                 }
210                 default:
211                         break;
212                 }
213         }
214
215         ref_count.detach();
216         data=0;
217         type=TYPE_NIL;
218 }
219
220
221 String
222 ValueBase::type_name(Type id)
223 {
224         // don't internationalize these type names - they're using in .sif files
225         switch(id)
226         {
227         case TYPE_REAL:                 return "real";
228         case TYPE_TIME:                 return "time";
229         case TYPE_INTEGER:              return "integer";
230         case TYPE_BOOL:                 return "bool";
231         case TYPE_ANGLE:                return "angle";
232         case TYPE_VECTOR:               return "vector";
233         case TYPE_COLOR:                return "color";
234         case TYPE_STRING:               return "string";
235         case TYPE_CANVAS:               return "canvas";
236         case TYPE_LIST:                 return "list";
237         case TYPE_SEGMENT:              return "segment";
238         case TYPE_GRADIENT:             return "gradient";
239         case TYPE_BLINEPOINT:   return "bline_point";
240         case TYPE_NIL:                  return "nil";
241         default:
242                 break;
243         }
244         synfig::warning("Encountered unknown ValueBase with an Type of %d",id);
245 //      assert(0);
246         return "UNKNOWN";
247 }
248
249 ValueBase::Type
250 ValueBase::ident_type(const String &str)
251 {
252         if(str=="nil" ||
253            str=="null")                         return TYPE_NIL;
254         else if(str=="time" ||
255                         str==_("time"))         return TYPE_TIME;
256         else if(str=="real" ||
257                         str=="float" ||
258                         str==_("real"))         return TYPE_REAL;
259         else if(str=="integer" ||
260                         str=="int" ||
261                         str==_("integer"))      return TYPE_INTEGER;
262         else if(str=="bool" ||
263                         str==_("bool"))         return TYPE_BOOL;
264         else if(str=="angle" ||
265                         str=="degrees" ||
266                         str=="radians" ||
267                         str=="rotations")       return TYPE_ANGLE;
268         else if(str=="vector" ||
269                         str=="point")           return TYPE_VECTOR;
270         else if(str=="color")           return TYPE_COLOR;
271         else if(str=="string")          return TYPE_STRING;
272         else if(str=="canvas")          return TYPE_CANVAS;
273         else if(str=="list")            return TYPE_LIST;
274         else if(str=="segment")         return TYPE_SEGMENT;
275         else if(str=="gradient")        return TYPE_GRADIENT;
276         else if(str=="bline_point" ||
277                         str=="blinepoint")      return TYPE_BLINEPOINT;
278
279         return TYPE_NIL;
280 }
281
282 bool
283 ValueBase::operator==(const ValueBase& rhs)const
284 {
285         if(get_type()!=rhs.get_type())
286                 return false;
287         if(data==rhs.data)
288                 return true;
289
290         switch(get_type())
291         {
292         case TYPE_TIME:                    return get(Time()).is_equal(rhs.get(Time()));
293         case TYPE_REAL:                    return abs(get(Real())-rhs.get(Real()))<=0.00000000000001;
294         case TYPE_INTEGER:                 return get(int())==rhs.get(int());
295         case TYPE_BOOL:                    return get(bool())==rhs.get(bool());
296         case TYPE_ANGLE:                   return get(Angle())==rhs.get(Angle());
297         case TYPE_VECTOR:                  return get(Vector()).is_equal_to(rhs.get(Vector()));
298         case TYPE_COLOR:                   return get(Color())==rhs.get(Color());
299         case TYPE_STRING:                  return get(String())==rhs.get(String());
300         case TYPE_CANVAS:                  return get(Canvas::LooseHandle())==rhs.get(Canvas::LooseHandle());
301         case TYPE_LIST:                    return get_list()==rhs.get_list();
302         case TYPE_SEGMENT:              // return get(Segment())==rhs.get(Segment());
303         case TYPE_GRADIENT:             // return get(Gradient())==rhs.get(Gradient());
304         case TYPE_BLINEPOINT:   // return get(BLinePoint())==rhs.get(BLinePoint());
305         case TYPE_NIL:
306         default:                                   return false;
307         }
308         return false;
309 }