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