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/common/extents.h>
26 #include <dali/public-api/math/angle-axis.h>
27 #include <dali/public-api/math/radian.h>
28 #include <dali/public-api/math/vector2.h>
29 #include <dali/public-api/math/vector3.h>
30 #include <dali/public-api/math/vector4.h>
31 #include <dali/public-api/math/matrix3.h>
32 #include <dali/public-api/math/matrix.h>
33 #include <dali/public-api/math/rect.h>
34 #include <dali/public-api/math/quaternion.h>
35 #include <dali/public-api/object/property-map.h>
36 #include <dali/public-api/object/property-array.h>
37 #include <dali/public-api/object/property-types.h>
38 #include <dali/integration-api/debug.h>
46 * Helper to check if the property value can be read as int/bool
48 inline bool IsIntegerType( Property::Type type )
50 return ( Property::BOOLEAN == type )||( Property::INTEGER == type );
54 struct Property::Value::Impl
57 : type( Property::NONE ),
61 Impl( bool booleanValue )
62 : type( Property::BOOLEAN ),
63 integerValue( booleanValue )
66 Impl( float floatValue )
67 : type( Property::FLOAT ),
68 floatValue( floatValue )
71 Impl( int integerValue )
72 : type( Property::INTEGER ),
73 integerValue( integerValue )
76 Impl( const Vector2& vectorValue )
77 : type( Property::VECTOR2 ),
78 vector2Value( new Vector2( vectorValue ) )
81 Impl( const Vector3& vectorValue )
82 : type( Property::VECTOR3 ),
83 vector3Value( new Vector3( vectorValue ) )
86 Impl( const Vector4& vectorValue )
87 : type( Property::VECTOR4 ),
88 vector4Value( new Vector4( vectorValue ) )
91 Impl( const Matrix3& matrixValue )
92 : type( Property::MATRIX3 ),
93 matrix3Value( new Matrix3( matrixValue ) )
97 Impl( const Matrix& matrixValue )
98 : type( Property::MATRIX ),
99 matrixValue( new Matrix( matrixValue ) )
103 Impl( const AngleAxis& angleAxisValue )
104 : type( Property::ROTATION ),
105 angleAxisValue( new AngleAxis(angleAxisValue) )
109 Impl( const Quaternion& quaternionValue )
110 : type( Property::ROTATION ),
111 angleAxisValue( new AngleAxis() )
113 quaternionValue.ToAxisAngle( angleAxisValue->axis, angleAxisValue->angle );
116 Impl(const std::string& stringValue)
117 : type( Property::STRING ),
118 stringValue( new std::string( stringValue ) )
122 Impl( const Rect<int>& rectValue )
123 : type( Property::RECTANGLE ),
124 rectValue( new Rect<int>( rectValue ) )
128 Impl( const Property::Array& arrayValue )
129 : type( Property::ARRAY ),
130 arrayValue( new Property::Array( arrayValue ) )
134 Impl( const Property::Map& mapValue )
135 : type( Property::MAP ),
136 mapValue( new Property::Map( mapValue ) )
140 Impl( const Extents& extentsValue )
141 : type( Property::EXTENTS ),
142 extentsValue( new Extents( extentsValue ) )
147 * Destructor, takes care of releasing the dynamically allocated types
153 case Property::NONE : // FALLTHROUGH
154 case Property::BOOLEAN : // FALLTHROUGH
155 case Property::FLOAT : // FALLTHROUGH
156 case Property::INTEGER :
158 break; // nothing to do
160 case Property::VECTOR2 :
165 case Property::VECTOR3:
170 case Property::VECTOR4:
175 case Property::MATRIX3:
180 case Property::MATRIX:
185 case Property::RECTANGLE:
190 case Property::ROTATION:
192 delete angleAxisValue;
195 case Property::STRING:
200 case Property::ARRAY:
210 case Property::EXTENTS:
225 // must use pointers for any class value pre c++ 11
226 Vector2* vector2Value;
227 Vector3* vector3Value;
228 Vector4* vector4Value;
229 Matrix3* matrix3Value;
231 AngleAxis* angleAxisValue;
232 std::string* stringValue;
233 Rect<int>* rectValue;
234 Property::Array* arrayValue;
235 Property::Map* mapValue;
236 Extents* extentsValue;
241 Impl( const Impl& ); ///< Undefined
242 Impl& operator=( const Impl& ); ///< Undefined
245 Property::Value::Value()
250 Property::Value::Value( bool booleanValue )
251 : mImpl( new Impl( booleanValue ) )
255 Property::Value::Value( float floatValue )
256 : mImpl( new Impl( floatValue ) )
260 Property::Value::Value( int integerValue )
261 : mImpl( new Impl( integerValue ) )
265 Property::Value::Value( const Vector2& vectorValue )
266 : mImpl( new Impl( vectorValue ) )
270 Property::Value::Value( const Vector3& vectorValue )
271 : mImpl( new Impl( vectorValue ) )
275 Property::Value::Value( const Vector4& vectorValue )
276 : mImpl( new Impl( vectorValue ) )
280 Property::Value::Value( const Matrix3& matrixValue )
281 : mImpl( new Impl( matrixValue ) )
285 Property::Value::Value( const Matrix& matrixValue )
286 : mImpl( new Impl( matrixValue ) )
290 Property::Value::Value( const Rect<int>& rectValue )
291 : mImpl( new Impl( rectValue ) )
295 Property::Value::Value( const AngleAxis& angleAxisValue )
296 : mImpl( new Impl( angleAxisValue ) )
300 Property::Value::Value( const Quaternion& quaternionValue )
301 : mImpl( new Impl( quaternionValue ) )
305 Property::Value::Value( const std::string& stringValue )
306 : mImpl( new Impl( stringValue ) )
310 Property::Value::Value( const char* stringValue )
313 if( stringValue ) // string constructor is undefined with NULL pointer
315 mImpl = new Impl( std::string(stringValue) );
319 mImpl = new Impl( std::string() );
323 Property::Value::Value( Property::Array& arrayValue )
324 : mImpl( new Impl( arrayValue ) )
328 Property::Value::Value( Property::Map& mapValue )
329 : mImpl( new Impl( mapValue ) )
333 Property::Value::Value( const Extents& extentsValue )
334 : mImpl( new Impl( extentsValue ) )
338 Property::Value::Value( Type type )
343 case Property::BOOLEAN:
345 mImpl = new Impl( false );
348 case Property::FLOAT:
350 mImpl = new Impl( 0.f );
353 case Property::INTEGER:
355 mImpl = new Impl( 0 );
358 case Property::VECTOR2:
360 mImpl = new Impl( Vector2::ZERO );
363 case Property::VECTOR3:
365 mImpl = new Impl( Vector3::ZERO );
368 case Property::VECTOR4:
370 mImpl = new Impl( Vector4::ZERO );
373 case Property::RECTANGLE:
375 mImpl = new Impl( Rect<int>(0,0,0,0) );
378 case Property::ROTATION:
380 mImpl = new Impl( AngleAxis() );
383 case Property::STRING:
385 mImpl = new Impl( std::string() );
388 case Property::MATRIX:
390 mImpl = new Impl( Matrix() );
393 case Property::MATRIX3:
395 mImpl = new Impl( Matrix3() );
398 case Property::ARRAY:
400 mImpl = new Impl( Property::Array() );
405 mImpl = new Impl( Property::Map() );
408 case Property::EXTENTS:
410 mImpl = new Impl( Extents() );
421 Property::Value::Value( const Property::Value& value )
424 // reuse assignment operator
428 Property::Value& Property::Value::operator=( const Property::Value& value )
430 if ( this == &value )
432 // skip self assignment
435 // if we are assigned an empty value, just drop impl
442 // first check if the type is the same, no need to change impl, just assign
443 if( mImpl && ( mImpl->type == value.mImpl->type ) )
445 switch( mImpl->type )
447 case Property::BOOLEAN:
449 mImpl->integerValue = value.mImpl->integerValue;
452 case Property::FLOAT:
454 mImpl->floatValue = value.mImpl->floatValue;
457 case Property::INTEGER:
459 mImpl->integerValue = value.mImpl->integerValue;
462 case Property::VECTOR2:
464 *mImpl->vector2Value = *value.mImpl->vector2Value; // type cannot change in mImpl so vector is allocated
467 case Property::VECTOR3:
469 *mImpl->vector3Value = *value.mImpl->vector3Value; // type cannot change in mImpl so vector is allocated
472 case Property::VECTOR4:
474 *mImpl->vector4Value = *value.mImpl->vector4Value; // type cannot change in mImpl so vector is allocated
477 case Property::RECTANGLE:
479 *mImpl->rectValue = *value.mImpl->rectValue; // type cannot change in mImpl so rect is allocated
482 case Property::ROTATION:
484 *mImpl->angleAxisValue = *value.mImpl->angleAxisValue; // type cannot change in mImpl so quaternion is allocated
487 case Property::STRING:
489 *mImpl->stringValue = *value.mImpl->stringValue; // type cannot change in mImpl so string is allocated
492 case Property::MATRIX:
494 *mImpl->matrixValue = *value.mImpl->matrixValue; // type cannot change in mImpl so matrix is allocated
497 case Property::MATRIX3:
499 *mImpl->matrix3Value = *value.mImpl->matrix3Value; // type cannot change in mImpl so matrix is allocated
502 case Property::ARRAY:
504 *mImpl->arrayValue = *value.mImpl->arrayValue; // type cannot change in mImpl so array is allocated
509 *mImpl->mapValue = *value.mImpl->mapValue; // type cannot change in mImpl so map is allocated
512 case Property::EXTENTS:
514 *mImpl->extentsValue = *value.mImpl->extentsValue; // type cannot change in mImpl so extents is allocated
518 { // mImpl will be NULL, there's no way to get to this case
524 // different type, release old impl and create new
525 Impl* newImpl( NULL );
526 switch ( value.mImpl->type )
528 case Property::BOOLEAN:
530 newImpl = new Impl( bool( value.mImpl->integerValue ) );
533 case Property::FLOAT:
535 newImpl = new Impl( value.mImpl->floatValue );
538 case Property::INTEGER:
540 newImpl = new Impl( value.mImpl->integerValue );
543 case Property::VECTOR2:
545 newImpl = new Impl( *value.mImpl->vector2Value ); // type cannot change in mImpl so vector is allocated
548 case Property::VECTOR3:
550 newImpl = new Impl( *value.mImpl->vector3Value ); // type cannot change in mImpl so vector is allocated
553 case Property::VECTOR4:
555 newImpl = new Impl( *value.mImpl->vector4Value ); // type cannot change in mImpl so vector is allocated
558 case Property::RECTANGLE:
560 newImpl = new Impl( *value.mImpl->rectValue ); // type cannot change in mImpl so rect is allocated
563 case Property::ROTATION:
565 newImpl = new Impl( *value.mImpl->angleAxisValue ); // type cannot change in mImpl so quaternion is allocated
568 case Property::MATRIX3:
570 newImpl = new Impl( *value.mImpl->matrix3Value ); // type cannot change in mImpl so matrix is allocated
573 case Property::MATRIX:
575 newImpl = new Impl( *value.mImpl->matrixValue ); // type cannot change in mImpl so matrix is allocated
578 case Property::STRING:
580 newImpl = new Impl( *value.mImpl->stringValue ); // type cannot change in mImpl so string is allocated
583 case Property::ARRAY:
585 newImpl = new Impl( *value.mImpl->arrayValue ); // type cannot change in mImpl so array is allocated
590 newImpl = new Impl( *value.mImpl->mapValue ); // type cannot change in mImpl so map is allocated
593 case Property::EXTENTS:
595 newImpl = new Impl( *value.mImpl->extentsValue ); // type cannot change in mImpl so extents is allocated
599 { // NULL value will be used for "empty" value
609 Property::Value::~Value()
614 Property::Type Property::Value::GetType() const
616 Property::Type type( Property::NONE );
624 bool Property::Value::Get( bool& booleanValue ) const
626 bool converted = false;
627 if( mImpl && IsIntegerType( mImpl->type ) )
629 booleanValue = mImpl->integerValue;
635 bool Property::Value::Get( float& floatValue ) const
637 bool converted = false;
640 if( mImpl->type == FLOAT )
642 floatValue = mImpl->floatValue;
645 else if( IsIntegerType( mImpl->type ) )
647 floatValue = static_cast< float >( mImpl->integerValue );
654 bool Property::Value::Get( int& integerValue ) const
656 bool converted = false;
659 if( IsIntegerType( mImpl->type ) )
661 integerValue = mImpl->integerValue;
664 else if( mImpl->type == FLOAT )
666 integerValue = static_cast< int >( mImpl->floatValue );
673 bool Property::Value::Get( Vector2& vectorValue ) const
675 bool converted = false;
678 // type cannot change in mImpl so vector is allocated
679 if( mImpl->type == VECTOR2 || mImpl->type == VECTOR3 || mImpl->type == VECTOR4 )
681 vectorValue = *(mImpl->vector2Value); // if Vector3 or 4 only x and y are assigned
688 bool Property::Value::Get( Vector3& vectorValue ) const
690 bool converted = false;
693 // type cannot change in mImpl so vector is allocated
694 if ( mImpl->type == VECTOR3 || mImpl->type == VECTOR4 )
696 vectorValue = *(mImpl->vector3Value); // if Vector4 only x,y,z are assigned
699 else if( mImpl->type == VECTOR2 )
701 vectorValue = *(mImpl->vector2Value);
708 bool Property::Value::Get( Vector4& vectorValue ) const
710 bool converted = false;
713 if( mImpl->type == VECTOR4 ) // type cannot change in mImpl so vector is allocated
715 vectorValue = *(mImpl->vector4Value);
718 else if( mImpl->type == VECTOR2 )
720 vectorValue = *(mImpl->vector2Value);
723 else if( mImpl->type == VECTOR3 )
725 vectorValue = *(mImpl->vector3Value);
732 bool Property::Value::Get( Matrix3& matrixValue ) const
734 bool converted = false;
735 if( mImpl && (mImpl->type == MATRIX3) ) // type cannot change in mImpl so matrix is allocated
737 matrixValue = *(mImpl->matrix3Value);
743 bool Property::Value::Get( Matrix& matrixValue ) const
745 bool converted = false;
746 if( mImpl && (mImpl->type == MATRIX) ) // type cannot change in mImpl so matrix is allocated
748 matrixValue = *(mImpl->matrixValue);
754 bool Property::Value::Get( Rect<int>& rectValue ) const
756 bool converted = false;
757 if( mImpl && (mImpl->type == RECTANGLE) ) // type cannot change in mImpl so rect is allocated
759 rectValue = *(mImpl->rectValue);
765 bool Property::Value::Get( AngleAxis& angleAxisValue ) const
767 bool converted = false;
768 if( mImpl && (mImpl->type == ROTATION) ) // type cannot change in mImpl so angleAxis is allocated
770 angleAxisValue = *(mImpl->angleAxisValue);
776 bool Property::Value::Get( Quaternion& quaternionValue ) const
778 bool converted = false;
779 if( mImpl && (mImpl->type == ROTATION) ) // type cannot change in mImpl so angleAxis is allocated
781 quaternionValue = Quaternion(mImpl->angleAxisValue->angle, mImpl->angleAxisValue->axis );
787 bool Property::Value::Get( std::string& stringValue ) const
789 bool converted = false;
790 if( mImpl && (mImpl->type == STRING) ) // type cannot change in mImpl so string is allocated
792 stringValue.assign( *(mImpl->stringValue) );
798 bool Property::Value::Get( Property::Array& arrayValue ) const
800 bool converted = false;
801 if( mImpl && (mImpl->type == ARRAY) ) // type cannot change in mImpl so array is allocated
803 arrayValue = *(mImpl->arrayValue);
809 bool Property::Value::Get( Property::Map& mapValue ) const
811 bool converted = false;
812 if( mImpl && (mImpl->type == MAP) ) // type cannot change in mImpl so map is allocated
814 mapValue = *(mImpl->mapValue);
820 Property::Array* Property::Value::GetArray() const
822 Property::Array* array = NULL;
823 if( mImpl && (mImpl->type == ARRAY) ) // type cannot change in mImpl so array is allocated
825 array = mImpl->arrayValue;
830 Property::Map* Property::Value::GetMap() const
832 Property::Map* map = NULL;
833 if( mImpl && (mImpl->type == MAP) ) // type cannot change in mImpl so map is allocated
835 map = mImpl->mapValue;
840 bool Property::Value::Get( Extents& extentsValue ) const
842 bool converted = false;
845 if( mImpl->type == EXTENTS )
847 extentsValue = *(mImpl->extentsValue);
850 else if( mImpl->type == VECTOR4 )
852 extentsValue.start = static_cast< uint16_t >( mImpl->vector4Value->x );
853 extentsValue.end = static_cast< uint16_t >( mImpl->vector4Value->y );
854 extentsValue.top = static_cast< uint16_t >( mImpl->vector4Value->z );
855 extentsValue.bottom = static_cast< uint16_t >( mImpl->vector4Value->w );
862 std::ostream& operator<<( std::ostream& stream, const Property::Value& value )
866 const Property::Value::Impl& impl( *value.mImpl );
870 case Dali::Property::BOOLEAN:
872 stream << impl.integerValue;
875 case Dali::Property::FLOAT:
877 stream << impl.floatValue;
880 case Dali::Property::INTEGER:
882 stream << impl.integerValue;
885 case Dali::Property::VECTOR2:
887 stream << *impl.vector2Value;
890 case Dali::Property::VECTOR3:
892 stream << *impl.vector3Value;
895 case Dali::Property::VECTOR4:
897 stream << *impl.vector4Value;
900 case Dali::Property::MATRIX3:
902 stream << *impl.matrix3Value;
905 case Dali::Property::MATRIX:
907 stream << *impl.matrixValue;
910 case Dali::Property::RECTANGLE:
912 stream << *impl.rectValue;
915 case Dali::Property::ROTATION:
917 stream << *impl.angleAxisValue;
920 case Dali::Property::STRING:
922 stream << *impl.stringValue;
925 case Dali::Property::ARRAY:
927 stream << *(value.GetArray());
930 case Dali::Property::MAP:
932 stream << *(value.GetMap());
935 case Dali::Property::EXTENTS:
937 stream << *impl.extentsValue;
940 case Dali::Property::NONE:
942 stream << "undefined type";
949 stream << "empty type";