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