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>
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 mImpl = new Impl( value.Get<Quaternion>() );
306 case Property::MATRIX3:
308 mImpl = new Impl( value.Get<Matrix3>());
312 case Property::MATRIX:
314 mImpl = new Impl( value.Get<Matrix>());
318 case Property::STRING:
320 mImpl = new Impl( value.Get<std::string>() );
326 mImpl = new Impl( value.Get<Property::Map>() );
330 case Property::ARRAY:
332 mImpl = new Impl( value.Get<Property::Array>() );
336 case Property::NONE: // fall
345 Property::Value::Value(Type type)
349 case Property::BOOLEAN:
351 mImpl = new Impl( false );
355 case Property::FLOAT:
357 mImpl = new Impl( 0.f );
361 case Property::INTEGER:
363 mImpl = new Impl( 0 );
367 case Property::UNSIGNED_INTEGER:
369 mImpl = new Impl( 0U );
373 case Property::VECTOR2:
375 mImpl = new Impl( Vector2::ZERO );
379 case Property::VECTOR3:
381 mImpl = new Impl( Vector3::ZERO );
385 case Property::VECTOR4:
387 mImpl = new Impl( Vector4::ZERO );
391 case Property::RECTANGLE:
393 mImpl = new Impl( Rect<int>(0,0,0,0) );
397 case Property::ROTATION:
399 mImpl = new Impl( Quaternion(0.f, Vector4::YAXIS) );
403 case Property::STRING:
405 mImpl = new Impl( std::string() );
411 mImpl = new Impl( Property::Map() );
415 case Property::MATRIX:
417 mImpl = new Impl( Matrix() );
421 case Property::MATRIX3:
423 mImpl = new Impl( Matrix3() );
427 case Property::ARRAY:
429 mImpl = new Impl( Property::Array() );
433 case Property::NONE: // fall
442 Property::Value& Property::Value::operator=(const Property::Value& value)
446 // skip self assignment
450 mImpl->mType = value.GetType();
452 switch (mImpl->mType)
454 case Property::BOOLEAN:
456 mImpl->mValue = value.Get<bool>();
460 case Property::FLOAT:
462 mImpl->mValue = value.Get<float>();
466 case Property::INTEGER:
468 mImpl->mValue = value.Get<int>();
472 case Property::UNSIGNED_INTEGER:
474 mImpl->mValue = value.Get<unsigned int>();
478 case Property::VECTOR2:
480 mImpl->mValue = value.Get<Vector2>();
484 case Property::VECTOR3:
486 mImpl->mValue = value.Get<Vector3>();
490 case Property::VECTOR4:
492 mImpl->mValue = value.Get<Vector4>();
496 case Property::RECTANGLE:
498 mImpl->mValue = value.Get<Rect<int> >();
502 case Property::ROTATION:
504 mImpl->mValue = value.Get<Quaternion>();
508 case Property::STRING:
510 mImpl->mValue = value.Get<std::string>();
514 case Property::MATRIX:
516 mImpl->mValue = value.Get<Matrix>();
520 case Property::MATRIX3:
522 mImpl->mValue = value.Get<Matrix3>();
528 mImpl->mValue = value.Get<Property::Map>();
532 case Property::ARRAY:
534 mImpl->mValue = value.Get<Property::Array>();
538 case Property::NONE: // fall
541 mImpl->mValue = Impl::AnyValue(0);
549 Property::Type Property::Value::GetType() const
554 void Property::Value::Get(bool& boolValue) const
556 DALI_ASSERT_DEBUG( Property::BOOLEAN == GetType() && "Property type invalid" ); // AnyCast does asserted type checking
558 boolValue = AnyCast<bool>(mImpl->mValue);
561 void Property::Value::Get(float& floatValue) const
563 DALI_ASSERT_DEBUG( Property::FLOAT == GetType() && "Property type invalid" );
565 floatValue = AnyCast<float>(mImpl->mValue);
568 void Property::Value::Get(int& integerValue) const
570 DALI_ASSERT_DEBUG( Property::INTEGER == GetType() && "Property type invalid" );
572 integerValue = AnyCast<int>(mImpl->mValue);
575 void Property::Value::Get(unsigned int& unsignedIntegerValue) const
577 DALI_ASSERT_DEBUG( Property::UNSIGNED_INTEGER == GetType() && "Property type invalid" );
579 unsignedIntegerValue = AnyCast<unsigned int>(mImpl->mValue);
582 void Property::Value::Get(Vector2& vectorValue) const
584 DALI_ASSERT_DEBUG( Property::VECTOR2 == GetType() && "Property type invalid" );
586 vectorValue = AnyCast<Vector2>(mImpl->mValue);
589 void Property::Value::Get(Vector3& vectorValue) const
591 DALI_ASSERT_DEBUG( Property::VECTOR3 == GetType() && "Property type invalid" );
593 vectorValue = AnyCast<Vector3>(mImpl->mValue);
596 void Property::Value::Get(Vector4& vectorValue) const
598 DALI_ASSERT_DEBUG( Property::VECTOR4 == GetType() && "Property type invalid" );
600 vectorValue = AnyCast<Vector4>(mImpl->mValue);
603 void Property::Value::Get(Matrix3& matrixValue) const
605 DALI_ASSERT_DEBUG( Property::MATRIX3 == GetType() && "Property type invalid" );
606 matrixValue = AnyCast<Matrix3>(mImpl->mValue);
609 void Property::Value::Get(Matrix& matrixValue) const
611 DALI_ASSERT_DEBUG( Property::MATRIX == GetType() && "Property type invalid" );
612 matrixValue = AnyCast<Matrix>(mImpl->mValue);
615 void Property::Value::Get(Rect<int>& rect) const
617 DALI_ASSERT_DEBUG( Property::RECTANGLE == GetType() && "Property type invalid" );
619 rect = AnyCast<Rect<int> >(mImpl->mValue);
622 void Property::Value::Get(AngleAxis& angleAxisValue) const
624 DALI_ASSERT_ALWAYS( Property::ROTATION == GetType() && "Property type invalid" );
626 // Orientations have two representations
627 DALI_ASSERT_DEBUG( typeid(Quaternion) == mImpl->mValue.GetType() ||
628 typeid(AngleAxis) == mImpl->mValue.GetType() );
630 if ( typeid(Quaternion) == mImpl->mValue.GetType() )
632 Quaternion quaternion = AnyCast<Quaternion>(mImpl->mValue);
634 Radian angleRadians(0.0f);
635 quaternion.ToAxisAngle( angleAxisValue.axis, angleRadians );
636 angleAxisValue.angle = angleRadians;
640 angleAxisValue = AnyCast<AngleAxis>(mImpl->mValue);
644 void Property::Value::Get(Quaternion& quaternionValue) const
646 DALI_ASSERT_DEBUG( 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 quaternionValue = AnyCast<Quaternion>(mImpl->mValue);
658 AngleAxis angleAxis = AnyCast<AngleAxis>(mImpl->mValue);
660 quaternionValue = Quaternion( Radian(angleAxis.angle), angleAxis.axis );
664 void Property::Value::Get(std::string &out) const
666 DALI_ASSERT_DEBUG(Property::STRING == GetType() && "Property type invalid");
668 out = AnyCast<std::string>(mImpl->mValue);
671 void Property::Value::Get(Property::Array &out) const
673 DALI_ASSERT_DEBUG(Property::ARRAY == GetType() && "Property type invalid");
675 out = AnyCast<Property::Array>(mImpl->mValue);
678 void Property::Value::Get(Property::Map &out) const
680 DALI_ASSERT_DEBUG(Property::MAP == GetType() && "Property type invalid");
682 out = AnyCast<Property::Map>(mImpl->mValue);
685 Property::Value& Property::Value::GetValue(const std::string& key) const
687 DALI_ASSERT_DEBUG(Property::MAP == GetType() && "Property type invalid");
689 Property::Map *container = AnyCast<Property::Map>(&(mImpl->mValue));
691 DALI_ASSERT_DEBUG(container);
695 Property::Value* value = container->Find( key );
702 DALI_LOG_WARNING("Cannot find property map key %s", key.c_str());
703 DALI_ASSERT_ALWAYS(!"Cannot find property map key");
706 bool Property::Value::HasKey(const std::string& key) const
710 if( Property::MAP == GetType() )
712 Property::Map *container = AnyCast<Property::Map>(&(mImpl->mValue));
714 DALI_ASSERT_DEBUG(container && "Property::Map has no container?");
718 Property::Value* value = container->Find( key );
730 const std::string& Property::Value::GetKey(const int index) const
736 Property::Map *container = AnyCast<Property::Map>(&(mImpl->mValue));
737 DALI_ASSERT_DEBUG(container && "Property::Map has no container?");
740 if(0 <= index && index < static_cast<int>(container->Count()))
742 return container->GetKey( index );
748 case Property::ARRAY:
749 case Property::BOOLEAN:
750 case Property::FLOAT:
751 case Property::UNSIGNED_INTEGER:
752 case Property::INTEGER:
753 case Property::VECTOR2:
754 case Property::VECTOR3:
755 case Property::VECTOR4:
756 case Property::MATRIX:
757 case Property::MATRIX3:
758 case Property::RECTANGLE:
759 case Property::ROTATION:
760 case Property::STRING:
761 case Property::TYPE_COUNT:
768 // should never return this
769 static std::string null;
774 void Property::Value::SetValue(const std::string& key, const Property::Value &value)
776 DALI_ASSERT_DEBUG(Property::MAP == GetType() && "Property type invalid");
778 Property::Map *container = AnyCast<Property::Map>(&(mImpl->mValue));
782 (*container)[ key ] = value;
786 Property::Value& Property::Value::GetItem(const int index) const
792 Property::Map *container = AnyCast<Property::Map>(&(mImpl->mValue));
794 DALI_ASSERT_DEBUG(container && "Property::Map has no container?");
797 DALI_ASSERT_ALWAYS(index < static_cast<int>(container->Count()) && "Property array index invalid");
798 DALI_ASSERT_ALWAYS(index >= 0 && "Property array index invalid");
800 return container->GetValue( index );
805 case Property::ARRAY:
808 Property::Array *container = AnyCast<Property::Array>(&(mImpl->mValue));
810 DALI_ASSERT_DEBUG(container && "Property::Map has no container?");
813 DALI_ASSERT_ALWAYS(index < static_cast<int>(container->size()) && "Property array index invalid");
814 DALI_ASSERT_ALWAYS(index >= 0 && "Property array index invalid");
816 for(Property::Array::iterator iter = container->begin(); iter != container->end(); ++iter)
828 case Property::BOOLEAN:
829 case Property::FLOAT:
830 case Property::INTEGER:
831 case Property::UNSIGNED_INTEGER:
832 case Property::VECTOR2:
833 case Property::VECTOR3:
834 case Property::VECTOR4:
835 case Property::MATRIX3:
836 case Property::MATRIX:
837 case Property::RECTANGLE:
838 case Property::ROTATION:
839 case Property::STRING:
840 case Property::TYPE_COUNT:
842 DALI_ASSERT_ALWAYS(!"Cannot GetItem on property Type; not a container");
846 } // switch GetType()
849 DALI_ASSERT_ALWAYS(!"Property value index not valid");
852 Property::Value& Property::Value::GetItem(const int index, std::string& key) const
854 Property::Value& ret( GetItem(index) );
856 if( Property::MAP == GetType() )
858 Property::Map *container = AnyCast<Property::Map>(&(mImpl->mValue));
859 if( index < static_cast<int>(container->Count()) )
861 key = container->GetKey( index );
868 void Property::Value::SetItem(const int index, const Property::Value &value)
874 Property::Map *container = AnyCast<Property::Map>(&(mImpl->mValue));
875 if( container && index < static_cast<int>(container->Count()) )
877 Property::Value& indexValue = container->GetValue( index );
883 case Property::ARRAY:
885 Property::Array *container = AnyCast<Property::Array>(&(mImpl->mValue));
886 if( container && index < static_cast<int>(container->size()) )
888 (*container)[index] = value;
894 case Property::BOOLEAN:
895 case Property::FLOAT:
896 case Property::INTEGER:
897 case Property::UNSIGNED_INTEGER:
898 case Property::VECTOR2:
899 case Property::VECTOR3:
900 case Property::VECTOR4:
901 case Property::MATRIX3:
902 case Property::MATRIX:
903 case Property::RECTANGLE:
904 case Property::ROTATION:
905 case Property::STRING:
906 case Property::TYPE_COUNT:
908 DALI_ASSERT_ALWAYS(!"Cannot SetItem on property Type; not a container");
914 int Property::Value::AppendItem(const Property::Value &value)
916 DALI_ASSERT_DEBUG(Property::ARRAY == GetType() && "Property type invalid");
918 Property::Array *container = AnyCast<Property::Array>(&(mImpl->mValue));
922 container->push_back(value);
923 return container->size() - 1;
932 int Property::Value::GetSize() const
940 Property::Map *container = AnyCast<Property::Map>(&(mImpl->mValue));
943 ret = container->Count();
948 case Property::ARRAY:
950 Property::Array *container = AnyCast<Property::Array>(&(mImpl->mValue));
953 ret = container->size();
959 case Property::BOOLEAN:
960 case Property::FLOAT:
961 case Property::INTEGER:
962 case Property::UNSIGNED_INTEGER:
963 case Property::VECTOR2:
964 case Property::VECTOR3:
965 case Property::VECTOR4:
966 case Property::MATRIX3:
967 case Property::MATRIX:
968 case Property::RECTANGLE:
969 case Property::ROTATION:
970 case Property::STRING:
971 case Property::TYPE_COUNT:
981 std::ostream& operator<< (std::ostream& stream, const Property::Value& value )
984 const Property::Value::Impl& impl( *value.mImpl );
988 case Dali::Property::STRING:
990 stream << AnyCast<std::string>(impl.mValue).c_str();
993 case Dali::Property::VECTOR2:
995 stream << AnyCast<Vector2>(impl.mValue);
998 case Dali::Property::VECTOR3:
1000 stream << AnyCast<Vector3>(impl.mValue);
1003 case Dali::Property::VECTOR4:
1005 stream << AnyCast<Vector4>(impl.mValue);
1008 case Dali::Property::MATRIX:
1010 stream << AnyCast<Matrix>(impl.mValue);
1013 case Dali::Property::BOOLEAN:
1015 stream << AnyCast<bool>(impl.mValue);
1018 case Dali::Property::FLOAT:
1020 stream << AnyCast<float>(impl.mValue);
1023 case Dali::Property::INTEGER:
1025 stream << AnyCast<int>(impl.mValue);
1028 case Dali::Property::UNSIGNED_INTEGER:
1030 stream << AnyCast<unsigned int>(impl.mValue);
1033 case Dali::Property::RECTANGLE:
1035 Dali::Rect<int> rect; // Propery Value rectangles are currently integer based
1040 case Dali::Property::MATRIX3:
1042 stream << AnyCast<Matrix3>(impl.mValue);
1045 case Dali::Property::ROTATION:
1047 // @todo this may change to Quaternion
1050 Dali::Vector4 v4 = q.EulerAngles();
1055 case Dali::Property::ARRAY:
1057 // @todo Need to think about the best way to support array
1058 // E.g Do we want to create a JSON style array like:
1059 // [ {"property-name-0":"property-value-0", "property-name-1":"property-value-1"} ]
1060 stream << "ARRAY unsupported";
1063 case Dali::Property::MAP:
1065 Dali::Property::Map map;
1067 stream << "Map containing " << map.Count() << " elements";
1070 case Dali::Property::TYPE_COUNT:
1072 stream << "unsupported TYPE_COUNT";
1077 stream << "unsupported type = " << value.GetType();