2 * Copyright (c) 2019 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
56 Impl( bool booleanValue )
57 : type( Property::BOOLEAN ),
58 integerValue( booleanValue )
61 Impl( float floatValue )
62 : type( Property::FLOAT ),
63 floatValue( floatValue )
66 Impl( int32_t integerValue )
67 : type( Property::INTEGER ),
68 integerValue( integerValue )
71 Impl( const Vector2& vectorValue )
72 : type( Property::VECTOR2 ),
73 vector2Value( new Vector2( vectorValue ) )
76 Impl( const Vector3& vectorValue )
77 : type( Property::VECTOR3 ),
78 vector3Value( new Vector3( vectorValue ) )
81 Impl( const Vector4& vectorValue )
82 : type( Property::VECTOR4 ),
83 vector4Value( new Vector4( vectorValue ) )
86 Impl( const Matrix3& matrixValue )
87 : type( Property::MATRIX3 ),
88 matrix3Value( new Matrix3( matrixValue ) )
92 Impl( const Matrix& matrixValue )
93 : type( Property::MATRIX ),
94 matrixValue( new Matrix( matrixValue ) )
98 Impl( const AngleAxis& angleAxisValue )
99 : type( Property::ROTATION ),
100 angleAxisValue( new AngleAxis(angleAxisValue) )
104 Impl( const Quaternion& quaternionValue )
105 : type( Property::ROTATION ),
106 angleAxisValue( new AngleAxis() )
108 quaternionValue.ToAxisAngle( angleAxisValue->axis, angleAxisValue->angle );
111 Impl( const std::string& stringValue )
112 : type( Property::STRING ),
113 stringValue( new std::string( stringValue ) )
117 Impl( const Rect<int32_t>& rectValue )
118 : type( Property::RECTANGLE ),
119 rectValue( new Rect<int>( rectValue ) )
123 Impl( const Property::Array& arrayValue )
124 : type( Property::ARRAY ),
125 arrayValue( new Property::Array( arrayValue ) )
129 Impl( Property::Array&& arrayValue )
130 : type( Property::ARRAY ),
131 arrayValue( new Property::Array( std::move( arrayValue ) ) )
135 Impl( const Property::Map& mapValue )
136 : type( Property::MAP ),
137 mapValue( new Property::Map( mapValue ) )
141 Impl( Property::Map&& mapValue )
142 : type( Property::MAP ),
143 mapValue( new Property::Map( std::move( mapValue ) ) )
147 Impl( const Extents& extentsValue )
148 : type( Property::EXTENTS ),
149 extentsValue( new Extents( extentsValue ) )
154 * Destructor, takes care of releasing the dynamically allocated types
160 case Property::NONE : // FALLTHROUGH
161 case Property::BOOLEAN : // FALLTHROUGH
162 case Property::FLOAT : // FALLTHROUGH
163 case Property::INTEGER :
165 break; // nothing to do
167 case Property::VECTOR2 :
172 case Property::VECTOR3:
177 case Property::VECTOR4:
182 case Property::MATRIX3:
187 case Property::MATRIX:
192 case Property::RECTANGLE:
197 case Property::ROTATION:
199 delete angleAxisValue;
202 case Property::STRING:
207 case Property::ARRAY:
217 case Property::EXTENTS:
230 int32_t integerValue;
232 // must use pointers for any class value pre c++ 11
233 Vector2* vector2Value;
234 Vector3* vector3Value;
235 Vector4* vector4Value;
236 Matrix3* matrix3Value;
238 AngleAxis* angleAxisValue;
239 std::string* stringValue;
240 Rect<int32_t>* rectValue;
241 Property::Array* arrayValue;
242 Property::Map* mapValue;
243 Extents* extentsValue;
249 Impl( const Impl& ) = delete;
250 Impl& operator=( const Impl& ) = delete;
254 Property::Value::Value()
259 Property::Value::Value( bool booleanValue )
260 : mImpl( new Impl( booleanValue ) )
264 Property::Value::Value( float floatValue )
265 : mImpl( new Impl( floatValue ) )
269 Property::Value::Value( int32_t integerValue )
270 : mImpl( new Impl( integerValue ) )
274 Property::Value::Value( const Vector2& vectorValue )
275 : mImpl( new Impl( vectorValue ) )
279 Property::Value::Value( const Vector3& vectorValue )
280 : mImpl( new Impl( vectorValue ) )
284 Property::Value::Value( const Vector4& vectorValue )
285 : mImpl( new Impl( vectorValue ) )
289 Property::Value::Value( const Matrix3& matrixValue )
290 : mImpl( new Impl( matrixValue ) )
294 Property::Value::Value( const Matrix& matrixValue )
295 : mImpl( new Impl( matrixValue ) )
299 Property::Value::Value( const Rect<int32_t>& rectValue )
300 : mImpl( new Impl( rectValue ) )
304 Property::Value::Value( const AngleAxis& angleAxisValue )
305 : mImpl( new Impl( angleAxisValue ) )
309 Property::Value::Value( const Quaternion& quaternionValue )
310 : mImpl( new Impl( quaternionValue ) )
314 Property::Value::Value( const std::string& stringValue )
315 : mImpl( new Impl( stringValue ) )
319 Property::Value::Value( const char* stringValue )
322 if( stringValue ) // string constructor is undefined with nullptr
324 mImpl = new Impl( std::string(stringValue) );
328 mImpl = new Impl( std::string() );
332 Property::Value::Value( Property::Array& arrayValue )
333 : mImpl( new Impl( arrayValue ) )
337 Property::Value::Value( Property::Array&& arrayValue )
338 : mImpl( new Impl( std::move( arrayValue ) ) )
342 Property::Value::Value( Property::Map& mapValue )
343 : mImpl( new Impl( mapValue ) )
347 Property::Value::Value( Property::Map&& mapValue )
348 : mImpl( new Impl( std::move( mapValue ) ) )
352 Property::Value::Value( const Extents& extentsValue )
353 : mImpl( new Impl( extentsValue ) )
357 Property::Value::Value( Type type )
362 case Property::BOOLEAN:
364 mImpl = new Impl( false );
367 case Property::FLOAT:
369 mImpl = new Impl( 0.f );
372 case Property::INTEGER:
374 mImpl = new Impl( 0 );
377 case Property::VECTOR2:
379 mImpl = new Impl( Vector2::ZERO );
382 case Property::VECTOR3:
384 mImpl = new Impl( Vector3::ZERO );
387 case Property::VECTOR4:
389 mImpl = new Impl( Vector4::ZERO );
392 case Property::RECTANGLE:
394 mImpl = new Impl( Rect<int32_t>(0,0,0,0) );
397 case Property::ROTATION:
399 mImpl = new Impl( AngleAxis() );
402 case Property::STRING:
404 mImpl = new Impl( std::string() );
407 case Property::MATRIX:
409 mImpl = new Impl( Matrix() );
412 case Property::MATRIX3:
414 mImpl = new Impl( Matrix3() );
417 case Property::ARRAY:
419 mImpl = new Impl( Property::Array() );
424 mImpl = new Impl( Property::Map() );
427 case Property::EXTENTS:
429 mImpl = new Impl( Extents() );
434 // No need to create an Impl
440 Property::Value::Value( const Property::Value& value )
443 // reuse assignment operator
447 Property::Value::Value( Property::Value&& value )
448 : mImpl( value.mImpl )
450 value.mImpl = nullptr;
453 Property::Value& Property::Value::operator=( const Property::Value& value )
455 if ( this == &value )
457 // skip self assignment
460 // if we are assigned an empty value, just drop impl
467 // first check if the type is the same, no need to change impl, just assign
468 if( mImpl && ( mImpl->type == value.mImpl->type ) )
470 switch( mImpl->type )
472 case Property::BOOLEAN:
474 mImpl->integerValue = value.mImpl->integerValue;
477 case Property::FLOAT:
479 mImpl->floatValue = value.mImpl->floatValue;
482 case Property::INTEGER:
484 mImpl->integerValue = value.mImpl->integerValue;
487 case Property::VECTOR2:
489 *mImpl->vector2Value = *value.mImpl->vector2Value; // type cannot change in mImpl so vector is allocated
492 case Property::VECTOR3:
494 *mImpl->vector3Value = *value.mImpl->vector3Value; // type cannot change in mImpl so vector is allocated
497 case Property::VECTOR4:
499 *mImpl->vector4Value = *value.mImpl->vector4Value; // type cannot change in mImpl so vector is allocated
502 case Property::RECTANGLE:
504 *mImpl->rectValue = *value.mImpl->rectValue; // type cannot change in mImpl so rect is allocated
507 case Property::ROTATION:
509 *mImpl->angleAxisValue = *value.mImpl->angleAxisValue; // type cannot change in mImpl so quaternion is allocated
512 case Property::STRING:
514 *mImpl->stringValue = *value.mImpl->stringValue; // type cannot change in mImpl so string is allocated
517 case Property::MATRIX:
519 *mImpl->matrixValue = *value.mImpl->matrixValue; // type cannot change in mImpl so matrix is allocated
522 case Property::MATRIX3:
524 *mImpl->matrix3Value = *value.mImpl->matrix3Value; // type cannot change in mImpl so matrix is allocated
527 case Property::ARRAY:
529 *mImpl->arrayValue = *value.mImpl->arrayValue; // type cannot change in mImpl so array is allocated
534 *mImpl->mapValue = *value.mImpl->mapValue; // type cannot change in mImpl so map is allocated
537 case Property::EXTENTS:
539 *mImpl->extentsValue = *value.mImpl->extentsValue; // type cannot change in mImpl so extents is allocated
543 { // mImpl will be a nullptr, there's no way to get to this case
549 // different type, release old impl and create new
550 Impl* newImpl( nullptr );
551 switch ( value.mImpl->type )
553 case Property::BOOLEAN:
555 newImpl = new Impl( bool( value.mImpl->integerValue ) );
558 case Property::FLOAT:
560 newImpl = new Impl( value.mImpl->floatValue );
563 case Property::INTEGER:
565 newImpl = new Impl( value.mImpl->integerValue );
568 case Property::VECTOR2:
570 newImpl = new Impl( *value.mImpl->vector2Value ); // type cannot change in mImpl so vector is allocated
573 case Property::VECTOR3:
575 newImpl = new Impl( *value.mImpl->vector3Value ); // type cannot change in mImpl so vector is allocated
578 case Property::VECTOR4:
580 newImpl = new Impl( *value.mImpl->vector4Value ); // type cannot change in mImpl so vector is allocated
583 case Property::RECTANGLE:
585 newImpl = new Impl( *value.mImpl->rectValue ); // type cannot change in mImpl so rect is allocated
588 case Property::ROTATION:
590 newImpl = new Impl( *value.mImpl->angleAxisValue ); // type cannot change in mImpl so quaternion is allocated
593 case Property::MATRIX3:
595 newImpl = new Impl( *value.mImpl->matrix3Value ); // type cannot change in mImpl so matrix is allocated
598 case Property::MATRIX:
600 newImpl = new Impl( *value.mImpl->matrixValue ); // type cannot change in mImpl so matrix is allocated
603 case Property::STRING:
605 newImpl = new Impl( *value.mImpl->stringValue ); // type cannot change in mImpl so string is allocated
608 case Property::ARRAY:
610 newImpl = new Impl( *value.mImpl->arrayValue ); // type cannot change in mImpl so array is allocated
615 newImpl = new Impl( *value.mImpl->mapValue ); // type cannot change in mImpl so map is allocated
618 case Property::EXTENTS:
620 newImpl = new Impl( *value.mImpl->extentsValue ); // type cannot change in mImpl so extents is allocated
624 { // nullptr value will be used for "empty" value
634 Property::Value& Property::Value::operator=( Property::Value&& value )
640 value.mImpl = nullptr;
646 Property::Value::~Value()
651 Property::Type Property::Value::GetType() const
653 Property::Type type( Property::NONE );
661 bool Property::Value::Get( bool& booleanValue ) const
663 bool converted = false;
664 if( mImpl && IsIntegerType( mImpl->type ) )
666 booleanValue = mImpl->integerValue;
672 bool Property::Value::Get( float& floatValue ) const
674 bool converted = false;
677 if( mImpl->type == FLOAT )
679 floatValue = mImpl->floatValue;
682 else if( IsIntegerType( mImpl->type ) )
684 floatValue = static_cast< float >( mImpl->integerValue );
691 bool Property::Value::Get( int32_t& integerValue ) const
693 bool converted = false;
696 if( IsIntegerType( mImpl->type ) )
698 integerValue = mImpl->integerValue;
701 else if( mImpl->type == FLOAT )
703 integerValue = static_cast< int32_t >( mImpl->floatValue );
710 bool Property::Value::Get( Vector2& vectorValue ) const
712 bool converted = false;
715 // type cannot change in mImpl so vector is allocated
716 if( mImpl->type == VECTOR2 || mImpl->type == VECTOR3 || mImpl->type == VECTOR4 )
718 vectorValue = *(mImpl->vector2Value); // if Vector3 or 4 only x and y are assigned
725 bool Property::Value::Get( Vector3& vectorValue ) const
727 bool converted = false;
730 // type cannot change in mImpl so vector is allocated
731 if ( mImpl->type == VECTOR3 || mImpl->type == VECTOR4 )
733 vectorValue = *(mImpl->vector3Value); // if Vector4 only x,y,z are assigned
736 else if( mImpl->type == VECTOR2 )
738 vectorValue = *(mImpl->vector2Value);
745 bool Property::Value::Get( Vector4& vectorValue ) const
747 bool converted = false;
750 if( mImpl->type == VECTOR4 ) // type cannot change in mImpl so vector is allocated
752 vectorValue = *(mImpl->vector4Value);
755 else if( mImpl->type == VECTOR2 )
757 vectorValue = *(mImpl->vector2Value);
760 else if( mImpl->type == VECTOR3 )
762 vectorValue = *(mImpl->vector3Value);
769 bool Property::Value::Get( Matrix3& matrixValue ) const
771 bool converted = false;
772 if( mImpl && (mImpl->type == MATRIX3) ) // type cannot change in mImpl so matrix is allocated
774 matrixValue = *(mImpl->matrix3Value);
780 bool Property::Value::Get( Matrix& matrixValue ) const
782 bool converted = false;
783 if( mImpl && (mImpl->type == MATRIX) ) // type cannot change in mImpl so matrix is allocated
785 matrixValue = *(mImpl->matrixValue);
791 bool Property::Value::Get( Rect<int32_t>& rectValue ) const
793 bool converted = false;
794 if( mImpl && (mImpl->type == RECTANGLE) ) // type cannot change in mImpl so rect is allocated
796 rectValue = *(mImpl->rectValue);
802 bool Property::Value::Get( AngleAxis& angleAxisValue ) const
804 bool converted = false;
805 if( mImpl && (mImpl->type == ROTATION) ) // type cannot change in mImpl so angleAxis is allocated
807 angleAxisValue = *(mImpl->angleAxisValue);
813 bool Property::Value::Get( Quaternion& quaternionValue ) const
815 bool converted = false;
816 if( mImpl && (mImpl->type == ROTATION) ) // type cannot change in mImpl so angleAxis is allocated
818 quaternionValue = Quaternion(mImpl->angleAxisValue->angle, mImpl->angleAxisValue->axis );
824 bool Property::Value::Get( std::string& stringValue ) const
826 bool converted = false;
827 if( mImpl && (mImpl->type == STRING) ) // type cannot change in mImpl so string is allocated
829 stringValue.assign( *(mImpl->stringValue) );
835 bool Property::Value::Get( Property::Array& arrayValue ) const
837 bool converted = false;
838 if( mImpl && (mImpl->type == ARRAY) ) // type cannot change in mImpl so array is allocated
840 arrayValue = *(mImpl->arrayValue);
846 bool Property::Value::Get( Property::Map& mapValue ) const
848 bool converted = false;
849 if( mImpl && (mImpl->type == MAP) ) // type cannot change in mImpl so map is allocated
851 mapValue = *(mImpl->mapValue);
857 Property::Array* Property::Value::GetArray() const
859 Property::Array* array = nullptr;
860 if( mImpl && (mImpl->type == ARRAY) ) // type cannot change in mImpl so array is allocated
862 array = mImpl->arrayValue;
867 Property::Map* Property::Value::GetMap() const
869 Property::Map* map = nullptr;
870 if( mImpl && (mImpl->type == MAP) ) // type cannot change in mImpl so map is allocated
872 map = mImpl->mapValue;
877 bool Property::Value::Get( Extents& extentsValue ) const
879 bool converted = false;
882 if( mImpl->type == EXTENTS )
884 extentsValue = *(mImpl->extentsValue);
887 else if( mImpl->type == VECTOR4 )
889 extentsValue.start = static_cast< uint16_t >( mImpl->vector4Value->x );
890 extentsValue.end = static_cast< uint16_t >( mImpl->vector4Value->y );
891 extentsValue.top = static_cast< uint16_t >( mImpl->vector4Value->z );
892 extentsValue.bottom = static_cast< uint16_t >( mImpl->vector4Value->w );
899 std::ostream& operator<<( std::ostream& stream, const Property::Value& value )
903 const Property::Value::Impl& impl( *value.mImpl );
907 case Dali::Property::BOOLEAN:
909 stream << impl.integerValue;
912 case Dali::Property::FLOAT:
914 stream << impl.floatValue;
917 case Dali::Property::INTEGER:
919 stream << impl.integerValue;
922 case Dali::Property::VECTOR2:
924 stream << *impl.vector2Value;
927 case Dali::Property::VECTOR3:
929 stream << *impl.vector3Value;
932 case Dali::Property::VECTOR4:
934 stream << *impl.vector4Value;
937 case Dali::Property::MATRIX3:
939 stream << *impl.matrix3Value;
942 case Dali::Property::MATRIX:
944 stream << *impl.matrixValue;
947 case Dali::Property::RECTANGLE:
949 stream << *impl.rectValue;
952 case Dali::Property::ROTATION:
954 stream << *impl.angleAxisValue;
957 case Dali::Property::STRING:
959 stream << *impl.stringValue;
962 case Dali::Property::ARRAY:
964 stream << *(value.GetArray());
967 case Dali::Property::MAP:
969 stream << *(value.GetMap());
972 case Dali::Property::EXTENTS:
974 stream << *impl.extentsValue;
977 case Dali::Property::NONE:
978 { // mImpl will be a nullptr, there's no way to get to this case
984 stream << "undefined type";