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 ) )
153 Impl( const std::initializer_list< KeyValuePair >& values )
154 : type( Property::MAP ),
155 mapValue( new Property::Map( values ) )
160 * Destructor, takes care of releasing the dynamically allocated types
166 case Property::NONE : // FALLTHROUGH
167 case Property::BOOLEAN : // FALLTHROUGH
168 case Property::FLOAT : // FALLTHROUGH
169 case Property::INTEGER :
171 break; // nothing to do
173 case Property::VECTOR2 :
178 case Property::VECTOR3:
183 case Property::VECTOR4:
188 case Property::MATRIX3:
193 case Property::MATRIX:
198 case Property::RECTANGLE:
203 case Property::ROTATION:
205 delete angleAxisValue;
208 case Property::STRING:
213 case Property::ARRAY:
223 case Property::EXTENTS:
236 int32_t integerValue;
238 // must use pointers for any class value pre c++ 11
239 Vector2* vector2Value;
240 Vector3* vector3Value;
241 Vector4* vector4Value;
242 Matrix3* matrix3Value;
244 AngleAxis* angleAxisValue;
245 std::string* stringValue;
246 Rect<int32_t>* rectValue;
247 Property::Array* arrayValue;
248 Property::Map* mapValue;
249 Extents* extentsValue;
255 Impl( const Impl& ) = delete;
256 Impl& operator=( const Impl& ) = delete;
260 Property::Value::Value()
265 Property::Value::Value( bool booleanValue )
266 : mImpl( new Impl( booleanValue ) )
270 Property::Value::Value( float floatValue )
271 : mImpl( new Impl( floatValue ) )
275 Property::Value::Value( int32_t integerValue )
276 : mImpl( new Impl( integerValue ) )
280 Property::Value::Value( const Vector2& vectorValue )
281 : mImpl( new Impl( vectorValue ) )
285 Property::Value::Value( const Vector3& vectorValue )
286 : mImpl( new Impl( vectorValue ) )
290 Property::Value::Value( const Vector4& vectorValue )
291 : mImpl( new Impl( vectorValue ) )
295 Property::Value::Value( const Matrix3& matrixValue )
296 : mImpl( new Impl( matrixValue ) )
300 Property::Value::Value( const Matrix& matrixValue )
301 : mImpl( new Impl( matrixValue ) )
305 Property::Value::Value( const Rect<int32_t>& rectValue )
306 : mImpl( new Impl( rectValue ) )
310 Property::Value::Value( const AngleAxis& angleAxisValue )
311 : mImpl( new Impl( angleAxisValue ) )
315 Property::Value::Value( const Quaternion& quaternionValue )
316 : mImpl( new Impl( quaternionValue ) )
320 Property::Value::Value( const std::string& stringValue )
321 : mImpl( new Impl( stringValue ) )
325 Property::Value::Value( const char* stringValue )
328 if( stringValue ) // string constructor is undefined with nullptr
330 mImpl = new Impl( std::string(stringValue) );
334 mImpl = new Impl( std::string() );
338 Property::Value::Value( Property::Array& arrayValue )
339 : mImpl( new Impl( arrayValue ) )
343 Property::Value::Value( Property::Array&& arrayValue )
344 : mImpl( new Impl( std::move( arrayValue ) ) )
348 Property::Value::Value( Property::Map& mapValue )
349 : mImpl( new Impl( mapValue ) )
353 Property::Value::Value( Property::Map&& mapValue )
354 : mImpl( new Impl( std::move( mapValue ) ) )
358 Property::Value::Value( const Extents& extentsValue )
359 : mImpl( new Impl( extentsValue ) )
363 Property::Value::Value( const std::initializer_list< KeyValuePair >& values )
364 : mImpl( new Impl( values ) )
368 Property::Value::Value( Type type )
373 case Property::BOOLEAN:
375 mImpl = new Impl( false );
378 case Property::FLOAT:
380 mImpl = new Impl( 0.f );
383 case Property::INTEGER:
385 mImpl = new Impl( 0 );
388 case Property::VECTOR2:
390 mImpl = new Impl( Vector2::ZERO );
393 case Property::VECTOR3:
395 mImpl = new Impl( Vector3::ZERO );
398 case Property::VECTOR4:
400 mImpl = new Impl( Vector4::ZERO );
403 case Property::RECTANGLE:
405 mImpl = new Impl( Rect<int32_t>(0,0,0,0) );
408 case Property::ROTATION:
410 mImpl = new Impl( AngleAxis() );
413 case Property::STRING:
415 mImpl = new Impl( std::string() );
418 case Property::MATRIX:
420 mImpl = new Impl( Matrix() );
423 case Property::MATRIX3:
425 mImpl = new Impl( Matrix3() );
428 case Property::ARRAY:
430 mImpl = new Impl( Property::Array() );
435 mImpl = new Impl( Property::Map() );
438 case Property::EXTENTS:
440 mImpl = new Impl( Extents() );
445 // No need to create an Impl
451 Property::Value::Value( const Property::Value& value )
454 // reuse assignment operator
458 Property::Value::Value( Property::Value&& value )
459 : mImpl( value.mImpl )
461 value.mImpl = nullptr;
464 Property::Value& Property::Value::operator=( const Property::Value& value )
466 if ( this == &value )
468 // skip self assignment
471 // if we are assigned an empty value, just drop impl
478 // first check if the type is the same, no need to change impl, just assign
479 if( mImpl && ( mImpl->type == value.mImpl->type ) )
481 switch( mImpl->type )
483 case Property::BOOLEAN:
485 mImpl->integerValue = value.mImpl->integerValue;
488 case Property::FLOAT:
490 mImpl->floatValue = value.mImpl->floatValue;
493 case Property::INTEGER:
495 mImpl->integerValue = value.mImpl->integerValue;
498 case Property::VECTOR2:
500 *mImpl->vector2Value = *value.mImpl->vector2Value; // type cannot change in mImpl so vector is allocated
503 case Property::VECTOR3:
505 *mImpl->vector3Value = *value.mImpl->vector3Value; // type cannot change in mImpl so vector is allocated
508 case Property::VECTOR4:
510 *mImpl->vector4Value = *value.mImpl->vector4Value; // type cannot change in mImpl so vector is allocated
513 case Property::RECTANGLE:
515 *mImpl->rectValue = *value.mImpl->rectValue; // type cannot change in mImpl so rect is allocated
518 case Property::ROTATION:
520 *mImpl->angleAxisValue = *value.mImpl->angleAxisValue; // type cannot change in mImpl so quaternion is allocated
523 case Property::STRING:
525 *mImpl->stringValue = *value.mImpl->stringValue; // type cannot change in mImpl so string is allocated
528 case Property::MATRIX:
530 *mImpl->matrixValue = *value.mImpl->matrixValue; // type cannot change in mImpl so matrix is allocated
533 case Property::MATRIX3:
535 *mImpl->matrix3Value = *value.mImpl->matrix3Value; // type cannot change in mImpl so matrix is allocated
538 case Property::ARRAY:
540 *mImpl->arrayValue = *value.mImpl->arrayValue; // type cannot change in mImpl so array is allocated
545 *mImpl->mapValue = *value.mImpl->mapValue; // type cannot change in mImpl so map is allocated
548 case Property::EXTENTS:
550 *mImpl->extentsValue = *value.mImpl->extentsValue; // type cannot change in mImpl so extents is allocated
554 { // mImpl will be a nullptr, there's no way to get to this case
560 // different type, release old impl and create new
561 Impl* newImpl( nullptr );
562 switch ( value.mImpl->type )
564 case Property::BOOLEAN:
566 newImpl = new Impl( bool( value.mImpl->integerValue ) );
569 case Property::FLOAT:
571 newImpl = new Impl( value.mImpl->floatValue );
574 case Property::INTEGER:
576 newImpl = new Impl( value.mImpl->integerValue );
579 case Property::VECTOR2:
581 newImpl = new Impl( *value.mImpl->vector2Value ); // type cannot change in mImpl so vector is allocated
584 case Property::VECTOR3:
586 newImpl = new Impl( *value.mImpl->vector3Value ); // type cannot change in mImpl so vector is allocated
589 case Property::VECTOR4:
591 newImpl = new Impl( *value.mImpl->vector4Value ); // type cannot change in mImpl so vector is allocated
594 case Property::RECTANGLE:
596 newImpl = new Impl( *value.mImpl->rectValue ); // type cannot change in mImpl so rect is allocated
599 case Property::ROTATION:
601 newImpl = new Impl( *value.mImpl->angleAxisValue ); // type cannot change in mImpl so quaternion is allocated
604 case Property::MATRIX3:
606 newImpl = new Impl( *value.mImpl->matrix3Value ); // type cannot change in mImpl so matrix is allocated
609 case Property::MATRIX:
611 newImpl = new Impl( *value.mImpl->matrixValue ); // type cannot change in mImpl so matrix is allocated
614 case Property::STRING:
616 newImpl = new Impl( *value.mImpl->stringValue ); // type cannot change in mImpl so string is allocated
619 case Property::ARRAY:
621 newImpl = new Impl( *value.mImpl->arrayValue ); // type cannot change in mImpl so array is allocated
626 newImpl = new Impl( *value.mImpl->mapValue ); // type cannot change in mImpl so map is allocated
629 case Property::EXTENTS:
631 newImpl = new Impl( *value.mImpl->extentsValue ); // type cannot change in mImpl so extents is allocated
635 { // nullptr value will be used for "empty" value
645 Property::Value& Property::Value::operator=( Property::Value&& value )
651 value.mImpl = nullptr;
657 Property::Value::~Value()
662 Property::Type Property::Value::GetType() const
664 Property::Type type( Property::NONE );
672 bool Property::Value::Get( bool& booleanValue ) const
674 bool converted = false;
675 if( mImpl && IsIntegerType( mImpl->type ) )
677 booleanValue = mImpl->integerValue;
683 bool Property::Value::Get( float& floatValue ) const
685 bool converted = false;
688 if( mImpl->type == FLOAT )
690 floatValue = mImpl->floatValue;
693 else if( IsIntegerType( mImpl->type ) )
695 floatValue = static_cast< float >( mImpl->integerValue );
702 bool Property::Value::Get( int32_t& integerValue ) const
704 bool converted = false;
707 if( IsIntegerType( mImpl->type ) )
709 integerValue = mImpl->integerValue;
712 else if( mImpl->type == FLOAT )
714 integerValue = static_cast< int32_t >( mImpl->floatValue );
721 bool Property::Value::Get( Vector2& vectorValue ) const
723 bool converted = false;
726 // type cannot change in mImpl so vector is allocated
727 if( mImpl->type == VECTOR2 || mImpl->type == VECTOR3 || mImpl->type == VECTOR4 )
729 vectorValue = *(mImpl->vector2Value); // if Vector3 or 4 only x and y are assigned
736 bool Property::Value::Get( Vector3& vectorValue ) const
738 bool converted = false;
741 // type cannot change in mImpl so vector is allocated
742 if ( mImpl->type == VECTOR3 || mImpl->type == VECTOR4 )
744 vectorValue = *(mImpl->vector3Value); // if Vector4 only x,y,z are assigned
747 else if( mImpl->type == VECTOR2 )
749 vectorValue = *(mImpl->vector2Value);
756 bool Property::Value::Get( Vector4& vectorValue ) const
758 bool converted = false;
761 if( mImpl->type == VECTOR4 ) // type cannot change in mImpl so vector is allocated
763 vectorValue = *(mImpl->vector4Value);
766 else if( mImpl->type == VECTOR2 )
768 vectorValue = *(mImpl->vector2Value);
771 else if( mImpl->type == VECTOR3 )
773 vectorValue = *(mImpl->vector3Value);
780 bool Property::Value::Get( Matrix3& matrixValue ) const
782 bool converted = false;
783 if( mImpl && (mImpl->type == MATRIX3) ) // type cannot change in mImpl so matrix is allocated
785 matrixValue = *(mImpl->matrix3Value);
791 bool Property::Value::Get( Matrix& matrixValue ) const
793 bool converted = false;
794 if( mImpl && (mImpl->type == MATRIX) ) // type cannot change in mImpl so matrix is allocated
796 matrixValue = *(mImpl->matrixValue);
802 bool Property::Value::Get( Rect<int32_t>& rectValue ) const
804 bool converted = false;
805 if( mImpl && (mImpl->type == RECTANGLE) ) // type cannot change in mImpl so rect is allocated
807 rectValue = *(mImpl->rectValue);
813 bool Property::Value::Get( AngleAxis& angleAxisValue ) const
815 bool converted = false;
816 if( mImpl && (mImpl->type == ROTATION) ) // type cannot change in mImpl so angleAxis is allocated
818 angleAxisValue = *(mImpl->angleAxisValue);
824 bool Property::Value::Get( Quaternion& quaternionValue ) const
826 bool converted = false;
827 if( mImpl && (mImpl->type == ROTATION) ) // type cannot change in mImpl so angleAxis is allocated
829 quaternionValue = Quaternion(mImpl->angleAxisValue->angle, mImpl->angleAxisValue->axis );
835 bool Property::Value::Get( std::string& stringValue ) const
837 bool converted = false;
838 if( mImpl && (mImpl->type == STRING) ) // type cannot change in mImpl so string is allocated
840 stringValue.assign( *(mImpl->stringValue) );
846 bool Property::Value::Get( Property::Array& arrayValue ) const
848 bool converted = false;
849 if( mImpl && (mImpl->type == ARRAY) ) // type cannot change in mImpl so array is allocated
851 arrayValue = *(mImpl->arrayValue);
857 bool Property::Value::Get( Property::Map& mapValue ) const
859 bool converted = false;
860 if( mImpl && (mImpl->type == MAP) ) // type cannot change in mImpl so map is allocated
862 mapValue = *(mImpl->mapValue);
868 Property::Array* Property::Value::GetArray() const
870 Property::Array* array = nullptr;
871 if( mImpl && (mImpl->type == ARRAY) ) // type cannot change in mImpl so array is allocated
873 array = mImpl->arrayValue;
878 Property::Map* Property::Value::GetMap() const
880 Property::Map* map = nullptr;
881 if( mImpl && (mImpl->type == MAP) ) // type cannot change in mImpl so map is allocated
883 map = mImpl->mapValue;
888 bool Property::Value::Get( Extents& extentsValue ) const
890 bool converted = false;
893 if( mImpl->type == EXTENTS )
895 extentsValue = *(mImpl->extentsValue);
898 else if( mImpl->type == VECTOR4 )
900 extentsValue.start = static_cast< uint16_t >( mImpl->vector4Value->x );
901 extentsValue.end = static_cast< uint16_t >( mImpl->vector4Value->y );
902 extentsValue.top = static_cast< uint16_t >( mImpl->vector4Value->z );
903 extentsValue.bottom = static_cast< uint16_t >( mImpl->vector4Value->w );
910 std::ostream& operator<<( std::ostream& stream, const Property::Value& value )
914 const Property::Value::Impl& impl( *value.mImpl );
918 case Dali::Property::BOOLEAN:
920 stream << impl.integerValue;
923 case Dali::Property::FLOAT:
925 stream << impl.floatValue;
928 case Dali::Property::INTEGER:
930 stream << impl.integerValue;
933 case Dali::Property::VECTOR2:
935 stream << *impl.vector2Value;
938 case Dali::Property::VECTOR3:
940 stream << *impl.vector3Value;
943 case Dali::Property::VECTOR4:
945 stream << *impl.vector4Value;
948 case Dali::Property::MATRIX3:
950 stream << *impl.matrix3Value;
953 case Dali::Property::MATRIX:
955 stream << *impl.matrixValue;
958 case Dali::Property::RECTANGLE:
960 stream << *impl.rectValue;
963 case Dali::Property::ROTATION:
965 stream << *impl.angleAxisValue;
968 case Dali::Property::STRING:
970 stream << *impl.stringValue;
973 case Dali::Property::ARRAY:
975 stream << *(value.GetArray());
978 case Dali::Property::MAP:
980 stream << *(value.GetMap());
983 case Dali::Property::EXTENTS:
985 stream << *impl.extentsValue;
988 case Dali::Property::NONE:
989 { // mImpl will be a nullptr, there's no way to get to this case
995 stream << "undefined type";