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/object/any.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>
43 struct Property::Value::Impl
46 : mType( Property::NONE )
51 : mType( PropertyTypes::Get<bool>() ),
56 Impl(float floatValue)
57 : mType( PropertyTypes::Get<float>() ),
62 Impl(int integerValue)
63 : mType( PropertyTypes::Get<int>() ),
64 mValue( integerValue )
68 Impl(unsigned int unsignedIntegerValue)
69 : mType( PropertyTypes::Get<unsigned int>() ),
70 mValue( unsignedIntegerValue )
74 Impl(const Vector2& vectorValue)
75 : mType( PropertyTypes::Get<Vector2>() ),
80 Impl(const Vector3& vectorValue)
81 : mType( PropertyTypes::Get<Vector3>() ),
86 Impl(const Vector4& vectorValue)
87 : mType( PropertyTypes::Get<Vector4>() ),
92 Impl(const Matrix3& matrixValue)
93 : mType(PropertyTypes::Get<Matrix3>()),
98 Impl(const Matrix& matrixValue)
99 : mType(PropertyTypes::Get<Matrix>()),
104 Impl(const AngleAxis& angleAxisValue)
105 : mType( PropertyTypes::Get<AngleAxis>() ),
106 mValue( angleAxisValue )
110 Impl(const Quaternion& quaternionValue)
111 : mType( PropertyTypes::Get<Quaternion>() ),
112 mValue( quaternionValue )
116 Impl(const std::string& stringValue)
117 : mType( PropertyTypes::Get<std::string>() ),
118 mValue( stringValue )
122 Impl(const Rect<int>& rect)
123 : mType( PropertyTypes::Get<Rect<int> >() ),
128 Impl(Property::Map container)
129 : mType( PropertyTypes::Get<Property::Map >() ),
134 Impl(Property::Array container)
135 : mType( PropertyTypes::Get<Property::Array >() ),
142 typedef Any AnyValue;
146 Property::Value::Value()
152 Property::Value::Value(bool boolValue)
155 mImpl = new Impl( boolValue );
158 Property::Value::Value(float floatValue)
161 mImpl = new Impl( floatValue );
164 Property::Value::Value(int integerValue)
167 mImpl = new Impl( integerValue );
170 Property::Value::Value(unsigned int unsignedIntegerValue)
173 mImpl = new Impl( unsignedIntegerValue );
176 Property::Value::Value(const Vector2& vectorValue)
179 mImpl = new Impl( vectorValue );
182 Property::Value::Value(const Vector3& vectorValue)
185 mImpl = new Impl( vectorValue );
188 Property::Value::Value(const Vector4& vectorValue)
191 mImpl = new Impl( vectorValue );
194 Property::Value::Value(const Matrix3& matrixValue)
197 mImpl = new Impl( matrixValue );
200 Property::Value::Value(const Matrix& matrixValue)
203 mImpl = new Impl( matrixValue );
206 Property::Value::Value(const Rect<int>& rect)
209 mImpl = new Impl( rect );
212 Property::Value::Value(const AngleAxis& angleAxisValue)
215 mImpl = new Impl( angleAxisValue );
218 Property::Value::Value(const Quaternion& quaternionValue)
220 mImpl = new Impl( quaternionValue );
223 Property::Value::Value(const std::string& stringValue)
225 mImpl = new Impl( stringValue );
228 Property::Value::Value(const char *stringValue)
230 mImpl = new Impl( std::string(stringValue) );
233 Property::Value::Value(Property::Array &arrayValue)
235 mImpl = new Impl( arrayValue );
238 Property::Value::Value(Property::Map &mapValue)
240 mImpl = new Impl( mapValue );
244 Property::Value::~Value()
249 Property::Value::Value(const Value& value)
251 switch (value.GetType())
253 case Property::BOOLEAN:
255 mImpl = new Impl( value.Get<bool>() );
259 case Property::FLOAT:
261 mImpl = new Impl( value.Get<float>() );
265 case Property::INTEGER:
267 mImpl = new Impl( value.Get<int>() );
271 case Property::UNSIGNED_INTEGER:
273 mImpl = new Impl( value.Get<unsigned int>() );
277 case Property::VECTOR2:
279 mImpl = new Impl( value.Get<Vector2>() );
283 case Property::VECTOR3:
285 mImpl = new Impl( value.Get<Vector3>() );
289 case Property::VECTOR4:
291 mImpl = new Impl( value.Get<Vector4>() );
295 case Property::RECTANGLE:
297 mImpl = new Impl( value.Get<Rect<int> >() );
301 case Property::ROTATION:
303 // Orientations have two representations
304 DALI_ASSERT_DEBUG( typeid(Quaternion) == value.mImpl->mValue.GetType() ||
305 typeid(AngleAxis) == value.mImpl->mValue.GetType() );
307 if ( typeid(Quaternion) == value.mImpl->mValue.GetType() )
309 mImpl = new Impl( value.Get<Quaternion>() );
313 mImpl = new Impl( value.Get<AngleAxis>() );
318 case Property::MATRIX3:
320 mImpl = new Impl( value.Get<Matrix3>());
324 case Property::MATRIX:
326 mImpl = new Impl( value.Get<Matrix>());
330 case Property::STRING:
332 mImpl = new Impl( value.Get<std::string>() );
338 mImpl = new Impl( value.Get<Property::Map>() );
342 case Property::ARRAY:
344 mImpl = new Impl( value.Get<Property::Array>() );
348 case Property::NONE: // fall
357 Property::Value::Value(Type type)
361 case Property::BOOLEAN:
363 mImpl = new Impl( false );
367 case Property::FLOAT:
369 mImpl = new Impl( 0.f );
373 case Property::INTEGER:
375 mImpl = new Impl( 0 );
379 case Property::UNSIGNED_INTEGER:
381 mImpl = new Impl( 0U );
385 case Property::VECTOR2:
387 mImpl = new Impl( Vector2::ZERO );
391 case Property::VECTOR3:
393 mImpl = new Impl( Vector3::ZERO );
397 case Property::VECTOR4:
399 mImpl = new Impl( Vector4::ZERO );
403 case Property::RECTANGLE:
405 mImpl = new Impl( Rect<int>(0,0,0,0) );
409 case Property::ROTATION:
411 mImpl = new Impl( Quaternion( Radian(0.f), Vector3::YAXIS) );
415 case Property::STRING:
417 mImpl = new Impl( std::string() );
423 mImpl = new Impl( Property::Map() );
427 case Property::MATRIX:
429 mImpl = new Impl( Matrix() );
433 case Property::MATRIX3:
435 mImpl = new Impl( Matrix3() );
439 case Property::ARRAY:
441 mImpl = new Impl( Property::Array() );
445 case Property::NONE: // fall
454 Property::Value& Property::Value::operator=(const Property::Value& value)
458 // skip self assignment
462 mImpl->mType = value.GetType();
464 switch (mImpl->mType)
466 case Property::BOOLEAN:
468 mImpl->mValue = value.Get<bool>();
472 case Property::FLOAT:
474 mImpl->mValue = value.Get<float>();
478 case Property::INTEGER:
480 mImpl->mValue = value.Get<int>();
484 case Property::UNSIGNED_INTEGER:
486 mImpl->mValue = value.Get<unsigned int>();
490 case Property::VECTOR2:
492 mImpl->mValue = value.Get<Vector2>();
496 case Property::VECTOR3:
498 mImpl->mValue = value.Get<Vector3>();
502 case Property::VECTOR4:
504 mImpl->mValue = value.Get<Vector4>();
508 case Property::RECTANGLE:
510 mImpl->mValue = value.Get<Rect<int> >();
514 case Property::ROTATION:
516 // Orientations have two representations
517 DALI_ASSERT_DEBUG( typeid(Quaternion) == value.mImpl->mValue.GetType() ||
518 typeid(AngleAxis) == value.mImpl->mValue.GetType() );
520 if ( typeid(Quaternion) == value.mImpl->mValue.GetType() )
522 mImpl = new Impl( value.Get<Quaternion>() );
526 mImpl = new Impl( value.Get<AngleAxis>() );
531 case Property::STRING:
533 mImpl->mValue = value.Get<std::string>();
537 case Property::MATRIX:
539 mImpl->mValue = value.Get<Matrix>();
543 case Property::MATRIX3:
545 mImpl->mValue = value.Get<Matrix3>();
551 mImpl->mValue = value.Get<Property::Map>();
555 case Property::ARRAY:
557 mImpl->mValue = value.Get<Property::Array>();
561 case Property::NONE: // fall
564 mImpl->mValue = Impl::AnyValue(0);
572 Property::Type Property::Value::GetType() const
577 void Property::Value::Get(bool& boolValue) const
579 DALI_ASSERT_DEBUG( Property::BOOLEAN == GetType() && "Property type invalid" ); // AnyCast does asserted type checking
581 boolValue = AnyCast<bool>(mImpl->mValue);
584 void Property::Value::Get(float& floatValue) const
586 DALI_ASSERT_DEBUG( Property::FLOAT == GetType() && "Property type invalid" );
588 floatValue = AnyCast<float>(mImpl->mValue);
591 void Property::Value::Get(int& integerValue) const
593 DALI_ASSERT_DEBUG( Property::INTEGER == GetType() && "Property type invalid" );
595 integerValue = AnyCast<int>(mImpl->mValue);
598 void Property::Value::Get(unsigned int& unsignedIntegerValue) const
600 DALI_ASSERT_DEBUG( Property::UNSIGNED_INTEGER == GetType() && "Property type invalid" );
602 unsignedIntegerValue = AnyCast<unsigned int>(mImpl->mValue);
605 void Property::Value::Get(Vector2& vectorValue) const
607 DALI_ASSERT_DEBUG( Property::VECTOR2 == GetType() && "Property type invalid" );
609 vectorValue = AnyCast<Vector2>(mImpl->mValue);
612 void Property::Value::Get(Vector3& vectorValue) const
614 DALI_ASSERT_DEBUG( Property::VECTOR3 == GetType() && "Property type invalid" );
616 vectorValue = AnyCast<Vector3>(mImpl->mValue);
619 void Property::Value::Get(Vector4& vectorValue) const
621 DALI_ASSERT_DEBUG( Property::VECTOR4 == GetType() && "Property type invalid" );
623 vectorValue = AnyCast<Vector4>(mImpl->mValue);
626 void Property::Value::Get(Matrix3& matrixValue) const
628 DALI_ASSERT_DEBUG( Property::MATRIX3 == GetType() && "Property type invalid" );
629 matrixValue = AnyCast<Matrix3>(mImpl->mValue);
632 void Property::Value::Get(Matrix& matrixValue) const
634 DALI_ASSERT_DEBUG( Property::MATRIX == GetType() && "Property type invalid" );
635 matrixValue = AnyCast<Matrix>(mImpl->mValue);
638 void Property::Value::Get(Rect<int>& rect) const
640 DALI_ASSERT_DEBUG( Property::RECTANGLE == GetType() && "Property type invalid" );
642 rect = AnyCast<Rect<int> >(mImpl->mValue);
645 void Property::Value::Get(AngleAxis& angleAxisValue) const
647 DALI_ASSERT_ALWAYS( Property::ROTATION == GetType() && "Property type invalid" );
649 // Orientations have two representations
650 DALI_ASSERT_DEBUG( typeid(Quaternion) == mImpl->mValue.GetType() ||
651 typeid(AngleAxis) == mImpl->mValue.GetType() );
653 if ( typeid(Quaternion) == mImpl->mValue.GetType() )
655 Quaternion quaternion = AnyCast<Quaternion>(mImpl->mValue);
657 quaternion.ToAxisAngle( angleAxisValue.axis, angleAxisValue.angle );
661 angleAxisValue = AnyCast<AngleAxis>(mImpl->mValue);
665 void Property::Value::Get(Quaternion& quaternionValue) const
667 DALI_ASSERT_DEBUG( Property::ROTATION == GetType() && "Property type invalid" );
669 // Orientations have two representations
670 DALI_ASSERT_DEBUG( typeid(Quaternion) == mImpl->mValue.GetType() ||
671 typeid(AngleAxis) == mImpl->mValue.GetType() );
673 if ( typeid(Quaternion) == mImpl->mValue.GetType() )
675 quaternionValue = AnyCast<Quaternion>(mImpl->mValue);
679 AngleAxis angleAxis = AnyCast<AngleAxis>(mImpl->mValue);
681 quaternionValue = Quaternion( Radian(angleAxis.angle), angleAxis.axis );
685 void Property::Value::Get(std::string &out) const
687 DALI_ASSERT_DEBUG(Property::STRING == GetType() && "Property type invalid");
689 out = AnyCast<std::string>(mImpl->mValue);
692 void Property::Value::Get(Property::Array &out) const
694 DALI_ASSERT_DEBUG(Property::ARRAY == GetType() && "Property type invalid");
696 out = AnyCast<Property::Array>(mImpl->mValue);
699 void Property::Value::Get(Property::Map &out) const
701 DALI_ASSERT_DEBUG(Property::MAP == GetType() && "Property type invalid");
703 out = AnyCast<Property::Map>(mImpl->mValue);
706 Property::Value& Property::Value::GetValue(const std::string& key) const
708 DALI_ASSERT_DEBUG(Property::MAP == GetType() && "Property type invalid");
710 Property::Map *container = AnyCast<Property::Map>(&(mImpl->mValue));
712 DALI_ASSERT_DEBUG(container);
716 Property::Value* value = container->Find( key );
723 DALI_LOG_WARNING("Cannot find property map key %s", key.c_str());
724 DALI_ASSERT_ALWAYS(!"Cannot find property map key");
727 bool Property::Value::HasKey(const std::string& key) const
731 if( Property::MAP == GetType() )
733 Property::Map *container = AnyCast<Property::Map>(&(mImpl->mValue));
735 DALI_ASSERT_DEBUG(container && "Property::Map has no container?");
739 Property::Value* value = container->Find( key );
751 const std::string& Property::Value::GetKey(const int index) const
757 Property::Map *container = AnyCast<Property::Map>(&(mImpl->mValue));
758 DALI_ASSERT_DEBUG(container && "Property::Map has no container?");
761 if(0 <= index && index < static_cast<int>(container->Count()))
763 return container->GetKey( index );
769 case Property::ARRAY:
770 case Property::BOOLEAN:
771 case Property::FLOAT:
772 case Property::UNSIGNED_INTEGER:
773 case Property::INTEGER:
774 case Property::VECTOR2:
775 case Property::VECTOR3:
776 case Property::VECTOR4:
777 case Property::MATRIX:
778 case Property::MATRIX3:
779 case Property::RECTANGLE:
780 case Property::ROTATION:
781 case Property::STRING:
782 case Property::TYPE_COUNT:
789 // should never return this
790 static std::string null;
795 void Property::Value::SetValue(const std::string& key, const Property::Value &value)
797 DALI_ASSERT_DEBUG(Property::MAP == GetType() && "Property type invalid");
799 Property::Map *container = AnyCast<Property::Map>(&(mImpl->mValue));
803 (*container)[ key ] = value;
807 Property::Value& Property::Value::GetItem(const int index) const
813 Property::Map *container = AnyCast<Property::Map>(&(mImpl->mValue));
815 DALI_ASSERT_DEBUG(container && "Property::Map has no container?");
818 DALI_ASSERT_ALWAYS(index < static_cast<int>(container->Count()) && "Property array index invalid");
819 DALI_ASSERT_ALWAYS(index >= 0 && "Property array index invalid");
821 return container->GetValue( index );
826 case Property::ARRAY:
828 Property::Array *container = AnyCast<Property::Array>(&(mImpl->mValue));
830 DALI_ASSERT_DEBUG(container && "Property::Map has no container?");
833 DALI_ASSERT_ALWAYS(index < static_cast<int>(container->Size()) && "Property array index invalid");
834 DALI_ASSERT_ALWAYS(index >= 0 && "Property array index invalid");
836 return (*container)[index];
842 case Property::BOOLEAN:
843 case Property::FLOAT:
844 case Property::INTEGER:
845 case Property::UNSIGNED_INTEGER:
846 case Property::VECTOR2:
847 case Property::VECTOR3:
848 case Property::VECTOR4:
849 case Property::MATRIX3:
850 case Property::MATRIX:
851 case Property::RECTANGLE:
852 case Property::ROTATION:
853 case Property::STRING:
854 case Property::TYPE_COUNT:
856 DALI_ASSERT_ALWAYS(!"Cannot GetItem on property Type; not a container");
860 } // switch GetType()
863 DALI_ASSERT_ALWAYS(!"Property value index not valid");
866 Property::Value& Property::Value::GetItem(const int index, std::string& key) const
868 Property::Value& ret( GetItem(index) );
870 if( Property::MAP == GetType() )
872 Property::Map *container = AnyCast<Property::Map>(&(mImpl->mValue));
873 if( index < static_cast<int>(container->Count()) )
875 key = container->GetKey( index );
882 void Property::Value::SetItem(const int index, const Property::Value &value)
888 Property::Map *container = AnyCast<Property::Map>(&(mImpl->mValue));
889 if( container && index < static_cast<int>(container->Count()) )
891 Property::Value& indexValue = container->GetValue( index );
897 case Property::ARRAY:
899 Property::Array *container = AnyCast<Property::Array>(&(mImpl->mValue));
900 if( container && index < static_cast<int>(container->Size()) )
902 (*container)[index] = value;
908 case Property::BOOLEAN:
909 case Property::FLOAT:
910 case Property::INTEGER:
911 case Property::UNSIGNED_INTEGER:
912 case Property::VECTOR2:
913 case Property::VECTOR3:
914 case Property::VECTOR4:
915 case Property::MATRIX3:
916 case Property::MATRIX:
917 case Property::RECTANGLE:
918 case Property::ROTATION:
919 case Property::STRING:
920 case Property::TYPE_COUNT:
922 DALI_ASSERT_ALWAYS(!"Cannot SetItem on property Type; not a container");
928 int Property::Value::AppendItem(const Property::Value &value)
930 DALI_ASSERT_DEBUG(Property::ARRAY == GetType() && "Property type invalid");
932 Property::Array *container = AnyCast<Property::Array>(&(mImpl->mValue));
936 container->PushBack(value);
937 return container->Size() - 1;
946 int Property::Value::GetSize() const
954 Property::Map *container = AnyCast<Property::Map>(&(mImpl->mValue));
957 ret = container->Count();
962 case Property::ARRAY:
964 Property::Array *container = AnyCast<Property::Array>(&(mImpl->mValue));
967 ret = container->Size();
973 case Property::BOOLEAN:
974 case Property::FLOAT:
975 case Property::INTEGER:
976 case Property::UNSIGNED_INTEGER:
977 case Property::VECTOR2:
978 case Property::VECTOR3:
979 case Property::VECTOR4:
980 case Property::MATRIX3:
981 case Property::MATRIX:
982 case Property::RECTANGLE:
983 case Property::ROTATION:
984 case Property::STRING:
985 case Property::TYPE_COUNT:
995 std::ostream& operator<< (std::ostream& stream, const Property::Value& value )
998 const Property::Value::Impl& impl( *value.mImpl );
1000 switch( impl.mType )
1002 case Dali::Property::STRING:
1004 stream << AnyCast<std::string>(impl.mValue).c_str();
1007 case Dali::Property::VECTOR2:
1009 stream << AnyCast<Vector2>(impl.mValue);
1012 case Dali::Property::VECTOR3:
1014 stream << AnyCast<Vector3>(impl.mValue);
1017 case Dali::Property::VECTOR4:
1019 stream << AnyCast<Vector4>(impl.mValue);
1022 case Dali::Property::MATRIX:
1024 stream << AnyCast<Matrix>(impl.mValue);
1027 case Dali::Property::BOOLEAN:
1029 stream << AnyCast<bool>(impl.mValue);
1032 case Dali::Property::FLOAT:
1034 stream << AnyCast<float>(impl.mValue);
1037 case Dali::Property::INTEGER:
1039 stream << AnyCast<int>(impl.mValue);
1042 case Dali::Property::UNSIGNED_INTEGER:
1044 stream << AnyCast<unsigned int>(impl.mValue);
1047 case Dali::Property::RECTANGLE:
1049 Dali::Rect<int> rect; // Propery Value rectangles are currently integer based
1054 case Dali::Property::MATRIX3:
1056 stream << AnyCast<Matrix3>(impl.mValue);
1059 case Dali::Property::ROTATION:
1061 // @todo this may change to Quaternion
1064 Dali::Vector4 v4 = q.EulerAngles();
1069 case Dali::Property::ARRAY:
1071 // @todo Need to think about the best way to support array
1072 // E.g Do we want to create a JSON style array like:
1073 // [ {"property-name-0":"property-value-0", "property-name-1":"property-value-1"} ]
1074 stream << "ARRAY unsupported";
1077 case Dali::Property::MAP:
1079 Dali::Property::Map map;
1081 stream << "Map containing " << map.Count() << " elements";
1084 case Dali::Property::TYPE_COUNT:
1086 stream << "unsupported TYPE_COUNT";
1091 stream << "unsupported type = " << value.GetType();