2 * Copyright (c) 2015 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #include <dali/public-api/object/property-value.h>
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>
45 * Helper to check if the property value can be read as int/unsigned int/bool
47 inline bool IsIntegerType( Property::Type type )
49 return ( Property::BOOLEAN == type )||( Property::INTEGER == type )||(Property::UNSIGNED_INTEGER == type );
53 struct Property::Value::Impl
56 : type( Property::NONE ),
60 Impl( bool booleanValue )
61 : type( Property::BOOLEAN ),
62 integerValue( booleanValue )
65 Impl( float floatValue )
66 : type( Property::FLOAT ),
67 floatValue( floatValue )
70 Impl( int integerValue )
71 : type( Property::INTEGER ),
72 integerValue( integerValue )
75 Impl( unsigned int unsignedIntegerValue )
76 : type( Property::UNSIGNED_INTEGER ),
77 unsignedIntegerValue( unsignedIntegerValue )
80 Impl( const Vector2& vectorValue )
81 : type( Property::VECTOR2 ),
82 vector2Value( new Vector2( vectorValue ) )
85 Impl( const Vector3& vectorValue )
86 : type( Property::VECTOR3 ),
87 vector3Value( new Vector3( vectorValue ) )
90 Impl( const Vector4& vectorValue )
91 : type( Property::VECTOR4 ),
92 vector4Value( new Vector4( vectorValue ) )
95 Impl( const Matrix3& matrixValue )
96 : type( Property::MATRIX3 ),
97 matrix3Value( new Matrix3( matrixValue ) )
101 Impl( const Matrix& matrixValue )
102 : type( Property::MATRIX ),
103 matrixValue( new Matrix( matrixValue ) )
107 Impl( const AngleAxis& angleAxisValue )
108 : type( Property::ROTATION ),
109 quaternionValue( new Quaternion( angleAxisValue.angle, angleAxisValue.axis ) )
113 Impl( const Quaternion& quaternionValue )
114 : type( Property::ROTATION ),
115 quaternionValue( new Quaternion( quaternionValue ) )
119 Impl(const std::string& stringValue)
120 : type( Property::STRING ),
121 stringValue( new std::string( stringValue ) )
125 Impl( const Rect<int>& rectValue )
126 : type( Property::RECTANGLE ),
127 rectValue( new Rect<int>( rectValue ) )
131 Impl( const Property::Array& arrayValue )
132 : type( Property::ARRAY ),
133 arrayValue( new Property::Array( arrayValue ) )
137 Impl( const Property::Map& mapValue )
138 : type( Property::MAP ),
139 mapValue( new Property::Map( mapValue ) )
144 * Destructor, takes care of releasing the dynamically allocated types
150 case Property::NONE : // FALLTHROUGH
151 case Property::BOOLEAN : // FALLTHROUGH
152 case Property::FLOAT : // FALLTHROUGH
153 case Property::INTEGER : // FALLTHROUGH
154 case Property::UNSIGNED_INTEGER :
156 break; // nothing to do
158 case Property::VECTOR2 :
163 case Property::VECTOR3:
168 case Property::VECTOR4:
173 case Property::MATRIX3:
178 case Property::MATRIX:
183 case Property::RECTANGLE:
188 case Property::ROTATION:
190 delete quaternionValue;
193 case Property::STRING:
198 case Property::ARRAY:
218 unsigned int unsignedIntegerValue;
219 // must use pointers for any class value pre c++ 11
220 Vector2* vector2Value;
221 Vector3* vector3Value;
222 Vector4* vector4Value;
223 Matrix3* matrix3Value;
225 Quaternion* quaternionValue;
226 std::string* stringValue;
227 Rect<int>* rectValue;
228 Property::Array* arrayValue;
229 Property::Map* mapValue;
233 Property::Value::Value()
238 Property::Value::Value( bool booleanValue )
239 : mImpl( new Impl( booleanValue ) )
243 Property::Value::Value( float floatValue )
244 : mImpl( new Impl( floatValue ) )
248 Property::Value::Value( int integerValue )
249 : mImpl( new Impl( integerValue ) )
253 Property::Value::Value( unsigned int unsignedIntegerValue )
254 : mImpl( new Impl( unsignedIntegerValue ) )
258 Property::Value::Value( const Vector2& vectorValue )
259 : mImpl( new Impl( vectorValue ) )
263 Property::Value::Value( const Vector3& vectorValue )
264 : mImpl( new Impl( vectorValue ) )
268 Property::Value::Value( const Vector4& vectorValue )
269 : mImpl( new Impl( vectorValue ) )
273 Property::Value::Value( const Matrix3& matrixValue )
274 : mImpl( new Impl( matrixValue ) )
278 Property::Value::Value( const Matrix& matrixValue )
279 : mImpl( new Impl( matrixValue ) )
283 Property::Value::Value( const Rect<int>& rectValue )
284 : mImpl( new Impl( rectValue ) )
288 Property::Value::Value( const AngleAxis& angleAxisValue )
289 : mImpl( new Impl( angleAxisValue ) )
293 Property::Value::Value( const Quaternion& quaternionValue )
294 : mImpl( new Impl( quaternionValue ) )
298 Property::Value::Value( const std::string& stringValue )
299 : mImpl( new Impl( stringValue ) )
303 Property::Value::Value( const char* stringValue )
306 if( stringValue ) // string constructor is undefined with NULL pointer
308 mImpl = new Impl( std::string(stringValue) );
312 mImpl = new Impl( std::string() );
316 Property::Value::Value( Property::Array& arrayValue )
317 : mImpl( new Impl( arrayValue ) )
321 Property::Value::Value( Property::Map& mapValue )
322 : mImpl( new Impl( mapValue ) )
326 Property::Value::Value( Type type )
330 case Property::BOOLEAN:
332 mImpl = new Impl( false );
335 case Property::FLOAT:
337 mImpl = new Impl( 0.f );
340 case Property::INTEGER:
342 mImpl = new Impl( 0 );
345 case Property::UNSIGNED_INTEGER:
347 mImpl = new Impl( 0U );
350 case Property::VECTOR2:
352 mImpl = new Impl( Vector2::ZERO );
355 case Property::VECTOR3:
357 mImpl = new Impl( Vector3::ZERO );
360 case Property::VECTOR4:
362 mImpl = new Impl( Vector4::ZERO );
365 case Property::RECTANGLE:
367 mImpl = new Impl( Rect<int>(0,0,0,0) );
370 case Property::ROTATION:
372 mImpl = new Impl( Quaternion() );
375 case Property::STRING:
377 mImpl = new Impl( std::string() );
380 case Property::MATRIX:
382 mImpl = new Impl( Matrix() );
385 case Property::MATRIX3:
387 mImpl = new Impl( Matrix3() );
390 case Property::ARRAY:
392 mImpl = new Impl( Property::Array() );
397 mImpl = new Impl( Property::Map() );
407 Property::Value::Value( const Property::Value& value )
410 // reuse assignment operator
414 Property::Value& Property::Value::operator=( const Property::Value& value )
416 if ( this == &value )
418 // skip self assignment
421 // if we are assigned an empty value, just drop impl
428 // first check if the type is the same, no need to change impl, just assign
429 if( mImpl && ( mImpl->type == value.mImpl->type ) )
431 switch( mImpl->type )
433 case Property::BOOLEAN:
435 mImpl->integerValue = value.mImpl->integerValue;
438 case Property::FLOAT:
440 mImpl->floatValue = value.mImpl->floatValue;
443 case Property::INTEGER:
445 mImpl->integerValue = value.mImpl->integerValue;
448 case Property::UNSIGNED_INTEGER:
450 mImpl->unsignedIntegerValue = value.mImpl->unsignedIntegerValue;
453 case Property::VECTOR2:
455 *mImpl->vector2Value = *value.mImpl->vector2Value; // type cannot change in mImpl so vector is allocated
458 case Property::VECTOR3:
460 *mImpl->vector3Value = *value.mImpl->vector3Value; // type cannot change in mImpl so vector is allocated
463 case Property::VECTOR4:
465 *mImpl->vector4Value = *value.mImpl->vector4Value; // type cannot change in mImpl so vector is allocated
468 case Property::RECTANGLE:
470 *mImpl->rectValue = *value.mImpl->rectValue; // type cannot change in mImpl so rect is allocated
473 case Property::ROTATION:
475 *mImpl->quaternionValue = *value.mImpl->quaternionValue; // type cannot change in mImpl so quaternion is allocated
478 case Property::STRING:
480 *mImpl->stringValue = *value.mImpl->stringValue; // type cannot change in mImpl so string is allocated
483 case Property::MATRIX:
485 *mImpl->matrixValue = *value.mImpl->matrixValue; // type cannot change in mImpl so matrix is allocated
488 case Property::MATRIX3:
490 *mImpl->matrix3Value = *value.mImpl->matrix3Value; // type cannot change in mImpl so matrix is allocated
493 case Property::ARRAY:
495 *mImpl->arrayValue = *value.mImpl->arrayValue; // type cannot change in mImpl so array is allocated
500 *mImpl->mapValue = *value.mImpl->mapValue; // type cannot change in mImpl so map is allocated
504 { // mImpl will be NULL, there's no way to get to this case
510 // different type, release old impl and create new
511 Impl* newImpl( NULL );
512 switch ( value.mImpl->type )
514 case Property::BOOLEAN:
516 newImpl = new Impl( bool( value.mImpl->integerValue ) );
519 case Property::FLOAT:
521 newImpl = new Impl( value.mImpl->floatValue );
524 case Property::INTEGER:
526 newImpl = new Impl( value.mImpl->integerValue );
529 case Property::UNSIGNED_INTEGER:
531 newImpl = new Impl( value.mImpl->unsignedIntegerValue );
534 case Property::VECTOR2:
536 newImpl = new Impl( *value.mImpl->vector2Value ); // type cannot change in mImpl so vector is allocated
539 case Property::VECTOR3:
541 newImpl = new Impl( *value.mImpl->vector3Value ); // type cannot change in mImpl so vector is allocated
544 case Property::VECTOR4:
546 newImpl = new Impl( *value.mImpl->vector4Value ); // type cannot change in mImpl so vector is allocated
549 case Property::RECTANGLE:
551 newImpl = new Impl( *value.mImpl->rectValue ); // type cannot change in mImpl so rect is allocated
554 case Property::ROTATION:
556 newImpl = new Impl( *value.mImpl->quaternionValue ); // type cannot change in mImpl so quaternion is allocated
559 case Property::MATRIX3:
561 newImpl = new Impl( *value.mImpl->matrix3Value ); // type cannot change in mImpl so matrix is allocated
564 case Property::MATRIX:
566 newImpl = new Impl( *value.mImpl->matrixValue ); // type cannot change in mImpl so matrix is allocated
569 case Property::STRING:
571 newImpl = new Impl( *value.mImpl->stringValue ); // type cannot change in mImpl so string is allocated
574 case Property::ARRAY:
576 newImpl = new Impl( *value.mImpl->arrayValue ); // type cannot change in mImpl so array is allocated
581 newImpl = new Impl( *value.mImpl->mapValue ); // type cannot change in mImpl so map is allocated
585 { // NULL value will be used for "empty" value
595 Property::Value::~Value()
600 Property::Type Property::Value::GetType() const
602 Property::Type type( Property::NONE );
610 bool Property::Value::Get( bool& booleanValue ) const
612 bool converted = false;
613 if( mImpl && IsIntegerType( mImpl->type ) )
615 booleanValue = mImpl->integerValue;
621 bool Property::Value::Get( float& floatValue ) const
623 bool converted = false;
626 if( mImpl->type == FLOAT )
628 floatValue = mImpl->floatValue;
631 else if( IsIntegerType( mImpl->type ) )
633 floatValue = static_cast< float >( mImpl->integerValue );
640 bool Property::Value::Get( int& integerValue ) const
642 bool converted = false;
645 if( IsIntegerType( mImpl->type ) )
647 integerValue = mImpl->integerValue;
650 else if( mImpl->type == FLOAT )
652 integerValue = static_cast< int >( mImpl->floatValue );
659 bool Property::Value::Get( unsigned int& unsignedIntegerValue ) const
661 bool converted = false;
662 if( mImpl && IsIntegerType( mImpl->type ) )
664 unsignedIntegerValue = mImpl->unsignedIntegerValue;
670 bool Property::Value::Get( Vector2& vectorValue ) const
672 bool converted = false;
673 if( mImpl && (mImpl->type == VECTOR2) ) // type cannot change in mImpl so vector is allocated
675 vectorValue = *(mImpl->vector2Value);
681 bool Property::Value::Get( Vector3& vectorValue ) const
683 bool converted = false;
684 if( mImpl && (mImpl->type == VECTOR3) ) // type cannot change in mImpl so vector is allocated
686 vectorValue = *(mImpl->vector3Value);
692 bool Property::Value::Get( Vector4& vectorValue ) const
694 bool converted = false;
695 if( mImpl && (mImpl->type == VECTOR4) ) // type cannot change in mImpl so vector is allocated
697 vectorValue = *(mImpl->vector4Value);
703 bool Property::Value::Get( Matrix3& matrixValue ) const
705 bool converted = false;
706 if( mImpl && (mImpl->type == MATRIX3) ) // type cannot change in mImpl so matrix is allocated
708 matrixValue = *(mImpl->matrix3Value);
714 bool Property::Value::Get( Matrix& matrixValue ) const
716 bool converted = false;
717 if( mImpl && (mImpl->type == MATRIX) ) // type cannot change in mImpl so matrix is allocated
719 matrixValue = *(mImpl->matrixValue);
725 bool Property::Value::Get( Rect<int>& rectValue ) const
727 bool converted = false;
728 if( mImpl && (mImpl->type == RECTANGLE) ) // type cannot change in mImpl so rect is allocated
730 rectValue = *(mImpl->rectValue);
736 bool Property::Value::Get( AngleAxis& angleAxisValue ) const
738 bool converted = false;
739 if( mImpl && (mImpl->type == ROTATION) ) // type cannot change in mImpl so quaternion is allocated
741 mImpl->quaternionValue->ToAxisAngle( angleAxisValue.axis, angleAxisValue.angle );
747 bool Property::Value::Get( Quaternion& quaternionValue ) const
749 bool converted = false;
750 if( mImpl && (mImpl->type == ROTATION) ) // type cannot change in mImpl so quaternion is allocated
752 quaternionValue = *(mImpl->quaternionValue);
758 bool Property::Value::Get( std::string& stringValue ) const
760 bool converted = false;
761 if( mImpl && (mImpl->type == STRING) ) // type cannot change in mImpl so string is allocated
763 stringValue.assign( *(mImpl->stringValue) );
769 bool Property::Value::Get( Property::Array& arrayValue ) const
771 bool converted = false;
772 if( mImpl && (mImpl->type == ARRAY) ) // type cannot change in mImpl so array is allocated
774 arrayValue = *(mImpl->arrayValue);
780 bool Property::Value::Get( Property::Map& mapValue ) const
782 bool converted = false;
783 if( mImpl && (mImpl->type == MAP) ) // type cannot change in mImpl so map is allocated
785 mapValue = *(mImpl->mapValue);
791 Property::Array* Property::Value::GetArray() const
793 Property::Array* array = NULL;
794 if( mImpl && (mImpl->type == ARRAY) ) // type cannot change in mImpl so array is allocated
796 array = mImpl->arrayValue;
801 Property::Map* Property::Value::GetMap() const
803 Property::Map* map = NULL;
804 if( mImpl && (mImpl->type == MAP) ) // type cannot change in mImpl so map is allocated
806 map = mImpl->mapValue;
811 std::ostream& operator<<( std::ostream& stream, const Property::Value& value )
815 const Property::Value::Impl& impl( *value.mImpl );
819 case Dali::Property::BOOLEAN:
821 stream << impl.integerValue;
824 case Dali::Property::FLOAT:
826 stream << impl.floatValue;
829 case Dali::Property::INTEGER:
831 stream << impl.integerValue;
834 case Dali::Property::UNSIGNED_INTEGER:
836 stream << impl.unsignedIntegerValue;
839 case Dali::Property::VECTOR2:
841 stream << *impl.vector2Value;
844 case Dali::Property::VECTOR3:
846 stream << *impl.vector3Value;
849 case Dali::Property::VECTOR4:
851 stream << *impl.vector4Value;
854 case Dali::Property::MATRIX3:
856 stream << *impl.matrix3Value;
859 case Dali::Property::MATRIX:
861 stream << *impl.matrixValue;
864 case Dali::Property::RECTANGLE:
866 stream << *impl.rectValue;
869 case Dali::Property::ROTATION:
871 stream << *impl.quaternionValue;
874 case Dali::Property::STRING:
876 stream << *impl.stringValue;
879 case Dali::Property::ARRAY:
881 stream << "Array containing" << impl.arrayValue->Count() << " elements"; // TODO add ostream<< operator in array
884 case Dali::Property::MAP:
886 stream << "Map containing " << impl.mapValue->Count() << " elements"; // TODO add ostream<< operator in map
889 case Dali::Property::NONE:
891 stream << "undefined type";
898 stream << "empty type";