Merge "Remove dali-any from Property::Value - reimplement multivalue using more effic...
[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::TYPE_COUNT :       // FALLTHROUGH
152       case Property::BOOLEAN :          // FALLTHROUGH
153       case Property::FLOAT :            // FALLTHROUGH
154       case Property::INTEGER :          // FALLTHROUGH
155       case Property::UNSIGNED_INTEGER :
156       {
157         break; // nothing to do
158       }
159       case Property::VECTOR2 :
160       {
161         delete vector2Value;
162         break;
163       }
164       case Property::VECTOR3:
165       {
166         delete vector3Value;
167         break;
168       }
169       case Property::VECTOR4:
170       {
171         delete vector4Value;
172         break;
173       }
174       case Property::MATRIX3:
175       {
176         delete matrix3Value;
177         break;
178       }
179       case Property::MATRIX:
180       {
181         delete matrixValue;
182         break;
183       }
184       case Property::RECTANGLE:
185       {
186         delete rectValue;
187         break;
188       }
189       case Property::ROTATION:
190       {
191         delete quaternionValue;
192         break;
193       }
194       case Property::STRING:
195       {
196         delete stringValue;
197         break;
198       }
199       case Property::ARRAY:
200       {
201         delete arrayValue;
202         break;
203       }
204       case Property::MAP:
205       {
206         delete mapValue;
207         break;
208       }
209     }
210   }
211
212 public: // Data
213
214   Type type;
215   union
216   {
217     int integerValue;
218     float floatValue;
219     unsigned int unsignedIntegerValue;
220     // must use pointers for any class value pre c++ 11
221     Vector2* vector2Value;
222     Vector3* vector3Value;
223     Vector4* vector4Value;
224     Matrix3* matrix3Value;
225     Matrix* matrixValue;
226     Quaternion* quaternionValue;
227     std::string* stringValue;
228     Rect<int>* rectValue;
229     Property::Array* arrayValue;
230     Property::Map* mapValue;
231   };
232 };
233
234 Property::Value::Value()
235 : mImpl( NULL )
236 {
237 }
238
239 Property::Value::Value( bool booleanValue )
240 : mImpl( new Impl( booleanValue ) )
241 {
242 }
243
244 Property::Value::Value( float floatValue )
245 : mImpl( new Impl( floatValue ) )
246 {
247 }
248
249 Property::Value::Value( int integerValue )
250 : mImpl( new Impl( integerValue ) )
251 {
252 }
253
254 Property::Value::Value( unsigned int unsignedIntegerValue )
255 : mImpl( new Impl( unsignedIntegerValue ) )
256 {
257 }
258
259 Property::Value::Value( const Vector2& vectorValue )
260 : mImpl( new Impl( vectorValue ) )
261 {
262 }
263
264 Property::Value::Value( const Vector3& vectorValue )
265 : mImpl( new Impl( vectorValue ) )
266 {
267 }
268
269 Property::Value::Value( const Vector4& vectorValue )
270 : mImpl( new Impl( vectorValue ) )
271 {
272 }
273
274 Property::Value::Value( const Matrix3& matrixValue )
275 : mImpl( new Impl( matrixValue ) )
276 {
277 }
278
279 Property::Value::Value( const Matrix& matrixValue )
280 : mImpl( new Impl( matrixValue ) )
281 {
282 }
283
284 Property::Value::Value( const Rect<int>& rectValue )
285 : mImpl( new Impl( rectValue ) )
286 {
287 }
288
289 Property::Value::Value( const AngleAxis& angleAxisValue )
290 : mImpl( new Impl( angleAxisValue ) )
291 {
292 }
293
294 Property::Value::Value( const Quaternion& quaternionValue )
295 : mImpl( new Impl( quaternionValue ) )
296 {
297 }
298
299 Property::Value::Value( const std::string& stringValue )
300 : mImpl( new Impl( stringValue ) )
301 {
302 }
303
304 Property::Value::Value( const char* stringValue )
305 : mImpl( new Impl( std::string(stringValue) ) )
306 {
307 }
308
309 Property::Value::Value( Property::Array& arrayValue )
310 : mImpl( new Impl( arrayValue ) )
311 {
312 }
313
314 Property::Value::Value( Property::Map& mapValue )
315 : mImpl( new Impl( mapValue ) )
316 {
317 }
318
319
320 Property::Value::~Value()
321 {
322   delete mImpl;
323 }
324
325 Property::Value::Value( const Property::Value& value )
326 : mImpl( NULL )
327 {
328   // reuse assignment operator
329   operator=( value );
330 }
331
332 Property::Value::Value( Type type )
333 {
334   switch (type)
335   {
336     case Property::BOOLEAN:
337     {
338       mImpl = new Impl( false );
339       break;
340     }
341     case Property::FLOAT:
342     {
343       mImpl = new Impl( 0.f );
344       break;
345     }
346     case Property::INTEGER:
347     {
348       mImpl = new Impl( 0 );
349       break;
350     }
351     case Property::UNSIGNED_INTEGER:
352     {
353       mImpl = new Impl( 0U );
354       break;
355     }
356     case Property::VECTOR2:
357     {
358       mImpl = new Impl( Vector2::ZERO );
359       break;
360     }
361     case Property::VECTOR3:
362     {
363       mImpl = new Impl( Vector3::ZERO );
364       break;
365     }
366     case Property::VECTOR4:
367     {
368       mImpl = new Impl( Vector4::ZERO );
369       break;
370     }
371     case Property::RECTANGLE:
372     {
373       mImpl = new Impl( Rect<int>(0,0,0,0) );
374       break;
375     }
376     case Property::ROTATION:
377     {
378       mImpl = new Impl( Quaternion() );
379       break;
380     }
381     case Property::STRING:
382     {
383       mImpl = new Impl( std::string() );
384       break;
385     }
386     case Property::MATRIX:
387     {
388       mImpl = new Impl( Matrix() );
389       break;
390     }
391     case Property::MATRIX3:
392     {
393       mImpl = new Impl( Matrix3() );
394       break;
395     }
396     case Property::ARRAY:
397     {
398       mImpl = new Impl( Property::Array() );
399       break;
400     }
401     case Property::MAP:
402     {
403       mImpl = new Impl( Property::Map() );
404       break;
405     }
406     case Property::NONE:
407     case Property::TYPE_COUNT:
408     {
409       mImpl = new Impl();
410       break;
411     }
412   }
413 }
414
415 Property::Value& Property::Value::operator=( const Property::Value& value )
416 {
417   if ( this == &value )
418   {
419     // skip self assignment
420     return *this;
421   }
422   // if we are assigned an empty value, just drop impl
423   if( !value.mImpl )
424   {
425     delete mImpl;
426     mImpl = NULL;
427     return *this;
428   }
429   // first check if the type is the same, no need to change impl, just assign
430   if( mImpl && ( mImpl->type == value.mImpl->type ) )
431   {
432     switch( mImpl->type )
433     {
434       case Property::BOOLEAN:
435       {
436         mImpl->integerValue = value.mImpl->integerValue;
437         break;
438       }
439       case Property::FLOAT:
440       {
441         mImpl->floatValue = value.mImpl->floatValue;
442         break;
443       }
444       case Property::INTEGER:
445       {
446         mImpl->integerValue = value.mImpl->integerValue;
447         break;
448       }
449       case Property::UNSIGNED_INTEGER:
450       {
451         mImpl->unsignedIntegerValue = value.mImpl->unsignedIntegerValue;
452         break;
453       }
454       case Property::VECTOR2:
455       {
456         *mImpl->vector2Value = *value.mImpl->vector2Value;
457         break;
458       }
459       case Property::VECTOR3:
460       {
461         *mImpl->vector3Value = *value.mImpl->vector3Value;
462         break;
463       }
464       case Property::VECTOR4:
465       {
466         *mImpl->vector4Value = *value.mImpl->vector4Value;
467         break;
468       }
469       case Property::RECTANGLE:
470       {
471         *mImpl->rectValue = *value.mImpl->rectValue;
472         break;
473       }
474       case Property::ROTATION:
475       {
476         *mImpl->quaternionValue = *value.mImpl->quaternionValue;
477         break;
478       }
479       case Property::STRING:
480       {
481         *mImpl->stringValue = *value.mImpl->stringValue;
482         break;
483       }
484       case Property::MATRIX:
485       {
486         *mImpl->matrixValue = *value.mImpl->matrixValue;
487         break;
488       }
489       case Property::MATRIX3:
490       {
491         *mImpl->matrix3Value = *value.mImpl->matrix3Value;
492         break;
493       }
494       case Property::ARRAY:
495       {
496         *mImpl->arrayValue = *value.mImpl->arrayValue;
497         break;
498       }
499       case Property::MAP:
500       {
501         *mImpl->mapValue = *value.mImpl->mapValue;
502         break;
503       }
504       case Property::NONE:
505       case Property::TYPE_COUNT:
506       { // mImpl will be NULL, there's no way to get to this case
507       }
508     }
509   }
510   else
511   {
512     // different type, release old impl and create new
513     Impl* newImpl( NULL );
514     switch ( value.mImpl->type )
515     {
516       case Property::BOOLEAN:
517       {
518         newImpl = new Impl( bool( value.mImpl->integerValue ) );
519         break;
520       }
521       case Property::FLOAT:
522       {
523         newImpl = new Impl( value.mImpl->floatValue );
524         break;
525       }
526       case Property::INTEGER:
527       {
528         newImpl = new Impl( value.mImpl->integerValue );
529         break;
530       }
531       case Property::UNSIGNED_INTEGER:
532       {
533         newImpl = new Impl( value.mImpl->unsignedIntegerValue );
534         break;
535       }
536       case Property::VECTOR2:
537       {
538         newImpl = new Impl( *value.mImpl->vector2Value );
539         break;
540       }
541       case Property::VECTOR3:
542       {
543         newImpl = new Impl( *value.mImpl->vector3Value );
544         break;
545       }
546       case Property::VECTOR4:
547       {
548         newImpl = new Impl( *value.mImpl->vector4Value );
549         break;
550       }
551       case Property::RECTANGLE:
552       {
553         newImpl = new Impl( *value.mImpl->rectValue );
554         break;
555       }
556       case Property::ROTATION:
557       {
558         newImpl = new Impl( *value.mImpl->quaternionValue );
559         break;
560       }
561       case Property::MATRIX3:
562       {
563         newImpl = new Impl( *value.mImpl->matrix3Value );
564         break;
565       }
566       case Property::MATRIX:
567       {
568         newImpl = new Impl( *value.mImpl->matrixValue );
569         break;
570       }
571       case Property::STRING:
572       {
573         newImpl = new Impl( *value.mImpl->stringValue );
574         break;
575       }
576       case Property::ARRAY:
577       {
578         newImpl = new Impl( *value.mImpl->arrayValue );
579         break;
580       }
581       case Property::MAP:
582       {
583         newImpl = new Impl( *value.mImpl->mapValue );
584         break;
585       }
586       case Property::NONE:
587       case Property::TYPE_COUNT:
588       { // NULL value will be used for "empty" value
589       }
590     }
591     delete mImpl;
592     mImpl = newImpl;
593   }
594
595   return *this;
596 }
597
598 Property::Type Property::Value::GetType() const
599 {
600   Property::Type type( Property::NONE );
601   if( mImpl )
602   {
603     type = mImpl->type;
604   }
605   return type;
606 }
607
608 void Property::Value::Get( bool& booleanValue ) const
609 {
610   if( mImpl && IsIntegerType( mImpl->type ) )
611   {
612     booleanValue = mImpl->integerValue;
613   }
614   else
615   {
616     booleanValue = false;
617   }
618 }
619
620 void Property::Value::Get( float& floatValue ) const
621 {
622   if( mImpl && mImpl->type == FLOAT )
623   {
624     floatValue = mImpl->floatValue;
625   }
626   else
627   {
628     floatValue = 0.f;
629   }
630 }
631
632 void Property::Value::Get( int& integerValue ) const
633 {
634   if( mImpl && IsIntegerType( mImpl->type ) )
635   {
636     integerValue = mImpl->integerValue;
637   }
638   else
639   {
640     integerValue = 0;
641   }
642 }
643
644 void Property::Value::Get( unsigned int& unsignedIntegerValue ) const
645 {
646   if( mImpl && IsIntegerType( mImpl->type ) )
647   {
648     unsignedIntegerValue = mImpl->unsignedIntegerValue;
649   }
650   else
651   {
652     unsignedIntegerValue = 0u;
653   }
654 }
655
656 void Property::Value::Get( Vector2& vectorValue ) const
657 {
658   if( mImpl && mImpl->type == VECTOR2 && mImpl->vector2Value )
659   {
660     vectorValue = *(mImpl->vector2Value);
661   }
662   else
663   {
664     vectorValue.x = vectorValue.y = 0.f;
665   }
666 }
667
668 void Property::Value::Get( Vector3& vectorValue ) const
669 {
670   if( mImpl && mImpl->type == VECTOR3 && mImpl->vector3Value )
671   {
672     vectorValue = *(mImpl->vector3Value);
673   }
674   else
675   {
676     vectorValue.x = vectorValue.y = vectorValue.z = 0.f;
677   }
678 }
679
680 void Property::Value::Get( Vector4& vectorValue ) const
681 {
682   if( mImpl && mImpl->type == VECTOR4 && mImpl->vector4Value )
683   {
684     vectorValue = *(mImpl->vector4Value);
685   }
686   else
687   {
688     vectorValue.x = vectorValue.y = vectorValue.z = vectorValue.w = 0.f;
689   }
690 }
691
692 void Property::Value::Get( Matrix3& matrixValue ) const
693 {
694   if( mImpl && mImpl->type == MATRIX3 && mImpl->matrix3Value )
695   {
696     matrixValue = *(mImpl->matrix3Value);
697   }
698   else
699   {
700     matrixValue.SetIdentity();
701   }
702 }
703
704 void Property::Value::Get( Matrix& matrixValue ) const
705 {
706   if( mImpl && mImpl->type == MATRIX && mImpl->matrixValue )
707   {
708     matrixValue = *(mImpl->matrixValue);
709   }
710   else
711   {
712     matrixValue.SetIdentity();
713   }
714 }
715
716 void Property::Value::Get( Rect<int>& rectValue ) const
717 {
718   if( mImpl && mImpl->type == RECTANGLE && mImpl->rectValue )
719   {
720     rectValue = *(mImpl->rectValue);
721   }
722   else
723   {
724     rectValue.x = rectValue.y = rectValue.width = rectValue.height = 0.f;
725   }
726 }
727
728 void Property::Value::Get( AngleAxis& angleAxisValue ) const
729 {
730   if( mImpl && mImpl->type == ROTATION && mImpl->quaternionValue )
731   {
732     mImpl->quaternionValue->ToAxisAngle( angleAxisValue.axis, angleAxisValue.angle );
733   }
734   else
735   {
736     angleAxisValue.angle = 0.f;
737     angleAxisValue.axis = Vector3::ZERO; // identity quaternion
738   }
739 }
740
741 void Property::Value::Get( Quaternion& quaternionValue ) const
742 {
743   if( mImpl && mImpl->type == ROTATION && mImpl->quaternionValue )
744   {
745     quaternionValue = *(mImpl->quaternionValue);
746   }
747   else
748   {
749     quaternionValue = Quaternion::IDENTITY;
750   }
751 }
752
753 void Property::Value::Get( std::string& stringValue ) const
754 {
755   if( mImpl && mImpl->type == STRING && mImpl->stringValue )
756   {
757     stringValue.assign( *(mImpl->stringValue) );
758   }
759   else
760   {
761     stringValue.clear();
762   }
763 }
764
765 void Property::Value::Get( Property::Array& arrayValue ) const
766 {
767   if( mImpl && mImpl->type == ARRAY && mImpl->arrayValue )
768   {
769     arrayValue = *(mImpl->arrayValue);
770   }
771   else
772   {
773     arrayValue.Clear();
774   }
775 }
776
777 void Property::Value::Get( Property::Map& mapValue ) const
778 {
779   if( mImpl && mImpl->type == MAP && mImpl->mapValue )
780   {
781     mapValue = *(mImpl->mapValue);
782   }
783   else
784   {
785     mapValue.Clear();
786   }
787 }
788
789 Property::Map* Property::Value::GetMap() const
790 {
791   Property::Map* map = NULL;
792   if( mImpl && mImpl->type == MAP && mImpl->mapValue )
793   {
794     map = mImpl->mapValue;
795   }
796   return map;
797 }
798
799 Property::Array* Property::Value::GetArray() const
800 {
801   Property::Array* array = NULL;
802   if( mImpl && mImpl->type == ARRAY && mImpl->arrayValue )
803   {
804     array = mImpl->arrayValue;
805   }
806   return array;
807 }
808
809 std::ostream& operator<<( std::ostream& stream, const Property::Value& value )
810 {
811   if( value.mImpl )
812   {
813     const Property::Value::Impl& impl( *value.mImpl );
814
815     switch( impl.type )
816     {
817       case Dali::Property::BOOLEAN:
818       {
819         stream << impl.integerValue;
820         break;
821       }
822       case Dali::Property::FLOAT:
823       {
824         stream << impl.floatValue;
825         break;
826       }
827       case Dali::Property::INTEGER:
828       {
829          stream << impl.integerValue;
830          break;
831       }
832       case Dali::Property::UNSIGNED_INTEGER:
833       {
834         stream << impl.unsignedIntegerValue;
835         break;
836       }
837       case Dali::Property::VECTOR2:
838       {
839         stream << *impl.vector2Value;
840         break;
841       }
842       case Dali::Property::VECTOR3:
843       {
844         stream << *impl.vector3Value;
845         break;
846       }
847       case Dali::Property::VECTOR4:
848       {
849         stream << *impl.vector4Value;
850         break;
851       }
852       case Dali::Property::MATRIX3:
853       {
854         stream << *impl.matrix3Value;
855         break;
856       }
857       case Dali::Property::MATRIX:
858       {
859         stream << *impl.matrixValue;
860         break;
861       }
862       case Dali::Property::RECTANGLE:
863       {
864         stream << *impl.rectValue;
865         break;
866       }
867       case Dali::Property::ROTATION:
868       {
869         stream << *impl.quaternionValue;
870         break;
871       }
872       case Dali::Property::STRING:
873       {
874         stream << *impl.stringValue;
875         break;
876       }
877       case Dali::Property::ARRAY:
878       {
879         stream << "Array containing" << impl.arrayValue->Count() << " elements"; // TODO add ostream<< operator in array
880         break;
881       }
882       case Dali::Property::MAP:
883       {
884         stream << "Map containing " << impl.mapValue->Count() << " elements"; // TODO add ostream<< operator in map
885         break;
886       }
887       case Dali::Property::NONE:
888       case Dali::Property::TYPE_COUNT:
889       {
890         stream << "undefined type";
891         break;
892       }
893     }
894   }
895   else
896   {
897     stream << "empty type";
898   }
899   return stream;
900 }
901
902
903 } // namespace Dali