UTC tests; PropertyValue, Vector2/3/4, Matrix
[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       // Orientations have two representations
304       DALI_ASSERT_DEBUG( typeid(Quaternion) == value.mImpl->mValue.GetType() ||
305                          typeid(AngleAxis)  == value.mImpl->mValue.GetType() );
306
307       if ( typeid(Quaternion) == value.mImpl->mValue.GetType() )
308       {
309         mImpl = new Impl( value.Get<Quaternion>() );
310       }
311       else
312       {
313         mImpl = new Impl( value.Get<AngleAxis>() );
314       }
315       break;
316     }
317
318     case Property::MATRIX3:
319     {
320       mImpl = new Impl( value.Get<Matrix3>());
321       break;
322     }
323
324     case Property::MATRIX:
325     {
326       mImpl = new Impl( value.Get<Matrix>());
327       break;
328     }
329
330     case Property::STRING:
331     {
332       mImpl = new Impl( value.Get<std::string>() );
333       break;
334     }
335
336     case Property::MAP:
337     {
338       mImpl = new Impl( value.Get<Property::Map>() );
339       break;
340     }
341
342     case Property::ARRAY:
343     {
344       mImpl = new Impl( value.Get<Property::Array>() );
345       break;
346     }
347
348     case Property::NONE: // fall
349     default:
350     {
351       mImpl = new Impl();
352       break;
353     }
354   }
355 }
356
357 Property::Value::Value(Type type)
358 {
359   switch (type)
360   {
361     case Property::BOOLEAN:
362     {
363       mImpl = new Impl( false );
364       break;
365     }
366
367     case Property::FLOAT:
368     {
369       mImpl = new Impl( 0.f );
370       break;
371     }
372
373     case Property::INTEGER:
374     {
375       mImpl = new Impl( 0 );
376       break;
377     }
378
379     case Property::UNSIGNED_INTEGER:
380     {
381       mImpl = new Impl( 0U );
382       break;
383     }
384
385     case Property::VECTOR2:
386     {
387       mImpl = new Impl( Vector2::ZERO );
388       break;
389     }
390
391     case Property::VECTOR3:
392     {
393       mImpl = new Impl( Vector3::ZERO );
394       break;
395     }
396
397     case Property::VECTOR4:
398     {
399       mImpl = new Impl( Vector4::ZERO );
400       break;
401     }
402
403     case Property::RECTANGLE:
404     {
405       mImpl = new Impl( Rect<int>(0,0,0,0) );
406       break;
407     }
408
409     case Property::ROTATION:
410     {
411       mImpl = new Impl( Quaternion( Radian(0.f), Vector3::YAXIS) );
412       break;
413     }
414
415     case Property::STRING:
416     {
417       mImpl = new Impl( std::string() );
418       break;
419     }
420
421     case Property::MAP:
422     {
423       mImpl = new Impl( Property::Map() );
424       break;
425     }
426
427     case Property::MATRIX:
428     {
429       mImpl = new Impl( Matrix() );
430       break;
431     }
432
433     case Property::MATRIX3:
434     {
435       mImpl = new Impl( Matrix3() );
436       break;
437     }
438
439     case Property::ARRAY:
440     {
441       mImpl = new Impl( Property::Array() );
442       break;
443     }
444
445     case Property::NONE: // fall
446     default:
447     {
448       mImpl = new Impl();
449       break;
450     }
451   }
452 }
453
454 Property::Value& Property::Value::operator=(const Property::Value& value)
455 {
456   if (this == &value)
457   {
458     // skip self assignment
459     return *this;
460   }
461
462   mImpl->mType = value.GetType();
463
464   switch (mImpl->mType)
465   {
466     case Property::BOOLEAN:
467     {
468       mImpl->mValue = value.Get<bool>();
469       break;
470     }
471
472     case Property::FLOAT:
473     {
474       mImpl->mValue = value.Get<float>();
475       break;
476     }
477
478     case Property::INTEGER:
479     {
480       mImpl->mValue = value.Get<int>();
481       break;
482     }
483
484     case Property::UNSIGNED_INTEGER:
485     {
486       mImpl->mValue = value.Get<unsigned int>();
487       break;
488     }
489
490     case Property::VECTOR2:
491     {
492       mImpl->mValue = value.Get<Vector2>();
493       break;
494     }
495
496     case Property::VECTOR3:
497     {
498       mImpl->mValue = value.Get<Vector3>();
499       break;
500     }
501
502     case Property::VECTOR4:
503     {
504       mImpl->mValue = value.Get<Vector4>();
505       break;
506     }
507
508     case Property::RECTANGLE:
509     {
510       mImpl->mValue = value.Get<Rect<int> >();
511       break;
512     }
513
514     case Property::ROTATION:
515     {
516       // Orientations have two representations
517       DALI_ASSERT_DEBUG( typeid(Quaternion) == value.mImpl->mValue.GetType() ||
518                          typeid(AngleAxis)  == value.mImpl->mValue.GetType() );
519
520       if ( typeid(Quaternion) == value.mImpl->mValue.GetType() )
521       {
522         mImpl = new Impl( value.Get<Quaternion>() );
523       }
524       else
525       {
526         mImpl = new Impl( value.Get<AngleAxis>() );
527       }
528       break;
529     }
530
531     case Property::STRING:
532     {
533       mImpl->mValue = value.Get<std::string>();
534       break;
535     }
536
537     case Property::MATRIX:
538     {
539       mImpl->mValue = value.Get<Matrix>();
540       break;
541     }
542
543     case Property::MATRIX3:
544     {
545       mImpl->mValue = value.Get<Matrix3>();
546       break;
547     }
548
549     case Property::MAP:
550     {
551       mImpl->mValue = value.Get<Property::Map>();
552       break;
553     }
554
555     case Property::ARRAY:
556     {
557       mImpl->mValue = value.Get<Property::Array>();
558       break;
559     }
560
561     case Property::NONE: // fall
562     default:
563     {
564       mImpl->mValue = Impl::AnyValue(0);
565       break;
566     }
567   }
568
569   return *this;
570 }
571
572 Property::Type Property::Value::GetType() const
573 {
574   return mImpl->mType;
575 }
576
577 void Property::Value::Get(bool& boolValue) const
578 {
579   DALI_ASSERT_DEBUG( Property::BOOLEAN == GetType() && "Property type invalid" );  // AnyCast does asserted type checking
580
581   boolValue = AnyCast<bool>(mImpl->mValue);
582 }
583
584 void Property::Value::Get(float& floatValue) const
585 {
586   DALI_ASSERT_DEBUG( Property::FLOAT == GetType() && "Property type invalid" );
587
588   floatValue = AnyCast<float>(mImpl->mValue);
589 }
590
591 void Property::Value::Get(int& integerValue) const
592 {
593   DALI_ASSERT_DEBUG( Property::INTEGER == GetType() && "Property type invalid" );
594
595   integerValue = AnyCast<int>(mImpl->mValue);
596 }
597
598 void Property::Value::Get(unsigned int& unsignedIntegerValue) const
599 {
600   DALI_ASSERT_DEBUG( Property::UNSIGNED_INTEGER == GetType() && "Property type invalid" );
601
602   unsignedIntegerValue = AnyCast<unsigned int>(mImpl->mValue);
603 }
604
605 void Property::Value::Get(Vector2& vectorValue) const
606 {
607   DALI_ASSERT_DEBUG( Property::VECTOR2 == GetType() && "Property type invalid" );
608
609   vectorValue = AnyCast<Vector2>(mImpl->mValue);
610 }
611
612 void Property::Value::Get(Vector3& vectorValue) const
613 {
614   DALI_ASSERT_DEBUG( Property::VECTOR3 == GetType() && "Property type invalid" );
615
616   vectorValue = AnyCast<Vector3>(mImpl->mValue);
617 }
618
619 void Property::Value::Get(Vector4& vectorValue) const
620 {
621   DALI_ASSERT_DEBUG( Property::VECTOR4 == GetType() && "Property type invalid" );
622
623   vectorValue = AnyCast<Vector4>(mImpl->mValue);
624 }
625
626 void Property::Value::Get(Matrix3& matrixValue) const
627 {
628   DALI_ASSERT_DEBUG( Property::MATRIX3 == GetType() && "Property type invalid" );
629   matrixValue = AnyCast<Matrix3>(mImpl->mValue);
630 }
631
632 void Property::Value::Get(Matrix& matrixValue) const
633 {
634   DALI_ASSERT_DEBUG( Property::MATRIX == GetType() && "Property type invalid" );
635   matrixValue = AnyCast<Matrix>(mImpl->mValue);
636 }
637
638 void Property::Value::Get(Rect<int>& rect) const
639 {
640   DALI_ASSERT_DEBUG( Property::RECTANGLE == GetType() && "Property type invalid" );
641
642   rect = AnyCast<Rect<int> >(mImpl->mValue);
643 }
644
645 void Property::Value::Get(AngleAxis& angleAxisValue) const
646 {
647   DALI_ASSERT_ALWAYS( Property::ROTATION == GetType() && "Property type invalid" );
648
649   // Orientations have two representations
650   DALI_ASSERT_DEBUG( typeid(Quaternion) == mImpl->mValue.GetType() ||
651                      typeid(AngleAxis)  == mImpl->mValue.GetType() );
652
653   if ( typeid(Quaternion) == mImpl->mValue.GetType() )
654   {
655     Quaternion quaternion = AnyCast<Quaternion>(mImpl->mValue);
656
657     quaternion.ToAxisAngle( angleAxisValue.axis, angleAxisValue.angle );
658   }
659   else
660   {
661     angleAxisValue = AnyCast<AngleAxis>(mImpl->mValue);
662   }
663 }
664
665 void Property::Value::Get(Quaternion& quaternionValue) const
666 {
667   DALI_ASSERT_DEBUG( Property::ROTATION == GetType() && "Property type invalid" );
668
669   // Orientations have two representations
670   DALI_ASSERT_DEBUG( typeid(Quaternion) == mImpl->mValue.GetType() ||
671                typeid(AngleAxis)  == mImpl->mValue.GetType() );
672
673   if ( typeid(Quaternion) == mImpl->mValue.GetType() )
674   {
675     quaternionValue = AnyCast<Quaternion>(mImpl->mValue);
676   }
677   else
678   {
679     AngleAxis angleAxis = AnyCast<AngleAxis>(mImpl->mValue);
680
681     quaternionValue = Quaternion( Radian(angleAxis.angle), angleAxis.axis );
682   }
683 }
684
685 void Property::Value::Get(std::string &out) const
686 {
687   DALI_ASSERT_DEBUG(Property::STRING == GetType() && "Property type invalid");
688
689   out = AnyCast<std::string>(mImpl->mValue);
690 }
691
692 void Property::Value::Get(Property::Array &out) const
693 {
694   DALI_ASSERT_DEBUG(Property::ARRAY == GetType() && "Property type invalid");
695
696   out = AnyCast<Property::Array>(mImpl->mValue);
697 }
698
699 void Property::Value::Get(Property::Map &out) const
700 {
701   DALI_ASSERT_DEBUG(Property::MAP == GetType() && "Property type invalid");
702
703   out = AnyCast<Property::Map>(mImpl->mValue);
704 }
705
706 Property::Value& Property::Value::GetValue(const std::string& key) const
707 {
708   DALI_ASSERT_DEBUG(Property::MAP == GetType() && "Property type invalid");
709
710   Property::Map *container = AnyCast<Property::Map>(&(mImpl->mValue));
711
712   DALI_ASSERT_DEBUG(container);
713
714   if(container)
715   {
716     Property::Value* value = container->Find( key );
717     if ( value )
718     {
719       return *value;
720     }
721   }
722
723   DALI_LOG_WARNING("Cannot find property map key %s", key.c_str());
724   DALI_ASSERT_ALWAYS(!"Cannot find property map key");
725 }
726
727 bool Property::Value::HasKey(const std::string& key) const
728 {
729   bool has = false;
730
731   if( Property::MAP == GetType() )
732   {
733     Property::Map *container = AnyCast<Property::Map>(&(mImpl->mValue));
734
735     DALI_ASSERT_DEBUG(container && "Property::Map has no container?");
736
737     if(container)
738     {
739       Property::Value* value = container->Find( key );
740       if ( value )
741       {
742         has = true;
743       }
744     }
745   }
746
747   return has;
748 }
749
750
751 const std::string& Property::Value::GetKey(const int index) const
752 {
753   switch( GetType() )
754   {
755     case Property::MAP:
756     {
757       Property::Map *container = AnyCast<Property::Map>(&(mImpl->mValue));
758       DALI_ASSERT_DEBUG(container && "Property::Map has no container?");
759       if(container)
760       {
761         if(0 <= index && index < static_cast<int>(container->Count()))
762         {
763           return container->GetKey( index );
764         }
765       }
766     }
767     break;
768     case Property::NONE:
769     case Property::ARRAY:
770     case Property::BOOLEAN:
771     case Property::FLOAT:
772     case Property::UNSIGNED_INTEGER:
773     case Property::INTEGER:
774     case Property::VECTOR2:
775     case Property::VECTOR3:
776     case Property::VECTOR4:
777     case Property::MATRIX:
778     case Property::MATRIX3:
779     case Property::RECTANGLE:
780     case Property::ROTATION:
781     case Property::STRING:
782     case Property::TYPE_COUNT:
783     {
784       break;
785     }
786   }
787
788
789   // should never return this
790   static std::string null;
791   return null;
792 }
793
794
795 void Property::Value::SetValue(const std::string& key, const Property::Value &value)
796 {
797   DALI_ASSERT_DEBUG(Property::MAP == GetType() && "Property type invalid");
798
799   Property::Map *container = AnyCast<Property::Map>(&(mImpl->mValue));
800
801   if(container)
802   {
803     (*container)[ key ] = value;
804   }
805 }
806
807 Property::Value& Property::Value::GetItem(const int index) const
808 {
809   switch( GetType() )
810   {
811     case Property::MAP:
812     {
813       Property::Map *container = AnyCast<Property::Map>(&(mImpl->mValue));
814
815       DALI_ASSERT_DEBUG(container && "Property::Map has no container?");
816       if(container)
817       {
818         DALI_ASSERT_ALWAYS(index < static_cast<int>(container->Count()) && "Property array index invalid");
819         DALI_ASSERT_ALWAYS(index >= 0 && "Property array index invalid");
820
821         return container->GetValue( index );
822       }
823     }
824     break;
825
826     case Property::ARRAY:
827     {
828       Property::Array *container = AnyCast<Property::Array>(&(mImpl->mValue));
829
830       DALI_ASSERT_DEBUG(container && "Property::Map has no container?");
831       if(container)
832       {
833         DALI_ASSERT_ALWAYS(index < static_cast<int>(container->Size()) && "Property array index invalid");
834         DALI_ASSERT_ALWAYS(index >= 0 && "Property array index invalid");
835
836         return (*container)[index];
837       }
838     }
839     break;
840
841     case Property::NONE:
842     case Property::BOOLEAN:
843     case Property::FLOAT:
844     case Property::INTEGER:
845     case Property::UNSIGNED_INTEGER:
846     case Property::VECTOR2:
847     case Property::VECTOR3:
848     case Property::VECTOR4:
849     case Property::MATRIX3:
850     case Property::MATRIX:
851     case Property::RECTANGLE:
852     case Property::ROTATION:
853     case Property::STRING:
854     case Property::TYPE_COUNT:
855     {
856       DALI_ASSERT_ALWAYS(!"Cannot GetItem on property Type; not a container");
857       break;
858     }
859
860   } // switch GetType()
861
862
863   DALI_ASSERT_ALWAYS(!"Property value index not valid");
864 }
865
866 Property::Value& Property::Value::GetItem(const int index, std::string& key) const
867 {
868   Property::Value& ret( GetItem(index) );
869
870   if( Property::MAP == GetType() )
871   {
872     Property::Map *container = AnyCast<Property::Map>(&(mImpl->mValue));
873     if( index < static_cast<int>(container->Count()) )
874     {
875       key = container->GetKey( index );
876     }
877   }
878
879   return ret;
880 }
881
882 void Property::Value::SetItem(const int index, const Property::Value &value)
883 {
884   switch( GetType() )
885   {
886     case Property::MAP:
887     {
888       Property::Map *container = AnyCast<Property::Map>(&(mImpl->mValue));
889       if( container && index < static_cast<int>(container->Count()) )
890       {
891         Property::Value& indexValue = container->GetValue( index );
892         indexValue = value;
893       }
894     }
895     break;
896
897     case Property::ARRAY:
898     {
899       Property::Array *container = AnyCast<Property::Array>(&(mImpl->mValue));
900       if( container && index < static_cast<int>(container->Size()) )
901       {
902         (*container)[index] = value;
903       }
904     }
905     break;
906
907     case Property::NONE:
908     case Property::BOOLEAN:
909     case Property::FLOAT:
910     case Property::INTEGER:
911     case Property::UNSIGNED_INTEGER:
912     case Property::VECTOR2:
913     case Property::VECTOR3:
914     case Property::VECTOR4:
915     case Property::MATRIX3:
916     case Property::MATRIX:
917     case Property::RECTANGLE:
918     case Property::ROTATION:
919     case Property::STRING:
920     case Property::TYPE_COUNT:
921     {
922       DALI_ASSERT_ALWAYS(!"Cannot SetItem on property Type; not a container");
923       break;
924     }
925   }
926 }
927
928 int Property::Value::AppendItem(const Property::Value &value)
929 {
930   DALI_ASSERT_DEBUG(Property::ARRAY == GetType() && "Property type invalid");
931
932   Property::Array *container = AnyCast<Property::Array>(&(mImpl->mValue));
933
934   if(container)
935   {
936     container->PushBack(value);
937     return container->Size() - 1;
938   }
939   else
940   {
941     return -1;
942   }
943
944 }
945
946 int Property::Value::GetSize() const
947 {
948   int ret = 0;
949
950   switch(GetType())
951   {
952     case Property::MAP:
953     {
954       Property::Map *container = AnyCast<Property::Map>(&(mImpl->mValue));
955       if(container)
956       {
957         ret = container->Count();
958       }
959     }
960     break;
961
962     case Property::ARRAY:
963     {
964       Property::Array *container = AnyCast<Property::Array>(&(mImpl->mValue));
965       if(container)
966       {
967         ret = container->Size();
968       }
969     }
970     break;
971
972     case Property::NONE:
973     case Property::BOOLEAN:
974     case Property::FLOAT:
975     case Property::INTEGER:
976     case Property::UNSIGNED_INTEGER:
977     case Property::VECTOR2:
978     case Property::VECTOR3:
979     case Property::VECTOR4:
980     case Property::MATRIX3:
981     case Property::MATRIX:
982     case Property::RECTANGLE:
983     case Property::ROTATION:
984     case Property::STRING:
985     case Property::TYPE_COUNT:
986     {
987       break;
988     }
989
990   }
991
992   return ret;
993 }
994
995 std::ostream& operator<< (std::ostream& stream, const Property::Value& value )
996 {
997
998   const Property::Value::Impl& impl( *value.mImpl );
999
1000   switch( impl.mType )
1001   {
1002     case Dali::Property::STRING:
1003     {
1004       stream <<  AnyCast<std::string>(impl.mValue).c_str();
1005       break;
1006     }
1007     case Dali::Property::VECTOR2:
1008     {
1009       stream << AnyCast<Vector2>(impl.mValue);
1010       break;
1011     }
1012     case Dali::Property::VECTOR3:
1013     {
1014       stream << AnyCast<Vector3>(impl.mValue);
1015       break;
1016     }
1017     case Dali::Property::VECTOR4:
1018     {
1019       stream << AnyCast<Vector4>(impl.mValue);
1020       break;
1021     }
1022     case Dali::Property::MATRIX:
1023     {
1024       stream << AnyCast<Matrix>(impl.mValue);
1025       break;
1026     }
1027     case Dali::Property::BOOLEAN:
1028     {
1029       stream << AnyCast<bool>(impl.mValue);
1030       break;
1031     }
1032     case Dali::Property::FLOAT:
1033     {
1034       stream << AnyCast<float>(impl.mValue);
1035       break;
1036     }
1037     case Dali::Property::INTEGER:
1038     {
1039        stream << AnyCast<int>(impl.mValue);
1040        break;
1041     }
1042     case Dali::Property::UNSIGNED_INTEGER:
1043     {
1044       stream << AnyCast<unsigned int>(impl.mValue);
1045       break;
1046     }
1047     case Dali::Property::RECTANGLE:
1048     {
1049       Dali::Rect<int> rect; // Propery Value rectangles are currently integer based
1050       value.Get( rect );
1051       stream << rect;
1052       break;
1053     }
1054     case Dali::Property::MATRIX3:
1055     {
1056       stream << AnyCast<Matrix3>(impl.mValue);
1057       break;
1058     }
1059     case Dali::Property::ROTATION:
1060     {
1061       // @todo this may change to Quaternion
1062       Dali::Quaternion q;
1063       value.Get( q );
1064       Dali::Vector4 v4 = q.EulerAngles();
1065       stream << v4;
1066       break;
1067     }
1068
1069     case Dali::Property::ARRAY:
1070     {
1071       // @todo Need to think about the best way to support array
1072       // E.g Do we want to create a JSON style array like:
1073       // [ {"property-name-0":"property-value-0", "property-name-1":"property-value-1"} ]
1074       stream << "ARRAY unsupported";
1075       break;
1076     }
1077     case Dali::Property::MAP:
1078     {
1079       Dali::Property::Map map;
1080       value.Get( map );
1081       stream << "Map containing " << map.Count() << " elements";
1082       break;
1083     }
1084     case Dali::Property::TYPE_COUNT:
1085     {
1086       stream << "unsupported TYPE_COUNT";
1087       break;
1088     }
1089     default:
1090     {
1091       stream << "unsupported type = " << value.GetType();
1092       break;
1093     }
1094   }
1095   return stream;
1096 }
1097
1098
1099 } // namespace Dali