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