From: David Steele Date: Thu, 21 Apr 2016 15:47:04 +0000 (+0100) Subject: Added terse syntax for Get/Set Property X-Git-Tag: dali_1.9.27~10 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=refs%2Fchanges%2F33%2F209233%2F10;p=platform%2Fcore%2Fuifw%2Fdali-core.git Added terse syntax for Get/Set Property Added an IndirectValue which enables the setting and getting of property values using the following syntax: actor["color"] = Color::BLACK; AngleAxis orientation = actor[Actor::Property::ORIENTATION]; Change-Id: I01088e5d7011a0b74bda1bf5a5f0f226c85a115c Signed-off-by: David Steele --- diff --git a/automated-tests/src/dali/dali-test-suite-utils/dali-test-suite-utils.h b/automated-tests/src/dali/dali-test-suite-utils/dali-test-suite-utils.h index 0c5efa3..ac9b214 100644 --- a/automated-tests/src/dali/dali-test-suite-utils/dali-test-suite-utils.h +++ b/automated-tests/src/dali/dali-test-suite-utils/dali-test-suite-utils.h @@ -305,6 +305,17 @@ void DALI_TEST_EQUALS( const std::string &str1, const char* str2, const char* lo void DALI_TEST_EQUALS( const char* str1, const std::string &str2, const char* location); /** + * Test if a property value type is equal to a trivial type. + */ +template +inline void DALI_TEST_VALUE_EQUALS( Property::Value&& value1, Type value2, float epsilon, const char* location) +{ + Property::Value value2b(value2); + DALI_TEST_EQUALS(value1, value2b, epsilon, location); +} + + +/** * Test whether one unsigned integer value is greater than another. * Test succeeds if value1 > value2 * @param[in] value1 The first value diff --git a/automated-tests/src/dali/utc-Dali-Handle.cpp b/automated-tests/src/dali/utc-Dali-Handle.cpp index 5f5e962..f406fd4 100644 --- a/automated-tests/src/dali/utc-Dali-Handle.cpp +++ b/automated-tests/src/dali/utc-Dali-Handle.cpp @@ -16,7 +16,7 @@ */ #include - +#include #include #include #include @@ -1828,6 +1828,7 @@ int UtcDaliHandleGetProperties(void) END_TEST; } + int UtcDaliHandleSetPropertyNegative(void) { TestApplication application; @@ -2171,3 +2172,123 @@ int UtcDaliHandleSupportsNegative(void) } END_TEST; } + + +int UtcDaliHandleIndexOperatorByIndexP01(void) +{ + TestApplication application; + Actor actor = Actor::New(); + + actor[Actor::Property::SIZE] = Vector3( 100.0f, 200.0f, 1.0f ); + + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::SIZE), Vector3( 100.0f, 200.0f, 1.0f ), 0.001f, TEST_LOCATION ); + + + actor.SetProperty( Actor::Property::POSITION, Vector3( 10.0f, 20.0f, 0.0f ) ); + + Vector3 position = actor[ Actor::Property::POSITION ]; + DALI_TEST_EQUALS( position, Vector3( 10.0f, 20.0f, 0.0f ), TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliHandleIndexOperatorByIndexP02(void) +{ + TestApplication application; + Actor actor = Actor::New(); + + const Vector4 defaultActorColor(1.0f, 1.0f, 1.0f, 1.0f); + actor.SetProperty(Actor::Property::COLOR, defaultActorColor); + actor[Actor::Property::COLOR_RED] = 0.5f; + + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_RED), 0.5f, 0.001f, TEST_LOCATION); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR), Vector4(0.5f, 1.0f, 1.0f, 1.0f), 0.001f, TEST_LOCATION); + + actor.SetProperty( Actor::Property::POSITION, Vector3( 10.0f, 20.0f, 0.0f ) ); + + DALI_TEST_EQUALS( (float)actor[ Actor::Property::POSITION_Z ], 0.0f, 0.001f, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliHandleIndexOperatorByIndexP03(void) +{ + TestApplication application; + Actor actor = Actor::New(); + + const Vector4 defaultActorColor(1.0f, 1.0f, 1.0f, 1.0f); + actor.SetProperty(Actor::Property::COLOR, defaultActorColor); + + // Value under test is second to allow compiler to deduce type + DALI_TEST_VALUE_EQUALS( actor[Actor::Property::COLOR_RED], 1.0f, 0.001f, TEST_LOCATION); + + actor.SetProperty( Actor::Property::POSITION, Vector3( 10.0f, 20.0f, 0.0f ) ); + + DALI_TEST_EQUALS( (float)actor[ Actor::Property::POSITION_Z ], 0.0f, 0.001f, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliHandleIndexOperatorByNameP01(void) +{ + TestApplication application; + Actor actor = Actor::New(); + + actor["size"] = Vector3( 100.0f, 200.0f, 1.0f ); + + DALI_TEST_VALUE_EQUALS( actor.GetProperty(Actor::Property::SIZE), Vector3( 100.0f, 200.0f, 1.0f ), 0.001f, TEST_LOCATION ); + + actor.SetProperty( Actor::Property::POSITION, Vector3( 10.0f, 20.0f, 0.0f ) ); + Vector3 position = actor[ "position" ]; + + DALI_TEST_EQUALS( position, Vector3( 10.0f, 20.0f, 0.0f ), 0.001f, TEST_LOCATION ); + + END_TEST; +} + + +int UtcDaliHandleIndexOperatorByNameP02(void) +{ + TestApplication application; + Actor actor = Actor::New(); + + const Vector4 defaultActorColor(1.0f, 1.0f, 1.0f, 1.0f); + actor.SetProperty(Actor::Property::COLOR, defaultActorColor); + actor["colorRed"] = 0.5f; + + DALI_TEST_VALUE_EQUALS( actor.GetProperty(Actor::Property::COLOR_RED), 0.5f, 0.001f, TEST_LOCATION); + DALI_TEST_VALUE_EQUALS( actor.GetProperty(Actor::Property::COLOR), Vector4(0.5f, 1.0f, 1.0f, 1.0f), 0.001f, TEST_LOCATION); + + actor.SetProperty( Actor::Property::POSITION, Vector3( 10.0f, 20.0f, 0.0f ) ); + + float positionY = actor[ "positionY" ]; + DALI_TEST_EQUALS( positionY, 20.0f, 0.001f, TEST_LOCATION ); + + // Should automatically promote IndirectValue to Property::Value rvalue. + DALI_TEST_VALUE_EQUALS( actor["positionZ"], 0.0f, 0.001f, TEST_LOCATION ); + + END_TEST; +} + + +int UtcDaliHandleIndexOperatorNegative02(void) +{ + TestApplication application; + + Actor actor; + try + { + Vector3 position = actor[Actor::Property::POSITION]; + if( position == position ) + { + DALI_TEST_CHECK(false); // Should throw before reaching here. + } + DALI_TEST_CHECK(false); // Should throw before reaching here. + } + catch(...) + { + DALI_TEST_CHECK(true); // Assert expected + } + + END_TEST; +} diff --git a/dali/public-api/file.list b/dali/public-api/file.list index a9c0577..e3946ba 100644 --- a/dali/public-api/file.list +++ b/dali/public-api/file.list @@ -47,8 +47,9 @@ SET( public_api_src_files ${public_api_src_dir}/math/vector4.cpp ${public_api_src_dir}/object/any.cpp ${public_api_src_dir}/object/base-handle.cpp - ${public_api_src_dir}/object/handle.cpp ${public_api_src_dir}/object/base-object.cpp + ${public_api_src_dir}/object/handle.cpp + ${public_api_src_dir}/object/indirect-value.cpp ${public_api_src_dir}/object/object-registry.cpp ${public_api_src_dir}/object/property.cpp ${public_api_src_dir}/object/property-array.cpp @@ -181,6 +182,7 @@ SET( public_api_core_object_header_files ${public_api_src_dir}/object/base-handle.h ${public_api_src_dir}/object/base-object.h ${public_api_src_dir}/object/handle.h + ${public_api_src_dir}/object/indirect-value.h ${public_api_src_dir}/object/object-registry.h ${public_api_src_dir}/object/property-array.h ${public_api_src_dir}/object/property-conditions.h diff --git a/dali/public-api/object/handle.cpp b/dali/public-api/object/handle.cpp index a22fc74..a067aee 100644 --- a/dali/public-api/object/handle.cpp +++ b/dali/public-api/object/handle.cpp @@ -164,6 +164,18 @@ void Handle::RemoveConstraints( uint32_t tag ) GetImplementation(*this).RemoveConstraints( tag ); } +IndirectValue Handle::operator[]( Property::Index index ) +{ + // Will assert on access if handle is empty + return IndirectValue(*this, index); +} + +IndirectValue Handle::operator[]( const std::string& name ) +{ + // Will assert immediately when GetPropertyIndex is called if handle is empty + return IndirectValue(*this, GetPropertyIndex(name)); +} + namespace WeightObject { diff --git a/dali/public-api/object/handle.h b/dali/public-api/object/handle.h index 02ffd8d..540a04e 100644 --- a/dali/public-api/object/handle.h +++ b/dali/public-api/object/handle.h @@ -25,11 +25,13 @@ // INTERNAL INCLUDES #include #include +#include #include #include #include #include + namespace Dali { /** @@ -409,6 +411,28 @@ public: * @pre The Object has been initialized. */ void RemoveConstraints( uint32_t tag ); + + /** + * @brief Index operator, using integer lookup. + * + * Returns an object that can be assigned to or cast from, enabling + * the indexed property to be either read or written. + * + * @param[in] index The index of the property to access. + * @return indirect value. Should have shorter scope than the handle + */ + IndirectValue operator[]( Property::Index index ); + + /** + * @brief Index operator, using name lookup. + * + * Returns an object that can be assigned to or cast from, enabling + * the named property to be either read or written. + * + * @param[in] name The name of the property to access. + * @return indirect value. Should have shorter scope than the handle + */ + IndirectValue operator[]( const std::string& name ); }; /** diff --git a/dali/public-api/object/indirect-value.cpp b/dali/public-api/object/indirect-value.cpp new file mode 100644 index 0000000..321feaa --- /dev/null +++ b/dali/public-api/object/indirect-value.cpp @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2020 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#include +#include +#include + +namespace Dali +{ + +IndirectValue::IndirectValue( Handle& handle, Property::Index index ) +: mHandle(handle.GetObjectPtr()), + mIndex(index), + mExtension(nullptr) +{ +} + +void IndirectValue::operator= (Property::Value value) +{ + Handle(static_cast(mHandle.Get())).SetProperty(mIndex, value); +} + +Property::Value IndirectValue::GetProperty() +{ + return Handle(static_cast(mHandle.Get())).GetProperty(mIndex); +} + +IndirectValue& IndirectValue::operator=( IndirectValue&& ) = default; + +IndirectValue::IndirectValue( IndirectValue&& ) = default; + + +} // namespace Dali diff --git a/dali/public-api/object/indirect-value.h b/dali/public-api/object/indirect-value.h new file mode 100644 index 0000000..39db23c --- /dev/null +++ b/dali/public-api/object/indirect-value.h @@ -0,0 +1,140 @@ +#ifndef DALI_INDIRECT_VALUE_H +#define DALI_INDIRECT_VALUE_H + +/* + * Copyright (c) 2020 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include + +namespace Dali +{ +/** + * @addtogroup dali_core_object + * @{ + */ + +class Handle; + + +/** + * @brief Dali::IndirectValue is an intermediate object that enables a simpler + * syntax for addressing properties. + * + * @SINCE_1_9.27 + * object["property"] = value; + * float value = object["property"]; + * + * It is not intended to be directly instantiated, instead, any Handle type + * will generate a temporary object using the above syntax. + */ +class DALI_CORE_API IndirectValue +{ +public: + /** + * @brief Assignment operator + * + * @SINCE_1_9.27 + * Enables "handle[property] = value" syntax. + * @param[in] value The value to assign + */ + void operator=(Property::Value value); + + /** + * @brief Explicit cast operator for property value. + * + * @SINCE_1_9.27 + * Enables implicit promotion of this to a Property::Value type parameter + * @return The property value + */ + operator Property::Value() + { + return GetProperty(); + } + + /** + * @brief Cast operator + * + * @SINCE_1_9.27 + * Enables "value = handle[property]" syntax. + * @tparam Type The type of the associated property + * @return The associated property cast to the desired type + */ + template + inline operator Type() + { + Property::Value value = GetProperty(); + return value.Get(); + } + +private: + /// @cond internal + + /** + * @brief Move constructor. + * + * @SINCE_1_9.27 + * Making this private to prevent construction of auto type or IndirectValue type. + * @param[in] rhs The object to move + */ + DALI_INTERNAL IndirectValue( IndirectValue&& rhs ); + + /** + * @brief Move assignment operator. + * + * @SINCE_1_9.27 + * Making this private to prevent assignment to auto type or IndirectValue type. + * @param[in] rhs The object to move + */ + DALI_INTERNAL IndirectValue& operator=( IndirectValue&& rhs ); + + /** + * @brief Accessor for handle property. + * + * @SINCE_1_9.27 + * @return The handle's property value + * @note Asserts if the handle is empty + */ + Property::Value GetProperty(); + + friend class Handle; ///< Only Handle types can construct this object + + /** + * @brief Private constructor + * + * @SINCE_1_9.27 + * @param[in] handle A reference to the associated handle + * @param[in] index The index to the associated property + */ + DALI_INTERNAL IndirectValue( Handle& handle, Property::Index index ); +private: + IntrusivePtr mHandle; ///< A handle to the property owner + Property::Index mIndex; ///< Index of the property in the property owner. + + struct Extension; ///< Reserved for future use + Extension* mExtension; ///< Reserved for future use + + /// @endcond +}; + +/** + * @} + */ +} // Namespace Dali + +#endif // DALI_INDIRECT_VALUE_H