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