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 mImpl = new Impl( value.Get<Quaternion>() );
307 case Property::MATRIX3:
309 mImpl = new Impl( value.Get<Matrix3>());
313 case Property::MATRIX:
315 mImpl = new Impl( value.Get<Matrix>());
319 case Property::STRING:
321 mImpl = new Impl( value.Get<std::string>() );
327 mImpl = new Impl( value.Get<Property::Map>() );
331 case Property::ARRAY:
333 mImpl = new Impl( value.Get<Property::Array>() );
337 case Property::NONE: // fall
346 Property::Value::Value(Type type)
350 case Property::BOOLEAN:
352 mImpl = new Impl( false );
356 case Property::FLOAT:
358 mImpl = new Impl( 0.f );
362 case Property::INTEGER:
364 mImpl = new Impl( 0 );
368 case Property::UNSIGNED_INTEGER:
370 mImpl = new Impl( 0U );
374 case Property::VECTOR2:
376 mImpl = new Impl( Vector2::ZERO );
380 case Property::VECTOR3:
382 mImpl = new Impl( Vector3::ZERO );
386 case Property::VECTOR4:
388 mImpl = new Impl( Vector4::ZERO );
392 case Property::RECTANGLE:
394 mImpl = new Impl( Rect<int>(0,0,0,0) );
398 case Property::ROTATION:
400 mImpl = new Impl( Quaternion( Radian(0.f), Vector3::YAXIS) );
404 case Property::STRING:
406 mImpl = new Impl( std::string() );
412 mImpl = new Impl( Property::Map() );
416 case Property::MATRIX:
418 mImpl = new Impl( Matrix() );
422 case Property::MATRIX3:
424 mImpl = new Impl( Matrix3() );
428 case Property::ARRAY:
430 mImpl = new Impl( Property::Array() );
434 case Property::NONE: // fall
443 Property::Value& Property::Value::operator=(const Property::Value& value)
447 // skip self assignment
451 mImpl->mType = value.GetType();
453 switch (mImpl->mType)
455 case Property::BOOLEAN:
457 mImpl->mValue = value.Get<bool>();
461 case Property::FLOAT:
463 mImpl->mValue = value.Get<float>();
467 case Property::INTEGER:
469 mImpl->mValue = value.Get<int>();
473 case Property::UNSIGNED_INTEGER:
475 mImpl->mValue = value.Get<unsigned int>();
479 case Property::VECTOR2:
481 mImpl->mValue = value.Get<Vector2>();
485 case Property::VECTOR3:
487 mImpl->mValue = value.Get<Vector3>();
491 case Property::VECTOR4:
493 mImpl->mValue = value.Get<Vector4>();
497 case Property::RECTANGLE:
499 mImpl->mValue = value.Get<Rect<int> >();
503 case Property::ROTATION:
505 mImpl->mValue = value.Get<Quaternion>();
509 case Property::STRING:
511 mImpl->mValue = value.Get<std::string>();
515 case Property::MATRIX:
517 mImpl->mValue = value.Get<Matrix>();
521 case Property::MATRIX3:
523 mImpl->mValue = value.Get<Matrix3>();
529 mImpl->mValue = value.Get<Property::Map>();
533 case Property::ARRAY:
535 mImpl->mValue = value.Get<Property::Array>();
539 case Property::NONE: // fall
542 mImpl->mValue = Impl::AnyValue(0);
550 Property::Type Property::Value::GetType() const
555 void Property::Value::Get(bool& boolValue) const
557 DALI_ASSERT_DEBUG( Property::BOOLEAN == GetType() && "Property type invalid" ); // AnyCast does asserted type checking
559 boolValue = AnyCast<bool>(mImpl->mValue);
562 void Property::Value::Get(float& floatValue) const
564 DALI_ASSERT_DEBUG( Property::FLOAT == GetType() && "Property type invalid" );
566 floatValue = AnyCast<float>(mImpl->mValue);
569 void Property::Value::Get(int& integerValue) const
571 DALI_ASSERT_DEBUG( Property::INTEGER == GetType() && "Property type invalid" );
573 integerValue = AnyCast<int>(mImpl->mValue);
576 void Property::Value::Get(unsigned int& unsignedIntegerValue) const
578 DALI_ASSERT_DEBUG( Property::UNSIGNED_INTEGER == GetType() && "Property type invalid" );
580 unsignedIntegerValue = AnyCast<unsigned int>(mImpl->mValue);
583 void Property::Value::Get(Vector2& vectorValue) const
585 DALI_ASSERT_DEBUG( Property::VECTOR2 == GetType() && "Property type invalid" );
587 vectorValue = AnyCast<Vector2>(mImpl->mValue);
590 void Property::Value::Get(Vector3& vectorValue) const
592 DALI_ASSERT_DEBUG( Property::VECTOR3 == GetType() && "Property type invalid" );
594 vectorValue = AnyCast<Vector3>(mImpl->mValue);
597 void Property::Value::Get(Vector4& vectorValue) const
599 DALI_ASSERT_DEBUG( Property::VECTOR4 == GetType() && "Property type invalid" );
601 vectorValue = AnyCast<Vector4>(mImpl->mValue);
604 void Property::Value::Get(Matrix3& matrixValue) const
606 DALI_ASSERT_DEBUG( Property::MATRIX3 == GetType() && "Property type invalid" );
607 matrixValue = AnyCast<Matrix3>(mImpl->mValue);
610 void Property::Value::Get(Matrix& matrixValue) const
612 DALI_ASSERT_DEBUG( Property::MATRIX == GetType() && "Property type invalid" );
613 matrixValue = AnyCast<Matrix>(mImpl->mValue);
616 void Property::Value::Get(Rect<int>& rect) const
618 DALI_ASSERT_DEBUG( Property::RECTANGLE == GetType() && "Property type invalid" );
620 rect = AnyCast<Rect<int> >(mImpl->mValue);
623 void Property::Value::Get(AngleAxis& angleAxisValue) const
625 DALI_ASSERT_ALWAYS( Property::ROTATION == GetType() && "Property type invalid" );
627 // Orientations have two representations
628 DALI_ASSERT_DEBUG( typeid(Quaternion) == mImpl->mValue.GetType() ||
629 typeid(AngleAxis) == mImpl->mValue.GetType() );
631 if ( typeid(Quaternion) == mImpl->mValue.GetType() )
633 Quaternion quaternion = AnyCast<Quaternion>(mImpl->mValue);
635 quaternion.ToAxisAngle( angleAxisValue.axis, angleAxisValue.angle );
639 angleAxisValue = AnyCast<AngleAxis>(mImpl->mValue);
643 void Property::Value::Get(Quaternion& quaternionValue) const
645 DALI_ASSERT_DEBUG( Property::ROTATION == GetType() && "Property type invalid" );
647 // Orientations have two representations
648 DALI_ASSERT_DEBUG( typeid(Quaternion) == mImpl->mValue.GetType() ||
649 typeid(AngleAxis) == mImpl->mValue.GetType() );
651 if ( typeid(Quaternion) == mImpl->mValue.GetType() )
653 quaternionValue = AnyCast<Quaternion>(mImpl->mValue);
657 AngleAxis angleAxis = AnyCast<AngleAxis>(mImpl->mValue);
659 quaternionValue = Quaternion( Radian(angleAxis.angle), angleAxis.axis );
663 void Property::Value::Get(std::string &out) const
665 DALI_ASSERT_DEBUG(Property::STRING == GetType() && "Property type invalid");
667 out = AnyCast<std::string>(mImpl->mValue);
670 void Property::Value::Get(Property::Array &out) const
672 DALI_ASSERT_DEBUG(Property::ARRAY == GetType() && "Property type invalid");
674 out = AnyCast<Property::Array>(mImpl->mValue);
677 void Property::Value::Get(Property::Map &out) const
679 DALI_ASSERT_DEBUG(Property::MAP == GetType() && "Property type invalid");
681 out = AnyCast<Property::Map>(mImpl->mValue);
684 Property::Value& Property::Value::GetValue(const std::string& key) const
686 DALI_ASSERT_DEBUG(Property::MAP == GetType() && "Property type invalid");
688 Property::Map *container = AnyCast<Property::Map>(&(mImpl->mValue));
690 DALI_ASSERT_DEBUG(container);
694 Property::Value* value = container->Find( key );
701 DALI_LOG_WARNING("Cannot find property map key %s", key.c_str());
702 DALI_ASSERT_ALWAYS(!"Cannot find property map key");
705 bool Property::Value::HasKey(const std::string& key) const
709 if( Property::MAP == GetType() )
711 Property::Map *container = AnyCast<Property::Map>(&(mImpl->mValue));
713 DALI_ASSERT_DEBUG(container && "Property::Map has no container?");
717 Property::Value* value = container->Find( key );
729 const std::string& Property::Value::GetKey(const int index) const
735 Property::Map *container = AnyCast<Property::Map>(&(mImpl->mValue));
736 DALI_ASSERT_DEBUG(container && "Property::Map has no container?");
739 if(0 <= index && index < static_cast<int>(container->Count()))
741 return container->GetKey( index );
747 case Property::ARRAY:
748 case Property::BOOLEAN:
749 case Property::FLOAT:
750 case Property::UNSIGNED_INTEGER:
751 case Property::INTEGER:
752 case Property::VECTOR2:
753 case Property::VECTOR3:
754 case Property::VECTOR4:
755 case Property::MATRIX:
756 case Property::MATRIX3:
757 case Property::RECTANGLE:
758 case Property::ROTATION:
759 case Property::STRING:
760 case Property::TYPE_COUNT:
767 // should never return this
768 static std::string null;
773 void Property::Value::SetValue(const std::string& key, const Property::Value &value)
775 DALI_ASSERT_DEBUG(Property::MAP == GetType() && "Property type invalid");
777 Property::Map *container = AnyCast<Property::Map>(&(mImpl->mValue));
781 (*container)[ key ] = value;
785 Property::Value& Property::Value::GetItem(const int index) const
791 Property::Map *container = AnyCast<Property::Map>(&(mImpl->mValue));
793 DALI_ASSERT_DEBUG(container && "Property::Map has no container?");
796 DALI_ASSERT_ALWAYS(index < static_cast<int>(container->Count()) && "Property array index invalid");
797 DALI_ASSERT_ALWAYS(index >= 0 && "Property array index invalid");
799 return container->GetValue( index );
804 case Property::ARRAY:
806 Property::Array *container = AnyCast<Property::Array>(&(mImpl->mValue));
808 DALI_ASSERT_DEBUG(container && "Property::Map has no container?");
811 DALI_ASSERT_ALWAYS(index < static_cast<int>(container->Size()) && "Property array index invalid");
812 DALI_ASSERT_ALWAYS(index >= 0 && "Property array index invalid");
814 return (*container)[index];
820 case Property::BOOLEAN:
821 case Property::FLOAT:
822 case Property::INTEGER:
823 case Property::UNSIGNED_INTEGER:
824 case Property::VECTOR2:
825 case Property::VECTOR3:
826 case Property::VECTOR4:
827 case Property::MATRIX3:
828 case Property::MATRIX:
829 case Property::RECTANGLE:
830 case Property::ROTATION:
831 case Property::STRING:
832 case Property::TYPE_COUNT:
834 DALI_ASSERT_ALWAYS(!"Cannot GetItem on property Type; not a container");
838 } // switch GetType()
841 DALI_ASSERT_ALWAYS(!"Property value index not valid");
844 Property::Value& Property::Value::GetItem(const int index, std::string& key) const
846 Property::Value& ret( GetItem(index) );
848 if( Property::MAP == GetType() )
850 Property::Map *container = AnyCast<Property::Map>(&(mImpl->mValue));
851 if( index < static_cast<int>(container->Count()) )
853 key = container->GetKey( index );
860 void Property::Value::SetItem(const int index, const Property::Value &value)
866 Property::Map *container = AnyCast<Property::Map>(&(mImpl->mValue));
867 if( container && index < static_cast<int>(container->Count()) )
869 Property::Value& indexValue = container->GetValue( index );
875 case Property::ARRAY:
877 Property::Array *container = AnyCast<Property::Array>(&(mImpl->mValue));
878 if( container && index < static_cast<int>(container->Size()) )
880 (*container)[index] = value;
886 case Property::BOOLEAN:
887 case Property::FLOAT:
888 case Property::INTEGER:
889 case Property::UNSIGNED_INTEGER:
890 case Property::VECTOR2:
891 case Property::VECTOR3:
892 case Property::VECTOR4:
893 case Property::MATRIX3:
894 case Property::MATRIX:
895 case Property::RECTANGLE:
896 case Property::ROTATION:
897 case Property::STRING:
898 case Property::TYPE_COUNT:
900 DALI_ASSERT_ALWAYS(!"Cannot SetItem on property Type; not a container");
906 int Property::Value::AppendItem(const Property::Value &value)
908 DALI_ASSERT_DEBUG(Property::ARRAY == GetType() && "Property type invalid");
910 Property::Array *container = AnyCast<Property::Array>(&(mImpl->mValue));
914 container->PushBack(value);
915 return container->Size() - 1;
924 int Property::Value::GetSize() const
932 Property::Map *container = AnyCast<Property::Map>(&(mImpl->mValue));
935 ret = container->Count();
940 case Property::ARRAY:
942 Property::Array *container = AnyCast<Property::Array>(&(mImpl->mValue));
945 ret = container->Size();
951 case Property::BOOLEAN:
952 case Property::FLOAT:
953 case Property::INTEGER:
954 case Property::UNSIGNED_INTEGER:
955 case Property::VECTOR2:
956 case Property::VECTOR3:
957 case Property::VECTOR4:
958 case Property::MATRIX3:
959 case Property::MATRIX:
960 case Property::RECTANGLE:
961 case Property::ROTATION:
962 case Property::STRING:
963 case Property::TYPE_COUNT:
973 std::ostream& operator<< (std::ostream& stream, const Property::Value& value )
976 const Property::Value::Impl& impl( *value.mImpl );
980 case Dali::Property::STRING:
982 stream << AnyCast<std::string>(impl.mValue).c_str();
985 case Dali::Property::VECTOR2:
987 stream << AnyCast<Vector2>(impl.mValue);
990 case Dali::Property::VECTOR3:
992 stream << AnyCast<Vector3>(impl.mValue);
995 case Dali::Property::VECTOR4:
997 stream << AnyCast<Vector4>(impl.mValue);
1000 case Dali::Property::MATRIX:
1002 stream << AnyCast<Matrix>(impl.mValue);
1005 case Dali::Property::BOOLEAN:
1007 stream << AnyCast<bool>(impl.mValue);
1010 case Dali::Property::FLOAT:
1012 stream << AnyCast<float>(impl.mValue);
1015 case Dali::Property::INTEGER:
1017 stream << AnyCast<int>(impl.mValue);
1020 case Dali::Property::UNSIGNED_INTEGER:
1022 stream << AnyCast<unsigned int>(impl.mValue);
1025 case Dali::Property::RECTANGLE:
1027 Dali::Rect<int> rect; // Propery Value rectangles are currently integer based
1032 case Dali::Property::MATRIX3:
1034 stream << AnyCast<Matrix3>(impl.mValue);
1037 case Dali::Property::ROTATION:
1039 // @todo this may change to Quaternion
1042 Dali::Vector4 v4 = q.EulerAngles();
1047 case Dali::Property::ARRAY:
1049 // @todo Need to think about the best way to support array
1050 // E.g Do we want to create a JSON style array like:
1051 // [ {"property-name-0":"property-value-0", "property-name-1":"property-value-1"} ]
1052 stream << "ARRAY unsupported";
1055 case Dali::Property::MAP:
1057 Dali::Property::Map map;
1059 stream << "Map containing " << map.Count() << " elements";
1062 case Dali::Property::TYPE_COUNT:
1064 stream << "unsupported TYPE_COUNT";
1069 stream << "unsupported type = " << value.GetType();