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/bool
47 inline bool IsIntegerType( Property::Type type )
49 return ( Property::BOOLEAN == type )||( Property::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( const Vector2& vectorValue )
76 : type( Property::VECTOR2 ),
77 vector2Value( new Vector2( vectorValue ) )
80 Impl( const Vector3& vectorValue )
81 : type( Property::VECTOR3 ),
82 vector3Value( new Vector3( vectorValue ) )
85 Impl( const Vector4& vectorValue )
86 : type( Property::VECTOR4 ),
87 vector4Value( new Vector4( vectorValue ) )
90 Impl( const Matrix3& matrixValue )
91 : type( Property::MATRIX3 ),
92 matrix3Value( new Matrix3( matrixValue ) )
96 Impl( const Matrix& matrixValue )
97 : type( Property::MATRIX ),
98 matrixValue( new Matrix( matrixValue ) )
102 Impl( const AngleAxis& angleAxisValue )
103 : type( Property::ROTATION ),
104 quaternionValue( new Quaternion( angleAxisValue.angle, angleAxisValue.axis ) )
108 Impl( const Quaternion& quaternionValue )
109 : type( Property::ROTATION ),
110 quaternionValue( new Quaternion( quaternionValue ) )
114 Impl(const std::string& stringValue)
115 : type( Property::STRING ),
116 stringValue( new std::string( stringValue ) )
120 Impl( const Rect<int>& rectValue )
121 : type( Property::RECTANGLE ),
122 rectValue( new Rect<int>( rectValue ) )
126 Impl( const Property::Array& arrayValue )
127 : type( Property::ARRAY ),
128 arrayValue( new Property::Array( arrayValue ) )
132 Impl( const Property::Map& mapValue )
133 : type( Property::MAP ),
134 mapValue( new Property::Map( mapValue ) )
139 * Destructor, takes care of releasing the dynamically allocated types
145 case Property::NONE : // FALLTHROUGH
146 case Property::BOOLEAN : // FALLTHROUGH
147 case Property::FLOAT : // FALLTHROUGH
148 case Property::INTEGER :
150 break; // nothing to do
152 case Property::VECTOR2 :
157 case Property::VECTOR3:
162 case Property::VECTOR4:
167 case Property::MATRIX3:
172 case Property::MATRIX:
177 case Property::RECTANGLE:
182 case Property::ROTATION:
184 delete quaternionValue;
187 case Property::STRING:
192 case Property::ARRAY:
212 // must use pointers for any class value pre c++ 11
213 Vector2* vector2Value;
214 Vector3* vector3Value;
215 Vector4* vector4Value;
216 Matrix3* matrix3Value;
218 Quaternion* quaternionValue;
219 std::string* stringValue;
220 Rect<int>* rectValue;
221 Property::Array* arrayValue;
222 Property::Map* mapValue;
226 Property::Value::Value()
231 Property::Value::Value( bool booleanValue )
232 : mImpl( new Impl( booleanValue ) )
236 Property::Value::Value( float floatValue )
237 : mImpl( new Impl( floatValue ) )
241 Property::Value::Value( int integerValue )
242 : mImpl( new Impl( integerValue ) )
246 Property::Value::Value( const Vector2& vectorValue )
247 : mImpl( new Impl( vectorValue ) )
251 Property::Value::Value( const Vector3& vectorValue )
252 : mImpl( new Impl( vectorValue ) )
256 Property::Value::Value( const Vector4& vectorValue )
257 : mImpl( new Impl( vectorValue ) )
261 Property::Value::Value( const Matrix3& matrixValue )
262 : mImpl( new Impl( matrixValue ) )
266 Property::Value::Value( const Matrix& matrixValue )
267 : mImpl( new Impl( matrixValue ) )
271 Property::Value::Value( const Rect<int>& rectValue )
272 : mImpl( new Impl( rectValue ) )
276 Property::Value::Value( const AngleAxis& angleAxisValue )
277 : mImpl( new Impl( angleAxisValue ) )
281 Property::Value::Value( const Quaternion& quaternionValue )
282 : mImpl( new Impl( quaternionValue ) )
286 Property::Value::Value( const std::string& stringValue )
287 : mImpl( new Impl( stringValue ) )
291 Property::Value::Value( const char* stringValue )
294 if( stringValue ) // string constructor is undefined with NULL pointer
296 mImpl = new Impl( std::string(stringValue) );
300 mImpl = new Impl( std::string() );
304 Property::Value::Value( Property::Array& arrayValue )
305 : mImpl( new Impl( arrayValue ) )
309 Property::Value::Value( Property::Map& mapValue )
310 : mImpl( new Impl( mapValue ) )
314 Property::Value::Value( Type type )
318 case Property::BOOLEAN:
320 mImpl = new Impl( false );
323 case Property::FLOAT:
325 mImpl = new Impl( 0.f );
328 case Property::INTEGER:
330 mImpl = new Impl( 0 );
333 case Property::VECTOR2:
335 mImpl = new Impl( Vector2::ZERO );
338 case Property::VECTOR3:
340 mImpl = new Impl( Vector3::ZERO );
343 case Property::VECTOR4:
345 mImpl = new Impl( Vector4::ZERO );
348 case Property::RECTANGLE:
350 mImpl = new Impl( Rect<int>(0,0,0,0) );
353 case Property::ROTATION:
355 mImpl = new Impl( Quaternion() );
358 case Property::STRING:
360 mImpl = new Impl( std::string() );
363 case Property::MATRIX:
365 mImpl = new Impl( Matrix() );
368 case Property::MATRIX3:
370 mImpl = new Impl( Matrix3() );
373 case Property::ARRAY:
375 mImpl = new Impl( Property::Array() );
380 mImpl = new Impl( Property::Map() );
391 Property::Value::Value( const Property::Value& value )
394 // reuse assignment operator
398 Property::Value& Property::Value::operator=( const Property::Value& value )
400 if ( this == &value )
402 // skip self assignment
405 // if we are assigned an empty value, just drop impl
412 // first check if the type is the same, no need to change impl, just assign
413 if( mImpl && ( mImpl->type == value.mImpl->type ) )
415 switch( mImpl->type )
417 case Property::BOOLEAN:
419 mImpl->integerValue = value.mImpl->integerValue;
422 case Property::FLOAT:
424 mImpl->floatValue = value.mImpl->floatValue;
427 case Property::INTEGER:
429 mImpl->integerValue = value.mImpl->integerValue;
432 case Property::VECTOR2:
434 *mImpl->vector2Value = *value.mImpl->vector2Value; // type cannot change in mImpl so vector is allocated
437 case Property::VECTOR3:
439 *mImpl->vector3Value = *value.mImpl->vector3Value; // type cannot change in mImpl so vector is allocated
442 case Property::VECTOR4:
444 *mImpl->vector4Value = *value.mImpl->vector4Value; // type cannot change in mImpl so vector is allocated
447 case Property::RECTANGLE:
449 *mImpl->rectValue = *value.mImpl->rectValue; // type cannot change in mImpl so rect is allocated
452 case Property::ROTATION:
454 *mImpl->quaternionValue = *value.mImpl->quaternionValue; // type cannot change in mImpl so quaternion is allocated
457 case Property::STRING:
459 *mImpl->stringValue = *value.mImpl->stringValue; // type cannot change in mImpl so string is allocated
462 case Property::MATRIX:
464 *mImpl->matrixValue = *value.mImpl->matrixValue; // type cannot change in mImpl so matrix is allocated
467 case Property::MATRIX3:
469 *mImpl->matrix3Value = *value.mImpl->matrix3Value; // type cannot change in mImpl so matrix is allocated
472 case Property::ARRAY:
474 *mImpl->arrayValue = *value.mImpl->arrayValue; // type cannot change in mImpl so array is allocated
479 *mImpl->mapValue = *value.mImpl->mapValue; // type cannot change in mImpl so map is allocated
483 { // mImpl will be NULL, there's no way to get to this case
489 // different type, release old impl and create new
490 Impl* newImpl( NULL );
491 switch ( value.mImpl->type )
493 case Property::BOOLEAN:
495 newImpl = new Impl( bool( value.mImpl->integerValue ) );
498 case Property::FLOAT:
500 newImpl = new Impl( value.mImpl->floatValue );
503 case Property::INTEGER:
505 newImpl = new Impl( value.mImpl->integerValue );
508 case Property::VECTOR2:
510 newImpl = new Impl( *value.mImpl->vector2Value ); // type cannot change in mImpl so vector is allocated
513 case Property::VECTOR3:
515 newImpl = new Impl( *value.mImpl->vector3Value ); // type cannot change in mImpl so vector is allocated
518 case Property::VECTOR4:
520 newImpl = new Impl( *value.mImpl->vector4Value ); // type cannot change in mImpl so vector is allocated
523 case Property::RECTANGLE:
525 newImpl = new Impl( *value.mImpl->rectValue ); // type cannot change in mImpl so rect is allocated
528 case Property::ROTATION:
530 newImpl = new Impl( *value.mImpl->quaternionValue ); // type cannot change in mImpl so quaternion is allocated
533 case Property::MATRIX3:
535 newImpl = new Impl( *value.mImpl->matrix3Value ); // type cannot change in mImpl so matrix is allocated
538 case Property::MATRIX:
540 newImpl = new Impl( *value.mImpl->matrixValue ); // type cannot change in mImpl so matrix is allocated
543 case Property::STRING:
545 newImpl = new Impl( *value.mImpl->stringValue ); // type cannot change in mImpl so string is allocated
548 case Property::ARRAY:
550 newImpl = new Impl( *value.mImpl->arrayValue ); // type cannot change in mImpl so array is allocated
555 newImpl = new Impl( *value.mImpl->mapValue ); // type cannot change in mImpl so map is allocated
559 { // NULL value will be used for "empty" value
569 Property::Value::~Value()
574 Property::Type Property::Value::GetType() const
576 Property::Type type( Property::NONE );
584 bool Property::Value::Get( bool& booleanValue ) const
586 bool converted = false;
587 if( mImpl && IsIntegerType( mImpl->type ) )
589 booleanValue = mImpl->integerValue;
595 bool Property::Value::Get( float& floatValue ) const
597 bool converted = false;
600 if( mImpl->type == FLOAT )
602 floatValue = mImpl->floatValue;
605 else if( IsIntegerType( mImpl->type ) )
607 floatValue = static_cast< float >( mImpl->integerValue );
614 bool Property::Value::Get( int& integerValue ) const
616 bool converted = false;
619 if( IsIntegerType( mImpl->type ) )
621 integerValue = mImpl->integerValue;
624 else if( mImpl->type == FLOAT )
626 integerValue = static_cast< int >( mImpl->floatValue );
633 bool Property::Value::Get( Vector2& vectorValue ) const
635 bool converted = false;
636 if( mImpl && (mImpl->type == VECTOR2) ) // type cannot change in mImpl so vector is allocated
638 vectorValue = *(mImpl->vector2Value);
644 bool Property::Value::Get( Vector3& vectorValue ) const
646 bool converted = false;
647 if( mImpl && (mImpl->type == VECTOR3) ) // type cannot change in mImpl so vector is allocated
649 vectorValue = *(mImpl->vector3Value);
655 bool Property::Value::Get( Vector4& vectorValue ) const
657 bool converted = false;
658 if( mImpl && (mImpl->type == VECTOR4) ) // type cannot change in mImpl so vector is allocated
660 vectorValue = *(mImpl->vector4Value);
666 bool Property::Value::Get( Matrix3& matrixValue ) const
668 bool converted = false;
669 if( mImpl && (mImpl->type == MATRIX3) ) // type cannot change in mImpl so matrix is allocated
671 matrixValue = *(mImpl->matrix3Value);
677 bool Property::Value::Get( Matrix& matrixValue ) const
679 bool converted = false;
680 if( mImpl && (mImpl->type == MATRIX) ) // type cannot change in mImpl so matrix is allocated
682 matrixValue = *(mImpl->matrixValue);
688 bool Property::Value::Get( Rect<int>& rectValue ) const
690 bool converted = false;
691 if( mImpl && (mImpl->type == RECTANGLE) ) // type cannot change in mImpl so rect is allocated
693 rectValue = *(mImpl->rectValue);
699 bool Property::Value::Get( AngleAxis& angleAxisValue ) const
701 bool converted = false;
702 if( mImpl && (mImpl->type == ROTATION) ) // type cannot change in mImpl so quaternion is allocated
704 mImpl->quaternionValue->ToAxisAngle( angleAxisValue.axis, angleAxisValue.angle );
710 bool Property::Value::Get( Quaternion& quaternionValue ) const
712 bool converted = false;
713 if( mImpl && (mImpl->type == ROTATION) ) // type cannot change in mImpl so quaternion is allocated
715 quaternionValue = *(mImpl->quaternionValue);
721 bool Property::Value::Get( std::string& stringValue ) const
723 bool converted = false;
724 if( mImpl && (mImpl->type == STRING) ) // type cannot change in mImpl so string is allocated
726 stringValue.assign( *(mImpl->stringValue) );
732 bool Property::Value::Get( Property::Array& arrayValue ) const
734 bool converted = false;
735 if( mImpl && (mImpl->type == ARRAY) ) // type cannot change in mImpl so array is allocated
737 arrayValue = *(mImpl->arrayValue);
743 bool Property::Value::Get( Property::Map& mapValue ) const
745 bool converted = false;
746 if( mImpl && (mImpl->type == MAP) ) // type cannot change in mImpl so map is allocated
748 mapValue = *(mImpl->mapValue);
754 Property::Array* Property::Value::GetArray() const
756 Property::Array* array = NULL;
757 if( mImpl && (mImpl->type == ARRAY) ) // type cannot change in mImpl so array is allocated
759 array = mImpl->arrayValue;
764 Property::Map* Property::Value::GetMap() const
766 Property::Map* map = NULL;
767 if( mImpl && (mImpl->type == MAP) ) // type cannot change in mImpl so map is allocated
769 map = mImpl->mapValue;
774 std::ostream& operator<<( std::ostream& stream, const Property::Value& value )
778 const Property::Value::Impl& impl( *value.mImpl );
782 case Dali::Property::BOOLEAN:
784 stream << impl.integerValue;
787 case Dali::Property::FLOAT:
789 stream << impl.floatValue;
792 case Dali::Property::INTEGER:
794 stream << impl.integerValue;
797 case Dali::Property::VECTOR2:
799 stream << *impl.vector2Value;
802 case Dali::Property::VECTOR3:
804 stream << *impl.vector3Value;
807 case Dali::Property::VECTOR4:
809 stream << *impl.vector4Value;
812 case Dali::Property::MATRIX3:
814 stream << *impl.matrix3Value;
817 case Dali::Property::MATRIX:
819 stream << *impl.matrixValue;
822 case Dali::Property::RECTANGLE:
824 stream << *impl.rectValue;
827 case Dali::Property::ROTATION:
829 stream << *impl.quaternionValue;
832 case Dali::Property::STRING:
834 stream << *impl.stringValue;
837 case Dali::Property::ARRAY:
839 stream << *(value.GetArray());
842 case Dali::Property::MAP:
844 stream << *(value.GetMap());
847 case Dali::Property::NONE:
849 stream << "undefined type";
856 stream << "empty type";