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