2 * Copyright (c) 2016 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 angleAxisValue( new AngleAxis(angleAxisValue) )
108 Impl( const Quaternion& quaternionValue )
109 : type( Property::ROTATION ),
110 angleAxisValue( new AngleAxis() )
112 quaternionValue.ToAxisAngle( angleAxisValue->axis, angleAxisValue->angle );
115 Impl(const std::string& stringValue)
116 : type( Property::STRING ),
117 stringValue( new std::string( stringValue ) )
121 Impl( const Rect<int>& rectValue )
122 : type( Property::RECTANGLE ),
123 rectValue( new Rect<int>( rectValue ) )
127 Impl( const Property::Array& arrayValue )
128 : type( Property::ARRAY ),
129 arrayValue( new Property::Array( arrayValue ) )
133 Impl( const Property::Map& mapValue )
134 : type( Property::MAP ),
135 mapValue( new Property::Map( mapValue ) )
140 * Destructor, takes care of releasing the dynamically allocated types
146 case Property::NONE : // FALLTHROUGH
147 case Property::BOOLEAN : // FALLTHROUGH
148 case Property::FLOAT : // FALLTHROUGH
149 case Property::INTEGER :
151 break; // nothing to do
153 case Property::VECTOR2 :
158 case Property::VECTOR3:
163 case Property::VECTOR4:
168 case Property::MATRIX3:
173 case Property::MATRIX:
178 case Property::RECTANGLE:
183 case Property::ROTATION:
185 delete angleAxisValue;
188 case Property::STRING:
193 case Property::ARRAY:
213 // must use pointers for any class value pre c++ 11
214 Vector2* vector2Value;
215 Vector3* vector3Value;
216 Vector4* vector4Value;
217 Matrix3* matrix3Value;
219 AngleAxis* angleAxisValue;
220 std::string* stringValue;
221 Rect<int>* rectValue;
222 Property::Array* arrayValue;
223 Property::Map* mapValue;
228 Impl( const Impl& ); ///< Undefined
229 Impl& operator=( const Impl& ); ///< Undefined
232 Property::Value::Value()
237 Property::Value::Value( bool booleanValue )
238 : mImpl( new Impl( booleanValue ) )
242 Property::Value::Value( float floatValue )
243 : mImpl( new Impl( floatValue ) )
247 Property::Value::Value( int integerValue )
248 : mImpl( new Impl( integerValue ) )
252 Property::Value::Value( const Vector2& vectorValue )
253 : mImpl( new Impl( vectorValue ) )
257 Property::Value::Value( const Vector3& vectorValue )
258 : mImpl( new Impl( vectorValue ) )
262 Property::Value::Value( const Vector4& vectorValue )
263 : mImpl( new Impl( vectorValue ) )
267 Property::Value::Value( const Matrix3& matrixValue )
268 : mImpl( new Impl( matrixValue ) )
272 Property::Value::Value( const Matrix& matrixValue )
273 : mImpl( new Impl( matrixValue ) )
277 Property::Value::Value( const Rect<int>& rectValue )
278 : mImpl( new Impl( rectValue ) )
282 Property::Value::Value( const AngleAxis& angleAxisValue )
283 : mImpl( new Impl( angleAxisValue ) )
287 Property::Value::Value( const Quaternion& quaternionValue )
288 : mImpl( new Impl( quaternionValue ) )
292 Property::Value::Value( const std::string& stringValue )
293 : mImpl( new Impl( stringValue ) )
297 Property::Value::Value( const char* stringValue )
300 if( stringValue ) // string constructor is undefined with NULL pointer
302 mImpl = new Impl( std::string(stringValue) );
306 mImpl = new Impl( std::string() );
310 Property::Value::Value( Property::Array& arrayValue )
311 : mImpl( new Impl( arrayValue ) )
315 Property::Value::Value( Property::Map& mapValue )
316 : mImpl( new Impl( mapValue ) )
320 Property::Value::Value( Type type )
325 case Property::BOOLEAN:
327 mImpl = new Impl( false );
330 case Property::FLOAT:
332 mImpl = new Impl( 0.f );
335 case Property::INTEGER:
337 mImpl = new Impl( 0 );
340 case Property::VECTOR2:
342 mImpl = new Impl( Vector2::ZERO );
345 case Property::VECTOR3:
347 mImpl = new Impl( Vector3::ZERO );
350 case Property::VECTOR4:
352 mImpl = new Impl( Vector4::ZERO );
355 case Property::RECTANGLE:
357 mImpl = new Impl( Rect<int>(0,0,0,0) );
360 case Property::ROTATION:
362 mImpl = new Impl( AngleAxis() );
365 case Property::STRING:
367 mImpl = new Impl( std::string() );
370 case Property::MATRIX:
372 mImpl = new Impl( Matrix() );
375 case Property::MATRIX3:
377 mImpl = new Impl( Matrix3() );
380 case Property::ARRAY:
382 mImpl = new Impl( Property::Array() );
387 mImpl = new Impl( Property::Map() );
398 Property::Value::Value( const Property::Value& value )
401 // reuse assignment operator
405 Property::Value& Property::Value::operator=( const Property::Value& value )
407 if ( this == &value )
409 // skip self assignment
412 // if we are assigned an empty value, just drop impl
419 // first check if the type is the same, no need to change impl, just assign
420 if( mImpl && ( mImpl->type == value.mImpl->type ) )
422 switch( mImpl->type )
424 case Property::BOOLEAN:
426 mImpl->integerValue = value.mImpl->integerValue;
429 case Property::FLOAT:
431 mImpl->floatValue = value.mImpl->floatValue;
434 case Property::INTEGER:
436 mImpl->integerValue = value.mImpl->integerValue;
439 case Property::VECTOR2:
441 *mImpl->vector2Value = *value.mImpl->vector2Value; // type cannot change in mImpl so vector is allocated
444 case Property::VECTOR3:
446 *mImpl->vector3Value = *value.mImpl->vector3Value; // type cannot change in mImpl so vector is allocated
449 case Property::VECTOR4:
451 *mImpl->vector4Value = *value.mImpl->vector4Value; // type cannot change in mImpl so vector is allocated
454 case Property::RECTANGLE:
456 *mImpl->rectValue = *value.mImpl->rectValue; // type cannot change in mImpl so rect is allocated
459 case Property::ROTATION:
461 *mImpl->angleAxisValue = *value.mImpl->angleAxisValue; // type cannot change in mImpl so quaternion is allocated
464 case Property::STRING:
466 *mImpl->stringValue = *value.mImpl->stringValue; // type cannot change in mImpl so string is allocated
469 case Property::MATRIX:
471 *mImpl->matrixValue = *value.mImpl->matrixValue; // type cannot change in mImpl so matrix is allocated
474 case Property::MATRIX3:
476 *mImpl->matrix3Value = *value.mImpl->matrix3Value; // type cannot change in mImpl so matrix is allocated
479 case Property::ARRAY:
481 *mImpl->arrayValue = *value.mImpl->arrayValue; // type cannot change in mImpl so array is allocated
486 *mImpl->mapValue = *value.mImpl->mapValue; // type cannot change in mImpl so map is allocated
490 { // mImpl will be NULL, there's no way to get to this case
496 // different type, release old impl and create new
497 Impl* newImpl( NULL );
498 switch ( value.mImpl->type )
500 case Property::BOOLEAN:
502 newImpl = new Impl( bool( value.mImpl->integerValue ) );
505 case Property::FLOAT:
507 newImpl = new Impl( value.mImpl->floatValue );
510 case Property::INTEGER:
512 newImpl = new Impl( value.mImpl->integerValue );
515 case Property::VECTOR2:
517 newImpl = new Impl( *value.mImpl->vector2Value ); // type cannot change in mImpl so vector is allocated
520 case Property::VECTOR3:
522 newImpl = new Impl( *value.mImpl->vector3Value ); // type cannot change in mImpl so vector is allocated
525 case Property::VECTOR4:
527 newImpl = new Impl( *value.mImpl->vector4Value ); // type cannot change in mImpl so vector is allocated
530 case Property::RECTANGLE:
532 newImpl = new Impl( *value.mImpl->rectValue ); // type cannot change in mImpl so rect is allocated
535 case Property::ROTATION:
537 newImpl = new Impl( *value.mImpl->angleAxisValue ); // type cannot change in mImpl so quaternion is allocated
540 case Property::MATRIX3:
542 newImpl = new Impl( *value.mImpl->matrix3Value ); // type cannot change in mImpl so matrix is allocated
545 case Property::MATRIX:
547 newImpl = new Impl( *value.mImpl->matrixValue ); // type cannot change in mImpl so matrix is allocated
550 case Property::STRING:
552 newImpl = new Impl( *value.mImpl->stringValue ); // type cannot change in mImpl so string is allocated
555 case Property::ARRAY:
557 newImpl = new Impl( *value.mImpl->arrayValue ); // type cannot change in mImpl so array is allocated
562 newImpl = new Impl( *value.mImpl->mapValue ); // type cannot change in mImpl so map is allocated
566 { // NULL value will be used for "empty" value
576 Property::Value::~Value()
581 Property::Type Property::Value::GetType() const
583 Property::Type type( Property::NONE );
591 bool Property::Value::Get( bool& booleanValue ) const
593 bool converted = false;
594 if( mImpl && IsIntegerType( mImpl->type ) )
596 booleanValue = mImpl->integerValue;
602 bool Property::Value::Get( float& floatValue ) const
604 bool converted = false;
607 if( mImpl->type == FLOAT )
609 floatValue = mImpl->floatValue;
612 else if( IsIntegerType( mImpl->type ) )
614 floatValue = static_cast< float >( mImpl->integerValue );
621 bool Property::Value::Get( int& integerValue ) const
623 bool converted = false;
626 if( IsIntegerType( mImpl->type ) )
628 integerValue = mImpl->integerValue;
631 else if( mImpl->type == FLOAT )
633 integerValue = static_cast< int >( mImpl->floatValue );
640 bool Property::Value::Get( Vector2& vectorValue ) const
642 bool converted = false;
645 // type cannot change in mImpl so vector is allocated
646 if( mImpl->type == VECTOR2 || mImpl->type == VECTOR3 || mImpl->type == VECTOR4 )
648 vectorValue = *(mImpl->vector2Value); // if Vector3 or 4 only x and y are assigned
655 bool Property::Value::Get( Vector3& vectorValue ) const
657 bool converted = false;
660 // type cannot change in mImpl so vector is allocated
661 if ( mImpl->type == VECTOR3 || mImpl->type == VECTOR4 )
663 vectorValue = *(mImpl->vector3Value); // if Vector4 only x,y,z are assigned
666 else if( mImpl->type == VECTOR2 )
668 vectorValue = *(mImpl->vector2Value);
675 bool Property::Value::Get( Vector4& vectorValue ) const
677 bool converted = false;
680 if( mImpl->type == VECTOR4 ) // type cannot change in mImpl so vector is allocated
682 vectorValue = *(mImpl->vector4Value);
685 else if( mImpl->type == VECTOR2 )
687 vectorValue = *(mImpl->vector2Value);
690 else if( mImpl->type == VECTOR3 )
692 vectorValue = *(mImpl->vector3Value);
699 bool Property::Value::Get( Matrix3& matrixValue ) const
701 bool converted = false;
702 if( mImpl && (mImpl->type == MATRIX3) ) // type cannot change in mImpl so matrix is allocated
704 matrixValue = *(mImpl->matrix3Value);
710 bool Property::Value::Get( Matrix& matrixValue ) const
712 bool converted = false;
713 if( mImpl && (mImpl->type == MATRIX) ) // type cannot change in mImpl so matrix is allocated
715 matrixValue = *(mImpl->matrixValue);
721 bool Property::Value::Get( Rect<int>& rectValue ) const
723 bool converted = false;
724 if( mImpl && (mImpl->type == RECTANGLE) ) // type cannot change in mImpl so rect is allocated
726 rectValue = *(mImpl->rectValue);
732 bool Property::Value::Get( AngleAxis& angleAxisValue ) const
734 bool converted = false;
735 if( mImpl && (mImpl->type == ROTATION) ) // type cannot change in mImpl so angleAxis is allocated
737 angleAxisValue = *(mImpl->angleAxisValue);
743 bool Property::Value::Get( Quaternion& quaternionValue ) const
745 bool converted = false;
746 if( mImpl && (mImpl->type == ROTATION) ) // type cannot change in mImpl so angleAxis is allocated
748 quaternionValue = Quaternion(mImpl->angleAxisValue->angle, mImpl->angleAxisValue->axis );
754 bool Property::Value::Get( std::string& stringValue ) const
756 bool converted = false;
757 if( mImpl && (mImpl->type == STRING) ) // type cannot change in mImpl so string is allocated
759 stringValue.assign( *(mImpl->stringValue) );
765 bool Property::Value::Get( Property::Array& arrayValue ) const
767 bool converted = false;
768 if( mImpl && (mImpl->type == ARRAY) ) // type cannot change in mImpl so array is allocated
770 arrayValue = *(mImpl->arrayValue);
776 bool Property::Value::Get( Property::Map& mapValue ) const
778 bool converted = false;
779 if( mImpl && (mImpl->type == MAP) ) // type cannot change in mImpl so map is allocated
781 mapValue = *(mImpl->mapValue);
787 Property::Array* Property::Value::GetArray() const
789 Property::Array* array = NULL;
790 if( mImpl && (mImpl->type == ARRAY) ) // type cannot change in mImpl so array is allocated
792 array = mImpl->arrayValue;
797 Property::Map* Property::Value::GetMap() const
799 Property::Map* map = NULL;
800 if( mImpl && (mImpl->type == MAP) ) // type cannot change in mImpl so map is allocated
802 map = mImpl->mapValue;
807 std::ostream& operator<<( std::ostream& stream, const Property::Value& value )
811 const Property::Value::Impl& impl( *value.mImpl );
815 case Dali::Property::BOOLEAN:
817 stream << impl.integerValue;
820 case Dali::Property::FLOAT:
822 stream << impl.floatValue;
825 case Dali::Property::INTEGER:
827 stream << impl.integerValue;
830 case Dali::Property::VECTOR2:
832 stream << *impl.vector2Value;
835 case Dali::Property::VECTOR3:
837 stream << *impl.vector3Value;
840 case Dali::Property::VECTOR4:
842 stream << *impl.vector4Value;
845 case Dali::Property::MATRIX3:
847 stream << *impl.matrix3Value;
850 case Dali::Property::MATRIX:
852 stream << *impl.matrixValue;
855 case Dali::Property::RECTANGLE:
857 stream << *impl.rectValue;
860 case Dali::Property::ROTATION:
862 stream << *impl.angleAxisValue;
865 case Dali::Property::STRING:
867 stream << *impl.stringValue;
870 case Dali::Property::ARRAY:
872 stream << *(value.GetArray());
875 case Dali::Property::MAP:
877 stream << *(value.GetMap());
880 case Dali::Property::NONE:
882 stream << "undefined type";
889 stream << "empty type";