2 * Copyright (c) 2014 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>
22 #include <dali/public-api/object/any.h>
23 #include <dali/public-api/math/angle-axis.h>
24 #include <dali/public-api/math/radian.h>
25 #include <dali/public-api/math/vector2.h>
26 #include <dali/public-api/math/vector3.h>
27 #include <dali/public-api/math/vector4.h>
28 #include <dali/public-api/math/matrix3.h>
29 #include <dali/public-api/math/matrix.h>
30 #include <dali/public-api/math/rect.h>
31 #include <dali/public-api/math/quaternion.h>
32 #include <dali/public-api/object/property-map.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 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_DEBUG( Property::BOOLEAN == GetType() && "Property type invalid" ); // AnyCast does asserted type checking
555 boolValue = AnyCast<bool>(mImpl->mValue);
558 void Property::Value::Get(float& floatValue) const
560 DALI_ASSERT_DEBUG( Property::FLOAT == GetType() && "Property type invalid" );
562 floatValue = AnyCast<float>(mImpl->mValue);
565 void Property::Value::Get(int& integerValue) const
567 DALI_ASSERT_DEBUG( Property::INTEGER == GetType() && "Property type invalid" );
569 integerValue = AnyCast<int>(mImpl->mValue);
572 void Property::Value::Get(unsigned int& unsignedIntegerValue) const
574 DALI_ASSERT_DEBUG( Property::UNSIGNED_INTEGER == GetType() && "Property type invalid" );
576 unsignedIntegerValue = AnyCast<unsigned int>(mImpl->mValue);
579 void Property::Value::Get(Vector2& vectorValue) const
581 DALI_ASSERT_DEBUG( Property::VECTOR2 == GetType() && "Property type invalid" );
583 vectorValue = AnyCast<Vector2>(mImpl->mValue);
586 void Property::Value::Get(Vector3& vectorValue) const
588 DALI_ASSERT_DEBUG( Property::VECTOR3 == GetType() && "Property type invalid" );
590 vectorValue = AnyCast<Vector3>(mImpl->mValue);
593 void Property::Value::Get(Vector4& vectorValue) const
595 DALI_ASSERT_DEBUG( Property::VECTOR4 == GetType() && "Property type invalid" );
597 vectorValue = AnyCast<Vector4>(mImpl->mValue);
600 void Property::Value::Get(Matrix3& matrixValue) const
602 DALI_ASSERT_DEBUG( Property::MATRIX3 == GetType() && "Property type invalid" );
603 matrixValue = AnyCast<Matrix3>(mImpl->mValue);
606 void Property::Value::Get(Matrix& matrixValue) const
608 DALI_ASSERT_DEBUG( Property::MATRIX == GetType() && "Property type invalid" );
609 matrixValue = AnyCast<Matrix>(mImpl->mValue);
612 void Property::Value::Get(Rect<int>& rect) const
614 DALI_ASSERT_DEBUG( Property::RECTANGLE == GetType() && "Property type invalid" );
616 rect = AnyCast<Rect<int> >(mImpl->mValue);
619 void Property::Value::Get(AngleAxis& angleAxisValue) const
621 DALI_ASSERT_ALWAYS( Property::ROTATION == GetType() && "Property type invalid" );
623 // Orientations have two representations
624 DALI_ASSERT_DEBUG( typeid(Quaternion) == mImpl->mValue.GetType() ||
625 typeid(AngleAxis) == mImpl->mValue.GetType() );
627 if ( typeid(Quaternion) == mImpl->mValue.GetType() )
629 Quaternion quaternion = AnyCast<Quaternion>(mImpl->mValue);
631 Radian angleRadians(0.0f);
632 quaternion.ToAxisAngle( angleAxisValue.axis, angleRadians );
633 angleAxisValue.angle = angleRadians;
637 angleAxisValue = AnyCast<AngleAxis>(mImpl->mValue);
641 void Property::Value::Get(Quaternion& quaternionValue) const
643 DALI_ASSERT_DEBUG( Property::ROTATION == GetType() && "Property type invalid" );
645 // Orientations have two representations
646 DALI_ASSERT_DEBUG( typeid(Quaternion) == mImpl->mValue.GetType() ||
647 typeid(AngleAxis) == mImpl->mValue.GetType() );
649 if ( typeid(Quaternion) == mImpl->mValue.GetType() )
651 quaternionValue = AnyCast<Quaternion>(mImpl->mValue);
655 AngleAxis angleAxis = AnyCast<AngleAxis>(mImpl->mValue);
657 quaternionValue = Quaternion( Radian(angleAxis.angle), angleAxis.axis );
661 void Property::Value::Get(std::string &out) const
663 DALI_ASSERT_DEBUG(Property::STRING == GetType() && "Property type invalid");
665 out = AnyCast<std::string>(mImpl->mValue);
668 void Property::Value::Get(Property::Array &out) const
670 DALI_ASSERT_DEBUG(Property::ARRAY == GetType() && "Property type invalid");
672 out = AnyCast<Property::Array>(mImpl->mValue);
675 void Property::Value::Get(Property::Map &out) const
677 DALI_ASSERT_DEBUG(Property::MAP == GetType() && "Property type invalid");
679 out = AnyCast<Property::Map>(mImpl->mValue);
682 Property::Value& Property::Value::GetValue(const std::string& key) const
684 DALI_ASSERT_DEBUG(Property::MAP == GetType() && "Property type invalid");
686 Property::Map *container = AnyCast<Property::Map>(&(mImpl->mValue));
688 DALI_ASSERT_DEBUG(container);
692 Property::Value* value = container->Find( key );
699 DALI_LOG_WARNING("Cannot find property map key %s", key.c_str());
700 DALI_ASSERT_ALWAYS(!"Cannot find property map key");
703 bool Property::Value::HasKey(const std::string& key) const
707 if( Property::MAP == GetType() )
709 Property::Map *container = AnyCast<Property::Map>(&(mImpl->mValue));
711 DALI_ASSERT_DEBUG(container && "Property::Map has no container?");
715 Property::Value* value = container->Find( key );
727 const std::string& Property::Value::GetKey(const int index) const
733 Property::Map *container = AnyCast<Property::Map>(&(mImpl->mValue));
734 DALI_ASSERT_DEBUG(container && "Property::Map has no container?");
737 if(0 <= index && index < static_cast<int>(container->Count()))
739 return container->GetKey( index );
745 case Property::ARRAY:
746 case Property::BOOLEAN:
747 case Property::FLOAT:
748 case Property::UNSIGNED_INTEGER:
749 case Property::INTEGER:
750 case Property::VECTOR2:
751 case Property::VECTOR3:
752 case Property::VECTOR4:
753 case Property::MATRIX:
754 case Property::MATRIX3:
755 case Property::RECTANGLE:
756 case Property::ROTATION:
757 case Property::STRING:
758 case Property::TYPE_COUNT:
765 // should never return this
766 static std::string null;
771 void Property::Value::SetValue(const std::string& key, const Property::Value &value)
773 DALI_ASSERT_DEBUG(Property::MAP == GetType() && "Property type invalid");
775 Property::Map *container = AnyCast<Property::Map>(&(mImpl->mValue));
779 (*container)[ key ] = value;
783 Property::Value& Property::Value::GetItem(const int index) const
789 Property::Map *container = AnyCast<Property::Map>(&(mImpl->mValue));
791 DALI_ASSERT_DEBUG(container && "Property::Map has no container?");
794 DALI_ASSERT_ALWAYS(index < static_cast<int>(container->Count()) && "Property array index invalid");
795 DALI_ASSERT_ALWAYS(index >= 0 && "Property array index invalid");
797 return container->GetValue( index );
802 case Property::ARRAY:
805 Property::Array *container = AnyCast<Property::Array>(&(mImpl->mValue));
807 DALI_ASSERT_DEBUG(container && "Property::Map has no container?");
810 DALI_ASSERT_ALWAYS(index < static_cast<int>(container->size()) && "Property array index invalid");
811 DALI_ASSERT_ALWAYS(index >= 0 && "Property array index invalid");
813 for(Property::Array::iterator iter = container->begin(); iter != container->end(); ++iter)
825 case Property::BOOLEAN:
826 case Property::FLOAT:
827 case Property::INTEGER:
828 case Property::UNSIGNED_INTEGER:
829 case Property::VECTOR2:
830 case Property::VECTOR3:
831 case Property::VECTOR4:
832 case Property::MATRIX3:
833 case Property::MATRIX:
834 case Property::RECTANGLE:
835 case Property::ROTATION:
836 case Property::STRING:
837 case Property::TYPE_COUNT:
839 DALI_ASSERT_ALWAYS(!"Cannot GetItem on property Type; not a container");
843 } // switch GetType()
846 DALI_ASSERT_ALWAYS(!"Property value index not valid");
849 Property::Value& Property::Value::GetItem(const int index, std::string& key) const
851 Property::Value& ret( GetItem(index) );
853 if( Property::MAP == GetType() )
855 Property::Map *container = AnyCast<Property::Map>(&(mImpl->mValue));
856 if( index < static_cast<int>(container->Count()) )
858 key = container->GetKey( index );
865 void Property::Value::SetItem(const int index, const Property::Value &value)
871 Property::Map *container = AnyCast<Property::Map>(&(mImpl->mValue));
872 if( container && index < static_cast<int>(container->Count()) )
874 Property::Value& indexValue = container->GetValue( index );
880 case Property::ARRAY:
882 Property::Array *container = AnyCast<Property::Array>(&(mImpl->mValue));
883 if( container && index < static_cast<int>(container->size()) )
885 (*container)[index] = value;
891 case Property::BOOLEAN:
892 case Property::FLOAT:
893 case Property::INTEGER:
894 case Property::UNSIGNED_INTEGER:
895 case Property::VECTOR2:
896 case Property::VECTOR3:
897 case Property::VECTOR4:
898 case Property::MATRIX3:
899 case Property::MATRIX:
900 case Property::RECTANGLE:
901 case Property::ROTATION:
902 case Property::STRING:
903 case Property::TYPE_COUNT:
905 DALI_ASSERT_ALWAYS(!"Cannot SetItem on property Type; not a container");
911 int Property::Value::AppendItem(const Property::Value &value)
913 DALI_ASSERT_DEBUG(Property::ARRAY == GetType() && "Property type invalid");
915 Property::Array *container = AnyCast<Property::Array>(&(mImpl->mValue));
919 container->push_back(value);
920 return container->size() - 1;
929 int Property::Value::GetSize() const
937 Property::Map *container = AnyCast<Property::Map>(&(mImpl->mValue));
940 ret = container->Count();
945 case Property::ARRAY:
947 Property::Array *container = AnyCast<Property::Array>(&(mImpl->mValue));
950 ret = container->size();
956 case Property::BOOLEAN:
957 case Property::FLOAT:
958 case Property::INTEGER:
959 case Property::UNSIGNED_INTEGER:
960 case Property::VECTOR2:
961 case Property::VECTOR3:
962 case Property::VECTOR4:
963 case Property::MATRIX3:
964 case Property::MATRIX:
965 case Property::RECTANGLE:
966 case Property::ROTATION:
967 case Property::STRING:
968 case Property::TYPE_COUNT:
978 std::ostream& operator<< (std::ostream& stream, const Property::Value& value )
981 const Property::Value::Impl& impl( *value.mImpl );
985 case Dali::Property::STRING:
987 stream << AnyCast<std::string>(impl.mValue).c_str();
990 case Dali::Property::VECTOR2:
992 stream << AnyCast<Vector2>(impl.mValue);
995 case Dali::Property::VECTOR3:
997 stream << AnyCast<Vector3>(impl.mValue);
1000 case Dali::Property::VECTOR4:
1002 stream << AnyCast<Vector4>(impl.mValue);
1005 case Dali::Property::MATRIX:
1007 stream << AnyCast<Matrix>(impl.mValue);
1010 case Dali::Property::BOOLEAN:
1012 stream << AnyCast<bool>(impl.mValue);
1015 case Dali::Property::FLOAT:
1017 stream << AnyCast<float>(impl.mValue);
1020 case Dali::Property::INTEGER:
1022 stream << AnyCast<int>(impl.mValue);
1025 case Dali::Property::UNSIGNED_INTEGER:
1027 stream << AnyCast<unsigned int>(impl.mValue);
1030 case Dali::Property::RECTANGLE:
1032 Dali::Rect<int> rect; // Propery Value rectangles are currently integer based
1037 case Dali::Property::MATRIX3:
1039 stream << AnyCast<Matrix3>(impl.mValue);
1042 case Dali::Property::ROTATION:
1044 // @todo this may change to Quaternion
1047 Dali::Vector4 v4 = q.EulerAngles();
1052 case Dali::Property::ARRAY:
1054 // @todo Need to think about the best way to support array
1055 // E.g Do we want to create a JSON style array like:
1056 // [ {"property-name-0":"property-value-0", "property-name-1":"property-value-1"} ]
1057 stream << "ARRAY unsupported";
1060 case Dali::Property::MAP:
1062 Dali::Property::Map map;
1064 stream << "Map containing " << map.Count() << " elements";
1067 case Dali::Property::TYPE_COUNT:
1069 stream << "unsupported TYPE_COUNT";
1074 stream << "unsupported type = " << value.GetType();