afaee1ef01fdb0ae159cbc62fd8fcefd249b7bce
[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/object/any.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 struct Property::Value::Impl
44 {
45   Impl()
46   : mType( Property::NONE )
47   {
48   }
49
50   Impl(bool boolValue)
51   : mType( PropertyTypes::Get<bool>() ),
52     mValue( boolValue )
53   {
54   }
55
56   Impl(float floatValue)
57   : mType( PropertyTypes::Get<float>() ),
58     mValue( floatValue )
59   {
60   }
61
62   Impl(int integerValue)
63   : mType( PropertyTypes::Get<int>() ),
64     mValue( integerValue )
65   {
66   }
67
68   Impl(unsigned int unsignedIntegerValue)
69   : mType( PropertyTypes::Get<unsigned int>() ),
70     mValue( unsignedIntegerValue )
71   {
72   }
73
74   Impl(const Vector2& vectorValue)
75   : mType( PropertyTypes::Get<Vector2>() ),
76     mValue( vectorValue )
77   {
78   }
79
80   Impl(const Vector3& vectorValue)
81   : mType( PropertyTypes::Get<Vector3>() ),
82     mValue( vectorValue )
83   {
84   }
85
86   Impl(const Vector4& vectorValue)
87   : mType( PropertyTypes::Get<Vector4>() ),
88     mValue( vectorValue )
89   {
90   }
91
92   Impl(const Matrix3& matrixValue)
93   : mType(PropertyTypes::Get<Matrix3>()),
94     mValue(matrixValue)
95   {
96   }
97
98   Impl(const Matrix& matrixValue)
99   : mType(PropertyTypes::Get<Matrix>()),
100     mValue(matrixValue)
101   {
102   }
103
104   Impl(const AngleAxis& angleAxisValue)
105   : mType( PropertyTypes::Get<AngleAxis>() ),
106     mValue( angleAxisValue )
107   {
108   }
109
110   Impl(const Quaternion& quaternionValue)
111   : mType( PropertyTypes::Get<Quaternion>() ),
112     mValue( quaternionValue )
113   {
114   }
115
116   Impl(const std::string& stringValue)
117     : mType( PropertyTypes::Get<std::string>() ),
118       mValue( stringValue )
119   {
120   }
121
122   Impl(const Rect<int>& rect)
123     : mType( PropertyTypes::Get<Rect<int> >() ),
124       mValue( rect )
125   {
126   }
127
128   Impl(Property::Map container)
129     : mType( PropertyTypes::Get<Property::Map >() ),
130       mValue( container )
131   {
132   }
133
134   Impl(Property::Array container)
135     : mType( PropertyTypes::Get<Property::Array >() ),
136       mValue( container )
137   {
138   }
139
140   Type mType;
141
142   typedef Any AnyValue;
143   AnyValue mValue;
144 };
145
146 Property::Value::Value()
147 : mImpl( NULL )
148 {
149   mImpl = new Impl();
150 }
151
152 Property::Value::Value(bool boolValue)
153 : mImpl( NULL )
154 {
155   mImpl = new Impl( boolValue );
156 }
157
158 Property::Value::Value(float floatValue)
159 : mImpl( NULL )
160 {
161   mImpl = new Impl( floatValue );
162 }
163
164 Property::Value::Value(int integerValue)
165 : mImpl( NULL )
166 {
167   mImpl = new Impl( integerValue );
168 }
169
170 Property::Value::Value(unsigned int unsignedIntegerValue)
171 : mImpl( NULL )
172 {
173   mImpl = new Impl( unsignedIntegerValue );
174 }
175
176 Property::Value::Value(const Vector2& vectorValue)
177 : mImpl( NULL )
178 {
179   mImpl = new Impl( vectorValue );
180 }
181
182 Property::Value::Value(const Vector3& vectorValue)
183 : mImpl( NULL )
184 {
185   mImpl = new Impl( vectorValue );
186 }
187
188 Property::Value::Value(const Vector4& vectorValue)
189 : mImpl( NULL )
190 {
191   mImpl = new Impl( vectorValue );
192 }
193
194 Property::Value::Value(const Matrix3& matrixValue)
195 : mImpl( NULL )
196 {
197   mImpl = new Impl( matrixValue );
198 }
199
200 Property::Value::Value(const Matrix& matrixValue)
201 : mImpl( NULL )
202 {
203   mImpl = new Impl( matrixValue );
204 }
205
206 Property::Value::Value(const Rect<int>& rect)
207 : mImpl( NULL )
208 {
209   mImpl = new Impl( rect );
210 }
211
212 Property::Value::Value(const AngleAxis& angleAxisValue)
213 : mImpl( NULL )
214 {
215   mImpl = new Impl( angleAxisValue );
216 }
217
218 Property::Value::Value(const Quaternion& quaternionValue)
219 {
220   mImpl = new Impl( quaternionValue );
221 }
222
223 Property::Value::Value(const std::string& stringValue)
224 {
225   mImpl = new Impl( stringValue );
226 }
227
228 Property::Value::Value(const char *stringValue)
229 {
230   mImpl = new Impl( std::string(stringValue) );
231 }
232
233 Property::Value::Value(Property::Array &arrayValue)
234 {
235   mImpl = new Impl( arrayValue );
236 }
237
238 Property::Value::Value(Property::Map &mapValue)
239 {
240   mImpl = new Impl( mapValue );
241 }
242
243
244 Property::Value::~Value()
245 {
246   delete mImpl;
247 }
248
249 Property::Value::Value(const Value& value)
250 {
251   switch (value.GetType())
252   {
253     case Property::BOOLEAN:
254     {
255       mImpl = new Impl( value.Get<bool>() );
256       break;
257     }
258
259     case Property::FLOAT:
260     {
261       mImpl = new Impl( value.Get<float>() );
262       break;
263     }
264
265     case Property::INTEGER:
266     {
267       mImpl = new Impl( value.Get<int>() );
268       break;
269     }
270
271     case Property::UNSIGNED_INTEGER:
272     {
273       mImpl = new Impl( value.Get<unsigned int>() );
274       break;
275     }
276
277     case Property::VECTOR2:
278     {
279       mImpl = new Impl( value.Get<Vector2>() );
280       break;
281     }
282
283     case Property::VECTOR3:
284     {
285       mImpl = new Impl( value.Get<Vector3>() );
286       break;
287     }
288
289     case Property::VECTOR4:
290     {
291       mImpl = new Impl( value.Get<Vector4>() );
292       break;
293     }
294
295     case Property::RECTANGLE:
296     {
297       mImpl = new Impl( value.Get<Rect<int> >() );
298       break;
299     }
300
301     case Property::ROTATION:
302     {
303       mImpl = new Impl( value.Get<Quaternion>() );
304       break;
305     }
306
307     case Property::MATRIX3:
308     {
309       mImpl = new Impl( value.Get<Matrix3>());
310       break;
311     }
312
313     case Property::MATRIX:
314     {
315       mImpl = new Impl( value.Get<Matrix>());
316       break;
317     }
318
319     case Property::STRING:
320     {
321       mImpl = new Impl( value.Get<std::string>() );
322       break;
323     }
324
325     case Property::MAP:
326     {
327       mImpl = new Impl( value.Get<Property::Map>() );
328       break;
329     }
330
331     case Property::ARRAY:
332     {
333       mImpl = new Impl( value.Get<Property::Array>() );
334       break;
335     }
336
337     case Property::NONE: // fall
338     default:
339     {
340       mImpl = new Impl();
341       break;
342     }
343   }
344 }
345
346 Property::Value::Value(Type type)
347 {
348   switch (type)
349   {
350     case Property::BOOLEAN:
351     {
352       mImpl = new Impl( false );
353       break;
354     }
355
356     case Property::FLOAT:
357     {
358       mImpl = new Impl( 0.f );
359       break;
360     }
361
362     case Property::INTEGER:
363     {
364       mImpl = new Impl( 0 );
365       break;
366     }
367
368     case Property::UNSIGNED_INTEGER:
369     {
370       mImpl = new Impl( 0U );
371       break;
372     }
373
374     case Property::VECTOR2:
375     {
376       mImpl = new Impl( Vector2::ZERO );
377       break;
378     }
379
380     case Property::VECTOR3:
381     {
382       mImpl = new Impl( Vector3::ZERO );
383       break;
384     }
385
386     case Property::VECTOR4:
387     {
388       mImpl = new Impl( Vector4::ZERO );
389       break;
390     }
391
392     case Property::RECTANGLE:
393     {
394       mImpl = new Impl( Rect<int>(0,0,0,0) );
395       break;
396     }
397
398     case Property::ROTATION:
399     {
400       mImpl = new Impl( Quaternion( Radian(0.f), Vector3::YAXIS) );
401       break;
402     }
403
404     case Property::STRING:
405     {
406       mImpl = new Impl( std::string() );
407       break;
408     }
409
410     case Property::MAP:
411     {
412       mImpl = new Impl( Property::Map() );
413       break;
414     }
415
416     case Property::MATRIX:
417     {
418       mImpl = new Impl( Matrix() );
419       break;
420     }
421
422     case Property::MATRIX3:
423     {
424       mImpl = new Impl( Matrix3() );
425       break;
426     }
427
428     case Property::ARRAY:
429     {
430       mImpl = new Impl( Property::Array() );
431       break;
432     }
433
434     case Property::NONE: // fall
435     default:
436     {
437       mImpl = new Impl();
438       break;
439     }
440   }
441 }
442
443 Property::Value& Property::Value::operator=(const Property::Value& value)
444 {
445   if (this == &value)
446   {
447     // skip self assignment
448     return *this;
449   }
450
451   mImpl->mType = value.GetType();
452
453   switch (mImpl->mType)
454   {
455     case Property::BOOLEAN:
456     {
457       mImpl->mValue = value.Get<bool>();
458       break;
459     }
460
461     case Property::FLOAT:
462     {
463       mImpl->mValue = value.Get<float>();
464       break;
465     }
466
467     case Property::INTEGER:
468     {
469       mImpl->mValue = value.Get<int>();
470       break;
471     }
472
473     case Property::UNSIGNED_INTEGER:
474     {
475       mImpl->mValue = value.Get<unsigned int>();
476       break;
477     }
478
479     case Property::VECTOR2:
480     {
481       mImpl->mValue = value.Get<Vector2>();
482       break;
483     }
484
485     case Property::VECTOR3:
486     {
487       mImpl->mValue = value.Get<Vector3>();
488       break;
489     }
490
491     case Property::VECTOR4:
492     {
493       mImpl->mValue = value.Get<Vector4>();
494       break;
495     }
496
497     case Property::RECTANGLE:
498     {
499       mImpl->mValue = value.Get<Rect<int> >();
500       break;
501     }
502
503     case Property::ROTATION:
504     {
505       mImpl->mValue = value.Get<Quaternion>();
506       break;
507     }
508
509     case Property::STRING:
510     {
511       mImpl->mValue = value.Get<std::string>();
512       break;
513     }
514
515     case Property::MATRIX:
516     {
517       mImpl->mValue = value.Get<Matrix>();
518       break;
519     }
520
521     case Property::MATRIX3:
522     {
523       mImpl->mValue = value.Get<Matrix3>();
524       break;
525     }
526
527     case Property::MAP:
528     {
529       mImpl->mValue = value.Get<Property::Map>();
530       break;
531     }
532
533     case Property::ARRAY:
534     {
535       mImpl->mValue = value.Get<Property::Array>();
536       break;
537     }
538
539     case Property::NONE: // fall
540     default:
541     {
542       mImpl->mValue = Impl::AnyValue(0);
543       break;
544     }
545   }
546
547   return *this;
548 }
549
550 Property::Type Property::Value::GetType() const
551 {
552   return mImpl->mType;
553 }
554
555 void Property::Value::Get(bool& boolValue) const
556 {
557   DALI_ASSERT_DEBUG( Property::BOOLEAN == GetType() && "Property type invalid" );  // AnyCast does asserted type checking
558
559   boolValue = AnyCast<bool>(mImpl->mValue);
560 }
561
562 void Property::Value::Get(float& floatValue) const
563 {
564   DALI_ASSERT_DEBUG( Property::FLOAT == GetType() && "Property type invalid" );
565
566   floatValue = AnyCast<float>(mImpl->mValue);
567 }
568
569 void Property::Value::Get(int& integerValue) const
570 {
571   DALI_ASSERT_DEBUG( Property::INTEGER == GetType() && "Property type invalid" );
572
573   integerValue = AnyCast<int>(mImpl->mValue);
574 }
575
576 void Property::Value::Get(unsigned int& unsignedIntegerValue) const
577 {
578   DALI_ASSERT_DEBUG( Property::UNSIGNED_INTEGER == GetType() && "Property type invalid" );
579
580   unsignedIntegerValue = AnyCast<unsigned int>(mImpl->mValue);
581 }
582
583 void Property::Value::Get(Vector2& vectorValue) const
584 {
585   DALI_ASSERT_DEBUG( Property::VECTOR2 == GetType() && "Property type invalid" );
586
587   vectorValue = AnyCast<Vector2>(mImpl->mValue);
588 }
589
590 void Property::Value::Get(Vector3& vectorValue) const
591 {
592   DALI_ASSERT_DEBUG( Property::VECTOR3 == GetType() && "Property type invalid" );
593
594   vectorValue = AnyCast<Vector3>(mImpl->mValue);
595 }
596
597 void Property::Value::Get(Vector4& vectorValue) const
598 {
599   DALI_ASSERT_DEBUG( Property::VECTOR4 == GetType() && "Property type invalid" );
600
601   vectorValue = AnyCast<Vector4>(mImpl->mValue);
602 }
603
604 void Property::Value::Get(Matrix3& matrixValue) const
605 {
606   DALI_ASSERT_DEBUG( Property::MATRIX3 == GetType() && "Property type invalid" );
607   matrixValue = AnyCast<Matrix3>(mImpl->mValue);
608 }
609
610 void Property::Value::Get(Matrix& matrixValue) const
611 {
612   DALI_ASSERT_DEBUG( Property::MATRIX == GetType() && "Property type invalid" );
613   matrixValue = AnyCast<Matrix>(mImpl->mValue);
614 }
615
616 void Property::Value::Get(Rect<int>& rect) const
617 {
618   DALI_ASSERT_DEBUG( Property::RECTANGLE == GetType() && "Property type invalid" );
619
620   rect = AnyCast<Rect<int> >(mImpl->mValue);
621 }
622
623 void Property::Value::Get(AngleAxis& angleAxisValue) const
624 {
625   DALI_ASSERT_ALWAYS( Property::ROTATION == GetType() && "Property type invalid" );
626
627   // Orientations have two representations
628   DALI_ASSERT_DEBUG( typeid(Quaternion) == mImpl->mValue.GetType() ||
629                      typeid(AngleAxis)  == mImpl->mValue.GetType() );
630
631   if ( typeid(Quaternion) == mImpl->mValue.GetType() )
632   {
633     Quaternion quaternion = AnyCast<Quaternion>(mImpl->mValue);
634
635     quaternion.ToAxisAngle( angleAxisValue.axis, angleAxisValue.angle );
636   }
637   else
638   {
639     angleAxisValue = AnyCast<AngleAxis>(mImpl->mValue);
640   }
641 }
642
643 void Property::Value::Get(Quaternion& quaternionValue) const
644 {
645   DALI_ASSERT_DEBUG( Property::ROTATION == GetType() && "Property type invalid" );
646
647   // Orientations have two representations
648   DALI_ASSERT_DEBUG( typeid(Quaternion) == mImpl->mValue.GetType() ||
649                typeid(AngleAxis)  == mImpl->mValue.GetType() );
650
651   if ( typeid(Quaternion) == mImpl->mValue.GetType() )
652   {
653     quaternionValue = AnyCast<Quaternion>(mImpl->mValue);
654   }
655   else
656   {
657     AngleAxis angleAxis = AnyCast<AngleAxis>(mImpl->mValue);
658
659     quaternionValue = Quaternion( Radian(angleAxis.angle), angleAxis.axis );
660   }
661 }
662
663 void Property::Value::Get(std::string &out) const
664 {
665   DALI_ASSERT_DEBUG(Property::STRING == GetType() && "Property type invalid");
666
667   out = AnyCast<std::string>(mImpl->mValue);
668 }
669
670 void Property::Value::Get(Property::Array &out) const
671 {
672   DALI_ASSERT_DEBUG(Property::ARRAY == GetType() && "Property type invalid");
673
674   out = AnyCast<Property::Array>(mImpl->mValue);
675 }
676
677 void Property::Value::Get(Property::Map &out) const
678 {
679   DALI_ASSERT_DEBUG(Property::MAP == GetType() && "Property type invalid");
680
681   out = AnyCast<Property::Map>(mImpl->mValue);
682 }
683
684 Property::Value& Property::Value::GetValue(const std::string& key) const
685 {
686   DALI_ASSERT_DEBUG(Property::MAP == GetType() && "Property type invalid");
687
688   Property::Map *container = AnyCast<Property::Map>(&(mImpl->mValue));
689
690   DALI_ASSERT_DEBUG(container);
691
692   if(container)
693   {
694     Property::Value* value = container->Find( key );
695     if ( value )
696     {
697       return *value;
698     }
699   }
700
701   DALI_LOG_WARNING("Cannot find property map key %s", key.c_str());
702   DALI_ASSERT_ALWAYS(!"Cannot find property map key");
703 }
704
705 bool Property::Value::HasKey(const std::string& key) const
706 {
707   bool has = false;
708
709   if( Property::MAP == GetType() )
710   {
711     Property::Map *container = AnyCast<Property::Map>(&(mImpl->mValue));
712
713     DALI_ASSERT_DEBUG(container && "Property::Map has no container?");
714
715     if(container)
716     {
717       Property::Value* value = container->Find( key );
718       if ( value )
719       {
720         has = true;
721       }
722     }
723   }
724
725   return has;
726 }
727
728
729 const std::string& Property::Value::GetKey(const int index) const
730 {
731   switch( GetType() )
732   {
733     case Property::MAP:
734     {
735       Property::Map *container = AnyCast<Property::Map>(&(mImpl->mValue));
736       DALI_ASSERT_DEBUG(container && "Property::Map has no container?");
737       if(container)
738       {
739         if(0 <= index && index < static_cast<int>(container->Count()))
740         {
741           return container->GetKey( index );
742         }
743       }
744     }
745     break;
746     case Property::NONE:
747     case Property::ARRAY:
748     case Property::BOOLEAN:
749     case Property::FLOAT:
750     case Property::UNSIGNED_INTEGER:
751     case Property::INTEGER:
752     case Property::VECTOR2:
753     case Property::VECTOR3:
754     case Property::VECTOR4:
755     case Property::MATRIX:
756     case Property::MATRIX3:
757     case Property::RECTANGLE:
758     case Property::ROTATION:
759     case Property::STRING:
760     case Property::TYPE_COUNT:
761     {
762       break;
763     }
764   }
765
766
767   // should never return this
768   static std::string null;
769   return null;
770 }
771
772
773 void Property::Value::SetValue(const std::string& key, const Property::Value &value)
774 {
775   DALI_ASSERT_DEBUG(Property::MAP == GetType() && "Property type invalid");
776
777   Property::Map *container = AnyCast<Property::Map>(&(mImpl->mValue));
778
779   if(container)
780   {
781     (*container)[ key ] = value;
782   }
783 }
784
785 Property::Value& Property::Value::GetItem(const int index) const
786 {
787   switch( GetType() )
788   {
789     case Property::MAP:
790     {
791       Property::Map *container = AnyCast<Property::Map>(&(mImpl->mValue));
792
793       DALI_ASSERT_DEBUG(container && "Property::Map has no container?");
794       if(container)
795       {
796         DALI_ASSERT_ALWAYS(index < static_cast<int>(container->Count()) && "Property array index invalid");
797         DALI_ASSERT_ALWAYS(index >= 0 && "Property array index invalid");
798
799         return container->GetValue( index );
800       }
801     }
802     break;
803
804     case Property::ARRAY:
805     {
806       Property::Array *container = AnyCast<Property::Array>(&(mImpl->mValue));
807
808       DALI_ASSERT_DEBUG(container && "Property::Map has no container?");
809       if(container)
810       {
811         DALI_ASSERT_ALWAYS(index < static_cast<int>(container->Size()) && "Property array index invalid");
812         DALI_ASSERT_ALWAYS(index >= 0 && "Property array index invalid");
813
814         return (*container)[index];
815       }
816     }
817     break;
818
819     case Property::NONE:
820     case Property::BOOLEAN:
821     case Property::FLOAT:
822     case Property::INTEGER:
823     case Property::UNSIGNED_INTEGER:
824     case Property::VECTOR2:
825     case Property::VECTOR3:
826     case Property::VECTOR4:
827     case Property::MATRIX3:
828     case Property::MATRIX:
829     case Property::RECTANGLE:
830     case Property::ROTATION:
831     case Property::STRING:
832     case Property::TYPE_COUNT:
833     {
834       DALI_ASSERT_ALWAYS(!"Cannot GetItem on property Type; not a container");
835       break;
836     }
837
838   } // switch GetType()
839
840
841   DALI_ASSERT_ALWAYS(!"Property value index not valid");
842 }
843
844 Property::Value& Property::Value::GetItem(const int index, std::string& key) const
845 {
846   Property::Value& ret( GetItem(index) );
847
848   if( Property::MAP == GetType() )
849   {
850     Property::Map *container = AnyCast<Property::Map>(&(mImpl->mValue));
851     if( index < static_cast<int>(container->Count()) )
852     {
853       key = container->GetKey( index );
854     }
855   }
856
857   return ret;
858 }
859
860 void Property::Value::SetItem(const int index, const Property::Value &value)
861 {
862   switch( GetType() )
863   {
864     case Property::MAP:
865     {
866       Property::Map *container = AnyCast<Property::Map>(&(mImpl->mValue));
867       if( container && index < static_cast<int>(container->Count()) )
868       {
869         Property::Value& indexValue = container->GetValue( index );
870         indexValue = value;
871       }
872     }
873     break;
874
875     case Property::ARRAY:
876     {
877       Property::Array *container = AnyCast<Property::Array>(&(mImpl->mValue));
878       if( container && index < static_cast<int>(container->Size()) )
879       {
880         (*container)[index] = value;
881       }
882     }
883     break;
884
885     case Property::NONE:
886     case Property::BOOLEAN:
887     case Property::FLOAT:
888     case Property::INTEGER:
889     case Property::UNSIGNED_INTEGER:
890     case Property::VECTOR2:
891     case Property::VECTOR3:
892     case Property::VECTOR4:
893     case Property::MATRIX3:
894     case Property::MATRIX:
895     case Property::RECTANGLE:
896     case Property::ROTATION:
897     case Property::STRING:
898     case Property::TYPE_COUNT:
899     {
900       DALI_ASSERT_ALWAYS(!"Cannot SetItem on property Type; not a container");
901       break;
902     }
903   }
904 }
905
906 int Property::Value::AppendItem(const Property::Value &value)
907 {
908   DALI_ASSERT_DEBUG(Property::ARRAY == GetType() && "Property type invalid");
909
910   Property::Array *container = AnyCast<Property::Array>(&(mImpl->mValue));
911
912   if(container)
913   {
914     container->PushBack(value);
915     return container->Size() - 1;
916   }
917   else
918   {
919     return -1;
920   }
921
922 }
923
924 int Property::Value::GetSize() const
925 {
926   int ret = 0;
927
928   switch(GetType())
929   {
930     case Property::MAP:
931     {
932       Property::Map *container = AnyCast<Property::Map>(&(mImpl->mValue));
933       if(container)
934       {
935         ret = container->Count();
936       }
937     }
938     break;
939
940     case Property::ARRAY:
941     {
942       Property::Array *container = AnyCast<Property::Array>(&(mImpl->mValue));
943       if(container)
944       {
945         ret = container->Size();
946       }
947     }
948     break;
949
950     case Property::NONE:
951     case Property::BOOLEAN:
952     case Property::FLOAT:
953     case Property::INTEGER:
954     case Property::UNSIGNED_INTEGER:
955     case Property::VECTOR2:
956     case Property::VECTOR3:
957     case Property::VECTOR4:
958     case Property::MATRIX3:
959     case Property::MATRIX:
960     case Property::RECTANGLE:
961     case Property::ROTATION:
962     case Property::STRING:
963     case Property::TYPE_COUNT:
964     {
965       break;
966     }
967
968   }
969
970   return ret;
971 }
972
973 std::ostream& operator<< (std::ostream& stream, const Property::Value& value )
974 {
975
976   const Property::Value::Impl& impl( *value.mImpl );
977
978   switch( impl.mType )
979   {
980     case Dali::Property::STRING:
981     {
982       stream <<  AnyCast<std::string>(impl.mValue).c_str();
983       break;
984     }
985     case Dali::Property::VECTOR2:
986     {
987       stream << AnyCast<Vector2>(impl.mValue);
988       break;
989     }
990     case Dali::Property::VECTOR3:
991     {
992       stream << AnyCast<Vector3>(impl.mValue);
993       break;
994     }
995     case Dali::Property::VECTOR4:
996     {
997       stream << AnyCast<Vector4>(impl.mValue);
998       break;
999     }
1000     case Dali::Property::MATRIX:
1001     {
1002       stream << AnyCast<Matrix>(impl.mValue);
1003       break;
1004     }
1005     case Dali::Property::BOOLEAN:
1006     {
1007       stream << AnyCast<bool>(impl.mValue);
1008       break;
1009     }
1010     case Dali::Property::FLOAT:
1011     {
1012       stream << AnyCast<float>(impl.mValue);
1013       break;
1014     }
1015     case Dali::Property::INTEGER:
1016     {
1017        stream << AnyCast<int>(impl.mValue);
1018        break;
1019     }
1020     case Dali::Property::UNSIGNED_INTEGER:
1021     {
1022       stream << AnyCast<unsigned int>(impl.mValue);
1023       break;
1024     }
1025     case Dali::Property::RECTANGLE:
1026     {
1027       Dali::Rect<int> rect; // Propery Value rectangles are currently integer based
1028       value.Get( rect );
1029       stream << rect;
1030       break;
1031     }
1032     case Dali::Property::MATRIX3:
1033     {
1034       stream << AnyCast<Matrix3>(impl.mValue);
1035       break;
1036     }
1037     case Dali::Property::ROTATION:
1038     {
1039       // @todo this may change to Quaternion
1040       Dali::Quaternion q;
1041       value.Get( q );
1042       Dali::Vector4 v4 = q.EulerAngles();
1043       stream << v4;
1044       break;
1045     }
1046
1047     case Dali::Property::ARRAY:
1048     {
1049       // @todo Need to think about the best way to support array
1050       // E.g Do we want to create a JSON style array like:
1051       // [ {"property-name-0":"property-value-0", "property-name-1":"property-value-1"} ]
1052       stream << "ARRAY unsupported";
1053       break;
1054     }
1055     case Dali::Property::MAP:
1056     {
1057       Dali::Property::Map map;
1058       value.Get( map );
1059       stream << "Map containing " << map.Count() << " elements";
1060       break;
1061     }
1062     case Dali::Property::TYPE_COUNT:
1063     {
1064       stream << "unsupported TYPE_COUNT";
1065       break;
1066     }
1067     default:
1068     {
1069       stream << "unsupported type = " << value.GetType();
1070       break;
1071     }
1072   }
1073   return stream;
1074 }
1075
1076
1077 } // namespace Dali