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