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