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-types.h>
37 #include <dali/integration-api/debug.h>
42 struct Property::Value::Impl
45 : mType( Property::NONE )
50 : mType( PropertyTypes::Get<bool>() ),
55 Impl(float floatValue)
56 : mType( PropertyTypes::Get<float>() ),
61 Impl(int integerValue)
62 : mType( PropertyTypes::Get<int>() ),
63 mValue( integerValue )
67 Impl(unsigned int unsignedIntegerValue)
68 : mType( PropertyTypes::Get<unsigned int>() ),
69 mValue( unsignedIntegerValue )
73 Impl(const Vector2& vectorValue)
74 : mType( PropertyTypes::Get<Vector2>() ),
79 Impl(const Vector3& vectorValue)
80 : mType( PropertyTypes::Get<Vector3>() ),
85 Impl(const Vector4& vectorValue)
86 : mType( PropertyTypes::Get<Vector4>() ),
91 Impl(const Matrix3& matrixValue)
92 : mType(PropertyTypes::Get<Matrix3>()),
97 Impl(const Matrix& matrixValue)
98 : mType(PropertyTypes::Get<Matrix>()),
103 Impl(const AngleAxis& angleAxisValue)
104 : mType( PropertyTypes::Get<AngleAxis>() ),
105 mValue( angleAxisValue )
109 Impl(const Quaternion& quaternionValue)
110 : mType( PropertyTypes::Get<Quaternion>() ),
111 mValue( quaternionValue )
115 Impl(const std::string& stringValue)
116 : mType( PropertyTypes::Get<std::string>() ),
117 mValue( stringValue )
121 Impl(const Rect<int>& rect)
122 : mType( PropertyTypes::Get<Rect<int> >() ),
127 Impl(Property::Map container)
128 : mType( PropertyTypes::Get<Property::Map >() ),
133 Impl(Property::Array container)
134 : mType( PropertyTypes::Get<Property::Array >() ),
141 typedef Any AnyValue;
145 Property::Value::Value()
151 Property::Value::Value(bool boolValue)
154 mImpl = new Impl( boolValue );
157 Property::Value::Value(float floatValue)
160 mImpl = new Impl( floatValue );
163 Property::Value::Value(int integerValue)
166 mImpl = new Impl( integerValue );
169 Property::Value::Value(unsigned int unsignedIntegerValue)
172 mImpl = new Impl( unsignedIntegerValue );
175 Property::Value::Value(const Vector2& vectorValue)
178 mImpl = new Impl( vectorValue );
181 Property::Value::Value(const Vector3& vectorValue)
184 mImpl = new Impl( vectorValue );
187 Property::Value::Value(const Vector4& vectorValue)
190 mImpl = new Impl( vectorValue );
193 Property::Value::Value(const Matrix3& matrixValue)
196 mImpl = new Impl( matrixValue );
199 Property::Value::Value(const Matrix& matrixValue)
202 mImpl = new Impl( matrixValue );
205 Property::Value::Value(const Rect<int>& rect)
208 mImpl = new Impl( rect );
211 Property::Value::Value(const AngleAxis& angleAxisValue)
214 mImpl = new Impl( angleAxisValue );
217 Property::Value::Value(const Quaternion& quaternionValue)
219 mImpl = new Impl( quaternionValue );
222 Property::Value::Value(const std::string& stringValue)
224 mImpl = new Impl( stringValue );
227 Property::Value::Value(const char *stringValue)
229 mImpl = new Impl( std::string(stringValue) );
232 Property::Value::Value(Property::Array &arrayValue)
234 mImpl = new Impl( arrayValue );
237 Property::Value::Value(Property::Map &mapValue)
239 mImpl = new Impl( mapValue );
243 Property::Value::~Value()
248 Property::Value::Value(const Value& value)
250 switch (value.GetType())
252 case Property::BOOLEAN:
254 mImpl = new Impl( value.Get<bool>() );
258 case Property::FLOAT:
260 mImpl = new Impl( value.Get<float>() );
264 case Property::INTEGER:
266 mImpl = new Impl( value.Get<int>() );
270 case Property::UNSIGNED_INTEGER:
272 mImpl = new Impl( value.Get<unsigned int>() );
276 case Property::VECTOR2:
278 mImpl = new Impl( value.Get<Vector2>() );
282 case Property::VECTOR3:
284 mImpl = new Impl( value.Get<Vector3>() );
288 case Property::VECTOR4:
290 mImpl = new Impl( value.Get<Vector4>() );
294 case Property::RECTANGLE:
296 mImpl = new Impl( value.Get<Rect<int> >() );
300 case Property::ROTATION:
302 // Orientations have two representations
303 DALI_ASSERT_DEBUG( typeid(Quaternion) == value.mImpl->mValue.GetType() ||
304 typeid(AngleAxis) == value.mImpl->mValue.GetType() );
306 if ( typeid(Quaternion) == value.mImpl->mValue.GetType() )
308 mImpl = new Impl( value.Get<Quaternion>() );
312 mImpl = new Impl( value.Get<AngleAxis>() );
317 case Property::MATRIX3:
319 mImpl = new Impl( value.Get<Matrix3>());
323 case Property::MATRIX:
325 mImpl = new Impl( value.Get<Matrix>());
329 case Property::STRING:
331 mImpl = new Impl( value.Get<std::string>() );
337 mImpl = new Impl( value.Get<Property::Map>() );
341 case Property::ARRAY:
343 mImpl = new Impl( value.Get<Property::Array>() );
347 case Property::NONE: // fall
356 Property::Value::Value(Type type)
360 case Property::BOOLEAN:
362 mImpl = new Impl( false );
366 case Property::FLOAT:
368 mImpl = new Impl( 0.f );
372 case Property::INTEGER:
374 mImpl = new Impl( 0 );
378 case Property::UNSIGNED_INTEGER:
380 mImpl = new Impl( 0U );
384 case Property::VECTOR2:
386 mImpl = new Impl( Vector2::ZERO );
390 case Property::VECTOR3:
392 mImpl = new Impl( Vector3::ZERO );
396 case Property::VECTOR4:
398 mImpl = new Impl( Vector4::ZERO );
402 case Property::RECTANGLE:
404 mImpl = new Impl( Rect<int>(0,0,0,0) );
408 case Property::ROTATION:
410 mImpl = new Impl( Quaternion( Radian(0.f), Vector3::YAXIS) );
414 case Property::STRING:
416 mImpl = new Impl( std::string() );
422 mImpl = new Impl( Property::Map() );
426 case Property::MATRIX:
428 mImpl = new Impl( Matrix() );
432 case Property::MATRIX3:
434 mImpl = new Impl( Matrix3() );
438 case Property::ARRAY:
440 mImpl = new Impl( Property::Array() );
444 case Property::NONE: // fall
453 Property::Value& Property::Value::operator=(const Property::Value& value)
457 // skip self assignment
461 mImpl->mType = value.GetType();
463 switch (mImpl->mType)
465 case Property::BOOLEAN:
467 mImpl->mValue = value.Get<bool>();
471 case Property::FLOAT:
473 mImpl->mValue = value.Get<float>();
477 case Property::INTEGER:
479 mImpl->mValue = value.Get<int>();
483 case Property::UNSIGNED_INTEGER:
485 mImpl->mValue = value.Get<unsigned int>();
489 case Property::VECTOR2:
491 mImpl->mValue = value.Get<Vector2>();
495 case Property::VECTOR3:
497 mImpl->mValue = value.Get<Vector3>();
501 case Property::VECTOR4:
503 mImpl->mValue = value.Get<Vector4>();
507 case Property::RECTANGLE:
509 mImpl->mValue = value.Get<Rect<int> >();
513 case Property::ROTATION:
515 // Orientations have two representations
516 DALI_ASSERT_DEBUG( typeid(Quaternion) == value.mImpl->mValue.GetType() ||
517 typeid(AngleAxis) == value.mImpl->mValue.GetType() );
519 if ( typeid(Quaternion) == value.mImpl->mValue.GetType() )
521 mImpl = new Impl( value.Get<Quaternion>() );
525 mImpl = new Impl( value.Get<AngleAxis>() );
530 case Property::STRING:
532 mImpl->mValue = value.Get<std::string>();
536 case Property::MATRIX:
538 mImpl->mValue = value.Get<Matrix>();
542 case Property::MATRIX3:
544 mImpl->mValue = value.Get<Matrix3>();
550 mImpl->mValue = value.Get<Property::Map>();
554 case Property::ARRAY:
556 mImpl->mValue = value.Get<Property::Array>();
560 case Property::NONE: // fall
563 mImpl->mValue = Impl::AnyValue(0);
571 Property::Type Property::Value::GetType() const
576 void Property::Value::Get(bool& boolValue) const
578 DALI_ASSERT_DEBUG( Property::BOOLEAN == GetType() && "Property type invalid" ); // AnyCast does asserted type checking
580 boolValue = AnyCast<bool>(mImpl->mValue);
583 void Property::Value::Get(float& floatValue) const
585 DALI_ASSERT_DEBUG( Property::FLOAT == GetType() && "Property type invalid" );
587 floatValue = AnyCast<float>(mImpl->mValue);
590 void Property::Value::Get(int& integerValue) const
592 DALI_ASSERT_DEBUG( Property::INTEGER == GetType() && "Property type invalid" );
594 integerValue = AnyCast<int>(mImpl->mValue);
597 void Property::Value::Get(unsigned int& unsignedIntegerValue) const
599 DALI_ASSERT_DEBUG( Property::UNSIGNED_INTEGER == GetType() && "Property type invalid" );
601 unsignedIntegerValue = AnyCast<unsigned int>(mImpl->mValue);
604 void Property::Value::Get(Vector2& vectorValue) const
606 DALI_ASSERT_DEBUG( Property::VECTOR2 == GetType() && "Property type invalid" );
608 vectorValue = AnyCast<Vector2>(mImpl->mValue);
611 void Property::Value::Get(Vector3& vectorValue) const
613 DALI_ASSERT_DEBUG( Property::VECTOR3 == GetType() && "Property type invalid" );
615 vectorValue = AnyCast<Vector3>(mImpl->mValue);
618 void Property::Value::Get(Vector4& vectorValue) const
620 DALI_ASSERT_DEBUG( Property::VECTOR4 == GetType() && "Property type invalid" );
622 vectorValue = AnyCast<Vector4>(mImpl->mValue);
625 void Property::Value::Get(Matrix3& matrixValue) const
627 DALI_ASSERT_DEBUG( Property::MATRIX3 == GetType() && "Property type invalid" );
628 matrixValue = AnyCast<Matrix3>(mImpl->mValue);
631 void Property::Value::Get(Matrix& matrixValue) const
633 DALI_ASSERT_DEBUG( Property::MATRIX == GetType() && "Property type invalid" );
634 matrixValue = AnyCast<Matrix>(mImpl->mValue);
637 void Property::Value::Get(Rect<int>& rect) const
639 DALI_ASSERT_DEBUG( Property::RECTANGLE == GetType() && "Property type invalid" );
641 rect = AnyCast<Rect<int> >(mImpl->mValue);
644 void Property::Value::Get(AngleAxis& angleAxisValue) const
646 DALI_ASSERT_ALWAYS( Property::ROTATION == GetType() && "Property type invalid" );
648 // Orientations have two representations
649 DALI_ASSERT_DEBUG( typeid(Quaternion) == mImpl->mValue.GetType() ||
650 typeid(AngleAxis) == mImpl->mValue.GetType() );
652 if ( typeid(Quaternion) == mImpl->mValue.GetType() )
654 Quaternion quaternion = AnyCast<Quaternion>(mImpl->mValue);
656 quaternion.ToAxisAngle( angleAxisValue.axis, angleAxisValue.angle );
660 angleAxisValue = AnyCast<AngleAxis>(mImpl->mValue);
664 void Property::Value::Get(Quaternion& quaternionValue) const
666 DALI_ASSERT_DEBUG( Property::ROTATION == GetType() && "Property type invalid" );
668 // Orientations have two representations
669 DALI_ASSERT_DEBUG( typeid(Quaternion) == mImpl->mValue.GetType() ||
670 typeid(AngleAxis) == mImpl->mValue.GetType() );
672 if ( typeid(Quaternion) == mImpl->mValue.GetType() )
674 quaternionValue = AnyCast<Quaternion>(mImpl->mValue);
678 AngleAxis angleAxis = AnyCast<AngleAxis>(mImpl->mValue);
680 quaternionValue = Quaternion( Radian(angleAxis.angle), angleAxis.axis );
684 void Property::Value::Get(std::string &out) const
686 DALI_ASSERT_DEBUG(Property::STRING == GetType() && "Property type invalid");
688 out = AnyCast<std::string>(mImpl->mValue);
691 void Property::Value::Get(Property::Array &out) const
693 DALI_ASSERT_DEBUG(Property::ARRAY == GetType() && "Property type invalid");
695 out = AnyCast<Property::Array>(mImpl->mValue);
698 void Property::Value::Get(Property::Map &out) const
700 DALI_ASSERT_DEBUG(Property::MAP == GetType() && "Property type invalid");
702 out = AnyCast<Property::Map>(mImpl->mValue);
705 Property::Value& Property::Value::GetValue(const std::string& key) const
707 DALI_ASSERT_DEBUG(Property::MAP == GetType() && "Property type invalid");
709 Property::Map *container = AnyCast<Property::Map>(&(mImpl->mValue));
711 DALI_ASSERT_DEBUG(container);
715 Property::Value* value = container->Find( key );
722 DALI_LOG_WARNING("Cannot find property map key %s", key.c_str());
723 DALI_ASSERT_ALWAYS(!"Cannot find property map key");
726 bool Property::Value::HasKey(const std::string& key) const
730 if( Property::MAP == GetType() )
732 Property::Map *container = AnyCast<Property::Map>(&(mImpl->mValue));
734 DALI_ASSERT_DEBUG(container && "Property::Map has no container?");
738 Property::Value* value = container->Find( key );
750 const std::string& Property::Value::GetKey(const int index) const
756 Property::Map *container = AnyCast<Property::Map>(&(mImpl->mValue));
757 DALI_ASSERT_DEBUG(container && "Property::Map has no container?");
760 if(0 <= index && index < static_cast<int>(container->Count()))
762 return container->GetKey( index );
768 case Property::ARRAY:
769 case Property::BOOLEAN:
770 case Property::FLOAT:
771 case Property::UNSIGNED_INTEGER:
772 case Property::INTEGER:
773 case Property::VECTOR2:
774 case Property::VECTOR3:
775 case Property::VECTOR4:
776 case Property::MATRIX:
777 case Property::MATRIX3:
778 case Property::RECTANGLE:
779 case Property::ROTATION:
780 case Property::STRING:
781 case Property::TYPE_COUNT:
788 // should never return this
789 static std::string null;
794 void Property::Value::SetValue(const std::string& key, const Property::Value &value)
796 DALI_ASSERT_DEBUG(Property::MAP == GetType() && "Property type invalid");
798 Property::Map *container = AnyCast<Property::Map>(&(mImpl->mValue));
802 (*container)[ key ] = value;
806 Property::Value& Property::Value::GetItem(const int index) const
812 Property::Map *container = AnyCast<Property::Map>(&(mImpl->mValue));
814 DALI_ASSERT_DEBUG(container && "Property::Map has no container?");
817 DALI_ASSERT_ALWAYS(index < static_cast<int>(container->Count()) && "Property array index invalid");
818 DALI_ASSERT_ALWAYS(index >= 0 && "Property array index invalid");
820 return container->GetValue( index );
825 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 for(Property::Array::iterator iter = container->begin(); iter != container->end(); ++iter)
848 case Property::BOOLEAN:
849 case Property::FLOAT:
850 case Property::INTEGER:
851 case Property::UNSIGNED_INTEGER:
852 case Property::VECTOR2:
853 case Property::VECTOR3:
854 case Property::VECTOR4:
855 case Property::MATRIX3:
856 case Property::MATRIX:
857 case Property::RECTANGLE:
858 case Property::ROTATION:
859 case Property::STRING:
860 case Property::TYPE_COUNT:
862 DALI_ASSERT_ALWAYS(!"Cannot GetItem on property Type; not a container");
866 } // switch GetType()
869 DALI_ASSERT_ALWAYS(!"Property value index not valid");
872 Property::Value& Property::Value::GetItem(const int index, std::string& key) const
874 Property::Value& ret( GetItem(index) );
876 if( Property::MAP == GetType() )
878 Property::Map *container = AnyCast<Property::Map>(&(mImpl->mValue));
879 if( index < static_cast<int>(container->Count()) )
881 key = container->GetKey( index );
888 void Property::Value::SetItem(const int index, const Property::Value &value)
894 Property::Map *container = AnyCast<Property::Map>(&(mImpl->mValue));
895 if( container && index < static_cast<int>(container->Count()) )
897 Property::Value& indexValue = container->GetValue( index );
903 case Property::ARRAY:
905 Property::Array *container = AnyCast<Property::Array>(&(mImpl->mValue));
906 if( container && index < static_cast<int>(container->size()) )
908 (*container)[index] = value;
914 case Property::BOOLEAN:
915 case Property::FLOAT:
916 case Property::INTEGER:
917 case Property::UNSIGNED_INTEGER:
918 case Property::VECTOR2:
919 case Property::VECTOR3:
920 case Property::VECTOR4:
921 case Property::MATRIX3:
922 case Property::MATRIX:
923 case Property::RECTANGLE:
924 case Property::ROTATION:
925 case Property::STRING:
926 case Property::TYPE_COUNT:
928 DALI_ASSERT_ALWAYS(!"Cannot SetItem on property Type; not a container");
934 int Property::Value::AppendItem(const Property::Value &value)
936 DALI_ASSERT_DEBUG(Property::ARRAY == GetType() && "Property type invalid");
938 Property::Array *container = AnyCast<Property::Array>(&(mImpl->mValue));
942 container->push_back(value);
943 return container->size() - 1;
952 int Property::Value::GetSize() const
960 Property::Map *container = AnyCast<Property::Map>(&(mImpl->mValue));
963 ret = container->Count();
968 case Property::ARRAY:
970 Property::Array *container = AnyCast<Property::Array>(&(mImpl->mValue));
973 ret = container->size();
979 case Property::BOOLEAN:
980 case Property::FLOAT:
981 case Property::INTEGER:
982 case Property::UNSIGNED_INTEGER:
983 case Property::VECTOR2:
984 case Property::VECTOR3:
985 case Property::VECTOR4:
986 case Property::MATRIX3:
987 case Property::MATRIX:
988 case Property::RECTANGLE:
989 case Property::ROTATION:
990 case Property::STRING:
991 case Property::TYPE_COUNT:
1001 std::ostream& operator<< (std::ostream& stream, const Property::Value& value )
1004 const Property::Value::Impl& impl( *value.mImpl );
1006 switch( impl.mType )
1008 case Dali::Property::STRING:
1010 stream << AnyCast<std::string>(impl.mValue).c_str();
1013 case Dali::Property::VECTOR2:
1015 stream << AnyCast<Vector2>(impl.mValue);
1018 case Dali::Property::VECTOR3:
1020 stream << AnyCast<Vector3>(impl.mValue);
1023 case Dali::Property::VECTOR4:
1025 stream << AnyCast<Vector4>(impl.mValue);
1028 case Dali::Property::MATRIX:
1030 stream << AnyCast<Matrix>(impl.mValue);
1033 case Dali::Property::BOOLEAN:
1035 stream << AnyCast<bool>(impl.mValue);
1038 case Dali::Property::FLOAT:
1040 stream << AnyCast<float>(impl.mValue);
1043 case Dali::Property::INTEGER:
1045 stream << AnyCast<int>(impl.mValue);
1048 case Dali::Property::UNSIGNED_INTEGER:
1050 stream << AnyCast<unsigned int>(impl.mValue);
1053 case Dali::Property::RECTANGLE:
1055 Dali::Rect<int> rect; // Propery Value rectangles are currently integer based
1060 case Dali::Property::MATRIX3:
1062 stream << AnyCast<Matrix3>(impl.mValue);
1065 case Dali::Property::ROTATION:
1067 // @todo this may change to Quaternion
1070 Dali::Vector4 v4 = q.EulerAngles();
1075 case Dali::Property::ARRAY:
1077 // @todo Need to think about the best way to support array
1078 // E.g Do we want to create a JSON style array like:
1079 // [ {"property-name-0":"property-value-0", "property-name-1":"property-value-1"} ]
1080 stream << "ARRAY unsupported";
1083 case Dali::Property::MAP:
1085 Dali::Property::Map map;
1087 stream << "Map containing " << map.Count() << " elements";
1090 case Dali::Property::TYPE_COUNT:
1092 stream << "unsupported TYPE_COUNT";
1097 stream << "unsupported type = " << value.GetType();