Merge branch 'devel/master' into devel/new_mesh
[platform/core/uifw/dali-core.git] / dali / public-api / object / property-value.cpp
1 /*
2  * Copyright (c) 2015 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 // CLASS HEADER
19 #include <dali/public-api/object/property-value.h>
20
21 // EXTERNAL INCLUDES
22 #include <ostream>
23
24 // INTERNAL INCLUDES
25 #include <dali/public-api/math/angle-axis.h>
26 #include <dali/public-api/math/radian.h>
27 #include <dali/public-api/math/vector2.h>
28 #include <dali/public-api/math/vector3.h>
29 #include <dali/public-api/math/vector4.h>
30 #include <dali/public-api/math/matrix3.h>
31 #include <dali/public-api/math/matrix.h>
32 #include <dali/public-api/math/rect.h>
33 #include <dali/public-api/math/quaternion.h>
34 #include <dali/public-api/object/property-map.h>
35 #include <dali/public-api/object/property-array.h>
36 #include <dali/public-api/object/property-types.h>
37 #include <dali/integration-api/debug.h>
38
39 namespace Dali
40 {
41
42 namespace
43 {
44 /**
45  * Helper to check if the property value can be read as int/unsigned int/bool
46  */
47 inline bool IsIntegerType( Property::Type type )
48 {
49   return ( Property::BOOLEAN == type )||( Property::INTEGER == type )||(Property::UNSIGNED_INTEGER == type );
50 }
51 }
52
53 struct Property::Value::Impl
54 {
55   Impl()
56   : type( Property::NONE ),
57     integerValue( 0 )
58   { }
59
60   Impl( bool booleanValue )
61   : type( Property::BOOLEAN ),
62     integerValue( booleanValue )
63   { }
64
65   Impl( float floatValue )
66   : type( Property::FLOAT ),
67     floatValue( floatValue )
68   { }
69
70   Impl( int integerValue )
71   : type( Property::INTEGER ),
72     integerValue( integerValue )
73   { }
74
75   Impl( unsigned int unsignedIntegerValue )
76   : type( Property::UNSIGNED_INTEGER ),
77     unsignedIntegerValue( unsignedIntegerValue )
78   { }
79
80   Impl( const Vector2& vectorValue )
81   : type( Property::VECTOR2 ),
82     vector2Value( new Vector2( vectorValue ) )
83   { }
84
85   Impl( const Vector3& vectorValue )
86   : type( Property::VECTOR3 ),
87     vector3Value( new Vector3( vectorValue ) )
88   { }
89
90   Impl( const Vector4& vectorValue )
91   : type( Property::VECTOR4 ),
92     vector4Value( new Vector4( vectorValue ) )
93   { }
94
95   Impl( const Matrix3& matrixValue )
96   : type( Property::MATRIX3 ),
97     matrix3Value( new Matrix3( matrixValue ) )
98   {
99   }
100
101   Impl( const Matrix& matrixValue )
102   : type( Property::MATRIX ),
103     matrixValue( new Matrix( matrixValue ) )
104   {
105   }
106
107   Impl( const AngleAxis& angleAxisValue )
108   : type( Property::ROTATION ),
109     quaternionValue( new Quaternion( angleAxisValue.angle, angleAxisValue.axis ) )
110   {
111   }
112
113   Impl( const Quaternion& quaternionValue )
114   : type( Property::ROTATION ),
115     quaternionValue( new Quaternion( quaternionValue ) )
116   {
117   }
118
119   Impl(const std::string& stringValue)
120   : type( Property::STRING ),
121     stringValue( new std::string( stringValue ) )
122   {
123   }
124
125   Impl( const Rect<int>& rectValue )
126   : type( Property::RECTANGLE ),
127     rectValue( new Rect<int>( rectValue ) )
128   {
129   }
130
131   Impl( const Property::Array& arrayValue )
132   : type( Property::ARRAY ),
133     arrayValue( new Property::Array( arrayValue ) )
134   {
135   }
136
137   Impl( const Property::Map& mapValue )
138   : type( Property::MAP ),
139     mapValue( new Property::Map( mapValue ) )
140   {
141   }
142
143   /**
144    * Destructor, takes care of releasing the dynamically allocated types
145    */
146   ~Impl()
147   {
148     switch( type )
149     {
150       case Property::NONE :             // FALLTHROUGH
151       case Property::BOOLEAN :          // FALLTHROUGH
152       case Property::FLOAT :            // FALLTHROUGH
153       case Property::INTEGER :          // FALLTHROUGH
154       case Property::UNSIGNED_INTEGER :
155       {
156         break; // nothing to do
157       }
158       case Property::VECTOR2 :
159       {
160         delete vector2Value;
161         break;
162       }
163       case Property::VECTOR3:
164       {
165         delete vector3Value;
166         break;
167       }
168       case Property::VECTOR4:
169       {
170         delete vector4Value;
171         break;
172       }
173       case Property::MATRIX3:
174       {
175         delete matrix3Value;
176         break;
177       }
178       case Property::MATRIX:
179       {
180         delete matrixValue;
181         break;
182       }
183       case Property::RECTANGLE:
184       {
185         delete rectValue;
186         break;
187       }
188       case Property::ROTATION:
189       {
190         delete quaternionValue;
191         break;
192       }
193       case Property::STRING:
194       {
195         delete stringValue;
196         break;
197       }
198       case Property::ARRAY:
199       {
200         delete arrayValue;
201         break;
202       }
203       case Property::MAP:
204       {
205         delete mapValue;
206         break;
207       }
208     }
209   }
210
211 public: // Data
212
213   Type type;
214   union
215   {
216     int integerValue;
217     float floatValue;
218     unsigned int unsignedIntegerValue;
219     // must use pointers for any class value pre c++ 11
220     Vector2* vector2Value;
221     Vector3* vector3Value;
222     Vector4* vector4Value;
223     Matrix3* matrix3Value;
224     Matrix* matrixValue;
225     Quaternion* quaternionValue;
226     std::string* stringValue;
227     Rect<int>* rectValue;
228     Property::Array* arrayValue;
229     Property::Map* mapValue;
230   };
231 };
232
233 Property::Value::Value()
234 : mImpl( NULL )
235 {
236 }
237
238 Property::Value::Value( bool booleanValue )
239 : mImpl( new Impl( booleanValue ) )
240 {
241 }
242
243 Property::Value::Value( float floatValue )
244 : mImpl( new Impl( floatValue ) )
245 {
246 }
247
248 Property::Value::Value( int integerValue )
249 : mImpl( new Impl( integerValue ) )
250 {
251 }
252
253 Property::Value::Value( unsigned int unsignedIntegerValue )
254 : mImpl( new Impl( unsignedIntegerValue ) )
255 {
256 }
257
258 Property::Value::Value( const Vector2& vectorValue )
259 : mImpl( new Impl( vectorValue ) )
260 {
261 }
262
263 Property::Value::Value( const Vector3& vectorValue )
264 : mImpl( new Impl( vectorValue ) )
265 {
266 }
267
268 Property::Value::Value( const Vector4& vectorValue )
269 : mImpl( new Impl( vectorValue ) )
270 {
271 }
272
273 Property::Value::Value( const Matrix3& matrixValue )
274 : mImpl( new Impl( matrixValue ) )
275 {
276 }
277
278 Property::Value::Value( const Matrix& matrixValue )
279 : mImpl( new Impl( matrixValue ) )
280 {
281 }
282
283 Property::Value::Value( const Rect<int>& rectValue )
284 : mImpl( new Impl( rectValue ) )
285 {
286 }
287
288 Property::Value::Value( const AngleAxis& angleAxisValue )
289 : mImpl( new Impl( angleAxisValue ) )
290 {
291 }
292
293 Property::Value::Value( const Quaternion& quaternionValue )
294 : mImpl( new Impl( quaternionValue ) )
295 {
296 }
297
298 Property::Value::Value( const std::string& stringValue )
299 : mImpl( new Impl( stringValue ) )
300 {
301 }
302
303 Property::Value::Value( const char* stringValue )
304 : mImpl( NULL )
305 {
306   if( stringValue ) // string constructor is undefined with NULL pointer
307   {
308     mImpl = new Impl( std::string(stringValue) );
309   }
310   else
311   {
312     mImpl = new Impl( std::string() );
313   }
314 }
315
316 Property::Value::Value( Property::Array& arrayValue )
317 : mImpl( new Impl( arrayValue ) )
318 {
319 }
320
321 Property::Value::Value( Property::Map& mapValue )
322 : mImpl( new Impl( mapValue ) )
323 {
324 }
325
326 Property::Value::Value( Type type )
327 {
328   switch (type)
329   {
330     case Property::BOOLEAN:
331     {
332       mImpl = new Impl( false );
333       break;
334     }
335     case Property::FLOAT:
336     {
337       mImpl = new Impl( 0.f );
338       break;
339     }
340     case Property::INTEGER:
341     {
342       mImpl = new Impl( 0 );
343       break;
344     }
345     case Property::UNSIGNED_INTEGER:
346     {
347       mImpl = new Impl( 0U );
348       break;
349     }
350     case Property::VECTOR2:
351     {
352       mImpl = new Impl( Vector2::ZERO );
353       break;
354     }
355     case Property::VECTOR3:
356     {
357       mImpl = new Impl( Vector3::ZERO );
358       break;
359     }
360     case Property::VECTOR4:
361     {
362       mImpl = new Impl( Vector4::ZERO );
363       break;
364     }
365     case Property::RECTANGLE:
366     {
367       mImpl = new Impl( Rect<int>(0,0,0,0) );
368       break;
369     }
370     case Property::ROTATION:
371     {
372       mImpl = new Impl( Quaternion() );
373       break;
374     }
375     case Property::STRING:
376     {
377       mImpl = new Impl( std::string() );
378       break;
379     }
380     case Property::MATRIX:
381     {
382       mImpl = new Impl( Matrix() );
383       break;
384     }
385     case Property::MATRIX3:
386     {
387       mImpl = new Impl( Matrix3() );
388       break;
389     }
390     case Property::ARRAY:
391     {
392       mImpl = new Impl( Property::Array() );
393       break;
394     }
395     case Property::MAP:
396     {
397       mImpl = new Impl( Property::Map() );
398       break;
399     }
400     case Property::NONE:
401     {
402       mImpl = new Impl();
403       break;
404     }
405   }
406 }
407 Property::Value::Value( const Property::Value& value )
408 : mImpl( NULL )
409 {
410   // reuse assignment operator
411   operator=( value );
412 }
413
414 Property::Value& Property::Value::operator=( const Property::Value& value )
415 {
416   if ( this == &value )
417   {
418     // skip self assignment
419     return *this;
420   }
421   // if we are assigned an empty value, just drop impl
422   if( !value.mImpl )
423   {
424     delete mImpl;
425     mImpl = NULL;
426     return *this;
427   }
428   // first check if the type is the same, no need to change impl, just assign
429   if( mImpl && ( mImpl->type == value.mImpl->type ) )
430   {
431     switch( mImpl->type )
432     {
433       case Property::BOOLEAN:
434       {
435         mImpl->integerValue = value.mImpl->integerValue;
436         break;
437       }
438       case Property::FLOAT:
439       {
440         mImpl->floatValue = value.mImpl->floatValue;
441         break;
442       }
443       case Property::INTEGER:
444       {
445         mImpl->integerValue = value.mImpl->integerValue;
446         break;
447       }
448       case Property::UNSIGNED_INTEGER:
449       {
450         mImpl->unsignedIntegerValue = value.mImpl->unsignedIntegerValue;
451         break;
452       }
453       case Property::VECTOR2:
454       {
455         *mImpl->vector2Value = *value.mImpl->vector2Value; // type cannot change in mImpl so vector is allocated
456         break;
457       }
458       case Property::VECTOR3:
459       {
460         *mImpl->vector3Value = *value.mImpl->vector3Value; // type cannot change in mImpl so vector is allocated
461         break;
462       }
463       case Property::VECTOR4:
464       {
465         *mImpl->vector4Value = *value.mImpl->vector4Value; // type cannot change in mImpl so vector is allocated
466         break;
467       }
468       case Property::RECTANGLE:
469       {
470         *mImpl->rectValue = *value.mImpl->rectValue; // type cannot change in mImpl so rect is allocated
471         break;
472       }
473       case Property::ROTATION:
474       {
475         *mImpl->quaternionValue = *value.mImpl->quaternionValue; // type cannot change in mImpl so quaternion is allocated
476         break;
477       }
478       case Property::STRING:
479       {
480         *mImpl->stringValue = *value.mImpl->stringValue; // type cannot change in mImpl so string is allocated
481         break;
482       }
483       case Property::MATRIX:
484       {
485         *mImpl->matrixValue = *value.mImpl->matrixValue; // type cannot change in mImpl so matrix is allocated
486         break;
487       }
488       case Property::MATRIX3:
489       {
490         *mImpl->matrix3Value = *value.mImpl->matrix3Value; // type cannot change in mImpl so matrix is allocated
491         break;
492       }
493       case Property::ARRAY:
494       {
495         *mImpl->arrayValue = *value.mImpl->arrayValue; // type cannot change in mImpl so array is allocated
496         break;
497       }
498       case Property::MAP:
499       {
500         *mImpl->mapValue = *value.mImpl->mapValue; // type cannot change in mImpl so map is allocated
501         break;
502       }
503       case Property::NONE:
504       { // mImpl will be NULL, there's no way to get to this case
505       }
506     }
507   }
508   else
509   {
510     // different type, release old impl and create new
511     Impl* newImpl( NULL );
512     switch ( value.mImpl->type )
513     {
514       case Property::BOOLEAN:
515       {
516         newImpl = new Impl( bool( value.mImpl->integerValue ) );
517         break;
518       }
519       case Property::FLOAT:
520       {
521         newImpl = new Impl( value.mImpl->floatValue );
522         break;
523       }
524       case Property::INTEGER:
525       {
526         newImpl = new Impl( value.mImpl->integerValue );
527         break;
528       }
529       case Property::UNSIGNED_INTEGER:
530       {
531         newImpl = new Impl( value.mImpl->unsignedIntegerValue );
532         break;
533       }
534       case Property::VECTOR2:
535       {
536         newImpl = new Impl( *value.mImpl->vector2Value ); // type cannot change in mImpl so vector is allocated
537         break;
538       }
539       case Property::VECTOR3:
540       {
541         newImpl = new Impl( *value.mImpl->vector3Value ); // type cannot change in mImpl so vector is allocated
542         break;
543       }
544       case Property::VECTOR4:
545       {
546         newImpl = new Impl( *value.mImpl->vector4Value ); // type cannot change in mImpl so vector is allocated
547         break;
548       }
549       case Property::RECTANGLE:
550       {
551         newImpl = new Impl( *value.mImpl->rectValue ); // type cannot change in mImpl so rect is allocated
552         break;
553       }
554       case Property::ROTATION:
555       {
556         newImpl = new Impl( *value.mImpl->quaternionValue ); // type cannot change in mImpl so quaternion is allocated
557         break;
558       }
559       case Property::MATRIX3:
560       {
561         newImpl = new Impl( *value.mImpl->matrix3Value ); // type cannot change in mImpl so matrix is allocated
562         break;
563       }
564       case Property::MATRIX:
565       {
566         newImpl = new Impl( *value.mImpl->matrixValue ); // type cannot change in mImpl so matrix is allocated
567         break;
568       }
569       case Property::STRING:
570       {
571         newImpl = new Impl( *value.mImpl->stringValue ); // type cannot change in mImpl so string is allocated
572         break;
573       }
574       case Property::ARRAY:
575       {
576         newImpl = new Impl( *value.mImpl->arrayValue ); // type cannot change in mImpl so array is allocated
577         break;
578       }
579       case Property::MAP:
580       {
581         newImpl = new Impl( *value.mImpl->mapValue ); // type cannot change in mImpl so map is allocated
582         break;
583       }
584       case Property::NONE:
585       { // NULL value will be used for "empty" value
586       }
587     }
588     delete mImpl;
589     mImpl = newImpl;
590   }
591
592   return *this;
593 }
594
595 Property::Value::~Value()
596 {
597   delete mImpl;
598 }
599
600 Property::Type Property::Value::GetType() const
601 {
602   Property::Type type( Property::NONE );
603   if( mImpl )
604   {
605     type = mImpl->type;
606   }
607   return type;
608 }
609
610 bool Property::Value::Get( bool& booleanValue ) const
611 {
612   bool converted = false;
613   if( mImpl && IsIntegerType( mImpl->type ) )
614   {
615     booleanValue = mImpl->integerValue;
616     converted = true;
617   }
618   return converted;
619 }
620
621 bool Property::Value::Get( float& floatValue ) const
622 {
623   bool converted = false;
624   if( mImpl && mImpl->type == FLOAT )
625   {
626     floatValue = mImpl->floatValue;
627     converted = true;
628   }
629   return converted;
630 }
631
632 bool Property::Value::Get( int& integerValue ) const
633 {
634   bool converted = false;
635   if( mImpl && IsIntegerType( mImpl->type ) )
636   {
637     integerValue = mImpl->integerValue;
638     converted = true;
639   }
640   return converted;
641 }
642
643 bool Property::Value::Get( unsigned int& unsignedIntegerValue ) const
644 {
645   bool converted = false;
646   if( mImpl && IsIntegerType( mImpl->type ) )
647   {
648     unsignedIntegerValue = mImpl->unsignedIntegerValue;
649     converted = true;
650   }
651   return converted;
652 }
653
654 bool Property::Value::Get( Vector2& vectorValue ) const
655 {
656   bool converted = false;
657   if( mImpl && (mImpl->type == VECTOR2) ) // type cannot change in mImpl so vector is allocated
658   {
659     vectorValue = *(mImpl->vector2Value);
660     converted = true;
661   }
662   return converted;
663 }
664
665 bool Property::Value::Get( Vector3& vectorValue ) const
666 {
667   bool converted = false;
668   if( mImpl && (mImpl->type == VECTOR3) ) // type cannot change in mImpl so vector is allocated
669   {
670     vectorValue = *(mImpl->vector3Value);
671     converted = true;
672   }
673   return converted;
674 }
675
676 bool Property::Value::Get( Vector4& vectorValue ) const
677 {
678   bool converted = false;
679   if( mImpl && (mImpl->type == VECTOR4) ) // type cannot change in mImpl so vector is allocated
680   {
681     vectorValue = *(mImpl->vector4Value);
682     converted = true;
683   }
684   return converted;
685 }
686
687 bool Property::Value::Get( Matrix3& matrixValue ) const
688 {
689   bool converted = false;
690   if( mImpl && (mImpl->type == MATRIX3) ) // type cannot change in mImpl so matrix is allocated
691   {
692     matrixValue = *(mImpl->matrix3Value);
693     converted = true;
694   }
695   return converted;
696 }
697
698 bool Property::Value::Get( Matrix& matrixValue ) const
699 {
700   bool converted = false;
701   if( mImpl && (mImpl->type == MATRIX) ) // type cannot change in mImpl so matrix is allocated
702   {
703     matrixValue = *(mImpl->matrixValue);
704     converted = true;
705   }
706   return converted;
707 }
708
709 bool Property::Value::Get( Rect<int>& rectValue ) const
710 {
711   bool converted = false;
712   if( mImpl && (mImpl->type == RECTANGLE) ) // type cannot change in mImpl so rect is allocated
713   {
714     rectValue = *(mImpl->rectValue);
715     converted = true;
716   }
717   return converted;
718 }
719
720 bool Property::Value::Get( AngleAxis& angleAxisValue ) const
721 {
722   bool converted = false;
723   if( mImpl && (mImpl->type == ROTATION) ) // type cannot change in mImpl so quaternion is allocated
724   {
725     mImpl->quaternionValue->ToAxisAngle( angleAxisValue.axis, angleAxisValue.angle );
726     converted = true;
727   }
728   return converted;
729 }
730
731 bool Property::Value::Get( Quaternion& quaternionValue ) const
732 {
733   bool converted = false;
734   if( mImpl && (mImpl->type == ROTATION) ) // type cannot change in mImpl so quaternion is allocated
735   {
736     quaternionValue = *(mImpl->quaternionValue);
737     converted = true;
738   }
739   return converted;
740 }
741
742 bool Property::Value::Get( std::string& stringValue ) const
743 {
744   bool converted = false;
745   if( mImpl && (mImpl->type == STRING) ) // type cannot change in mImpl so string is allocated
746   {
747     stringValue.assign( *(mImpl->stringValue) );
748     converted = true;
749   }
750   return converted;
751 }
752
753 bool Property::Value::Get( Property::Array& arrayValue ) const
754 {
755   bool converted = false;
756   if( mImpl && (mImpl->type == ARRAY) ) // type cannot change in mImpl so array is allocated
757   {
758     arrayValue = *(mImpl->arrayValue);
759     converted = true;
760   }
761   return converted;
762 }
763
764 bool Property::Value::Get( Property::Map& mapValue ) const
765 {
766   bool converted = false;
767   if( mImpl && (mImpl->type == MAP) ) // type cannot change in mImpl so map is allocated
768   {
769     mapValue = *(mImpl->mapValue);
770     converted = true;
771   }
772   return converted;
773 }
774
775 Property::Array* Property::Value::GetArray() const
776 {
777   Property::Array* array = NULL;
778   if( mImpl && (mImpl->type == ARRAY) ) // type cannot change in mImpl so array is allocated
779   {
780     array = mImpl->arrayValue;
781   }
782   return array;
783 }
784
785 Property::Map* Property::Value::GetMap() const
786 {
787   Property::Map* map = NULL;
788   if( mImpl && (mImpl->type == MAP) ) // type cannot change in mImpl so map is allocated
789   {
790     map = mImpl->mapValue;
791   }
792   return map;
793 }
794
795 std::ostream& operator<<( std::ostream& stream, const Property::Value& value )
796 {
797   if( value.mImpl )
798   {
799     const Property::Value::Impl& impl( *value.mImpl );
800
801     switch( impl.type )
802     {
803       case Dali::Property::BOOLEAN:
804       {
805         stream << impl.integerValue;
806         break;
807       }
808       case Dali::Property::FLOAT:
809       {
810         stream << impl.floatValue;
811         break;
812       }
813       case Dali::Property::INTEGER:
814       {
815          stream << impl.integerValue;
816          break;
817       }
818       case Dali::Property::UNSIGNED_INTEGER:
819       {
820         stream << impl.unsignedIntegerValue;
821         break;
822       }
823       case Dali::Property::VECTOR2:
824       {
825         stream << *impl.vector2Value;
826         break;
827       }
828       case Dali::Property::VECTOR3:
829       {
830         stream << *impl.vector3Value;
831         break;
832       }
833       case Dali::Property::VECTOR4:
834       {
835         stream << *impl.vector4Value;
836         break;
837       }
838       case Dali::Property::MATRIX3:
839       {
840         stream << *impl.matrix3Value;
841         break;
842       }
843       case Dali::Property::MATRIX:
844       {
845         stream << *impl.matrixValue;
846         break;
847       }
848       case Dali::Property::RECTANGLE:
849       {
850         stream << *impl.rectValue;
851         break;
852       }
853       case Dali::Property::ROTATION:
854       {
855         stream << *impl.quaternionValue;
856         break;
857       }
858       case Dali::Property::STRING:
859       {
860         stream << *impl.stringValue;
861         break;
862       }
863       case Dali::Property::ARRAY:
864       {
865         stream << "Array containing" << impl.arrayValue->Count() << " elements"; // TODO add ostream<< operator in array
866         break;
867       }
868       case Dali::Property::MAP:
869       {
870         stream << "Map containing " << impl.mapValue->Count() << " elements"; // TODO add ostream<< operator in map
871         break;
872       }
873       case Dali::Property::NONE:
874       {
875         stream << "undefined type";
876         break;
877       }
878     }
879   }
880   else
881   {
882     stream << "empty type";
883   }
884   return stream;
885 }
886
887
888 } // namespace Dali