2 // Copyright (c) 2014 Samsung Electronics Co., Ltd.
4 // Licensed under the Flora License, Version 1.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://floralicense.org/license/
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.
18 #include <dali/public-api/object/property-value.h>
21 #include <boost/any.hpp>
24 #include <dali/public-api/math/angle-axis.h>
25 #include <dali/public-api/math/radian.h>
26 #include <dali/public-api/math/vector2.h>
27 #include <dali/public-api/math/vector3.h>
28 #include <dali/public-api/math/vector4.h>
29 #include <dali/public-api/math/matrix3.h>
30 #include <dali/public-api/math/matrix.h>
31 #include <dali/public-api/math/rect.h>
32 #include <dali/public-api/math/quaternion.h>
33 #include <dali/public-api/object/property-types.h>
34 #include <dali/integration-api/debug.h>
39 struct Property::Value::Impl
42 : mType( Property::NONE )
47 : mType( PropertyTypes::Get<bool>() ),
52 Impl(float floatValue)
53 : mType( PropertyTypes::Get<float>() ),
58 Impl(int integerValue)
59 : mType( PropertyTypes::Get<int>() ),
60 mValue( integerValue )
64 Impl(unsigned int unsignedIntegerValue)
65 : mType( PropertyTypes::Get<unsigned int>() ),
66 mValue( unsignedIntegerValue )
70 Impl(const Vector2& vectorValue)
71 : mType( PropertyTypes::Get<Vector2>() ),
76 Impl(const Vector3& vectorValue)
77 : mType( PropertyTypes::Get<Vector3>() ),
82 Impl(const Vector4& vectorValue)
83 : mType( PropertyTypes::Get<Vector4>() ),
88 Impl(const Matrix3& matrixValue)
89 : mType(PropertyTypes::Get<Matrix3>()),
94 Impl(const Matrix& matrixValue)
95 : mType(PropertyTypes::Get<Matrix>()),
100 Impl(const AngleAxis& angleAxisValue)
101 : mType( PropertyTypes::Get<AngleAxis>() ),
102 mValue( angleAxisValue )
106 Impl(const Quaternion& quaternionValue)
107 : mType( PropertyTypes::Get<Quaternion>() ),
108 mValue( quaternionValue )
112 Impl(const std::string& stringValue)
113 : mType( PropertyTypes::Get<std::string>() ),
114 mValue( stringValue )
118 Impl(const Rect<int>& rect)
119 : mType( PropertyTypes::Get<Rect<int> >() ),
124 Impl(Property::Map container)
125 : mType( PropertyTypes::Get<Property::Map >() ),
130 Impl(Property::Array container)
131 : mType( PropertyTypes::Get<Property::Array >() ),
138 typedef boost::any AnyValue;
142 Property::Value::Value()
148 Property::Value::Value(bool boolValue)
151 mImpl = new Impl( boolValue );
154 Property::Value::Value(float floatValue)
157 mImpl = new Impl( floatValue );
160 Property::Value::Value(int integerValue)
163 mImpl = new Impl( integerValue );
166 Property::Value::Value(unsigned int unsignedIntegerValue)
169 mImpl = new Impl( unsignedIntegerValue );
172 Property::Value::Value(const Vector2& vectorValue)
175 mImpl = new Impl( vectorValue );
178 Property::Value::Value(const Vector3& vectorValue)
181 mImpl = new Impl( vectorValue );
184 Property::Value::Value(const Vector4& vectorValue)
187 mImpl = new Impl( vectorValue );
190 Property::Value::Value(const Matrix3& matrixValue)
193 mImpl = new Impl( matrixValue );
196 Property::Value::Value(const Matrix& matrixValue)
199 mImpl = new Impl( matrixValue );
202 Property::Value::Value(const Rect<int>& rect)
205 mImpl = new Impl( rect );
208 Property::Value::Value(const AngleAxis& angleAxisValue)
211 mImpl = new Impl( angleAxisValue );
214 Property::Value::Value(const Quaternion& quaternionValue)
216 mImpl = new Impl( quaternionValue );
219 Property::Value::Value(const std::string& stringValue)
221 mImpl = new Impl( stringValue );
224 Property::Value::Value(const char *stringValue)
226 mImpl = new Impl( std::string(stringValue) );
229 Property::Value::Value(Property::Array &arrayValue)
231 mImpl = new Impl( arrayValue );
234 Property::Value::Value(Property::Map &mapValue)
236 mImpl = new Impl( mapValue );
240 Property::Value::~Value()
245 Property::Value::Value(const Value& value)
247 switch (value.GetType())
249 case Property::BOOLEAN:
251 mImpl = new Impl( value.Get<bool>() );
255 case Property::FLOAT:
257 mImpl = new Impl( value.Get<float>() );
261 case Property::INTEGER:
263 mImpl = new Impl( value.Get<int>() );
267 case Property::UNSIGNED_INTEGER:
269 mImpl = new Impl( value.Get<unsigned int>() );
273 case Property::VECTOR2:
275 mImpl = new Impl( value.Get<Vector2>() );
279 case Property::VECTOR3:
281 mImpl = new Impl( value.Get<Vector3>() );
285 case Property::VECTOR4:
287 mImpl = new Impl( value.Get<Vector4>() );
291 case Property::RECTANGLE:
293 mImpl = new Impl( value.Get<Rect<int> >() );
297 case Property::ROTATION:
299 mImpl = new Impl( value.Get<Quaternion>() );
303 case Property::MATRIX3:
305 mImpl = new Impl( value.Get<Matrix3>());
309 case Property::MATRIX:
311 mImpl = new Impl( value.Get<Matrix>());
315 case Property::STRING:
317 mImpl = new Impl( value.Get<std::string>() );
323 mImpl = new Impl( value.Get<Property::Map>() );
327 case Property::ARRAY:
329 mImpl = new Impl( value.Get<Property::Array>() );
333 case Property::NONE: // fall
342 Property::Value::Value(Type type)
346 case Property::BOOLEAN:
348 mImpl = new Impl( false );
352 case Property::FLOAT:
354 mImpl = new Impl( 0.f );
358 case Property::INTEGER:
360 mImpl = new Impl( 0 );
364 case Property::UNSIGNED_INTEGER:
366 mImpl = new Impl( 0U );
370 case Property::VECTOR2:
372 mImpl = new Impl( Vector2::ZERO );
376 case Property::VECTOR3:
378 mImpl = new Impl( Vector3::ZERO );
382 case Property::VECTOR4:
384 mImpl = new Impl( Vector4::ZERO );
388 case Property::RECTANGLE:
390 mImpl = new Impl( Rect<int>(0,0,0,0) );
394 case Property::ROTATION:
396 mImpl = new Impl( Quaternion(0.f, Vector4::YAXIS) );
400 case Property::STRING:
402 mImpl = new Impl( std::string() );
408 mImpl = new Impl( Property::Map() );
412 case Property::MATRIX:
414 mImpl = new Impl( Matrix() );
418 case Property::MATRIX3:
420 mImpl = new Impl( Matrix3() );
424 case Property::ARRAY:
426 mImpl = new Impl( Property::Array() );
430 case Property::NONE: // fall
439 Property::Value& Property::Value::operator=(const Property::Value& value)
443 // skip self assignment
447 mImpl->mType = value.GetType();
449 switch (mImpl->mType)
451 case Property::BOOLEAN:
453 mImpl->mValue = value.Get<bool>();
457 case Property::FLOAT:
459 mImpl->mValue = value.Get<float>();
463 case Property::INTEGER:
465 mImpl->mValue = value.Get<int>();
469 case Property::UNSIGNED_INTEGER:
471 mImpl->mValue = value.Get<unsigned int>();
475 case Property::VECTOR2:
477 mImpl->mValue = value.Get<Vector2>();
481 case Property::VECTOR3:
483 mImpl->mValue = value.Get<Vector3>();
487 case Property::VECTOR4:
489 mImpl->mValue = value.Get<Vector4>();
493 case Property::RECTANGLE:
495 mImpl->mValue = value.Get<Rect<int> >();
499 case Property::ROTATION:
501 mImpl->mValue = value.Get<Quaternion>();
505 case Property::STRING:
507 mImpl->mValue = value.Get<std::string>();
511 case Property::MATRIX:
513 mImpl->mValue = value.Get<Matrix>();
517 case Property::MATRIX3:
519 mImpl->mValue = value.Get<Matrix3>();
525 mImpl->mValue = value.Get<Property::Map>();
529 case Property::ARRAY:
531 mImpl->mValue = value.Get<Property::Array>();
535 case Property::NONE: // fall
538 mImpl->mValue = Impl::AnyValue(0);
546 Property::Type Property::Value::GetType() const
551 void Property::Value::Get(bool& boolValue) const
553 DALI_ASSERT_ALWAYS( Property::BOOLEAN == GetType() && "Property type invalid" );
555 boolValue = boost::any_cast<bool>(mImpl->mValue);
558 void Property::Value::Get(float& floatValue) const
560 DALI_ASSERT_ALWAYS( Property::FLOAT == GetType() && "Property type invalid" );
562 floatValue = boost::any_cast<float>(mImpl->mValue);
565 void Property::Value::Get(int& integerValue) const
567 DALI_ASSERT_ALWAYS( Property::INTEGER == GetType() && "Property type invalid" );
569 integerValue = boost::any_cast<int>(mImpl->mValue);
572 void Property::Value::Get(unsigned int& unsignedIntegerValue) const
574 DALI_ASSERT_ALWAYS( Property::UNSIGNED_INTEGER == GetType() && "Property type invalid" );
576 unsignedIntegerValue = boost::any_cast<unsigned int>(mImpl->mValue);
579 void Property::Value::Get(Vector2& vectorValue) const
581 DALI_ASSERT_ALWAYS( Property::VECTOR2 == GetType() && "Property type invalid" );
583 vectorValue = boost::any_cast<Vector2>(mImpl->mValue);
586 void Property::Value::Get(Vector3& vectorValue) const
588 DALI_ASSERT_ALWAYS( Property::VECTOR3 == GetType() && "Property type invalid" );
590 vectorValue = boost::any_cast<Vector3>(mImpl->mValue);
593 void Property::Value::Get(Vector4& vectorValue) const
595 DALI_ASSERT_ALWAYS( Property::VECTOR4 == GetType() && "Property type invalid" );
597 vectorValue = boost::any_cast<Vector4>(mImpl->mValue);
600 void Property::Value::Get(Matrix3& matrixValue) const
602 DALI_ASSERT_ALWAYS( Property::MATRIX3 == GetType() && "Property type invalid" );
603 matrixValue = boost::any_cast<Matrix3>(mImpl->mValue);
606 void Property::Value::Get(Matrix& matrixValue) const
608 DALI_ASSERT_ALWAYS( Property::MATRIX == GetType() && "Property type invalid" );
609 matrixValue = boost::any_cast<Matrix>(mImpl->mValue);
612 void Property::Value::Get(Rect<int>& rect) const
614 DALI_ASSERT_ALWAYS( Property::RECTANGLE == GetType() && "Property type invalid" );
616 rect = boost::any_cast<Rect<int> >(mImpl->mValue);
619 void Property::Value::Get(AngleAxis& angleAxisValue) const
621 DALI_ASSERT_ALWAYS( Property::ROTATION == GetType() && "Property type invalid" );
623 // Rotations have two representations
624 DALI_ASSERT_DEBUG( typeid(Quaternion) == mImpl->mValue.type() ||
625 typeid(AngleAxis) == mImpl->mValue.type() );
627 if ( typeid(Quaternion) == mImpl->mValue.type() )
629 Quaternion quaternion = boost::any_cast<Quaternion>(mImpl->mValue);
631 Radian angleRadians(0.0f);
632 quaternion.ToAxisAngle( angleAxisValue.axis, angleRadians );
633 angleAxisValue.angle = angleRadians;
637 angleAxisValue = boost::any_cast<AngleAxis>(mImpl->mValue);
641 void Property::Value::Get(Quaternion& quaternionValue) const
643 DALI_ASSERT_ALWAYS( Property::ROTATION == GetType() && "Property type invalid" );
645 // Rotations have two representations
646 DALI_ASSERT_DEBUG( typeid(Quaternion) == mImpl->mValue.type() ||
647 typeid(AngleAxis) == mImpl->mValue.type() );
649 if ( typeid(Quaternion) == mImpl->mValue.type() )
651 quaternionValue = boost::any_cast<Quaternion>(mImpl->mValue);
655 AngleAxis angleAxis = boost::any_cast<AngleAxis>(mImpl->mValue);
657 quaternionValue = Quaternion( Radian(angleAxis.angle), angleAxis.axis );
661 void Property::Value::Get(std::string &out) const
663 DALI_ASSERT_ALWAYS(Property::STRING == GetType() && "Property type invalid");
665 out = boost::any_cast<std::string>(mImpl->mValue);
668 void Property::Value::Get(Property::Array &out) const
670 DALI_ASSERT_ALWAYS(Property::ARRAY == GetType() && "Property type invalid");
672 out = boost::any_cast<Property::Array>(mImpl->mValue);
675 void Property::Value::Get(Property::Map &out) const
677 DALI_ASSERT_ALWAYS(Property::MAP == GetType() && "Property type invalid");
679 out = boost::any_cast<Property::Map>(mImpl->mValue);
682 Property::Value& Property::Value::GetValue(const std::string& key) const
684 DALI_ASSERT_ALWAYS(Property::MAP == GetType() && "Property type invalid");
686 Property::Map *container = boost::any_cast<Property::Map>(&(mImpl->mValue));
688 DALI_ASSERT_DEBUG(container);
692 for(Property::Map::iterator iter = container->begin(); iter != container->end(); ++iter)
694 if(iter->first == key)
701 DALI_LOG_WARNING("Cannot find property map key %s", key.c_str());
702 DALI_ASSERT_ALWAYS(!"Cannot find property map key");
704 // should never return this
705 static Property::Value null;
709 bool Property::Value::HasKey(const std::string& key) const
713 if( Property::MAP == GetType() )
715 Property::Map *container = boost::any_cast<Property::Map>(&(mImpl->mValue));
717 DALI_ASSERT_DEBUG(container && "Property::Map has no container?");
721 for(Property::Map::iterator iter = container->begin(); iter != container->end(); ++iter)
723 if(iter->first == key)
735 const std::string& Property::Value::GetKey(const int index) const
742 Property::Map *container = boost::any_cast<Property::Map>(&(mImpl->mValue));
743 DALI_ASSERT_DEBUG(container && "Property::Map has no container?");
746 if(0 <= index && index < static_cast<int>(container->size()))
748 for(Property::Map::iterator iter = container->begin(); iter != container->end(); ++iter)
760 case Property::ARRAY:
761 case Property::BOOLEAN:
762 case Property::FLOAT:
763 case Property::UNSIGNED_INTEGER:
764 case Property::INTEGER:
765 case Property::VECTOR2:
766 case Property::VECTOR3:
767 case Property::VECTOR4:
768 case Property::MATRIX:
769 case Property::MATRIX3:
770 case Property::RECTANGLE:
771 case Property::ROTATION:
772 case Property::STRING:
773 case Property::TYPE_COUNT:
780 // should never return this
781 static std::string null;
786 void Property::Value::SetValue(const std::string& key, const Property::Value &value)
788 DALI_ASSERT_ALWAYS(Property::MAP == GetType() && "Property type invalid");
790 Property::Map *container = boost::any_cast<Property::Map>(&(mImpl->mValue));
794 for(Property::Map::iterator iter = container->begin(); iter != container->end(); ++iter)
796 if(iter->first == key)
798 iter->second = value;
803 // if we get here its a new key
804 container->push_back(Property::StringValuePair(key, value));
809 Property::Value& Property::Value::GetItem(const int index) const
816 Property::Map *container = boost::any_cast<Property::Map>(&(mImpl->mValue));
818 DALI_ASSERT_DEBUG(container && "Property::Map has no container?");
821 DALI_ASSERT_ALWAYS(index < static_cast<int>(container->size()) && "Property array index invalid");
822 DALI_ASSERT_ALWAYS(index >= 0 && "Property array index invalid");
824 for(Property::Map::iterator iter = container->begin(); iter != container->end(); ++iter)
835 case Property::ARRAY:
838 Property::Array *container = boost::any_cast<Property::Array>(&(mImpl->mValue));
840 DALI_ASSERT_DEBUG(container && "Property::Map has no container?");
843 DALI_ASSERT_ALWAYS(index < static_cast<int>(container->size()) && "Property array index invalid");
844 DALI_ASSERT_ALWAYS(index >= 0 && "Property array index invalid");
846 for(Property::Array::iterator iter = container->begin(); iter != container->end(); ++iter)
858 case Property::BOOLEAN:
859 case Property::FLOAT:
860 case Property::INTEGER:
861 case Property::UNSIGNED_INTEGER:
862 case Property::VECTOR2:
863 case Property::VECTOR3:
864 case Property::VECTOR4:
865 case Property::MATRIX3:
866 case Property::MATRIX:
867 case Property::RECTANGLE:
868 case Property::ROTATION:
869 case Property::STRING:
870 case Property::TYPE_COUNT:
872 DALI_ASSERT_ALWAYS(!"Cannot GetItem on property Type; not a container");
876 } // switch GetType()
879 DALI_ASSERT_ALWAYS(!"Property value index not valid");
881 // should never return this
882 static Property::Value null;
886 void Property::Value::SetItem(const int index, const Property::Value &value)
892 Property::Map *container = boost::any_cast<Property::Map>(&(mImpl->mValue));
893 if( container && index < static_cast<int>(container->size()) )
896 for(Property::Map::iterator iter = container->begin(); iter != container->end(); ++iter)
900 iter->second = value;
908 case Property::ARRAY:
910 Property::Array *container = boost::any_cast<Property::Array>(&(mImpl->mValue));
911 if( container && index < static_cast<int>(container->size()) )
913 (*container)[index] = value;
919 case Property::BOOLEAN:
920 case Property::FLOAT:
921 case Property::INTEGER:
922 case Property::UNSIGNED_INTEGER:
923 case Property::VECTOR2:
924 case Property::VECTOR3:
925 case Property::VECTOR4:
926 case Property::MATRIX3:
927 case Property::MATRIX:
928 case Property::RECTANGLE:
929 case Property::ROTATION:
930 case Property::STRING:
931 case Property::TYPE_COUNT:
933 DALI_ASSERT_ALWAYS(!"Cannot SetItem on property Type; not a container");
939 int Property::Value::AppendItem(const Property::Value &value)
941 DALI_ASSERT_ALWAYS(Property::ARRAY == GetType() && "Property type invalid");
943 Property::Array *container = boost::any_cast<Property::Array>(&(mImpl->mValue));
947 container->push_back(value);
948 return container->size() - 1;
957 int Property::Value::GetSize() const
965 Property::Map *container = boost::any_cast<Property::Map>(&(mImpl->mValue));
968 ret = container->size();
973 case Property::ARRAY:
975 Property::Array *container = boost::any_cast<Property::Array>(&(mImpl->mValue));
978 ret = container->size();
984 case Property::BOOLEAN:
985 case Property::FLOAT:
986 case Property::INTEGER:
987 case Property::UNSIGNED_INTEGER:
988 case Property::VECTOR2:
989 case Property::VECTOR3:
990 case Property::VECTOR4:
991 case Property::MATRIX3:
992 case Property::MATRIX:
993 case Property::RECTANGLE:
994 case Property::ROTATION:
995 case Property::STRING:
996 case Property::TYPE_COUNT: