From: Bowon Ryu Date: Tue, 16 Nov 2021 09:27:48 +0000 (+0000) Subject: Merge "Fix: The last line of the text overlaps with the text-editor's border/edge... X-Git-Tag: dali_2.0.53~1 X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git;a=commitdiff_plain;h=3ea3bc2160dead96a69eae4c12175b6bd760a006;hp=2c9abc8a3797a3317e0de7c23b1a15424facefb7 Merge "Fix: The last line of the text overlaps with the text-editor's border/edge" into devel/master --- diff --git a/automated-tests/src/dali-scene-loader/utc-Dali-StringCallback.cpp b/automated-tests/src/dali-scene-loader/utc-Dali-StringCallback.cpp index acd5183..113f40a 100644 --- a/automated-tests/src/dali-scene-loader/utc-Dali-StringCallback.cpp +++ b/automated-tests/src/dali-scene-loader/utc-Dali-StringCallback.cpp @@ -41,6 +41,6 @@ int UtcDaliUtilsDefaultStringCallback(void) { InstallLogFunction(TestLogFunction); DefaultErrorCallback("Hello world!"); - DALI_TEST_EQUAL(std::string(sBuffer), "2: DefaultErrorCallback Hello world!"); + DALI_TEST_EQUAL(std::string(sBuffer), "2: string-callback.cpp: DefaultErrorCallback(26) > Hello world!"); END_TEST; } diff --git a/automated-tests/src/dali-toolkit-internal/dali-toolkit-test-utils/accessibility-test-utils.cpp b/automated-tests/src/dali-toolkit-internal/dali-toolkit-test-utils/accessibility-test-utils.cpp index a9d9f03..b654d52 100644 --- a/automated-tests/src/dali-toolkit-internal/dali-toolkit-test-utils/accessibility-test-utils.cpp +++ b/automated-tests/src/dali-toolkit-internal/dali-toolkit-test-utils/accessibility-test-utils.cpp @@ -4,303 +4,312 @@ #include #include "dbus-wrapper.h" -namespace Dali { - namespace Accessibility { - - using MethodType = TestDBusWrapper::MethodType; - using MessagePtr = DBusWrapper::MessagePtr; - - static bool MoveOutedCalled = false; - - void TestEnableSC(bool b) { - static bool firstTime = true; - if (b && firstTime) { - firstTime = false; - auto bridge = Accessibility::Bridge::GetCurrentBridge(); - Dali::Stage stage = Dali::Stage::GetCurrent(); - auto accessible = Accessibility::Accessible::Get( stage.GetRootLayer() ); -// bridge->SetApplicationChild( accessible ); // BART - bridge->AddTopLevelWindow( accessible ); // BART - bridge->SetApplicationName( "TestApp" ); - bridge->Initialize(); - - static bool ScreenReaderEnabled = false; - static bool IsEnabled = false; - - auto wr = static_cast(DBusWrapper::Installed()); - - wr->testMethods[std::tuple{"/org/a11y/bus", "org.a11y.Status", "ScreenReaderEnabled", MethodType::Getter}] = [wr](const MessagePtr &m) -> MessagePtr { - auto reply = wr->newReplyMessage(m); - wr->Encode(reply, std::tuple>{ ScreenReaderEnabled }); - return reply; - }; - wr->testMethods[std::tuple{"/org/a11y/bus", "org.a11y.Status", "IsEnabled", MethodType::Getter}] = [wr](const MessagePtr &m) -> MessagePtr { - auto reply = wr->newReplyMessage(m); - wr->Encode(reply, std::tuple>{ IsEnabled }); - return reply; - }; - wr->testMethods[std::tuple{"/org/a11y/bus", "org.a11y.Bus", "GetAddress", MethodType::Method}] = [wr](const MessagePtr &m) -> MessagePtr { - auto reply = wr->newReplyMessage(m); - wr->Encode(reply, std::tuple{ "bus" }); - return reply; - }; - wr->testMethods[std::tuple{"/org/a11y/atspi/accessible/root", "org.a11y.atspi.Socket", "Embed", MethodType::Method}] = [wr](const MessagePtr &m) -> MessagePtr { - auto reply = wr->newReplyMessage(m); - wr->Encode(reply, std::tuple
{ {"bus", "root"} }); - return reply; - }; - wr->testMethods[std::tuple{"/org/a11y/atspi/accessible", "org.a11y.atspi.Event.Object", "PropertyChange", MethodType::Method}] = - [wr](const MessagePtr &m) -> MessagePtr { - return wr->newReplyMessage(m); - }; - wr->testMethods[std::tuple{"/org/a11y/atspi/accessible", "org.a11y.atspi.Event.Object", "StateChanged", MethodType::Method}] = - [wr](const MessagePtr &m) -> MessagePtr { - return wr->newReplyMessage(m); - }; - wr->testMethods[std::tuple{"/org/a11y/atspi/accessible", "org.a11y.atspi.Event.Object", "BoundsChanged", MethodType::Method}] = - [wr](const MessagePtr &m) -> MessagePtr { - return wr->newReplyMessage(m); - }; - wr->testMethods[std::tuple{"/org/a11y/atspi/accessible", "org.a11y.atspi.Event.Object", "ActiveDescendantChanged", MethodType::Method}] = - [wr](const MessagePtr &m) -> MessagePtr { - return wr->newReplyMessage(m); - }; - wr->testMethods[std::tuple{"/org/a11y/atspi/accessible", "org.a11y.atspi.Event.Object", "TextChanged", MethodType::Method}] = - [wr](const MessagePtr &m) -> MessagePtr { - return wr->newReplyMessage(m); - }; - wr->testMethods[std::tuple{"/org/a11y/atspi/accessible", "org.a11y.atspi.Event.Object", "TextCaretMoved", MethodType::Method}] = - [wr](const MessagePtr &m) -> MessagePtr { - return wr->newReplyMessage(m); - }; - wr->testMethods[std::tuple{"/org/a11y/atspi/accessible", "org.a11y.atspi.Event.Object", "MoveOuted", MethodType::Method}] = - [wr](const MessagePtr &m) -> MessagePtr { - MoveOutedCalled = true; - return wr->newReplyMessage(m); - }; - } - auto wr = static_cast(DBusWrapper::Installed()); - wr->fromTestChangeProperty("/org/a11y/bus", "org.a11y.Status", "ScreenReaderEnabled", b); - wr->fromTestChangeProperty("/org/a11y/bus", "org.a11y.Status", "IsEnabled", b); - } - - std::vector
TestGetChildren(const Address &adr) - { - auto wr = static_cast(DBusWrapper::Installed()); - auto chs = wr->fromTestCall>(adr.GetPath(), "org.a11y.atspi.Accessible", "GetChildren", std::tuple<>()); - return std::move(std::get<0>(chs)); - } - - std::string TestGetName(const Address &adr) - { - auto wr = static_cast(DBusWrapper::Installed()); - auto name = wr->fromTestGet(adr.GetPath(), "org.a11y.atspi.Accessible", "Name"); - return name; - } - - std::string TestGetDescription(const Address &adr) - { - auto wr = static_cast(DBusWrapper::Installed()); - auto description = wr->fromTestGet(adr.GetPath(), "org.a11y.atspi.Accessible", "Description"); - return description; - } - - uint32_t TestGetRole(const Address &adr) - { - auto wr = static_cast(DBusWrapper::Installed()); - auto chs = wr->fromTestCall(adr.GetPath(), "org.a11y.atspi.Accessible", "GetRole", std::tuple<>()); - return std::move(std::get<0>(chs)); - } - - std::string TestGetRoleName(const Address &adr) - { - auto wr = static_cast(DBusWrapper::Installed()); - auto chs = wr->fromTestCall(adr.GetPath(), "org.a11y.atspi.Accessible", "GetRoleName", std::tuple<>()); - return std::move(std::get<0>(chs)); - } - - Address TestGetParent(const Address &adr) - { - auto wr = static_cast(DBusWrapper::Installed()); - auto chs = wr->fromTestGet< Address >(adr.GetPath(), "org.a11y.atspi.Accessible", "Parent"); - return chs; - } - - std::string TestGetLocalizedRoleName(const Address &adr) - { - auto wr = static_cast(DBusWrapper::Installed()); - auto chs = wr->fromTestCall(adr.GetPath(), "org.a11y.atspi.Accessible", "GetLocalizedRoleName", std::tuple<>()); - return std::move(std::get<0>(chs)); - } - - std::array< uint32_t, 2 > TestGetStates(const Address &adr) - { - auto wr = static_cast(DBusWrapper::Installed()); - auto chs = wr->fromTestCall>(adr.GetPath(), "org.a11y.atspi.Accessible", "GetState", std::tuple<>()); - return std::move(std::get<0>(chs)); - } - - std::unordered_map< std::string, std::string > TestGetAttributes(const Address &adr) - { - auto wr = static_cast(DBusWrapper::Installed()); - auto chs = wr->fromTestCall>(adr.GetPath(), "org.a11y.atspi.Accessible", "GetAttributes", std::tuple<>()); - return std::move(std::get<0>(chs)); - } - - bool TestDoGesture(const Address &adr, Dali::Accessibility::Gesture type, int32_t xBeg, int32_t xEnd, int32_t yBeg, int32_t yEnd, Dali::Accessibility::GestureState state, uint32_t eventTime) - { - auto wr = static_cast(DBusWrapper::Installed()); - auto chs = wr->fromTestCall< bool >(adr.GetPath(), "org.a11y.atspi.Accessible", "DoGesture", - std::tuple< Dali::Accessibility::Gesture, int32_t, int32_t, int32_t, int32_t, Dali::Accessibility::GestureState, uint32_t >(type, xBeg, xEnd, yBeg, yEnd, state, eventTime )); - return std::move(std::get<0>(chs)); - } - - std::vector< std::tuple< uint32_t, std::vector< Dali::Accessibility::Address > > > TestGetRelationSet(const Address &adr) - { - auto wr = static_cast(DBusWrapper::Installed()); - auto chs = wr->fromTestCall< std::vector< std::tuple< uint32_t, std::vector< Dali::Accessibility::Address > > > >(adr.GetPath(), "org.a11y.atspi.Accessible", "GetRelationSet", std::tuple<>()); - return std::move(std::get<0>(chs)); - } - - Address TestGetChildAtIndex(const Address &adr, int index) - { - auto wr = static_cast(DBusWrapper::Installed()); - auto chs = wr->fromTestCall< Address >(adr.GetPath(), "org.a11y.atspi.Accessible", "GetChildAtIndex", std::tuple< int >( index )); - return std::move(std::get<0>(chs)); - } - - ComponentLayer TestGetLayer(const Address &adr) - { - auto wr = static_cast(DBusWrapper::Installed()); - auto chs = wr->fromTestCall< Dali::Accessibility::ComponentLayer >(adr.GetPath(), "org.a11y.atspi.Component", "GetLayer", std::tuple<>()); - return std::move(std::get<0>(chs)); - } - - int TestGetIndexInParent(const Address &adr) - { - auto wr = static_cast(DBusWrapper::Installed()); - auto chs = wr->fromTestCall< int >(adr.GetPath(), "org.a11y.atspi.Accessible", "GetIndexInParent", std::tuple<>()); - return std::move(std::get<0>(chs)); - } - - bool TestGrabFocus(const Address &adr) - { - auto wr = static_cast(DBusWrapper::Installed()); - auto chs = wr->fromTestCall< bool >(adr.GetPath(), "org.a11y.atspi.Component", "GrabFocus", std::tuple<>()); - return std::move(std::get<0>(chs)); - } - - bool TestGrabHighlight(const Address &adr) - { - auto wr = static_cast(DBusWrapper::Installed()); - auto chs = wr->fromTestCall< bool >(adr.GetPath(), "org.a11y.atspi.Component", "GrabHighlight", std::tuple<>()); - return std::move(std::get<0>(chs)); - } - - bool TestClearHighlight(const Address &adr) - { - auto wr = static_cast(DBusWrapper::Installed()); - auto chs = wr->fromTestCall< bool >(adr.GetPath(), "org.a11y.atspi.Component", "ClearHighlight", std::tuple<>()); - return std::move(std::get<0>(chs)); - } - - std::tuple< int32_t, int32_t, int32_t, int32_t > TestGetExtents(const Address &adr, Dali::Accessibility::CoordinateType coordinateType) - { - auto wr = static_cast(DBusWrapper::Installed()); - auto chs = wr->fromTestCall< std::tuple< int32_t, int32_t, int32_t, int32_t > >(adr.GetPath(), "org.a11y.atspi.Component", "GetExtents", std::make_tuple(static_cast(coordinateType))); - return std::move(std::get<0>(chs)); - } - - int TestGetMdiZOrder(const Address &adr) - { - auto wr = static_cast(DBusWrapper::Installed()); - auto chs = wr->fromTestCall< int16_t >(adr.GetPath(), "org.a11y.atspi.Component", "GetMDIZOrder", std::tuple<>()); - return std::move(std::get<0>(chs)); - } - - double TestGetAlpha(const Address &adr) - { - auto wr = static_cast(DBusWrapper::Installed()); - auto chs = wr->fromTestCall< double >(adr.GetPath(), "org.a11y.atspi.Component", "GetAlpha", std::tuple<>()); - return std::move(std::get<0>(chs)); - } - - std::string TestGetActionName( const Address &adr, size_t index ) - { - auto wr = static_cast(DBusWrapper::Installed()); - auto chs = wr->fromTestCall< std::string >(adr.GetPath(), "org.a11y.atspi.Action", "GetName", std::tuple< int32_t >( index )); - return std::move(std::get<0>(chs)); - } - - std::string TestGetLocalizedActionName( const Address &adr, size_t index ) - { - auto wr = static_cast(DBusWrapper::Installed()); - auto chs = wr->fromTestCall< std::string >(adr.GetPath(), "org.a11y.atspi.Action", "GetLocalizedName", std::tuple< int32_t >( index )); - return std::move(std::get<0>(chs)); - } - - size_t TestGetActionCount( const Address &adr ) - { - auto wr = static_cast(DBusWrapper::Installed()); - auto count = wr->fromTestGet< int32_t >(adr.GetPath(), "org.a11y.atspi.Action", "NActions"); - return count; - } - - bool TestDoAction ( const Address &adr, size_t index ) - { - auto wr = static_cast(DBusWrapper::Installed()); - auto chs = wr->fromTestCall< bool >(adr.GetPath(), "org.a11y.atspi.Action", "DoAction", std::tuple< int32_t >( index )); - return std::move(std::get<0>(chs)); - } - - bool TestDoAction ( const Address &adr, const std::string& name ) - { - auto wr = static_cast(DBusWrapper::Installed()); - auto chs = wr->fromTestCall< bool >(adr.GetPath(), "org.a11y.atspi.Action", "DoActionName", std::tuple< std::string >( name )); - return std::move(std::get<0>(chs)); - } - - std::string TestGetActionKeyBinding ( const Address &adr, size_t index ) - { - auto wr = static_cast(DBusWrapper::Installed()); - auto chs = wr->fromTestCall< std::string >(adr.GetPath(), "org.a11y.atspi.Action", "GetKeyBinding", std::tuple< int32_t >( index )); - return std::move(std::get<0>(chs)); - } - - std::string TestGetActionDescription ( const Address &adr, size_t index ) - { - auto wr = static_cast(DBusWrapper::Installed()); - auto chs = wr->fromTestCall< std::string >(adr.GetPath(), "org.a11y.atspi.Action", "GetDescription", std::tuple< int32_t >( index )); - return std::move(std::get<0>(chs)); - } - - void TestResetMoveOutedCalled () - { - MoveOutedCalled = false; - } - - bool TestGetMoveOutedCalled () - { - return MoveOutedCalled; - } - - void printTree(const Address &root, size_t depth) - { - auto name = TestGetName(root); - printf("%10s", root.GetPath().c_str()); - for(unsigned int i = 0; i < depth; ++i) printf(" "); - printf("%s\n", name.c_str()); - auto chs = TestGetChildren(root); - for(auto &c : chs) - printTree(c, depth + 1); - } - - bool Find( const std::vector< std::string > &collection, const std::string &key) - { - for ( auto& it : collection) - if( it == key ) - return true; - return false; - } +namespace Dali +{ +namespace Accessibility +{ + using MethodType = TestDBusWrapper::MethodType; + using MessagePtr = DBusWrapper::MessagePtr; + + static bool gMoveOutedCalled = false; + + void TestEnableSC(bool b) + { + static bool firstTime = true; + if (b && firstTime) + { + firstTime = false; + auto bridge = Accessibility::Bridge::GetCurrentBridge(); + Dali::Stage stage = Dali::Stage::GetCurrent(); + auto accessible = Accessibility::Accessible::Get( stage.GetRootLayer(), true ); + bridge->AddTopLevelWindow( accessible ); + bridge->SetApplicationName( "TestApp" ); + bridge->Initialize(); + + static bool ScreenReaderEnabled = false; + static bool IsEnabled = false; + + auto wr = static_cast(DBusWrapper::Installed()); + + wr->testMethods[std::tuple{"/org/a11y/bus", "org.a11y.Status", "ScreenReaderEnabled", MethodType::Getter}] = [wr](const MessagePtr &m) -> MessagePtr { + auto reply = wr->newReplyMessage(m); + wr->Encode(reply, std::tuple>{ ScreenReaderEnabled }); + return reply; + }; + wr->testMethods[std::tuple{"/org/a11y/bus", "org.a11y.Status", "IsEnabled", MethodType::Getter}] = [wr](const MessagePtr &m) -> MessagePtr { + auto reply = wr->newReplyMessage(m); + wr->Encode(reply, std::tuple>{ IsEnabled }); + return reply; + }; + wr->testMethods[std::tuple{"/org/a11y/bus", "org.a11y.Bus", "GetAddress", MethodType::Method}] = [wr](const MessagePtr &m) -> MessagePtr { + auto reply = wr->newReplyMessage(m); + wr->Encode(reply, std::tuple{ "bus" }); + return reply; + }; + wr->testMethods[std::tuple{"/org/a11y/atspi/accessible/root", "org.a11y.atspi.Socket", "Embed", MethodType::Method}] = [wr](const MessagePtr &m) -> MessagePtr { + auto reply = wr->newReplyMessage(m); + wr->Encode(reply, std::tuple
{ {"bus", "root"} }); + return reply; + }; + wr->testMethods[std::tuple{"/org/a11y/atspi/accessible", "org.a11y.atspi.Event.Object", "PropertyChange", MethodType::Method}] = + [wr](const MessagePtr &m) -> MessagePtr { + return wr->newReplyMessage(m); + }; + wr->testMethods[std::tuple{"/org/a11y/atspi/accessible", "org.a11y.atspi.Event.Object", "StateChanged", MethodType::Method}] = + [wr](const MessagePtr &m) -> MessagePtr { + return wr->newReplyMessage(m); + }; + wr->testMethods[std::tuple{"/org/a11y/atspi/accessible", "org.a11y.atspi.Event.Object", "BoundsChanged", MethodType::Method}] = + [wr](const MessagePtr &m) -> MessagePtr { + return wr->newReplyMessage(m); + }; + wr->testMethods[std::tuple{"/org/a11y/atspi/accessible", "org.a11y.atspi.Event.Object", "ActiveDescendantChanged", MethodType::Method}] = + [wr](const MessagePtr &m) -> MessagePtr { + return wr->newReplyMessage(m); + }; + wr->testMethods[std::tuple{"/org/a11y/atspi/accessible", "org.a11y.atspi.Event.Object", "TextChanged", MethodType::Method}] = + [wr](const MessagePtr &m) -> MessagePtr { + return wr->newReplyMessage(m); + }; + wr->testMethods[std::tuple{"/org/a11y/atspi/accessible", "org.a11y.atspi.Event.Object", "TextCaretMoved", MethodType::Method}] = + [wr](const MessagePtr &m) -> MessagePtr { + return wr->newReplyMessage(m); + }; + wr->testMethods[std::tuple{"/org/a11y/atspi/accessible", "org.a11y.atspi.Event.Object", "MoveOuted", MethodType::Method}] = + [wr](const MessagePtr &m) -> MessagePtr { + gMoveOutedCalled = true; + return wr->newReplyMessage(m); + }; } -} + auto wr = static_cast(DBusWrapper::Installed()); + wr->fromTestChangeProperty("/org/a11y/bus", "org.a11y.Status", "ScreenReaderEnabled", b); + wr->fromTestChangeProperty("/org/a11y/bus", "org.a11y.Status", "IsEnabled", b); + } + + std::vector
TestGetChildren(const Address &adr) + { + auto wr = static_cast(DBusWrapper::Installed()); + auto chs = wr->fromTestCall>(adr.GetPath(), "org.a11y.atspi.Accessible", "GetChildren", std::tuple<>()); + return std::move(std::get<0>(chs)); + } + + std::string TestGetName(const Address &adr) + { + auto wr = static_cast(DBusWrapper::Installed()); + auto name = wr->fromTestGet(adr.GetPath(), "org.a11y.atspi.Accessible", "Name"); + return name; + } + + std::string TestGetDescription(const Address &adr) + { + auto wr = static_cast(DBusWrapper::Installed()); + auto description = wr->fromTestGet(adr.GetPath(), "org.a11y.atspi.Accessible", "Description"); + return description; + } + + uint32_t TestGetRole(const Address &adr) + { + auto wr = static_cast(DBusWrapper::Installed()); + auto chs = wr->fromTestCall(adr.GetPath(), "org.a11y.atspi.Accessible", "GetRole", std::tuple<>()); + return std::move(std::get<0>(chs)); + } + + std::string TestGetRoleName(const Address &adr) + { + auto wr = static_cast(DBusWrapper::Installed()); + auto chs = wr->fromTestCall(adr.GetPath(), "org.a11y.atspi.Accessible", "GetRoleName", std::tuple<>()); + return std::move(std::get<0>(chs)); + } + + Address TestGetParent(const Address &adr) + { + auto wr = static_cast(DBusWrapper::Installed()); + auto chs = wr->fromTestGet< Address >(adr.GetPath(), "org.a11y.atspi.Accessible", "Parent"); + return chs; + } + + std::string TestGetLocalizedRoleName(const Address &adr) + { + auto wr = static_cast(DBusWrapper::Installed()); + auto chs = wr->fromTestCall(adr.GetPath(), "org.a11y.atspi.Accessible", "GetLocalizedRoleName", std::tuple<>()); + return std::move(std::get<0>(chs)); + } + + std::array< uint32_t, 2 > TestGetStates(const Address &adr) + { + auto wr = static_cast(DBusWrapper::Installed()); + auto chs = wr->fromTestCall>(adr.GetPath(), "org.a11y.atspi.Accessible", "GetState", std::tuple<>()); + return std::move(std::get<0>(chs)); + } + + std::unordered_map< std::string, std::string > TestGetAttributes(const Address &adr) + { + auto wr = static_cast(DBusWrapper::Installed()); + auto chs = wr->fromTestCall>(adr.GetPath(), "org.a11y.atspi.Accessible", "GetAttributes", std::tuple<>()); + return std::move(std::get<0>(chs)); + } + + bool TestDoGesture(const Address &adr, Dali::Accessibility::Gesture type, int32_t xBeg, int32_t xEnd, int32_t yBeg, int32_t yEnd, Dali::Accessibility::GestureState state, uint32_t eventTime) + { + auto wr = static_cast(DBusWrapper::Installed()); + auto chs = wr->fromTestCall< bool >(adr.GetPath(), "org.a11y.atspi.Accessible", "DoGesture", + std::tuple< Dali::Accessibility::Gesture, int32_t, int32_t, int32_t, int32_t, Dali::Accessibility::GestureState, uint32_t >(type, xBeg, xEnd, yBeg, yEnd, state, eventTime )); + return std::move(std::get<0>(chs)); + } + + std::vector< std::tuple< uint32_t, std::vector< Dali::Accessibility::Address > > > TestGetRelationSet(const Address &adr) + { + auto wr = static_cast(DBusWrapper::Installed()); + auto chs = wr->fromTestCall< std::vector< std::tuple< uint32_t, std::vector< Dali::Accessibility::Address > > > >(adr.GetPath(), "org.a11y.atspi.Accessible", "GetRelationSet", std::tuple<>()); + return std::move(std::get<0>(chs)); + } + + Address TestGetChildAtIndex(const Address &adr, int index) + { + auto wr = static_cast(DBusWrapper::Installed()); + auto chs = wr->fromTestCall< Address >(adr.GetPath(), "org.a11y.atspi.Accessible", "GetChildAtIndex", std::tuple< int >( index )); + return std::move(std::get<0>(chs)); + } + + ComponentLayer TestGetLayer(const Address &adr) + { + auto wr = static_cast(DBusWrapper::Installed()); + auto chs = wr->fromTestCall< Dali::Accessibility::ComponentLayer >(adr.GetPath(), "org.a11y.atspi.Component", "GetLayer", std::tuple<>()); + return std::move(std::get<0>(chs)); + } + + int TestGetIndexInParent(const Address &adr) + { + auto wr = static_cast(DBusWrapper::Installed()); + auto chs = wr->fromTestCall< int >(adr.GetPath(), "org.a11y.atspi.Accessible", "GetIndexInParent", std::tuple<>()); + return std::move(std::get<0>(chs)); + } + + bool TestGrabFocus(const Address &adr) + { + auto wr = static_cast(DBusWrapper::Installed()); + auto chs = wr->fromTestCall< bool >(adr.GetPath(), "org.a11y.atspi.Component", "GrabFocus", std::tuple<>()); + return std::move(std::get<0>(chs)); + } + + bool TestGrabHighlight(const Address &adr) + { + auto wr = static_cast(DBusWrapper::Installed()); + auto chs = wr->fromTestCall< bool >(adr.GetPath(), "org.a11y.atspi.Component", "GrabHighlight", std::tuple<>()); + return std::move(std::get<0>(chs)); + } + + bool TestClearHighlight(const Address &adr) + { + auto wr = static_cast(DBusWrapper::Installed()); + auto chs = wr->fromTestCall< bool >(adr.GetPath(), "org.a11y.atspi.Component", "ClearHighlight", std::tuple<>()); + return std::move(std::get<0>(chs)); + } + + std::tuple< int32_t, int32_t, int32_t, int32_t > TestGetExtents(const Address &adr, Dali::Accessibility::CoordinateType coordinateType) + { + auto wr = static_cast(DBusWrapper::Installed()); + auto chs = wr->fromTestCall< std::tuple< int32_t, int32_t, int32_t, int32_t > >(adr.GetPath(), "org.a11y.atspi.Component", "GetExtents", std::make_tuple(static_cast(coordinateType))); + return std::move(std::get<0>(chs)); + } + + int TestGetMdiZOrder(const Address &adr) + { + auto wr = static_cast(DBusWrapper::Installed()); + auto chs = wr->fromTestCall< int16_t >(adr.GetPath(), "org.a11y.atspi.Component", "GetMDIZOrder", std::tuple<>()); + return std::move(std::get<0>(chs)); + } + + double TestGetAlpha(const Address &adr) + { + auto wr = static_cast(DBusWrapper::Installed()); + auto chs = wr->fromTestCall< double >(adr.GetPath(), "org.a11y.atspi.Component", "GetAlpha", std::tuple<>()); + return std::move(std::get<0>(chs)); + } + + std::string TestGetActionName(const Address &adr, size_t index) + { + auto wr = static_cast(DBusWrapper::Installed()); + auto chs = wr->fromTestCall< std::string >(adr.GetPath(), "org.a11y.atspi.Action", "GetName", std::tuple< int32_t >( index )); + return std::move(std::get<0>(chs)); + } + + std::string TestGetLocalizedActionName(const Address &adr, size_t index) + { + auto wr = static_cast(DBusWrapper::Installed()); + auto chs = wr->fromTestCall< std::string >(adr.GetPath(), "org.a11y.atspi.Action", "GetLocalizedName", std::tuple< int32_t >( index )); + return std::move(std::get<0>(chs)); + } + + size_t TestGetActionCount(const Address &adr) + { + auto wr = static_cast(DBusWrapper::Installed()); + auto count = wr->fromTestGet< int32_t >(adr.GetPath(), "org.a11y.atspi.Action", "NActions"); + return count; + } + + bool TestDoAction(const Address &adr, size_t index) + { + auto wr = static_cast(DBusWrapper::Installed()); + auto chs = wr->fromTestCall< bool >(adr.GetPath(), "org.a11y.atspi.Action", "DoAction", std::tuple< int32_t >( index )); + return std::move(std::get<0>(chs)); + } + + bool TestDoAction(const Address &adr, const std::string& name) + { + auto wr = static_cast(DBusWrapper::Installed()); + auto chs = wr->fromTestCall< bool >(adr.GetPath(), "org.a11y.atspi.Action", "DoActionName", std::tuple< std::string >( name )); + return std::move(std::get<0>(chs)); + } + + std::string TestGetActionKeyBinding(const Address &adr, size_t index) + { + auto wr = static_cast(DBusWrapper::Installed()); + auto chs = wr->fromTestCall< std::string >(adr.GetPath(), "org.a11y.atspi.Action", "GetKeyBinding", std::tuple< int32_t >( index )); + return std::move(std::get<0>(chs)); + } + + std::string TestGetActionDescription(const Address &adr, size_t index) + { + auto wr = static_cast(DBusWrapper::Installed()); + auto chs = wr->fromTestCall< std::string >(adr.GetPath(), "org.a11y.atspi.Action", "GetDescription", std::tuple< int32_t >( index )); + return std::move(std::get<0>(chs)); + } + + void TestResetMoveOutedCalled () + { + gMoveOutedCalled = false; + } + + bool TestGetMoveOutedCalled () + { + return gMoveOutedCalled; + } + + void PrintTree(const Address &root, size_t depth) + { + auto name = TestGetName(root); + printf("%10s", root.GetPath().c_str()); + for(unsigned int i = 0; i < depth; ++i) printf(" "); + printf("%s\n", name.c_str()); + auto chs = TestGetChildren(root); + for(auto &c : chs) + { + PrintTree(c, depth + 1); + } + } + + bool Find(const std::vector< std::string > &collection, const std::string &key) + { + for(auto& it : collection) + { + if(it == key) + { + return true; + } + } + return false; + } + +} // namespace Accessibility +} // namespace Dali diff --git a/automated-tests/src/dali-toolkit-internal/dali-toolkit-test-utils/accessibility-test-utils.h b/automated-tests/src/dali-toolkit-internal/dali-toolkit-test-utils/accessibility-test-utils.h index 6c172fd..92388e2 100644 --- a/automated-tests/src/dali-toolkit-internal/dali-toolkit-test-utils/accessibility-test-utils.h +++ b/automated-tests/src/dali-toolkit-internal/dali-toolkit-test-utils/accessibility-test-utils.h @@ -3,42 +3,43 @@ #include - -namespace Dali { - namespace Accessibility { - void TestEnableSC(bool b); - std::vector
TestGetChildren(const Address &adr); - std::string TestGetName(const Address &adr); - std::string TestGetDescription(const Address &adr); - uint32_t TestGetRole(const Address &adr); - std::string TestGetRoleName(const Address &adr); - Address TestGetParent(const Address &adr); - std::string TestGetLocalizedRoleName(const Address &adr); - std::array< uint32_t, 2 > TestGetStates(const Address &adr); - std::unordered_map< std::string, std::string > TestGetAttributes(const Address &adr); - bool TestDoGesture(const Address &adr, Dali::Accessibility::Gesture type, int32_t xBeg, int32_t xEnd, int32_t yBeg, int32_t yEnd, Dali::Accessibility::GestureState state, uint32_t eventTime); - std::vector< std::tuple< uint32_t, std::vector< Dali::Accessibility::Address > > > TestGetRelationSet(const Address &adr); - Address TestGetChildAtIndex(const Address &adr, int index); - ComponentLayer TestGetLayer(const Address &adr); - int TestGetIndexInParent(const Address &adr); - bool TestGrabFocus(const Address &adr); - bool TestGrabHighlight(const Address &adr); - bool TestClearHighlight(const Address &adr); - std::tuple< int32_t, int32_t, int32_t, int32_t > TestGetExtents(const Address &adr, Dali::Accessibility::CoordinateType coordinateType ); - int TestGetMdiZOrder(const Address &adr); - double TestGetAlpha(const Address &adr); - void printTree(const Address &root, size_t depth = 0); - bool Find( const std::vector< std::string > &collection, const std::string &key); - std::string TestGetActionName( const Address &adr, size_t index ); - std::string TestGetLocalizedActionName( const Address &adr, size_t index ); - size_t TestGetActionCount( const Address &adr ); - bool TestDoAction ( const Address &adr, size_t index ); - bool TestDoAction ( const Address &adr, const std::string& name ); - std::string TestGetActionKeyBinding ( const Address &adr, size_t index ); - std::string TestGetActionDescription ( const Address &adr, size_t index ); - void TestResetMoveOutedCalled (); - bool TestGetMoveOutedCalled (); - } -} +namespace Dali +{ +namespace Accessibility +{ + void TestEnableSC(bool b); + std::vector
TestGetChildren(const Address &adr); + std::string TestGetName(const Address &adr); + std::string TestGetDescription(const Address &adr); + uint32_t TestGetRole(const Address &adr); + std::string TestGetRoleName(const Address &adr); + Address TestGetParent(const Address &adr); + std::string TestGetLocalizedRoleName(const Address &adr); + std::array< uint32_t, 2 > TestGetStates(const Address &adr); + std::unordered_map< std::string, std::string > TestGetAttributes(const Address &adr); + bool TestDoGesture(const Address &adr, Dali::Accessibility::Gesture type, int32_t xBeg, int32_t xEnd, int32_t yBeg, int32_t yEnd, Dali::Accessibility::GestureState state, uint32_t eventTime); + std::vector< std::tuple< uint32_t, std::vector< Dali::Accessibility::Address > > > TestGetRelationSet(const Address &adr); + Address TestGetChildAtIndex(const Address &adr, int index); + ComponentLayer TestGetLayer(const Address &adr); + int TestGetIndexInParent(const Address &adr); + bool TestGrabFocus(const Address &adr); + bool TestGrabHighlight(const Address &adr); + bool TestClearHighlight(const Address &adr); + std::tuple< int32_t, int32_t, int32_t, int32_t > TestGetExtents(const Address &adr, Dali::Accessibility::CoordinateType coordinateType ); + int TestGetMdiZOrder(const Address &adr); + double TestGetAlpha(const Address &adr); + void PrintTree(const Address &root, size_t depth = 0); + bool Find( const std::vector< std::string > &collection, const std::string &key); + std::string TestGetActionName( const Address &adr, size_t index ); + std::string TestGetLocalizedActionName( const Address &adr, size_t index ); + size_t TestGetActionCount( const Address &adr ); + bool TestDoAction ( const Address &adr, size_t index ); + bool TestDoAction ( const Address &adr, const std::string& name ); + std::string TestGetActionKeyBinding ( const Address &adr, size_t index ); + std::string TestGetActionDescription ( const Address &adr, size_t index ); + void TestResetMoveOutedCalled (); + bool TestGetMoveOutedCalled (); +} // namespace Accessibility +} // namespace Dali #endif //__DALI_TOOLKIT_ACCESSIBILITY_TEST_UTILS__ diff --git a/automated-tests/src/dali-toolkit-internal/utc-Dali-Accessibility-Controls-BridgeUp.cpp b/automated-tests/src/dali-toolkit-internal/utc-Dali-Accessibility-Controls-BridgeUp.cpp index 0b1ec0e..047018d 100644 --- a/automated-tests/src/dali-toolkit-internal/utc-Dali-Accessibility-Controls-BridgeUp.cpp +++ b/automated-tests/src/dali-toolkit-internal/utc-Dali-Accessibility-Controls-BridgeUp.cpp @@ -1157,6 +1157,7 @@ int UtcDaliAccessibilityScrollToChildNonScrollable(void) DALI_TEST_EQUALS(accessible->IsScrollable(), false, TEST_LOCATION); DALI_TEST_EQUALS(accessible->ScrollToChild({}), false, TEST_LOCATION); + DALI_TEST_EQUALS(accessible->GetInternalActor(), Dali::Actor{}, TEST_LOCATION); Dali::Accessibility::TestEnableSC( false ); END_TEST; diff --git a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-application.cpp b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-application.cpp index 5e69c95..440270a 100644 --- a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-application.cpp +++ b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-application.cpp @@ -19,6 +19,8 @@ namespace Dali { +const Rect TestApplication::DEFAULT_SURFACE_RECT = Rect(0, 0, TestApplication::DEFAULT_SURFACE_WIDTH, TestApplication::DEFAULT_SURFACE_HEIGHT); + bool TestApplication::mLoggingEnabled = true; TestApplication::TestApplication(uint32_t surfaceWidth, @@ -225,7 +227,7 @@ bool TestApplication::PreRenderWithPartialUpdate(uint32_t intervalMilliseconds, bool TestApplication::RenderWithPartialUpdate(std::vector>& damagedRects, Rect& clippingRect) { - mCore->RenderScene(mRenderStatus, mScene, true /*render the off-screen buffers*/, clippingRect); + mCore->RenderScene(mRenderStatus, mScene, true /*render the off-screen buffers*/); mCore->RenderScene(mRenderStatus, mScene, false /*render the surface*/, clippingRect); mCore->PostRender(false /*do not skip rendering*/); diff --git a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-application.h b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-application.h index 4f32cd8..02143a7 100644 --- a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-application.h +++ b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-application.h @@ -38,6 +38,8 @@ public: static const uint32_t DEFAULT_SURFACE_WIDTH = 480; static const uint32_t DEFAULT_SURFACE_HEIGHT = 800; + static const Rect DEFAULT_SURFACE_RECT; + static constexpr uint32_t DEFAULT_HORIZONTAL_DPI = 220; static constexpr uint32_t DEFAULT_VERTICAL_DPI = 217; diff --git a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-canvas-renderer.cpp b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-canvas-renderer.cpp index 56c0cd8..43aa8ce 100644 --- a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-canvas-renderer.cpp +++ b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-canvas-renderer.cpp @@ -39,7 +39,7 @@ class CanvasRenderer: public Dali::BaseObject public: CanvasRenderer( const Vector2& size ) : mDrawable(nullptr), - mPixelBuffer( Devel::PixelBuffer::New(size.width, size.height, Dali::Pixel::RGBA8888) ), + mTexture ( Dali::Texture::New( Dali::TextureType::TEXTURE_2D, Pixel::RGBA8888, size.width, size.height ) ), mSize(size), mViewBox(size) { @@ -59,6 +59,11 @@ public: return true; } + Dali::Texture GetRasterizedTexture() + { + return mTexture; + } + bool Rasterize() { return true; @@ -97,12 +102,6 @@ public: return false; } - Devel::PixelBuffer GetPixelBuffer() - { - return mPixelBuffer; - } - - bool SetSize(Vector2 size) { mSize = size; @@ -137,7 +136,7 @@ public: public: Dali::CanvasRenderer::Drawable* mDrawable; - Devel::PixelBuffer mPixelBuffer; + Dali::Texture mTexture; Vector2 mSize; Vector2 mViewBox; }; @@ -200,9 +199,9 @@ bool CanvasRenderer::Rasterize() return Internal::Adaptor::GetImplementation(*this).Rasterize(); } -Devel::PixelBuffer CanvasRenderer::GetPixelBuffer() +Dali::Texture CanvasRenderer::GetRasterizedTexture() { - return Internal::Adaptor::GetImplementation(*this).GetPixelBuffer(); + return Internal::Adaptor::GetImplementation(*this).GetRasterizedTexture(); } bool CanvasRenderer::AddDrawable(Dali::CanvasRenderer::Drawable& drawable) diff --git a/automated-tests/src/dali-toolkit/utc-Dali-AnimatedVectorImageVisual.cpp b/automated-tests/src/dali-toolkit/utc-Dali-AnimatedVectorImageVisual.cpp index 7f43240..1eb713e 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-AnimatedVectorImageVisual.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-AnimatedVectorImageVisual.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -707,7 +708,7 @@ int UtcDaliAnimatedVectorImageVisualPlayRange(void) attributes.Clear(); attributes.Add( DevelImageVisual::Property::PLAY_RANGE, array ); - DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedVectorImageVisual::Action::UPDATE_PROPERTY, attributes ); + DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelVisual::Action::UPDATE_PROPERTY, attributes ); application.SendNotification(); application.Render(); @@ -746,7 +747,7 @@ int UtcDaliAnimatedVectorImageVisualPlayRange(void) attributes.Clear(); attributes.Add( DevelImageVisual::Property::PLAY_RANGE, array ); - DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedVectorImageVisual::Action::UPDATE_PROPERTY, attributes ); + DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelVisual::Action::UPDATE_PROPERTY, attributes ); application.SendNotification(); application.Render(); @@ -825,7 +826,7 @@ int UtcDaliAnimatedVectorImageVisualPlayRangeMarker(void) attributes.Clear(); attributes.Add( DevelImageVisual::Property::PLAY_RANGE, array ); - DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedVectorImageVisual::Action::UPDATE_PROPERTY, attributes ); + DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelVisual::Action::UPDATE_PROPERTY, attributes ); application.SendNotification(); application.Render(); @@ -849,7 +850,7 @@ int UtcDaliAnimatedVectorImageVisualPlayRangeMarker(void) attributes.Clear(); attributes.Add( DevelImageVisual::Property::PLAY_RANGE, array ); - DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedVectorImageVisual::Action::UPDATE_PROPERTY, attributes ); + DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelVisual::Action::UPDATE_PROPERTY, attributes ); application.SendNotification(); application.Render(); @@ -956,7 +957,7 @@ int UtcDaliAnimatedVectorImageVisualJumpTo(void) Property::Map attributes; attributes.Add( DevelImageVisual::Property::PLAY_RANGE, array ); - DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedVectorImageVisual::Action::UPDATE_PROPERTY, attributes ); + DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelVisual::Action::UPDATE_PROPERTY, attributes ); DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedVectorImageVisual::Action::JUMP_TO, 3 ); @@ -979,7 +980,7 @@ int UtcDaliAnimatedVectorImageVisualJumpTo(void) array.PushBack( 4 ); attributes.Add( DevelImageVisual::Property::PLAY_RANGE, array ); - DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedVectorImageVisual::Action::UPDATE_PROPERTY, attributes ); + DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelVisual::Action::UPDATE_PROPERTY, attributes ); attributes.Clear(); DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedVectorImageVisual::Action::PLAY, attributes ); @@ -1074,7 +1075,7 @@ int UtcDaliAnimatedVectorImageVisualUpdateProperty(void) attributes.Add( DevelImageVisual::Property::PLAY_RANGE, playRange ); attributes.Add( DevelImageVisual::Property::LOOP_COUNT, 5 ); - DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedVectorImageVisual::Action::UPDATE_PROPERTY, attributes ); + DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelVisual::Action::UPDATE_PROPERTY, attributes ); application.SendNotification(); application.Render(); @@ -1100,7 +1101,7 @@ int UtcDaliAnimatedVectorImageVisualUpdateProperty(void) attributes.Add( DevelImageVisual::Property::PLAY_RANGE, playRange ); - DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedVectorImageVisual::Action::UPDATE_PROPERTY, attributes ); + DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelVisual::Action::UPDATE_PROPERTY, attributes ); application.SendNotification(); application.Render(); @@ -1125,7 +1126,7 @@ int UtcDaliAnimatedVectorImageVisualUpdateProperty(void) attributes.Add( DevelImageVisual::Property::LOOP_COUNT, 10 ); - DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedVectorImageVisual::Action::UPDATE_PROPERTY, attributes ); + DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelVisual::Action::UPDATE_PROPERTY, attributes ); application.SendNotification(); application.Render(); @@ -1176,7 +1177,7 @@ int UtcDaliAnimatedVectorImageVisualStopBehavior(void) // Change stop behavior attributes.Add( DevelImageVisual::Property::STOP_BEHAVIOR, DevelImageVisual::StopBehavior::LAST_FRAME ); - DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedVectorImageVisual::Action::UPDATE_PROPERTY, attributes ); + DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelVisual::Action::UPDATE_PROPERTY, attributes ); attributes.Clear(); @@ -1201,7 +1202,7 @@ int UtcDaliAnimatedVectorImageVisualStopBehavior(void) attributes.Add( DevelImageVisual::Property::STOP_BEHAVIOR, DevelImageVisual::StopBehavior::CURRENT_FRAME ); attributes.Add( DevelImageVisual::Property::LOOP_COUNT, -1 ); - DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedVectorImageVisual::Action::UPDATE_PROPERTY, attributes ); + DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelVisual::Action::UPDATE_PROPERTY, attributes ); attributes.Clear(); @@ -1271,7 +1272,7 @@ int UtcDaliAnimatedVectorImageVisualLoopingMode(void) // Change stop behavior attributes.Add( DevelImageVisual::Property::STOP_BEHAVIOR, DevelImageVisual::StopBehavior::CURRENT_FRAME ); - DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedVectorImageVisual::Action::UPDATE_PROPERTY, attributes ); + DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelVisual::Action::UPDATE_PROPERTY, attributes ); // Play again DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedVectorImageVisual::Action::PLAY, attributes ); @@ -1289,7 +1290,7 @@ int UtcDaliAnimatedVectorImageVisualLoopingMode(void) // Change looping mode attributes.Add( DevelImageVisual::Property::LOOPING_MODE, DevelImageVisual::LoopingMode::RESTART ); - DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedVectorImageVisual::Action::UPDATE_PROPERTY, attributes ); + DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelVisual::Action::UPDATE_PROPERTY, attributes ); // Play again DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedVectorImageVisual::Action::PLAY, attributes ); @@ -1418,8 +1419,8 @@ int UtcDaliAnimatedVectorImageVisualMultipleInstances(void) Property::Map attributes; attributes.Add( DevelImageVisual::Property::STOP_BEHAVIOR, DevelImageVisual::StopBehavior::LAST_FRAME ); - DevelControl::DoAction( actor1, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedVectorImageVisual::Action::UPDATE_PROPERTY, attributes ); - DevelControl::DoAction( actor2, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedVectorImageVisual::Action::UPDATE_PROPERTY, attributes ); + DevelControl::DoAction( actor1, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelVisual::Action::UPDATE_PROPERTY, attributes ); + DevelControl::DoAction( actor2, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelVisual::Action::UPDATE_PROPERTY, attributes ); DevelControl::DoAction( actor1, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedVectorImageVisual::Action::PLAY, Property::Map() ); diff --git a/automated-tests/src/dali-toolkit/utc-Dali-ArcVisual.cpp b/automated-tests/src/dali-toolkit/utc-Dali-ArcVisual.cpp index 583ce16..146a1b5 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-ArcVisual.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-ArcVisual.cpp @@ -22,7 +22,7 @@ #include #include #include -#include +#include #include #include "dummy-control.h" @@ -307,7 +307,7 @@ int UtcDaliArcVisualUpdateProperty(void) .Add( DevelArcVisual::Property::START_ANGLE, startAngle ) .Add( DevelArcVisual::Property::SWEEP_ANGLE, sweepAngle ); - DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelArcVisual::Action::UPDATE_PROPERTY, attributes ); + DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelVisual::Action::UPDATE_PROPERTY, attributes ); application.SendNotification(); application.Render(); diff --git a/automated-tests/src/dali-toolkit/utc-Dali-CanvasView.cpp b/automated-tests/src/dali-toolkit/utc-Dali-CanvasView.cpp index 36cf1df..cee41e0 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-CanvasView.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-CanvasView.cpp @@ -302,42 +302,6 @@ int UtcDaliCanvasViewRasterizeTaskGetCanvasViewP(void) END_TEST; } -int UtcDaliCanvasViewRasterizeTaskGetBufferSizeP(void) -{ - ToolkitTestApplication application; - - Dali::Toolkit::Internal::CanvasView* dummyInternalCanvasView = new Dali::Toolkit::Internal::CanvasView(Vector2(100,100)); - DALI_TEST_CHECK( dummyInternalCanvasView ); - - Dali::CanvasRenderer dummyCanvasRenderer = Dali::CanvasRenderer::New(Vector2(100, 100)); - DALI_TEST_CHECK( dummyCanvasRenderer ); - - IntrusivePtr task = new Dali::Toolkit::Internal::CanvasRendererRasterizingTask(dummyInternalCanvasView, dummyCanvasRenderer); - DALI_TEST_CHECK( task ); - - //There is no rasterized buffer. - DALI_TEST_EQUALS( task->GetBufferSize(), Vector2(0, 0), TEST_LOCATION ); - - END_TEST; -} - -int UtcDaliCanvasViewRasterizeTaskGetPixelDataP(void) -{ - - Dali::Toolkit::Internal::CanvasView* dummyInternalCanvasView = new Dali::Toolkit::Internal::CanvasView(Vector2(100,100)); - DALI_TEST_CHECK( dummyInternalCanvasView ); - - Dali::CanvasRenderer dummyCanvasRenderer = Dali::CanvasRenderer::New(Vector2(100, 100)); - DALI_TEST_CHECK( dummyCanvasRenderer ); - - IntrusivePtr task = new Dali::Toolkit::Internal::CanvasRendererRasterizingTask(dummyInternalCanvasView, dummyCanvasRenderer); - DALI_TEST_CHECK( task ); - - DALI_TEST_EQUALS( task->GetPixelData(), PixelData(), TEST_LOCATION ); - - END_TEST; -} - int UtcDaliCanvasViewRasterizeThreadP(void) { ToolkitTestApplication application; @@ -488,13 +452,13 @@ int UtcDaliCanvasViewRasterizeThreadRasterizationCompletedSignalP(void) { ToolkitTestApplication application; - Dali::Toolkit::Internal::CanvasView* dummyInternalCanvasView = new Dali::Toolkit::Internal::CanvasView(Vector2(100,100)); - DALI_TEST_CHECK( dummyInternalCanvasView ); + Dali::Toolkit::CanvasView canvasView = Dali::Toolkit::CanvasView::New(Vector2(100, 100)); + Dali::Toolkit::Internal::CanvasView& dummyInternalCanvasView = GetImpl(canvasView); Dali::CanvasRenderer dummyCanvasRenderer = Dali::CanvasRenderer::New(Vector2(100, 100)); DALI_TEST_CHECK( dummyCanvasRenderer ); - IntrusivePtr task = new Dali::Toolkit::Internal::CanvasRendererRasterizingTask(dummyInternalCanvasView, dummyCanvasRenderer); + IntrusivePtr task = new Dali::Toolkit::Internal::CanvasRendererRasterizingTask(&dummyInternalCanvasView, dummyCanvasRenderer); DALI_TEST_CHECK( task ); Dali::Toolkit::Internal::CanvasViewRasterizeThread *dummyThread = new Dali::Toolkit::Internal::CanvasViewRasterizeThread(); @@ -504,10 +468,10 @@ int UtcDaliCanvasViewRasterizeThreadRasterizationCompletedSignalP(void) dummyThread->Process(false); - PixelData pixelData = CreatePixelData( 100, 100 ); + auto texture = Texture::New( Dali::TextureType::TEXTURE_2D, Pixel::RGBA8888, 100, 100 ); - dummyThread->RasterizationCompletedSignal().Connect(dummyInternalCanvasView, &Dali::Toolkit::Internal::CanvasView::ApplyRasterizedImage); - dummyThread->RasterizationCompletedSignal().Emit(pixelData); + dummyThread->RasterizationCompletedSignal().Connect(&dummyInternalCanvasView, &Dali::Toolkit::Internal::CanvasView::ApplyRasterizedImage); + dummyThread->RasterizationCompletedSignal().Emit(texture); application.SendNotification(); application.Render(); diff --git a/automated-tests/src/dali-toolkit/utc-Dali-GlView.cpp b/automated-tests/src/dali-toolkit/utc-Dali-GlView.cpp index 9f74b72..9cefe16 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-GlView.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-GlView.cpp @@ -181,15 +181,15 @@ void resizeCB(Vector2 size) { } -int UtcDaliGlViewRegisterGlCallbackN(void) +int UtcDaliGlViewRegisterGlCallbacksN(void) { ToolkitTestApplication application; - tet_infoline("UtcDaliGlViewRegisterGlCallback"); + tet_infoline("UtcDaliGlViewRegisterGlCallbacksN"); GlView view; try { - view.RegisterGlCallback(Dali::MakeCallback(glInit), Dali::MakeCallback(glRenderFrame), Dali::MakeCallback(glTerminate)); + view.RegisterGlCallbacks(Dali::MakeCallback(glInit), Dali::MakeCallback(glRenderFrame), Dali::MakeCallback(glTerminate)); DALI_TEST_CHECK(false); } catch(...) @@ -243,7 +243,7 @@ int UtcDaliGlViewWindowVisibilityChanged(void) application.GetScene().Add( view ); view.SetRenderingMode(GlView::RenderingMode::CONTINUOUS); view.SetGraphicsConfig(true, true, 0, GlView::GraphicsApiVersion::GLES_VERSION_2_0); - view.RegisterGlCallback(Dali::MakeCallback(glInit), Dali::MakeCallback(glRenderFrame), Dali::MakeCallback(glTerminate)); + view.RegisterGlCallbacks(Dali::MakeCallback(glInit), Dali::MakeCallback(glRenderFrame), Dali::MakeCallback(glTerminate)); view.SetResizeCallback(Dali::MakeCallback(resizeCB)); application.SendNotification(); @@ -268,7 +268,7 @@ int UtcDaliGlViewOnScene(void) application.GetScene().Add( view ); view.SetRenderingMode(GlView::RenderingMode::CONTINUOUS); view.SetGraphicsConfig(true, true, 0, GlView::GraphicsApiVersion::GLES_VERSION_2_0); - view.RegisterGlCallback(Dali::MakeCallback(glInit), Dali::MakeCallback(glRenderFrame), Dali::MakeCallback(glTerminate)); + view.RegisterGlCallbacks(Dali::MakeCallback(glInit), Dali::MakeCallback(glRenderFrame), Dali::MakeCallback(glTerminate)); application.SendNotification(); application.Render(); @@ -314,7 +314,7 @@ int UtcDaliGlViewResize(void) application.GetScene().Add( view ); view.SetGraphicsConfig(true, true, 0, GlView::GraphicsApiVersion::GLES_VERSION_2_0); - view.RegisterGlCallback(Dali::MakeCallback(glInit), Dali::MakeCallback(glRenderFrame), Dali::MakeCallback(glTerminate)); + view.RegisterGlCallbacks(Dali::MakeCallback(glInit), Dali::MakeCallback(glRenderFrame), Dali::MakeCallback(glTerminate)); view.SetResizeCallback(Dali::MakeCallback(resizeCB)); view.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT); view.SetProperty(Actor::Property::SIZE, Vector2(360.0f, 360.0f)); diff --git a/automated-tests/src/dali-toolkit/utc-Dali-TextLabel.cpp b/automated-tests/src/dali-toolkit/utc-Dali-TextLabel.cpp index 5495c9d..c9453e1 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-TextLabel.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-TextLabel.cpp @@ -836,6 +836,13 @@ int UtcDaliToolkitTextLabelEmojisP(void) application.SendNotification(); application.Render(); + // EMOJI + ZWJ + EMOJI case for coverage. + const std::string emojiWithZWJ = "👩‍🔬"; + label.SetProperty( TextLabel::Property::TEXT, emojiWithZWJ ); + + application.SendNotification(); + application.Render(); + END_TEST; } diff --git a/automated-tests/src/dali-toolkit/utc-Dali-Transition.cpp b/automated-tests/src/dali-toolkit/utc-Dali-Transition.cpp index 7e36d2c..0ead710 100755 --- a/automated-tests/src/dali-toolkit/utc-Dali-Transition.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-Transition.cpp @@ -24,6 +24,8 @@ #include #include #include +#include +#include using namespace Dali; using namespace Dali::Toolkit; @@ -118,7 +120,7 @@ int UtcDaliTransitionSetGetProperty01(void) application.SendNotification(); application.Render(20); - Transition transition = Transition::New(control1, control2, TimePeriod(-0.1f, -0.1f)); + Transition transition = Transition::New(control1, control2, true, TimePeriod(-0.1f, -0.1f)); TimePeriod timePeriod = transition.GetTimePeriod(); DALI_TEST_EQUALS(0.0f, timePeriod.durationSeconds, TEST_LOCATION); DALI_TEST_EQUALS(0.0f, timePeriod.delaySeconds, TEST_LOCATION); @@ -178,7 +180,7 @@ int UtcDaliTransitionSetGetProperty02(void) application.SendNotification(); application.Render(20); - Transition transition = Transition::New(control1, control2, TimePeriod(-0.1f)); + Transition transition = Transition::New(control1, control2, true, TimePeriod(-0.1f)); TimePeriod timePeriod = transition.GetTimePeriod(); DALI_TEST_EQUALS(0.0f, timePeriod.durationSeconds, TEST_LOCATION); DALI_TEST_EQUALS(0.0f, timePeriod.delaySeconds, TEST_LOCATION); @@ -268,7 +270,7 @@ int UtcDaliTransitionBetweenControlPair(void) application.SendNotification(); application.Render(20); - Transition transition = Transition::New(control1, control2, TimePeriod(0.5f)); + Transition transition = Transition::New(control1, control2, true, TimePeriod(0.5f)); TransitionSet transitionSet = TransitionSet::New(); transitionSet.AddTransition(transition); transitionSet.Play(); @@ -333,6 +335,185 @@ int UtcDaliTransitionBetweenControlPair(void) END_TEST; } +int UtcDaliTransitionBetweenControlPair2(void) +{ + ToolkitTestApplication application; + tet_infoline(" UtcDaliTransitionBetweenControlPair2 - source target will be transitioned."); + + Vector3 sourcePosition(100, 200, 0); + Vector3 sourceSize(150, 150, 0); + Vector3 sourceScale(1, 2, 0); + Vector4 sourceColor(1.0f, 1.0f, 1.0f, 0.5f); + float sourceOpacity(0.5f); + float sourceRadius(30.f); + float sourceBorderlineWidth(60.0f); + Vector4 sourceBorderlineColor(1.0f, 0.0f, 0.0f, 1.0f); + float sourceBorderlineOffset(1.f); + Vector4 sourceRadiusV4 = Vector4(sourceRadius, sourceRadius, sourceRadius, sourceRadius); + + Vector3 destinationPosition(50, 50, 0); + Vector3 destinationSize(120, 120, 0); + Vector3 destinationScale(2, 1, 0); + Vector4 destinationColor(1.0f, 0.5f, 1.0f, 0.8f); + float destinationOpacity(0.8f); + float destinationRadius(50.f); + float destinationBorderlineWidth(80.0f); + Vector4 destinationBorderlineColor(0.5f, 1.0f, 0.5f, 0.3f); + float destinationBorderlineOffset(-1.0f); + Vector4 destinationRadiusV4 = Vector4(destinationRadius, destinationRadius, destinationRadius, destinationRadius); + + Control control1 = Control::New(); + control1.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER); + control1.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER); + control1.SetProperty(Actor::Property::POSITION, sourcePosition); + control1.SetProperty(Actor::Property::SIZE, sourceSize); + control1.SetProperty(Actor::Property::SCALE, sourceScale); + control1.SetProperty(Actor::Property::COLOR, sourceColor); + control1.SetProperty(Actor::Property::OPACITY, sourceOpacity); + Property::Map controlProperty1; + controlProperty1.Insert(Toolkit::Visual::Property::TYPE, Toolkit::Visual::COLOR); + controlProperty1.Insert(Toolkit::ColorVisual::Property::MIX_COLOR, Vector4(1.0f, 0.0f, 0.0f, 1.0f)); + controlProperty1.Insert(Toolkit::DevelVisual::Property::CORNER_RADIUS, sourceRadius); + controlProperty1.Insert(Toolkit::DevelVisual::Property::BORDERLINE_WIDTH, sourceBorderlineWidth); + controlProperty1.Insert(Toolkit::DevelVisual::Property::BORDERLINE_COLOR, sourceBorderlineColor); + controlProperty1.Insert(Toolkit::DevelVisual::Property::BORDERLINE_OFFSET, sourceBorderlineOffset); + control1.SetProperty(Toolkit::Control::Property::BACKGROUND, controlProperty1); + + Control control2 = Control::New(); + control2.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER); + control2.SetProperty(Actor::Property::ANCHOR_POINT, ParentOrigin::CENTER); + control2.SetProperty(Actor::Property::POSITION, destinationPosition); + control2.SetProperty(Actor::Property::SIZE, destinationSize); + control2.SetProperty(Actor::Property::SCALE, destinationScale); + control2.SetProperty(Actor::Property::COLOR, destinationColor); + control2.SetProperty(Actor::Property::OPACITY, destinationOpacity); + Property::Map controlProperty2; + controlProperty2.Insert(Toolkit::Visual::Property::TYPE, Toolkit::Visual::COLOR); + controlProperty2.Insert(Toolkit::ColorVisual::Property::MIX_COLOR, Vector4(1.0f, 1.0f, 0.0f, 0.5f)); + controlProperty2.Insert(Toolkit::DevelVisual::Property::CORNER_RADIUS, destinationRadius); + controlProperty2.Insert(Toolkit::DevelVisual::Property::BORDERLINE_WIDTH, destinationBorderlineWidth); + controlProperty2.Insert(Toolkit::DevelVisual::Property::BORDERLINE_COLOR, destinationBorderlineColor); + controlProperty2.Insert(Toolkit::DevelVisual::Property::BORDERLINE_OFFSET, destinationBorderlineOffset); + control2.SetProperty(Toolkit::Control::Property::BACKGROUND, controlProperty2); + + DALI_TEST_EQUALS(destinationPosition, control2.GetProperty(Actor::Property::POSITION), TEST_LOCATION); + Property::Map backgroundMap = control2.GetProperty(Toolkit::Control::Property::BACKGROUND); + Vector4 cornerRadius = backgroundMap.Find(Toolkit::DevelVisual::Property::CORNER_RADIUS)->Get(); + DALI_TEST_EQUALS(destinationRadiusV4, cornerRadius, TEST_LOCATION); + float borderlineWidth = backgroundMap.Find(Toolkit::DevelVisual::Property::BORDERLINE_WIDTH)->Get(); + DALI_TEST_EQUALS(destinationBorderlineWidth, borderlineWidth, TEST_LOCATION); + Vector4 borderlineColor = backgroundMap.Find(Toolkit::DevelVisual::Property::BORDERLINE_COLOR)->Get(); + DALI_TEST_EQUALS(destinationBorderlineColor, borderlineColor, TEST_LOCATION); + float borderlineOffset = backgroundMap.Find(Toolkit::DevelVisual::Property::BORDERLINE_OFFSET)->Get(); + DALI_TEST_EQUALS(destinationBorderlineOffset, borderlineOffset, TEST_LOCATION); + + application.GetScene().Add(control1); + application.GetScene().Add(control2); + + application.SendNotification(); + application.Render(20); + + Transition transition = Transition::New(control1, control2, false, TimePeriod(0.5f)); + TransitionSet transitionSet = TransitionSet::New(); + transitionSet.AddTransition(transition); + transitionSet.Play(); + + bool signalReceived(false); + TransitionFinishCheck finishCheck(signalReceived); + transitionSet.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(50); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + + DALI_TEST_NOT_EQUALS(destinationPosition, control1.GetCurrentProperty(Actor::Property::POSITION), 0.00001f, TEST_LOCATION); + DALI_TEST_EQUALS(1, control1.GetRendererCount(), TEST_LOCATION); + + Dali::Renderer renderer = control1.GetRendererAt(0); + Property::Index index = renderer.GetPropertyIndex(DevelVisual::Property::CORNER_RADIUS); + cornerRadius = renderer.GetCurrentProperty(index); + DALI_TEST_NOT_EQUALS(destinationRadiusV4, cornerRadius, 0.00001f, TEST_LOCATION); + + index = renderer.GetPropertyIndex(DevelVisual::Property::BORDERLINE_WIDTH); + borderlineWidth = renderer.GetCurrentProperty(index); + DALI_TEST_NOT_EQUALS(destinationBorderlineWidth, borderlineWidth, 0.00001f, TEST_LOCATION); + + index = renderer.GetPropertyIndex(DevelVisual::Property::BORDERLINE_COLOR); + borderlineColor = renderer.GetCurrentProperty(index); + DALI_TEST_NOT_EQUALS(destinationBorderlineColor, borderlineColor, 0.00001f, TEST_LOCATION); + + index = renderer.GetPropertyIndex(DevelVisual::Property::BORDERLINE_OFFSET); + borderlineOffset = renderer.GetCurrentProperty(index); + DALI_TEST_NOT_EQUALS(destinationBorderlineOffset, borderlineOffset, 0.00001f, TEST_LOCATION); + + application.SendNotification(); + application.Render(700); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + + // After the transition is finished, + // every current and renderer propeties of control1 are equal to destination properties. + DALI_TEST_EQUALS(destinationPosition, control1.GetCurrentProperty(Actor::Property::POSITION), TEST_LOCATION); + DALI_TEST_EQUALS(destinationSize, control1.GetCurrentProperty(Actor::Property::SIZE), TEST_LOCATION); + DALI_TEST_EQUALS(destinationScale, control1.GetCurrentProperty(Actor::Property::SCALE), TEST_LOCATION); + DALI_TEST_EQUALS(destinationColor, control1.GetCurrentProperty(Actor::Property::COLOR), TEST_LOCATION); + DALI_TEST_EQUALS(destinationOpacity, control1.GetCurrentProperty(Actor::Property::OPACITY), TEST_LOCATION); + + DALI_TEST_EQUALS(1, control1.GetRendererCount(), TEST_LOCATION); + renderer = control1.GetRendererAt(0); + index = renderer.GetPropertyIndex(DevelVisual::Property::CORNER_RADIUS); + cornerRadius = renderer.GetCurrentProperty(index); + DALI_TEST_EQUALS(destinationRadiusV4, cornerRadius, TEST_LOCATION); + + index = renderer.GetPropertyIndex(DevelVisual::Property::BORDERLINE_WIDTH); + borderlineWidth = renderer.GetCurrentProperty(index); + DALI_TEST_EQUALS(destinationBorderlineWidth, borderlineWidth, TEST_LOCATION); + + index = renderer.GetPropertyIndex(DevelVisual::Property::BORDERLINE_COLOR); + borderlineColor = renderer.GetCurrentProperty(index); + DALI_TEST_EQUALS(destinationBorderlineColor, borderlineColor, TEST_LOCATION); + + index = renderer.GetPropertyIndex(DevelVisual::Property::BORDERLINE_OFFSET); + borderlineOffset = renderer.GetCurrentProperty(index); + DALI_TEST_EQUALS(destinationBorderlineOffset, borderlineOffset, TEST_LOCATION); + + // every actor properties of control1 are returned to the source properties. + DALI_TEST_EQUALS(sourcePosition, control1.GetProperty(Actor::Property::POSITION), TEST_LOCATION); + DALI_TEST_EQUALS(sourceSize, control1.GetProperty(Actor::Property::SIZE), TEST_LOCATION); + DALI_TEST_EQUALS(sourceScale, control1.GetProperty(Actor::Property::SCALE), TEST_LOCATION); + DALI_TEST_EQUALS(sourceColor, control1.GetProperty(Actor::Property::COLOR), TEST_LOCATION); + DALI_TEST_EQUALS(sourceOpacity, control1.GetProperty(Actor::Property::OPACITY), TEST_LOCATION); + + application.SendNotification(); + application.Render(20); + + // after next update, renderer properties are returned to the source properties. + DALI_TEST_EQUALS(1, control1.GetRendererCount(), TEST_LOCATION); + renderer = control1.GetRendererAt(0); + index = renderer.GetPropertyIndex(DevelVisual::Property::CORNER_RADIUS); + cornerRadius = renderer.GetCurrentProperty(index); + DALI_TEST_EQUALS(sourceRadiusV4, cornerRadius, TEST_LOCATION); + + index = renderer.GetPropertyIndex(DevelVisual::Property::BORDERLINE_WIDTH); + borderlineWidth = renderer.GetCurrentProperty(index); + DALI_TEST_EQUALS(sourceBorderlineWidth, borderlineWidth, TEST_LOCATION); + + index = renderer.GetPropertyIndex(DevelVisual::Property::BORDERLINE_COLOR); + borderlineColor = renderer.GetCurrentProperty(index); + DALI_TEST_EQUALS(sourceBorderlineColor, borderlineColor, TEST_LOCATION); + + index = renderer.GetPropertyIndex(DevelVisual::Property::BORDERLINE_OFFSET); + borderlineOffset = renderer.GetCurrentProperty(index); + DALI_TEST_EQUALS(sourceBorderlineOffset, borderlineOffset, TEST_LOCATION); + + END_TEST; +} + int UtcDaliTransitionBetweenControlPairWithoutEmptySourceBackground(void) { ToolkitTestApplication application; @@ -377,7 +558,7 @@ int UtcDaliTransitionBetweenControlPairWithoutEmptySourceBackground(void) application.SendNotification(); application.Render(20); - Transition transition = Transition::New(control1, control2, TimePeriod(0.5f)); + Transition transition = Transition::New(control1, control2, true, TimePeriod(0.5f)); TransitionSet transitionSet = TransitionSet::New(); transitionSet.AddTransition(transition); transitionSet.Play(); @@ -474,7 +655,7 @@ int UtcDaliTransitionBetweenImageViewPair(void) Vector3 startWorldPosition = control1.GetProperty(Actor::Property::WORLD_POSITION); Vector3 finishWorldPosition = control2.GetProperty(Actor::Property::WORLD_POSITION); - Transition transition = Transition::New(control1, control2, TimePeriod(0.5f)); + Transition transition = Transition::New(control1, control2, true, TimePeriod(0.5f)); TransitionSet transitionSet = TransitionSet::New(); transitionSet.AddTransition(transition); transitionSet.Play(); @@ -562,7 +743,7 @@ int UtcDaliTransitionBetweenImageViewPairWithDelay(void) Vector3 startWorldPosition = control1.GetProperty(Actor::Property::WORLD_POSITION); Vector3 finishWorldPosition = control2.GetProperty(Actor::Property::WORLD_POSITION); - Transition transition = Transition::New(control1, control2, TimePeriod(0.5f, 0.5f)); + Transition transition = Transition::New(control1, control2, true, TimePeriod(0.5f, 0.5f)); TransitionSet transitionSet = TransitionSet::New(); transitionSet.AddTransition(transition); transitionSet.Play(); @@ -654,7 +835,7 @@ int UtcDaliTransitionBetweenControlPairWithTree(void) application.SendNotification(); application.Render(20); - Transition transition = Transition::New(control1, control2, TimePeriod(0.5f)); + Transition transition = Transition::New(control1, control2, true, TimePeriod(0.5f)); TransitionSet transitionSet = TransitionSet::New(); transitionSet.AddTransition(transition); transitionSet.Play(); @@ -721,7 +902,7 @@ int UtcDaliTransitionBetweenControlPairWithTreeWithChild(void) application.SendNotification(); application.Render(20); - Transition transition = Transition::New(control1, control2, TimePeriod(0.5f)); + Transition transition = Transition::New(control1, control2, true, TimePeriod(0.5f)); transition.TransitionWithChild(true); TransitionSet transitionSet = TransitionSet::New(); transitionSet.AddTransition(transition); @@ -801,7 +982,7 @@ int UtcDaliTransitionBetweenControlPairWithTreeWithoutPositionInheritance(void) control3.SetProperty(Actor::Property::INHERIT_ORIENTATION, true); control3.SetProperty(Actor::Property::INHERIT_SCALE, true); - transition = Transition::New(control1, control3, TimePeriod(0.5f)); + transition = Transition::New(control1, control3, true, TimePeriod(0.5f)); transitionSet = TransitionSet::New(); transitionSet.AddTransition(transition); transitionSet.Play(); @@ -892,7 +1073,7 @@ int UtcDaliTransitionBetweenControlPairWithTreeWithoutOrientationInheritance(voi bool signalReceived(false); TransitionFinishCheck finishCheck(signalReceived); - transition = Transition::New(control1, control3, TimePeriod(0.5f)); + transition = Transition::New(control1, control3, true, TimePeriod(0.5f)); transitionSet = TransitionSet::New(); transitionSet.AddTransition(transition); transitionSet.Play(); @@ -978,7 +1159,7 @@ int UtcDaliTransitionBetweenControlPairWithTreeWithoutScaleInheritance(void) bool signalReceived(false); TransitionFinishCheck finishCheck(signalReceived); - transition = Transition::New(control1, control3, TimePeriod(0.5f)); + transition = Transition::New(control1, control3, true, TimePeriod(0.5f)); transitionSet = TransitionSet::New(); transitionSet.AddTransition(transition); transitionSet.Play(); @@ -1007,3 +1188,82 @@ int UtcDaliTransitionBetweenControlPairWithTreeWithoutScaleInheritance(void) END_TEST; } + + +int UtcDaliMultipleTransitionAppearing(void) +{ + ToolkitTestApplication application; + tet_infoline("UtcDaliMultipleTransitionAppearing"); + + Control control = Control::New(); + control.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT); + control.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT); + control.SetProperty(Actor::Property::POSITION, Vector3(100, 200, 0)); + control.SetProperty(Actor::Property::SIZE, Vector3(150, 150, 0)); + Property::Map controlProperty; + controlProperty.Insert(Toolkit::Visual::Property::TYPE, Toolkit::Visual::COLOR); + controlProperty.Insert(Toolkit::ColorVisual::Property::MIX_COLOR, Vector4(1.0f, 0.0f, 0.0f, 1.0f)); + control.SetProperty(Toolkit::Control::Property::BACKGROUND, controlProperty); + + application.GetScene().Add(control); + + application.SendNotification(); + application.Render(20); + + DALI_TEST_EQUALS(1.0f, control.GetCurrentProperty(Actor::Property::OPACITY), TEST_LOCATION); + + TransitionSet transitionSet = TransitionSet::New(); + FadeTransition fade = FadeTransition::New(control, 0.5, TimePeriod(1.0f, 1.0f)); + fade.SetAppearingTransition(true); // set fade in + transitionSet.AddTransition(fade); + SlideTransition slide = SlideTransition::New(control, Dali::Toolkit::SlideTransitionDirection::BOTTOM, TimePeriod(0.5f, 1.0f)); + slide.SetAppearingTransition(true); // set slide + transitionSet.AddTransition(slide); + transitionSet.Play(); + + bool signalReceived(false); + TransitionFinishCheck finishCheck(signalReceived); + transitionSet.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(300); + + float currentOpacity = control.GetCurrentProperty(Actor::Property::OPACITY); + DALI_TEST_CHECK(currentOpacity == 0.0f); + + application.SendNotification(); + application.Render(400); + + currentOpacity = control.GetCurrentProperty(Actor::Property::OPACITY); + DALI_TEST_CHECK(currentOpacity == 0.5f); + + application.SendNotification(); + application.Render(500); + + currentOpacity = control.GetCurrentProperty(Actor::Property::OPACITY); + DALI_TEST_CHECK(currentOpacity > 0.5f && currentOpacity < 1.0f); + + application.SendNotification(); + application.Render(500); + + currentOpacity = control.GetCurrentProperty(Actor::Property::OPACITY); + DALI_TEST_CHECK(currentOpacity > 0.5f && currentOpacity < 1.0f); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + + application.SendNotification(); + application.Render(500); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + + application.SendNotification(); + application.Render(20); + + DALI_TEST_EQUALS(1.0f, control.GetCurrentProperty(Actor::Property::OPACITY), TEST_LOCATION); + + END_TEST; +} diff --git a/dali-toolkit/devel-api/controls/accessible-impl.cpp b/dali-toolkit/devel-api/controls/accessible-impl.cpp index 9f1c78e..9f6f4f9 100644 --- a/dali-toolkit/devel-api/controls/accessible-impl.cpp +++ b/dali-toolkit/devel-api/controls/accessible-impl.cpp @@ -363,7 +363,6 @@ void AccessibleImpl::ScrollToSelf() parent->ScrollToChild(child->Self()); } - child = parent; parent = dynamic_cast(parent->GetParent()); } } @@ -542,6 +541,11 @@ std::vector AccessibleImpl::GetRelationSet() return ret; } +Dali::Actor AccessibleImpl::GetInternalActor() +{ + return Dali::Actor{}; +} + bool AccessibleImpl::ScrollToChild(Actor child) { return false; diff --git a/dali-toolkit/devel-api/controls/accessible-impl.h b/dali-toolkit/devel-api/controls/accessible-impl.h index aa5084a..8bd0714 100644 --- a/dali-toolkit/devel-api/controls/accessible-impl.h +++ b/dali-toolkit/devel-api/controls/accessible-impl.h @@ -226,12 +226,17 @@ public: std::vector GetRelationSet() override; /** + * @copydoc Dali::Accessibility::Accessible::GetInternalActor() + */ + Dali::Actor GetInternalActor() override; + + /** * @copydoc Dali::Accessibility::Accessible::GetStates() */ virtual Dali::Accessibility::States CalculateStates(); /** - * @brief Makes sure that a given child of this container (e.g. ItemView) is visible + * @brief Makes sure that a given child (descendant) of this container (e.g. ItemView) is visible * @return false if scrolling is not supported or child is already visible */ virtual bool ScrollToChild(Actor child); diff --git a/dali-toolkit/devel-api/controls/control-devel.cpp b/dali-toolkit/devel-api/controls/control-devel.cpp index 55becb3..dc7a128 100644 --- a/dali-toolkit/devel-api/controls/control-devel.cpp +++ b/dali-toolkit/devel-api/controls/control-devel.cpp @@ -122,19 +122,6 @@ Dali::Property GetVisualProperty(Control control, Dali::Property::Index index, D return controlDataImpl.GetVisualProperty(index, visualPropertyKey); } -void CreateTransitions(Control control, Dali::Animation& animation, Dali::Toolkit::Control source, AlphaFunction alphaFunction, TimePeriod timePeriod) -{ - if(animation) - { - // make visual transition of control visual. - Internal::Control& internalControl = Toolkit::Internal::GetImplementation(control); - Internal::Control::Impl& controlDataImpl = Internal::Control::Impl::Get(internalControl); - controlDataImpl.MakeVisualTransition(animation, source, Toolkit::Control::Property::BACKGROUND, alphaFunction, timePeriod); - controlDataImpl.MakeVisualTransition(animation, source, Toolkit::DevelControl::Property::SHADOW, alphaFunction, timePeriod); - internalControl.OnCreateTransitions(animation, source, alphaFunction, timePeriod); - } -} - static Toolkit::Internal::Control::Impl* GetControlImplementation(Dali::Actor actor) { Dali::Toolkit::Control control = Toolkit::Control::DownCast(actor); diff --git a/dali-toolkit/devel-api/controls/control-devel.h b/dali-toolkit/devel-api/controls/control-devel.h index 36b83f9..8877646 100644 --- a/dali-toolkit/devel-api/controls/control-devel.h +++ b/dali-toolkit/devel-api/controls/control-devel.h @@ -371,20 +371,6 @@ DALI_TOOLKIT_API VisualEventSignalType& VisualEventSignal(Control control); DALI_TOOLKIT_API Dali::Property GetVisualProperty(Control control, Dali::Property::Index index, Dali::Property::Key visualPropertyKey); /** - * @brief Retrieve visual/renderer property animation between this Control and source control. - * Input animation must be created before this method called. - * And the animations between this method created are added the input animation. - * This method generates visual/renderer property animation but not creates Actor property animation. - * - * @param[in] control The control - * @param[in] animation generated animation - * @param[in] source source control of the animation. - * @param[in] alphaFunction AlphaFunction of the animation - * @param[in] timePeriod TimePeriod of the animation - */ -DALI_TOOLKIT_API void CreateTransitions(Control control, Dali::Animation& animation, Dali::Toolkit::Control source, AlphaFunction alphaFunction, TimePeriod timePeriod); - -/** * @brief The signal is emmited as a succession of "activate" signal send by accessibility client. * @return The signal to connect to */ diff --git a/dali-toolkit/devel-api/file.list b/dali-toolkit/devel-api/file.list index e94f60b..c88b7a0 100755 --- a/dali-toolkit/devel-api/file.list +++ b/dali-toolkit/devel-api/file.list @@ -77,6 +77,7 @@ SET( devel_api_src_files SET( devel_api_header_files ${devel_api_src_dir}/direction-enums.h ${devel_api_src_dir}/toolkit-property-index-ranges.h + ${devel_api_src_dir}/toolkit-action-index-ranges.h ) SET( devel_api_accessibility-manager_header_files @@ -168,13 +169,12 @@ SET( devel_api_visuals_header_files ${devel_api_src_dir}/visuals/animated-image-visual-actions-devel.h ${devel_api_src_dir}/visuals/animated-vector-image-visual-actions-devel.h ${devel_api_src_dir}/visuals/animated-vector-image-visual-signals-devel.h - ${devel_api_src_dir}/visuals/arc-visual-actions-devel.h ${devel_api_src_dir}/visuals/arc-visual-properties-devel.h - ${devel_api_src_dir}/visuals/color-visual-actions-devel.h ${devel_api_src_dir}/visuals/color-visual-properties-devel.h ${devel_api_src_dir}/visuals/image-visual-properties-devel.h ${devel_api_src_dir}/visuals/image-visual-actions-devel.h ${devel_api_src_dir}/visuals/text-visual-properties-devel.h + ${devel_api_src_dir}/visuals/visual-actions-devel.h ${devel_api_src_dir}/visuals/visual-properties-devel.h ) diff --git a/dali-toolkit/devel-api/toolkit-action-index-ranges.h b/dali-toolkit/devel-api/toolkit-action-index-ranges.h new file mode 100644 index 0000000..8e5dbc4 --- /dev/null +++ b/dali-toolkit/devel-api/toolkit-action-index-ranges.h @@ -0,0 +1,51 @@ +#ifndef DALI_TOOLKIT_ACTION_INDEX_RANGES_H +#define DALI_TOOLKIT_ACTION_INDEX_RANGES_H + +/* + * Copyright (c) 2021 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. + * + */ + +// EXTERNAL INCLUDES +#include + +namespace Dali +{ +namespace Toolkit +{ +/** + * @addtogroup dali_toolkit_controls + * @{ + */ + +/** + * @brief Enumeration for the start and end action ranges. + */ +enum ActionRanges +{ + VISUAL_ACTION_BASE_START_INDEX = 0, ///< Visual Action Base Start Index. + VISUAL_ACTION_BASE_END_INDEX = VISUAL_ACTION_BASE_START_INDEX + 100, ///< Visual Action Base End Index. + VISUAL_ACTION_START_INDEX = VISUAL_ACTION_BASE_END_INDEX + 1, ///< Visual Action Start Index. + VISUAL_ACTION_END_INDEX = VISUAL_ACTION_START_INDEX + 100000, ///< Visual Action End Index. +}; + +/** + * @} + */ +} // namespace Toolkit + +} // namespace Dali + +#endif // DALI_TOOLKIT_ACTION_INDEX_RANGES_H diff --git a/dali-toolkit/devel-api/visuals/animated-image-visual-actions-devel.h b/dali-toolkit/devel-api/visuals/animated-image-visual-actions-devel.h index dbe9631..94ae63c 100644 --- a/dali-toolkit/devel-api/visuals/animated-image-visual-actions-devel.h +++ b/dali-toolkit/devel-api/visuals/animated-image-visual-actions-devel.h @@ -2,7 +2,7 @@ #define DALI_TOOLKIT_DEVEL_API_VISUALS_ANIMATED_IMAGE_VISUAL_ACTIONS_DEVEL_H /* - * Copyright (c) 2020 Samsung Electronics Co., Ltd. + * Copyright (c) 2021 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. @@ -17,6 +17,7 @@ * limitations under the License. * */ +#include namespace Dali { @@ -34,10 +35,10 @@ namespace Action */ enum Type { - PLAY, ///< Play the animated GIF. This is also Default playback mode. - PAUSE, ///< Pause the animated GIF. - STOP, ///< Stop the animated GIF. - JUMP_TO ///< Jump to the specified frame. Property::INTEGER value should be passed. + PLAY = VISUAL_ACTION_START_INDEX, ///< Play the animated GIF. This is also Default playback mode. + PAUSE, ///< Pause the animated GIF. + STOP, ///< Stop the animated GIF. + JUMP_TO ///< Jump to the specified frame. Property::INTEGER value should be passed. }; } // namespace Action diff --git a/dali-toolkit/devel-api/visuals/animated-vector-image-visual-actions-devel.h b/dali-toolkit/devel-api/visuals/animated-vector-image-visual-actions-devel.h index 2955d17..ecb91ae 100644 --- a/dali-toolkit/devel-api/visuals/animated-vector-image-visual-actions-devel.h +++ b/dali-toolkit/devel-api/visuals/animated-vector-image-visual-actions-devel.h @@ -17,6 +17,7 @@ * limitations under the License. * */ +#include namespace Dali { @@ -34,11 +35,10 @@ namespace Action */ enum Type { - PLAY, ///< Play the animated vector image. - PAUSE, ///< Pause the animated vector image. - STOP, ///< Stop the animated vector image. This is also Default playback mode. - JUMP_TO, ///< Jump to the specified frame. Property::INTEGER value should be passed. - UPDATE_PROPERTY ///< Update the properties of the animated vector image. + PLAY = VISUAL_ACTION_START_INDEX, ///< Play the animated vector image. + PAUSE, ///< Pause the animated vector image. + STOP, ///< Stop the animated vector image. This is also Default playback mode. + JUMP_TO, ///< Jump to the specified frame. Property::INTEGER value should be passed. }; } // namespace Action diff --git a/dali-toolkit/devel-api/visuals/arc-visual-actions-devel.h b/dali-toolkit/devel-api/visuals/arc-visual-actions-devel.h deleted file mode 100644 index 9657084..0000000 --- a/dali-toolkit/devel-api/visuals/arc-visual-actions-devel.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef DALI_TOOLKIT_DEVEL_API_VISUALS_ARC_VISUAL_ACTIONS_DEVEL_H -#define DALI_TOOLKIT_DEVEL_API_VISUALS_ARC_VISUAL_ACTIONS_DEVEL_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. - * - */ - -namespace Dali -{ -namespace Toolkit -{ -namespace DevelArcVisual -{ -/** - * @brief Actions that the arc visual can perform. These actions are called through the Visual::Base::DoAction API. - */ -namespace Action -{ -/** - * @brief The available actions for this visual - */ -enum Type -{ - /** - * @brief Update the properties of the visual. - * @note DevelArcVisual::Property::THICKNESS, DevelArcVisual::Property::START_ANGLE and DevelArcVisual::Property::SWEEP_ANGLE can be updated. - */ - UPDATE_PROPERTY = 0 -}; - -} // namespace Action - -} // namespace DevelArcVisual - -} // namespace Toolkit - -} // namespace Dali - -#endif // DALI_TOOLKIT_DEVEL_API_VISUALS_ARC_VISUAL_ACTIONS_DEVEL_H diff --git a/dali-toolkit/devel-api/visuals/image-visual-actions-devel.h b/dali-toolkit/devel-api/visuals/image-visual-actions-devel.h index 89ea2d6..66b4715 100644 --- a/dali-toolkit/devel-api/visuals/image-visual-actions-devel.h +++ b/dali-toolkit/devel-api/visuals/image-visual-actions-devel.h @@ -2,7 +2,7 @@ #define DALI_TOOLKIT_DEVEL_API_VISUALS_IMAGE_VISUAL_ACTIONS_DEVEL_H /* - * Copyright (c) 2020 Samsung Electronics Co., Ltd. + * Copyright (c) 2021 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. @@ -17,6 +17,7 @@ * limitations under the License. * */ +#include namespace Dali { @@ -34,7 +35,7 @@ namespace Action */ enum Type { - RELOAD = 0 ///< Force reloading of the image, all visuals using this image will get the latest one. + RELOAD = VISUAL_ACTION_START_INDEX ///< Force reloading of the image, all visuals using this image will get the latest one. }; } // namespace Action diff --git a/dali-toolkit/devel-api/visuals/color-visual-actions-devel.h b/dali-toolkit/devel-api/visuals/visual-actions-devel.h similarity index 60% rename from dali-toolkit/devel-api/visuals/color-visual-actions-devel.h rename to dali-toolkit/devel-api/visuals/visual-actions-devel.h index 16e599a..cf74766 100644 --- a/dali-toolkit/devel-api/visuals/color-visual-actions-devel.h +++ b/dali-toolkit/devel-api/visuals/visual-actions-devel.h @@ -1,8 +1,8 @@ -#ifndef DALI_TOOLKIT_DEVEL_API_VISUALS_COLOR_VISUAL_ACTIONS_DEVEL_H -#define DALI_TOOLKIT_DEVEL_API_VISUALS_COLOR_VISUAL_ACTIONS_DEVEL_H +#ifndef DALI_TOOLKIT_DEVEL_API_VISUALS_VISUAL_ACTIONS_DEVEL_H +#define DALI_TOOLKIT_DEVEL_API_VISUALS_VISUAL_ACTIONS_DEVEL_H /* - * Copyright (c) 2020 Samsung Electronics Co., Ltd. + * Copyright (c) 2021 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. @@ -18,14 +18,18 @@ * */ +// EXTERNAL INCLUDES +#include + namespace Dali { namespace Toolkit { -namespace DevelColorVisual +namespace DevelVisual { + /** - * @brief Actions that the color visual can perform. These actions are called through the Visual::Base::DoAction API. + * @brief Actions that the visual can perform. These actions are called through the Visual::Base::DoAction API. */ namespace Action { @@ -37,15 +41,15 @@ enum Type /** * @brief Update the properties of the visual. */ - UPDATE_PROPERTY = 0 + UPDATE_PROPERTY = VISUAL_ACTION_BASE_START_INDEX }; } // namespace Action -} // namespace DevelColorVisual +} // namespace DevelVisual } // namespace Toolkit } // namespace Dali -#endif // DALI_TOOLKIT_DEVEL_API_VISUALS_COLOR_VISUAL_ACTIONS_DEVEL_H +#endif // DALI_TOOLKIT_DEVEL_API_VISUALS_VISUAL_ACTIONS_DEVEL_H diff --git a/dali-toolkit/internal/controls/canvas-view/canvas-view-impl.cpp b/dali-toolkit/internal/controls/canvas-view/canvas-view-impl.cpp index 5741a42..e8fefbf 100644 --- a/dali-toolkit/internal/controls/canvas-view/canvas-view-impl.cpp +++ b/dali-toolkit/internal/controls/canvas-view/canvas-view-impl.cpp @@ -23,6 +23,7 @@ #include #include #include +#include // INTERNAL INCLUDES #include @@ -196,43 +197,25 @@ void CanvasView::AddRasterizationTask() } } -void CanvasView::ApplyRasterizedImage(PixelData rasterizedPixelData) +void CanvasView::ApplyRasterizedImage(Texture rasterizedTexture) { - if(rasterizedPixelData) + if (rasterizedTexture && rasterizedTexture.GetWidth() != 0 && rasterizedTexture.GetHeight() != 0) { - auto rasterizedPixelDataWidth = rasterizedPixelData.GetWidth(); - auto rasterizedPixelDataHeight = rasterizedPixelData.GetHeight(); - - if(rasterizedPixelDataWidth > 0 && rasterizedPixelDataHeight > 0) + if(!mTextureSet) { - if(!mTexture || mTexture.GetWidth() != rasterizedPixelDataWidth || mTexture.GetHeight() != rasterizedPixelDataHeight) - { - mTexture = Texture::New(TextureType::TEXTURE_2D, rasterizedPixelData.GetPixelFormat(), rasterizedPixelDataWidth, rasterizedPixelDataHeight); - mTexture.Upload(rasterizedPixelData); + std::string fragmentShader = SHADER_CANVAS_VIEW_FRAG.data(); + DevelTexture::ApplyNativeFragmentShader(rasterizedTexture, fragmentShader); - if(!mTextureSet) - { - mTextureSet = TextureSet::New(); - Geometry geometry = VisualFactoryCache::CreateQuadGeometry(); - Shader shader = Shader::New(SHADER_CANVAS_VIEW_VERT, SHADER_CANVAS_VIEW_FRAG); - Renderer renderer = Renderer::New(geometry, shader); - renderer.SetTextures(mTextureSet); - renderer.SetProperty(Renderer::Property::BLEND_PRE_MULTIPLIED_ALPHA, true); - - Actor actor = Self(); - if(actor) - { - actor.AddRenderer(renderer); - } - } - mTextureSet.SetTexture(0, mTexture); - } - else - { - //Update texture - mTexture.Upload(rasterizedPixelData); - } + mTextureSet = TextureSet::New(); + Geometry geometry = VisualFactoryCache::CreateQuadGeometry(); + Shader shader = Shader::New(SHADER_CANVAS_VIEW_VERT, fragmentShader); + Renderer renderer = Renderer::New(geometry, shader); + + renderer.SetTextures(mTextureSet); + renderer.SetProperty(Renderer::Property::BLEND_PRE_MULTIPLIED_ALPHA, true); + Self().AddRenderer(renderer); } + mTextureSet.SetTexture(0, rasterizedTexture); } //If there are accumulated changes to CanvasRenderer during Rasterize, Rasterize once again. diff --git a/dali-toolkit/internal/controls/canvas-view/canvas-view-impl.h b/dali-toolkit/internal/controls/canvas-view/canvas-view-impl.h index 6b6cf93..4e492eb 100644 --- a/dali-toolkit/internal/controls/canvas-view/canvas-view-impl.h +++ b/dali-toolkit/internal/controls/canvas-view/canvas-view-impl.h @@ -135,9 +135,9 @@ public: /** * @bried Apply the rasterized image to the canvas view * - * @param[in] rasterizedPixelData The pixel buffer with the rasterized pixels + * @param[in] rasterizedTexture The texture with the rasterized pixels */ - void ApplyRasterizedImage(PixelData rasterizedPixelData); + void ApplyRasterizedImage(Texture rasterizedTexture); private: CanvasView(const CanvasView&) = delete; diff --git a/dali-toolkit/internal/controls/canvas-view/canvas-view-rasterize-thread.cpp b/dali-toolkit/internal/controls/canvas-view/canvas-view-rasterize-thread.cpp index 97835c5..ba3daae 100644 --- a/dali-toolkit/internal/controls/canvas-view/canvas-view-rasterize-thread.cpp +++ b/dali-toolkit/internal/controls/canvas-view/canvas-view-rasterize-thread.cpp @@ -31,8 +31,7 @@ namespace Internal CanvasRendererRasterizingTask::CanvasRendererRasterizingTask(CanvasView* canvasView, CanvasRenderer canvasRenderer) : mCanvasView(canvasView), mCanvasRenderer(canvasRenderer), - mPixelData(PixelData()), - mBufferSize(0, 0) + mRasterizedTexture() { } @@ -40,17 +39,7 @@ bool CanvasRendererRasterizingTask::Rasterize() { if(mCanvasRenderer && mCanvasRenderer.Rasterize()) { - Devel::PixelBuffer pixbuf = mCanvasRenderer.GetPixelBuffer(); - auto width = pixbuf.GetWidth(); - auto height = pixbuf.GetHeight(); - if(width > 0 && height > 0) - { - mBufferSize.width = width; - mBufferSize.height = height; - - mPixelData = Devel::PixelBuffer::Convert(pixbuf); - return true; - } + return true; } return false; } @@ -60,14 +49,9 @@ CanvasView* CanvasRendererRasterizingTask::GetCanvasView() const return mCanvasView.Get(); } -PixelData CanvasRendererRasterizingTask::GetPixelData() const -{ - return mPixelData; -} - -Vector2 CanvasRendererRasterizingTask::GetBufferSize() const +Texture CanvasRendererRasterizingTask::GetRasterizedTexture() { - return mBufferSize; + return mCanvasRenderer.GetRasterizedTexture(); } CanvasViewRasterizeThread::CanvasViewRasterizeThread() @@ -220,7 +204,7 @@ void CanvasViewRasterizeThread::ApplyRasterized() { while(CanvasRendererRasterizingTaskPtr task = NextCompletedTask()) { - RasterizationCompletedSignal().Emit(task->GetPixelData()); + RasterizationCompletedSignal().Emit(task->GetRasterizedTexture()); // Here texture get } UnregisterProcessor(); diff --git a/dali-toolkit/internal/controls/canvas-view/canvas-view-rasterize-thread.h b/dali-toolkit/internal/controls/canvas-view/canvas-view-rasterize-thread.h index 0c16fd9..f89bb91 100644 --- a/dali-toolkit/internal/controls/canvas-view/canvas-view-rasterize-thread.h +++ b/dali-toolkit/internal/controls/canvas-view/canvas-view-rasterize-thread.h @@ -25,7 +25,6 @@ #include #include #include -#include #include #include #include @@ -81,15 +80,9 @@ public: /** * Get the rasterization result. - * @return The pixel data with the rasterized pixels. + * @return The texture with the rasterized pixels. */ - PixelData GetPixelData() const; - - /** - * Get size of rasterization result. - * @return The size of the pixel data. - */ - Vector2 GetBufferSize() const; + Texture GetRasterizedTexture(); private: // Undefined @@ -101,8 +94,7 @@ private: private: CanvasViewPtr mCanvasView; CanvasRenderer mCanvasRenderer; - PixelData mPixelData; - Vector2 mBufferSize; + Texture mRasterizedTexture; }; /** @@ -112,7 +104,7 @@ class CanvasViewRasterizeThread : public Thread, Integration::Processor { public: /// @brief ApplyRasterizedImage Event signal type - using RasterizationCompletedSignalType = Signal; + using RasterizationCompletedSignalType = Signal; public: /** diff --git a/dali-toolkit/internal/controls/control/control-data-impl.cpp b/dali-toolkit/internal/controls/control/control-data-impl.cpp index f9f4376..d9a554e 100644 --- a/dali-toolkit/internal/controls/control/control-data-impl.cpp +++ b/dali-toolkit/internal/controls/control/control-data-impl.cpp @@ -36,6 +36,7 @@ #include // INTERNAL INCLUDES +#include #include #include #include @@ -506,7 +507,7 @@ Control::Impl::Impl(Control& controlImpl) mNeedToEmitResourceReady(false), mDispatchKeyEvents(true) { - Dali::Accessibility::Accessible::RegisterControlAccessibilityGetter( + Dali::Accessibility::Accessible::RegisterExternalAccessibleGetter( [](Dali::Actor actor) -> Dali::Accessibility::Accessible* { return Control::Impl::GetAccessibilityObject(actor); }); @@ -1970,115 +1971,46 @@ Dali::Property Control::Impl::GetVisualProperty(Dali::Property::Index index, Dal return Dali::Property(handle, Property::INVALID_INDEX); } -void Control::Impl::MakeVisualTransition(Dali::Animation& animation, Dali::Toolkit::Control source, Dali::Property::Index visualIndex, AlphaFunction alphaFunction, TimePeriod timePeriod) +void Control::Impl::CreateTransitions(std::vector>& sourceProperties, + std::vector>& destinationProperties, + Dali::Toolkit::Control source, Dali::Toolkit::Control destination) { - Dali::Toolkit::Control sourceHandle = Dali::Toolkit::Control::DownCast(source); - Property::Map sourceMap = sourceHandle.GetProperty(visualIndex); - Dali::Toolkit::Control destinationHandle = Dali::Toolkit::Control::DownCast(mControlImpl.Self()); - Property::Map destinationMap = destinationHandle.GetProperty(visualIndex); - - Vector4 mixColor(1.0f, 1.0f, 1.0f, 1.0f); - Vector4 cornerRadius(0.0f, 0.0f, 0.0f, 0.0f); - float borderlineWidth(0.0f); - Vector4 borderlineColor(0.0f, 0.0f, 0.0f, 1.0f); - float borderlineOffset(0.0f); - - if(!destinationMap.Empty()) + // Retrieves background properties to be transitioned. + Dali::Property::Map backgroundSourcePropertyMap, backgroundDestinationPropertyMap; + mControlImpl.MakeVisualTransition(backgroundSourcePropertyMap, backgroundDestinationPropertyMap, source, destination, Toolkit::Control::Property::BACKGROUND); + if(backgroundSourcePropertyMap.Count() > 0) { - static auto findValueVector4 = [](const Property::Map& map, Property::Index index, const Vector4& defaultValue = Vector4()) -> Vector4 { - Property::Value* propertyValue = map.Find(index); - if(propertyValue) - { - return propertyValue->Get(); - } - return defaultValue; - }; - - static auto findValueFloat = [](const Property::Map& map, Property::Index index, const float& defaultValue = 0.0f) -> float { - Property::Value* propertyValue = map.Find(index); - if(propertyValue) - { - return propertyValue->Get(); - } - return defaultValue; - }; - - mixColor = findValueVector4(destinationMap, Dali::Toolkit::Visual::Property::MIX_COLOR, mixColor); - cornerRadius = findValueVector4(destinationMap, Toolkit::DevelVisual::Property::CORNER_RADIUS, cornerRadius); - borderlineWidth = findValueFloat(destinationMap, Toolkit::DevelVisual::Property::BORDERLINE_WIDTH, borderlineWidth); - borderlineColor = findValueVector4(destinationMap, Toolkit::DevelVisual::Property::BORDERLINE_COLOR, borderlineColor); - borderlineOffset = findValueFloat(destinationMap, Toolkit::DevelVisual::Property::BORDERLINE_OFFSET, borderlineOffset); - - if(sourceMap.Empty()) - { - sourceMap.Insert(Toolkit::Visual::Property::TYPE, Toolkit::Visual::COLOR); - sourceMap.Insert(Dali::Toolkit::Visual::Property::MIX_COLOR, Color::TRANSPARENT); - sourceMap.Insert(Toolkit::DevelVisual::Property::CORNER_RADIUS, cornerRadius); - sourceMap.Insert(Toolkit::DevelVisual::Property::BORDERLINE_WIDTH, borderlineWidth); - sourceMap.Insert(Toolkit::DevelVisual::Property::BORDERLINE_COLOR, borderlineColor); - sourceMap.Insert(Toolkit::DevelVisual::Property::BORDERLINE_OFFSET, borderlineOffset); - } - - Vector4 sourceMixColor = findValueVector4(sourceMap, Dali::Toolkit::Visual::Property::MIX_COLOR, mixColor); - Vector4 sourceCornerRadius = findValueVector4(sourceMap, Toolkit::DevelVisual::Property::CORNER_RADIUS, cornerRadius); - float sourceBorderlineWidth = findValueFloat(sourceMap, Toolkit::DevelVisual::Property::BORDERLINE_WIDTH, borderlineWidth); - Vector4 sourceBorderlineColor = findValueVector4(sourceMap, Toolkit::DevelVisual::Property::BORDERLINE_COLOR, borderlineColor); - float sourceBorderlineOffset = findValueFloat(sourceMap, Toolkit::DevelVisual::Property::BORDERLINE_OFFSET, borderlineOffset); - - std::vector properties; - std::vector> values; - - if(Vector3(sourceMixColor) != Vector3(mixColor)) - { - properties.push_back(GetVisualProperty(visualIndex, Dali::Toolkit::Visual::Property::MIX_COLOR)); - values.push_back(std::make_pair(Vector3(sourceMixColor), Vector3(mixColor))); - } - - if(std::abs(sourceMixColor.a - mixColor.a) > Math::MACHINE_EPSILON_1) - { - properties.push_back(GetVisualProperty(visualIndex, Dali::Toolkit::Visual::Property::OPACITY)); - values.push_back(std::make_pair(sourceMixColor.a, mixColor.a)); - } - - if(sourceCornerRadius != cornerRadius) - { - properties.push_back(GetVisualProperty(visualIndex, Dali::Toolkit::DevelVisual::Property::CORNER_RADIUS)); - values.push_back(std::make_pair(sourceCornerRadius, cornerRadius)); - } + sourceProperties.push_back(std::pair(Toolkit::Control::Property::BACKGROUND, backgroundSourcePropertyMap)); + destinationProperties.push_back(std::pair(Toolkit::Control::Property::BACKGROUND, backgroundDestinationPropertyMap)); + } - if(sourceBorderlineWidth != borderlineWidth) - { - properties.push_back(GetVisualProperty(visualIndex, Dali::Toolkit::DevelVisual::Property::BORDERLINE_WIDTH)); - values.push_back(std::make_pair(sourceBorderlineWidth, borderlineWidth)); - } + // Retrieves shadow properties to be transitioned. + Dali::Property::Map shadowSourcePropertyMap, shadowDestinationPropertyMap; + mControlImpl.MakeVisualTransition(shadowSourcePropertyMap, shadowDestinationPropertyMap, source, destination, Toolkit::DevelControl::Property::SHADOW); + if(shadowSourcePropertyMap.Count() > 0) + { + sourceProperties.push_back(std::pair(Toolkit::DevelControl::Property::SHADOW, shadowSourcePropertyMap)); + destinationProperties.push_back(std::pair(Toolkit::DevelControl::Property::SHADOW, shadowDestinationPropertyMap)); + } - if(sourceBorderlineColor != borderlineColor) - { - properties.push_back(GetVisualProperty(visualIndex, Dali::Toolkit::DevelVisual::Property::BORDERLINE_COLOR)); - values.push_back(std::make_pair(sourceBorderlineColor, borderlineColor)); - } + // Retrieves transition from inherited class. + mControlImpl.OnCreateTransitions(sourceProperties, destinationProperties, source, destination); +} - if(sourceBorderlineOffset != borderlineOffset) +void Control::Impl::UpdateVisualProperties(const std::vector>& properties) +{ + for(auto&& data : properties) + { + if(data.first == Toolkit::Control::Property::BACKGROUND) { - properties.push_back(GetVisualProperty(visualIndex, Dali::Toolkit::DevelVisual::Property::BORDERLINE_OFFSET)); - values.push_back(std::make_pair(sourceBorderlineOffset, borderlineOffset)); + DoAction(Toolkit::Control::Property::BACKGROUND, DevelVisual::Action::UPDATE_PROPERTY, data.second); } - - for(uint32_t i = 0; i < properties.size(); ++i) + else if(data.first == Toolkit::DevelControl::Property::SHADOW) { - if(timePeriod.delaySeconds > 0.0f) - { - Dali::KeyFrames initialKeyframes = Dali::KeyFrames::New(); - initialKeyframes.Add(0.0f, values[i].first); - initialKeyframes.Add(1.0f, values[i].first); - animation.AnimateBetween(properties[i], initialKeyframes, TimePeriod(timePeriod.delaySeconds)); - } - Dali::KeyFrames keyframes = Dali::KeyFrames::New(); - keyframes.Add(0.0f, values[i].first); - keyframes.Add(1.0f, values[i].second); - animation.AnimateBetween(properties[i], keyframes, alphaFunction, timePeriod); + DoAction(Toolkit::DevelControl::Property::SHADOW, DevelVisual::Action::UPDATE_PROPERTY, data.second); } } + mControlImpl.OnUpdateVisualProperties(properties); } void Control::Impl::EmitResourceReadySignal() diff --git a/dali-toolkit/internal/controls/control/control-data-impl.h b/dali-toolkit/internal/controls/control/control-data-impl.h index 94da0fc..55c49a6 100644 --- a/dali-toolkit/internal/controls/control/control-data-impl.h +++ b/dali-toolkit/internal/controls/control/control-data-impl.h @@ -393,16 +393,32 @@ public: Dali::Property GetVisualProperty(Dali::Property::Index index, Dali::Property::Key visualPropertyKey); /** - * @brief Make visual transition from source control to this control about specific Property::Index - * If both of source and this control have Property::Index property, than create animation between them. + * @brief Retrieves source and destination visual properties for the Transition of this Control. + * The properties of this Control will be transitioned from the propeties of source Control to that of destination control. + * If a property value is different between source and destination Control, + * the property information of each Control will be included in sourceProperties and destinationProperties. * - * @param[in] animation Return animation from source to this control. - * @param[in] source Source control to be used property animation. - * @param[in] visualIndex Property::Index to make animation. - * @param[in] alphaFunction alpha function of the animation. - * @param[in] timePeriod time period of the animation. + * @param[out] sourceProperties Source property list to be applied on this Control. + * @param[out] destinationProperties Destination property list to be applied on this Control. + * @param[in] source Source control of the animation. + * @param[in] destination Destination control of the animation. + * + * @note This method do not handle Actor properties. + * And the size and order of the sourceProperties and destinationProperties must be synchronized. + * + * This method triggers Control::OnCreateTransition(). + */ + void CreateTransitions(std::vector>& sourceProperties, + std::vector>& destinationProperties, + Dali::Toolkit::Control source, Dali::Toolkit::Control destination); + + /** + * @brief Update visual properties. + * @param[in] properties Property list to be used to update visual properties of this Control. + * + * @note This method triggers Control::OnUpdateVisualProperties(). */ - void MakeVisualTransition(Dali::Animation& animation, Dali::Toolkit::Control source, Dali::Property::Index visualIndex, AlphaFunction alphaFunction, TimePeriod timePeriod); + void UpdateVisualProperties(const std::vector>& properties); /** * @brief Gets the current control's accessible object. diff --git a/dali-toolkit/internal/controls/flex-container/flex-container-impl.cpp b/dali-toolkit/internal/controls/flex-container/flex-container-impl.cpp index a3c092d..4a3b065 100644 --- a/dali-toolkit/internal/controls/flex-container/flex-container-impl.cpp +++ b/dali-toolkit/internal/controls/flex-container/flex-container-impl.cpp @@ -39,7 +39,7 @@ namespace // currently not called from code so compiler will optimize these away, kept here for future debugging #define FLEX_CONTAINER_TAG "DALI Toolkit::FlexContainer " -#define FC_LOG(fmt, args, ...) Debug::LogMessage(Debug::DebugInfo, FLEX_CONTAINER_TAG fmt, ##args) +#define FC_LOG(fmt, args, ...) Debug::LogMessageWithFunctionLine(Debug::DebugInfo, FLEX_CONTAINER_TAG fmt, ##args) // #define FLEX_CONTAINER_DEBUG 1 #if defined(FLEX_CONTAINER_DEBUG) diff --git a/dali-toolkit/internal/controls/gl-view/gl-view-impl.cpp b/dali-toolkit/internal/controls/gl-view/gl-view-impl.cpp index 64e31d6..b37189a 100644 --- a/dali-toolkit/internal/controls/gl-view/gl-view-impl.cpp +++ b/dali-toolkit/internal/controls/gl-view/gl-view-impl.cpp @@ -67,11 +67,11 @@ GlView::~GlView() } } -void GlView::RegisterGlCallback(CallbackBase* initCallback, CallbackBase* renderFrameCallback, CallbackBase* terminateCallback) +void GlView::RegisterGlCallbacks(CallbackBase* initCallback, CallbackBase* renderFrameCallback, CallbackBase* terminateCallback) { if(mRenderThread) { - mRenderThread->RegisterGlCallback(initCallback, renderFrameCallback, terminateCallback); + mRenderThread->RegisterGlCallbacks(initCallback, renderFrameCallback, terminateCallback); } } diff --git a/dali-toolkit/internal/controls/gl-view/gl-view-impl.h b/dali-toolkit/internal/controls/gl-view/gl-view-impl.h index c0114ca..2dcb0b1 100644 --- a/dali-toolkit/internal/controls/gl-view/gl-view-impl.h +++ b/dali-toolkit/internal/controls/gl-view/gl-view-impl.h @@ -55,9 +55,9 @@ public: GlView(Dali::Toolkit::GlView::ColorFormat colorFormat); /** - * @copydoc Dali::Toolkit::GlView::RegisterGlCallback() + * @copydoc Dali::Toolkit::GlView::RegisterGlCallbacks() */ - void RegisterGlCallback(CallbackBase* initCallback, CallbackBase* renderFrameCallback, CallbackBase* terminateCallback); + void RegisterGlCallbacks(CallbackBase* initCallback, CallbackBase* renderFrameCallback, CallbackBase* terminateCallback); /** * @copydoc Dali::Toolkit::GlView::SetResizeCallback() diff --git a/dali-toolkit/internal/controls/gl-view/gl-view-render-thread.cpp b/dali-toolkit/internal/controls/gl-view/gl-view-render-thread.cpp index db2e98c..3e84cfd 100644 --- a/dali-toolkit/internal/controls/gl-view/gl-view-render-thread.cpp +++ b/dali-toolkit/internal/controls/gl-view/gl-view-render-thread.cpp @@ -72,7 +72,7 @@ GlViewRenderThread::GlViewRenderThread(Dali::NativeImageSourceQueuePtr queue) } } -void GlViewRenderThread::RegisterGlCallback(CallbackBase* initCallback, CallbackBase* renderFrameCallback, CallbackBase* terminateCallback) +void GlViewRenderThread::RegisterGlCallbacks(CallbackBase* initCallback, CallbackBase* renderFrameCallback, CallbackBase* terminateCallback) { if(!mGlInitCallback && !mGlRenderFrameCallback && !mGlTerminateCallback) { diff --git a/dali-toolkit/internal/controls/gl-view/gl-view-render-thread.h b/dali-toolkit/internal/controls/gl-view/gl-view-render-thread.h index c27c832..753526e 100644 --- a/dali-toolkit/internal/controls/gl-view/gl-view-render-thread.h +++ b/dali-toolkit/internal/controls/gl-view/gl-view-render-thread.h @@ -54,9 +54,9 @@ public: virtual ~GlViewRenderThread(); /** - * @copydoc Dali::Toolkit::GlView::RegisterGlCallback() + * @copydoc Dali::Toolkit::GlView::RegisterGlCallbacks() */ - void RegisterGlCallback(CallbackBase* initCallback, CallbackBase* renderFrameCallback, CallbackBase* terminateCallback); + void RegisterGlCallbacks(CallbackBase* initCallback, CallbackBase* renderFrameCallback, CallbackBase* terminateCallback); /** * @copydoc Dali::Toolkit::GlView::SetResizeCallback() diff --git a/dali-toolkit/internal/controls/image-view/image-view-impl.cpp b/dali-toolkit/internal/controls/image-view/image-view-impl.cpp index e3701ec..1a653a1 100644 --- a/dali-toolkit/internal/controls/image-view/image-view-impl.cpp +++ b/dali-toolkit/internal/controls/image-view/image-view-impl.cpp @@ -24,6 +24,7 @@ #include // INTERNAL INCLUDES +#include #include #include #include @@ -284,114 +285,36 @@ void ImageView::OnRelayout(const Vector2& size, RelayoutContainer& container) } } -void ImageView::OnCreateTransitions(Dali::Animation& animation, Dali::Toolkit::Control source, AlphaFunction alphaFunction, TimePeriod timePeriod) +void ImageView::OnCreateTransitions(std::vector>& sourceProperties, + std::vector>& destinationProperties, + Dali::Toolkit::Control source, + Dali::Toolkit::Control destination) { - Dali::Toolkit::ImageView destinationHandle = Toolkit::ImageView(GetOwner()); - Toolkit::Visual::Base destinationVisual = DevelControl::GetVisual(GetImplementation(destinationHandle), Toolkit::ImageView::Property::IMAGE); - Property::Map destinationMap; - - if(!destinationVisual) - { - return; - } - - destinationVisual.CreatePropertyMap(destinationMap); - - static auto findValueVector4 = [](const Property::Map& map, Property::Index index, const Vector4& defaultValue = Vector4()) -> Vector4 { - Property::Value* propertyValue = map.Find(index); - if(propertyValue) - { - return propertyValue->Get(); - } - return defaultValue; - }; - - static auto findValueFloat = [](const Property::Map& map, Property::Index index, const float& defaultValue = 0.0f) -> float { - Property::Value* propertyValue = map.Find(index); - if(propertyValue) - { - return propertyValue->Get(); - } - return defaultValue; - }; - - Vector4 sourceMixColor(0.0f, 0.0f, 0.0f, 0.0f); - Vector4 sourceCornerRadius(0.0f, 0.0f, 0.0f, 0.0f); - float sourceBorderlineWidth(0.0f); - Vector4 sourceBorderlineColor(0.0f, 0.0f, 0.0f, 1.0f); - float sourceBorderlineOffset(0.0f); - Vector4 destinationMixColor = findValueVector4(destinationMap, Dali::Toolkit::Visual::Property::MIX_COLOR, sourceMixColor); - Vector4 destinationCornerRadius = findValueVector4(destinationMap, Toolkit::DevelVisual::Property::CORNER_RADIUS, sourceCornerRadius); - float destinationBorderlineWidth = findValueFloat(destinationMap, Toolkit::DevelVisual::Property::BORDERLINE_WIDTH, sourceBorderlineWidth); - Vector4 destinationBorderlineColor = findValueVector4(destinationMap, Toolkit::DevelVisual::Property::BORDERLINE_COLOR, sourceBorderlineColor); - float destinationBorderlineOffset = findValueFloat(destinationMap, Toolkit::DevelVisual::Property::BORDERLINE_OFFSET, sourceBorderlineOffset); - - Dali::Toolkit::ImageView sourceHandle = Dali::Toolkit::ImageView::DownCast(source); - Toolkit::Visual::Base sourceVisual; - Property::Map sourceMap; - - if(sourceHandle) - { - sourceVisual = DevelControl::GetVisual(GetImplementation(sourceHandle), Toolkit::ImageView::Property::IMAGE); - } - - if(sourceVisual) + // Retrieves image properties to be transitioned. + Dali::Property::Map imageSourcePropertyMap, imageDestinationPropertyMap; + MakeVisualTransition(imageSourcePropertyMap, imageDestinationPropertyMap, source, destination, Toolkit::ImageView::Property::IMAGE); + if(imageSourcePropertyMap.Count() > 0) { - sourceVisual.CreatePropertyMap(sourceMap); - sourceMixColor = findValueVector4(sourceMap, Dali::Toolkit::Visual::Property::MIX_COLOR, sourceMixColor); - sourceCornerRadius = findValueVector4(sourceMap, Toolkit::DevelVisual::Property::CORNER_RADIUS, sourceCornerRadius); - sourceBorderlineWidth = findValueFloat(sourceMap, Toolkit::DevelVisual::Property::BORDERLINE_WIDTH, sourceBorderlineWidth); - sourceBorderlineColor = findValueVector4(sourceMap, Toolkit::DevelVisual::Property::BORDERLINE_COLOR, sourceBorderlineColor); - sourceBorderlineOffset = findValueFloat(sourceMap, Toolkit::DevelVisual::Property::BORDERLINE_OFFSET, sourceBorderlineOffset); + sourceProperties.push_back(std::pair(Toolkit::ImageView::Property::IMAGE, imageSourcePropertyMap)); + destinationProperties.push_back(std::pair(Toolkit::ImageView::Property::IMAGE, imageDestinationPropertyMap)); } +} - std::vector properties; - std::vector> values; - - if(Vector3(sourceMixColor) != Vector3(destinationMixColor)) - { - properties.push_back(DevelControl::GetVisualProperty(destinationHandle, Toolkit::ImageView::Property::IMAGE, Toolkit::Visual::Property::MIX_COLOR)); - values.push_back(std::make_pair(Vector3(sourceMixColor), Vector3(destinationMixColor))); - } - if(std::abs(sourceMixColor.a - destinationMixColor.a) > Math::MACHINE_EPSILON_1) - { - properties.push_back(DevelControl::GetVisualProperty(destinationHandle, Toolkit::ImageView::Property::IMAGE, Toolkit::Visual::Property::OPACITY)); - values.push_back(std::make_pair(sourceMixColor.a, destinationMixColor.a)); - } - if(sourceCornerRadius != destinationCornerRadius) - { - properties.push_back(DevelControl::GetVisualProperty(destinationHandle, Toolkit::ImageView::Property::IMAGE, Toolkit::DevelVisual::Property::CORNER_RADIUS)); - values.push_back(std::make_pair(sourceCornerRadius, destinationCornerRadius)); - } - if(sourceBorderlineWidth != destinationBorderlineWidth) - { - properties.push_back(DevelControl::GetVisualProperty(destinationHandle, Toolkit::ImageView::Property::IMAGE, Toolkit::DevelVisual::Property::BORDERLINE_WIDTH)); - values.push_back(std::make_pair(sourceBorderlineWidth, destinationBorderlineWidth)); - } - if(sourceBorderlineColor != destinationBorderlineColor) - { - properties.push_back(DevelControl::GetVisualProperty(destinationHandle, Toolkit::ImageView::Property::IMAGE, Toolkit::DevelVisual::Property::BORDERLINE_COLOR)); - values.push_back(std::make_pair(sourceBorderlineColor, destinationBorderlineColor)); - } - if(sourceBorderlineOffset != destinationBorderlineOffset) +void ImageView::OnUpdateVisualProperties(const std::vector>& properties) +{ + Toolkit::Visual::Base visual = DevelControl::GetVisual(*this, Toolkit::ImageView::Property::IMAGE); + if(visual) { - properties.push_back(DevelControl::GetVisualProperty(destinationHandle, Toolkit::ImageView::Property::IMAGE, Toolkit::DevelVisual::Property::BORDERLINE_OFFSET)); - values.push_back(std::make_pair(sourceBorderlineOffset, destinationBorderlineOffset)); - } + Dali::Toolkit::Control handle(GetOwner()); - for(uint32_t i = 0; i < properties.size(); ++i) - { - if(timePeriod.delaySeconds > 0.0f) + for(auto&& data : properties) { - Dali::KeyFrames initialKeyframes = Dali::KeyFrames::New(); - initialKeyframes.Add(0.0f, values[i].first); - initialKeyframes.Add(1.0f, values[i].first); - animation.AnimateBetween(properties[i], initialKeyframes, TimePeriod(timePeriod.delaySeconds)); + if(data.first == Toolkit::ImageView::Property::IMAGE) + { + DevelControl::DoAction(handle, Toolkit::ImageView::Property::IMAGE, DevelVisual::Action::UPDATE_PROPERTY, data.second); + break; + } } - Dali::KeyFrames keyframes = Dali::KeyFrames::New(); - keyframes.Add(0.0f, values[i].first); - keyframes.Add(1.0f, values[i].second); - animation.AnimateBetween(properties[i], keyframes, alphaFunction, timePeriod); } } diff --git a/dali-toolkit/internal/controls/image-view/image-view-impl.h b/dali-toolkit/internal/controls/image-view/image-view-impl.h index 023930e..ef48839 100644 --- a/dali-toolkit/internal/controls/image-view/image-view-impl.h +++ b/dali-toolkit/internal/controls/image-view/image-view-impl.h @@ -136,7 +136,15 @@ private: // From Control /** * @copydoc Toolkit::Control::OnCreateTransitions() */ - virtual void OnCreateTransitions(Dali::Animation& animation, Dali::Toolkit::Control source, AlphaFunction alphaFunction, TimePeriod timePeriod) override; + virtual void OnCreateTransitions(std::vector>& sourceProperties, + std::vector>& destinationProperties, + Dali::Toolkit::Control source, + Dali::Toolkit::Control destination) override; + + /** + * @copydoc Toolkit::Control::OnUpdateVisualProperties() + */ + virtual void OnUpdateVisualProperties(const std::vector>& properties) override; private: /** diff --git a/dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-impl-constraints.cpp b/dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-impl-constraints.cpp new file mode 100644 index 0000000..24827dd --- /dev/null +++ b/dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-impl-constraints.cpp @@ -0,0 +1,552 @@ +/* + * Copyright (c) 2021 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. + * + */ + +// CLASS HEADER +#include + +// INTERNAL INCLUDES +#include +#include + +namespace Dali +{ +namespace Toolkit +{ +namespace Internal +{ +namespace +{ + +float FinalDefaultAlphaFunction(float offset) +{ + return offset * 0.5f; +} + +/** + * Internal Relative position Constraint + * Generates the relative position value of the scroll view + * based on the absolute position, and it's relation to the + * scroll domain. This is a value from 0.0f to 1.0f in each + * scroll position axis. + */ +void InternalRelativePositionConstraint(Vector2& relativePosition, const PropertyInputContainer& inputs) +{ + Vector2 position = -inputs[0]->GetVector2(); + const Vector2& min = inputs[1]->GetVector2(); + const Vector2& max = inputs[2]->GetVector2(); + const Vector3& size = inputs[3]->GetVector3(); + + position.x = WrapInDomain(position.x, min.x, max.x); + position.y = WrapInDomain(position.y, min.y, max.y); + + Vector2 domainSize = (max - min) - size.GetVectorXY(); + + relativePosition.x = domainSize.x > Math::MACHINE_EPSILON_1 ? fabsf((position.x - min.x) / domainSize.x) : 0.0f; + relativePosition.y = domainSize.y > Math::MACHINE_EPSILON_1 ? fabsf((position.y - min.y) / domainSize.y) : 0.0f; +} + +/** + * Internal scroll domain Constraint + * Generates the scroll domain of the scroll view. + */ +void InternalScrollDomainConstraint(Vector2& scrollDomain, const PropertyInputContainer& inputs) +{ + const Vector2& min = inputs[0]->GetVector2(); + const Vector2& max = inputs[1]->GetVector2(); + const Vector3& size = inputs[2]->GetVector3(); + + scrollDomain = (max - min) - size.GetVectorXY(); +} + +/** + * Internal maximum scroll position Constraint + * Generates the maximum scroll position of the scroll view. + */ +void InternalPrePositionMaxConstraint(Vector2& scrollMax, const PropertyInputContainer& inputs) +{ + const Vector2& max = inputs[0]->GetVector2(); + const Vector3& size = inputs[1]->GetVector3(); + + scrollMax = max - size.GetVectorXY(); +} + +/** + * Internal Pre-Position Property Constraint. + * + * Generates position property based on current position + gesture displacement. + * Or generates position property based on positionX/Y. + * Note: This is the position prior to any clamping at scroll boundaries. + */ +struct InternalPrePositionConstraint +{ + InternalPrePositionConstraint(const Vector2& initialPanPosition, + const Vector2& initialPanMask, + bool axisAutoLock, + float axisAutoLockGradient, + ScrollView::LockAxis initialLockAxis, + const Vector2& maxOvershoot, + const RulerPtr& rulerX, + const RulerPtr& rulerY) + : mLocalStart(initialPanPosition), + mInitialPanMask(initialPanMask), + mMaxOvershoot(maxOvershoot), + mAxisAutoLockGradient(axisAutoLockGradient), + mLockAxis(initialLockAxis), + mAxisAutoLock(axisAutoLock), + mWasPanning(false) + { + const RulerDomain& rulerDomainX = rulerX->GetDomain(); + const RulerDomain& rulerDomainY = rulerY->GetDomain(); + mDomainMin = Vector2(rulerDomainX.min, -rulerDomainY.min); + mDomainMax = Vector2(-rulerDomainX.max, -rulerDomainY.max); + mClampX = rulerDomainX.enabled; + mClampY = rulerDomainY.enabled; + mFixedRulerX = rulerX->GetType() == Ruler::FIXED; + mFixedRulerY = rulerY->GetType() == Ruler::FIXED; + } + + void operator()(Vector2& scrollPostPosition, const PropertyInputContainer& inputs) + { + const Vector2& panPosition = inputs[0]->GetVector2(); + const bool& inGesture = inputs[1]->GetBoolean(); + + // First check if we are within a gesture. + // The ScrollView may have received a start gesture from ::OnPan() + // while the finish gesture is received now in this constraint. + // This gesture must then be rejected as the value will be "old". + // Typically the last value from the end of the last gesture. + // If we are rejecting the gesture, we simply don't modify the constraint target. + if(inGesture) + { + if(!mWasPanning) + { + mPrePosition = scrollPostPosition; + mStartPosition = mPrePosition; + mCurrentPanMask = mInitialPanMask; + mWasPanning = true; + } + + // Calculate Deltas... + const Vector2& currentPosition = panPosition; + Vector2 panDelta(currentPosition - mLocalStart); + + // Axis Auto Lock - locks the panning to the horizontal or vertical axis if the pan + // appears mostly horizontal or mostly vertical respectively... + if(mAxisAutoLock) + { + mLockAxis = GetLockAxis(panDelta, mLockAxis, mAxisAutoLockGradient); + if(mLockAxis == ScrollView::LockVertical) + { + mCurrentPanMask.y = 0.0f; + } + else if(mLockAxis == ScrollView::LockHorizontal) + { + mCurrentPanMask.x = 0.0f; + } + } + + // Restrict deltas based on ruler enable/disable and axis-lock state... + panDelta *= mCurrentPanMask; + + // Perform Position transform based on input deltas... + scrollPostPosition = mPrePosition; + scrollPostPosition += panDelta; + + // if no wrapping then clamp preposition to maximum overshoot amount + const Vector3& size = inputs[2]->GetVector3(); + if(mClampX) + { + float newXPosition = Clamp(scrollPostPosition.x, (mDomainMax.x + size.x) - mMaxOvershoot.x, mDomainMin.x + mMaxOvershoot.x); + if((newXPosition < scrollPostPosition.x - Math::MACHINE_EPSILON_1) || (newXPosition > scrollPostPosition.x + Math::MACHINE_EPSILON_1)) + { + mPrePosition.x = newXPosition; + mLocalStart.x = panPosition.x; + } + scrollPostPosition.x = newXPosition; + } + if(mClampY) + { + float newYPosition = Clamp(scrollPostPosition.y, (mDomainMax.y + size.y) - mMaxOvershoot.y, mDomainMin.y + mMaxOvershoot.y); + if((newYPosition < scrollPostPosition.y - Math::MACHINE_EPSILON_1) || (newYPosition > scrollPostPosition.y + Math::MACHINE_EPSILON_1)) + { + mPrePosition.y = newYPosition; + mLocalStart.y = panPosition.y; + } + scrollPostPosition.y = newYPosition; + } + + // If we are using a fixed ruler in a particular axis, limit the maximum pages scrolled on that axis. + if(mFixedRulerX || mFixedRulerY) + { + // Here we limit the maximum amount that can be moved from the starting position of the gesture to one page. + // We do this only if we have a fixed ruler (on that axis) and the mode is enabled. + // Note: 1.0f is subtracted to keep the value within one page size (otherwise we stray on to the page after). + // Note: A further 1.0f is subtracted to handle a compensation that happens later within the flick handling code in SnapWithVelocity(). + // When a flick is completed, an adjustment of 1.0f is sometimes made to allow for the scenario where: + // A flick finishes before the update thread has advanced the scroll position past the previous snap point. + Vector2 viewPageSizeLimit(size.x - (1.0f + 1.0f), size.y - (1.0f - 1.0f)); + Vector2 minPosition(mStartPosition.x - viewPageSizeLimit.x, mStartPosition.y - viewPageSizeLimit.y); + Vector2 maxPosition(mStartPosition.x + viewPageSizeLimit.x, mStartPosition.y + viewPageSizeLimit.y); + + if(mFixedRulerX) + { + scrollPostPosition.x = Clamp(scrollPostPosition.x, minPosition.x, maxPosition.x); + } + if(mFixedRulerY) + { + scrollPostPosition.y = Clamp(scrollPostPosition.y, minPosition.y, maxPosition.y); + } + } + } + } + + Vector2 mPrePosition; + Vector2 mLocalStart; + Vector2 mStartPosition; ///< The start position of the gesture - used to limit scroll amount (not modified by clamping). + Vector2 mInitialPanMask; ///< Initial pan mask (based on ruler settings). + Vector2 mCurrentPanMask; ///< Current pan mask that can be altered by axis lock mode. + Vector2 mDomainMin; + Vector2 mDomainMax; + Vector2 mMaxOvershoot; + + float mAxisAutoLockGradient; ///< Set by ScrollView + ScrollView::LockAxis mLockAxis; + + bool mAxisAutoLock : 1; ///< Set by ScrollView + bool mWasPanning : 1; + bool mClampX : 1; + bool mClampY : 1; + bool mFixedRulerX : 1; + bool mFixedRulerY : 1; +}; + +/** + * Internal Position Property Constraint. + * + * Generates position property based on pre-position + * Note: This is the position after clamping. + * (uses result of InternalPrePositionConstraint) + */ +struct InternalPositionConstraint +{ + InternalPositionConstraint(const RulerDomain& domainX, const RulerDomain& domainY, bool wrap) + : mDomainMin(-domainX.min, -domainY.min), + mDomainMax(-domainX.max, -domainY.max), + mClampX(domainX.enabled), + mClampY(domainY.enabled), + mWrap(wrap) + { + } + + void operator()(Vector2& position, const PropertyInputContainer& inputs) + { + position = inputs[0]->GetVector2(); + const Vector2& size = inputs[3]->GetVector3().GetVectorXY(); + const Vector2& min = inputs[1]->GetVector2(); + const Vector2& max = inputs[2]->GetVector2(); + + if(mWrap) + { + position.x = -WrapInDomain(-position.x, min.x, max.x); + position.y = -WrapInDomain(-position.y, min.y, max.y); + } + else + { + // clamp post position to domain + position.x = mClampX ? Clamp(position.x, mDomainMax.x + size.x, mDomainMin.x) : position.x; + position.y = mClampY ? Clamp(position.y, mDomainMax.y + size.y, mDomainMin.y) : position.y; + } + } + + Vector2 mDomainMin; + Vector2 mDomainMax; + bool mClampX; + bool mClampY; + bool mWrap; +}; + +/** + * This constraint updates the X overshoot property using the difference + * SCROLL_PRE_POSITION.x and SCROLL_POSITION.x, returning a relative value between 0.0f and 1.0f + */ +struct OvershootXConstraint +{ + OvershootXConstraint(float maxOvershoot) + : mMaxOvershoot(maxOvershoot) + { + } + + void operator()(float& current, const PropertyInputContainer& inputs) + { + if(inputs[2]->GetBoolean()) + { + const Vector2& scrollPrePosition = inputs[0]->GetVector2(); + const Vector2& scrollPostPosition = inputs[1]->GetVector2(); + float newOvershoot = scrollPrePosition.x - scrollPostPosition.x; + current = (newOvershoot > 0.0f ? std::min(newOvershoot, mMaxOvershoot) : std::max(newOvershoot, -mMaxOvershoot)) / mMaxOvershoot; + } + else + { + current = 0.0f; + } + } + + float mMaxOvershoot; +}; + +/** + * This constraint updates the Y overshoot property using the difference + * SCROLL_PRE_POSITION.y and SCROLL_POSITION.y, returning a relative value between 0.0f and 1.0f + */ +struct OvershootYConstraint +{ + OvershootYConstraint(float maxOvershoot) + : mMaxOvershoot(maxOvershoot) + { + } + + void operator()(float& current, const PropertyInputContainer& inputs) + { + if(inputs[2]->GetBoolean()) + { + const Vector2& scrollPrePosition = inputs[0]->GetVector2(); + const Vector2& scrollPostPosition = inputs[1]->GetVector2(); + float newOvershoot = scrollPrePosition.y - scrollPostPosition.y; + current = (newOvershoot > 0.0f ? std::min(newOvershoot, mMaxOvershoot) : std::max(newOvershoot, -mMaxOvershoot)) / mMaxOvershoot; + } + else + { + current = 0.0f; + } + } + + float mMaxOvershoot; +}; + +/** + * Internal Position-Delta Property Constraint. + * + * Generates position-delta property based on scroll-position + scroll-offset properties. + */ +void InternalPositionDeltaConstraint(Vector2& current, const PropertyInputContainer& inputs) +{ + const Vector2& scrollPosition = inputs[0]->GetVector2(); + const Vector2& scrollOffset = inputs[1]->GetVector2(); + + current = scrollPosition + scrollOffset; +} + +/** + * Internal Final Position Constraint + * The position of content is: + * of scroll-position + f(scroll-overshoot) + * where f(...) function defines how overshoot + * should affect final-position. + */ +struct InternalFinalConstraint +{ + InternalFinalConstraint(AlphaFunctionPrototype functionX, + AlphaFunctionPrototype functionY) + : mFunctionX(functionX), + mFunctionY(functionY) + { + } + + void operator()(Vector2& current, const PropertyInputContainer& inputs) + { + const float& overshootx = inputs[1]->GetFloat(); + const float& overshooty = inputs[2]->GetFloat(); + Vector2 offset(mFunctionX(overshootx), + mFunctionY(overshooty)); + + current = inputs[0]->GetVector2() - offset; + } + + AlphaFunctionPrototype mFunctionX; + AlphaFunctionPrototype mFunctionY; +}; + +} // namespace + +void ScrollViewConstraints::UpdateMainInternalConstraint(ScrollView& scrollView) +{ + // TODO: Only update the constraints which have changed, rather than remove all and add all again. + // Requires a dali-core ApplyConstraintAt, or a ReplaceConstraint. The former is probably more flexible. + Actor scrollViewActor = scrollView.Self(); + PanGestureDetector detector(scrollView.GetPanGestureDetector()); + + if(mScrollMainInternalPositionConstraint) + { + mScrollMainInternalPositionConstraint.Remove(); + mScrollMainInternalDeltaConstraint.Remove(); + mScrollMainInternalFinalConstraint.Remove(); + mScrollMainInternalRelativeConstraint.Remove(); + mScrollMainInternalDomainConstraint.Remove(); + mScrollMainInternalPrePositionMaxConstraint.Remove(); + } + if(mScrollMainInternalPrePositionConstraint) + { + mScrollMainInternalPrePositionConstraint.Remove(); + } + + // TODO: It's probably better to use a local displacement value as this will give a displacement when scrolling just commences + // but we need to make sure than the gesture system gives displacement since last frame (60Hz), not displacement since last touch event (90Hz). + + // 1. First calculate the pre-position (this is the scroll position if no clamping has taken place) + Vector2 initialPanMask = Vector2(scrollView.mRulerX->IsEnabled() ? 1.0f : 0.0f, scrollView.mRulerY->IsEnabled() ? 1.0f : 0.0f); + + if(scrollView.mLockAxis == ScrollView::LockVertical) + { + initialPanMask.y = 0.0f; + } + else if(scrollView.mLockAxis == ScrollView::LockHorizontal) + { + initialPanMask.x = 0.0f; + } + + if(scrollView.mPanning) + { + mScrollMainInternalPrePositionConstraint = Constraint::New(scrollViewActor, + Toolkit::ScrollView::Property::SCROLL_PRE_POSITION, + InternalPrePositionConstraint(scrollView.mPanStartPosition, + initialPanMask, + scrollView.mAxisAutoLock, + scrollView.mAxisAutoLockGradient, + scrollView.mLockAxis, + scrollView.mMaxOvershoot, + scrollView.mRulerX, + scrollView.mRulerY)); + mScrollMainInternalPrePositionConstraint.AddSource(Source(detector, PanGestureDetector::Property::LOCAL_POSITION)); + mScrollMainInternalPrePositionConstraint.AddSource(Source(detector, PanGestureDetector::Property::PANNING)); + mScrollMainInternalPrePositionConstraint.AddSource(Source(scrollViewActor, Actor::Property::SIZE)); + mScrollMainInternalPrePositionConstraint.Apply(); + } + + // 2. Second calculate the clamped position (actual position) + mScrollMainInternalPositionConstraint = Constraint::New(scrollViewActor, + Toolkit::ScrollView::Property::SCROLL_POSITION, + InternalPositionConstraint(scrollView.mRulerX->GetDomain(), + scrollView.mRulerY->GetDomain(), + scrollView.mWrapMode)); + mScrollMainInternalPositionConstraint.AddSource(LocalSource(Toolkit::ScrollView::Property::SCROLL_PRE_POSITION)); + mScrollMainInternalPositionConstraint.AddSource(LocalSource(Toolkit::Scrollable::Property::SCROLL_POSITION_MIN)); + mScrollMainInternalPositionConstraint.AddSource(LocalSource(Toolkit::Scrollable::Property::SCROLL_POSITION_MAX)); + mScrollMainInternalPositionConstraint.AddSource(Source(scrollViewActor, Actor::Property::SIZE)); + mScrollMainInternalPositionConstraint.Apply(); + + mScrollMainInternalDeltaConstraint = Constraint::New(scrollViewActor, Toolkit::ScrollView::Property::SCROLL_POSITION_DELTA, InternalPositionDeltaConstraint); + mScrollMainInternalDeltaConstraint.AddSource(LocalSource(Toolkit::ScrollView::Property::SCROLL_POSITION)); + mScrollMainInternalDeltaConstraint.AddSource(LocalSource(Toolkit::ScrollView::Property::SCROLL_DOMAIN_OFFSET)); + mScrollMainInternalDeltaConstraint.Apply(); + + mScrollMainInternalFinalConstraint = Constraint::New(scrollViewActor, Toolkit::ScrollView::Property::SCROLL_FINAL, InternalFinalConstraint(FinalDefaultAlphaFunction, FinalDefaultAlphaFunction)); + mScrollMainInternalFinalConstraint.AddSource(LocalSource(Toolkit::ScrollView::Property::SCROLL_POSITION)); + mScrollMainInternalFinalConstraint.AddSource(LocalSource(Toolkit::ScrollView::Property::OVERSHOOT_X)); + mScrollMainInternalFinalConstraint.AddSource(LocalSource(Toolkit::ScrollView::Property::OVERSHOOT_Y)); + mScrollMainInternalFinalConstraint.Apply(); + + mScrollMainInternalRelativeConstraint = Constraint::New(scrollViewActor, Toolkit::Scrollable::Property::SCROLL_RELATIVE_POSITION, InternalRelativePositionConstraint); + mScrollMainInternalRelativeConstraint.AddSource(LocalSource(Toolkit::ScrollView::Property::SCROLL_POSITION)); + mScrollMainInternalRelativeConstraint.AddSource(LocalSource(Toolkit::Scrollable::Property::SCROLL_POSITION_MIN)); + mScrollMainInternalRelativeConstraint.AddSource(LocalSource(Toolkit::Scrollable::Property::SCROLL_POSITION_MAX)); + mScrollMainInternalRelativeConstraint.AddSource(LocalSource(Actor::Property::SIZE)); + mScrollMainInternalRelativeConstraint.Apply(); + + mScrollMainInternalDomainConstraint = Constraint::New(scrollViewActor, Toolkit::ScrollView::Property::SCROLL_DOMAIN_SIZE, InternalScrollDomainConstraint); + mScrollMainInternalDomainConstraint.AddSource(LocalSource(Toolkit::Scrollable::Property::SCROLL_POSITION_MIN)); + mScrollMainInternalDomainConstraint.AddSource(LocalSource(Toolkit::Scrollable::Property::SCROLL_POSITION_MAX)); + mScrollMainInternalDomainConstraint.AddSource(LocalSource(Actor::Property::SIZE)); + mScrollMainInternalDomainConstraint.Apply(); + + mScrollMainInternalPrePositionMaxConstraint = Constraint::New(scrollViewActor, Toolkit::ScrollView::Property::SCROLL_PRE_POSITION_MAX, InternalPrePositionMaxConstraint); + mScrollMainInternalPrePositionMaxConstraint.AddSource(LocalSource(Toolkit::Scrollable::Property::SCROLL_POSITION_MAX)); + mScrollMainInternalPrePositionMaxConstraint.AddSource(LocalSource(Actor::Property::SIZE)); + mScrollMainInternalPrePositionMaxConstraint.Apply(); + + // When panning we want to make sure overshoot values are affected by pre position and post position + SetOvershootConstraintsEnabled(scrollView, !scrollView.mWrapMode); +} + +void ScrollViewConstraints::SetOvershootConstraintsEnabled(ScrollView& scrollView, bool enabled) +{ + Actor scrollViewActor(scrollView.Self()); + // remove and reset, it may now be in wrong order with the main internal constraints + if(mScrollMainInternalOvershootXConstraint) + { + mScrollMainInternalOvershootXConstraint.Remove(); + mScrollMainInternalOvershootXConstraint.Reset(); + mScrollMainInternalOvershootYConstraint.Remove(); + mScrollMainInternalOvershootYConstraint.Reset(); + } + if(enabled) + { + mScrollMainInternalOvershootXConstraint = Constraint::New(scrollViewActor, Toolkit::ScrollView::Property::OVERSHOOT_X, OvershootXConstraint(scrollView.mMaxOvershoot.x)); + mScrollMainInternalOvershootXConstraint.AddSource(LocalSource(Toolkit::ScrollView::Property::SCROLL_PRE_POSITION)); + mScrollMainInternalOvershootXConstraint.AddSource(LocalSource(Toolkit::ScrollView::Property::SCROLL_POSITION)); + mScrollMainInternalOvershootXConstraint.AddSource(LocalSource(Toolkit::Scrollable::Property::CAN_SCROLL_HORIZONTAL)); + mScrollMainInternalOvershootXConstraint.Apply(); + + mScrollMainInternalOvershootYConstraint = Constraint::New(scrollViewActor, Toolkit::ScrollView::Property::OVERSHOOT_Y, OvershootYConstraint(scrollView.mMaxOvershoot.y)); + mScrollMainInternalOvershootYConstraint.AddSource(LocalSource(Toolkit::ScrollView::Property::SCROLL_PRE_POSITION)); + mScrollMainInternalOvershootYConstraint.AddSource(LocalSource(Toolkit::ScrollView::Property::SCROLL_POSITION)); + mScrollMainInternalOvershootYConstraint.AddSource(LocalSource(Toolkit::Scrollable::Property::CAN_SCROLL_VERTICAL)); + mScrollMainInternalOvershootYConstraint.Apply(); + } + else + { + scrollViewActor.SetProperty(Toolkit::ScrollView::Property::OVERSHOOT_X, 0.0f); + scrollViewActor.SetProperty(Toolkit::ScrollView::Property::OVERSHOOT_Y, 0.0f); + } +} + +void ScrollViewConstraints::SetInternalConstraints(ScrollView& scrollView) +{ + // Internal constraints (applied to target ScrollBase Actor itself) ///////// + UpdateMainInternalConstraint(scrollView); + + // User definable constraints to apply to all child actors ////////////////// + Actor scrollViewActor = scrollView.Self(); + + // Apply some default constraints to ScrollView & its bound actors + // Movement + Wrap function + + Constraint constraint; + + // MoveActor (scrolling) + constraint = Constraint::New(scrollViewActor, Actor::Property::POSITION, MoveActorConstraint); + constraint.AddSource(Source(scrollViewActor, Toolkit::ScrollView::Property::SCROLL_POSITION)); + constraint.SetRemoveAction(Constraint::DISCARD); + scrollView.ApplyConstraintToBoundActors(constraint); + + // WrapActor (wrap functionality) + constraint = Constraint::New(scrollViewActor, Actor::Property::POSITION, WrapActorConstraint); + constraint.AddSource(LocalSource(Actor::Property::SCALE)); + constraint.AddSource(LocalSource(Actor::Property::ANCHOR_POINT)); + constraint.AddSource(LocalSource(Actor::Property::SIZE)); + constraint.AddSource(Source(scrollViewActor, Toolkit::Scrollable::Property::SCROLL_POSITION_MIN)); + constraint.AddSource(Source(scrollViewActor, Toolkit::Scrollable::Property::SCROLL_POSITION_MAX)); + constraint.AddSource(Source(scrollViewActor, Toolkit::ScrollView::Property::WRAP)); + constraint.SetRemoveAction(Constraint::DISCARD); + scrollView.ApplyConstraintToBoundActors(constraint); +} + + +} // namespace Internal + +} // namespace Toolkit + +} // namespace Dali diff --git a/dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-impl-constraints.h b/dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-impl-constraints.h new file mode 100644 index 0000000..540a3fd --- /dev/null +++ b/dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-impl-constraints.h @@ -0,0 +1,89 @@ +#ifndef DALI_TOOLKIT_INTERNAL_SCROLL_VIEW_CONSTRAINTS_H +#define DALI_TOOLKIT_INTERNAL_SCROLL_VIEW_CONSTRAINTS_H + +/* + * Copyright (c) 2021 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. + * + */ + +// EXTERNAL INCLUDES +#include + +namespace Dali +{ +namespace Toolkit +{ +namespace Internal +{ + +class ScrollView; + +/// Sets up and owns the Constraints used by the ScrollView class +class ScrollViewConstraints +{ +public: + + ScrollViewConstraints() = default; ///< Default Constructor + ~ScrollViewConstraints() = default; ///< Default Non-Virtual Destructor + + // Not copyable or moveable + ScrollViewConstraints(const ScrollViewConstraints&) = delete; + ScrollViewConstraints(ScrollViewConstraints&&) = delete; + ScrollViewConstraints& operator=(const ScrollViewConstraints&) = delete; + ScrollViewConstraints& operator=(ScrollViewConstraints&&) = delete; + + /** + * Updates the main internal scroll constraints with new ruler and domain values + * + * @param[in] scrollView A reference to the scroll view object + */ + void UpdateMainInternalConstraint(Internal::ScrollView& scrollView); + + /** + * Enables/disables the overshoot constraints + * + * @param[in] scrollView A reference to the scroll view object + * @param[in] enabled whether to enable or disable the overshoot constraints + */ + void SetOvershootConstraintsEnabled(ScrollView& scrollView, bool enabled); + + /** + * Sets internal constraints for this ScrollView. + * Many of these internal constraints are based on properties within ScrollView. + * + * @param[in] scrollView A reference to the scroll view object + */ + void SetInternalConstraints(ScrollView& scrollView); + +public: + + Constraint mScrollMainInternalPrePositionConstraint; + Constraint mScrollMainInternalPositionConstraint; + Constraint mScrollMainInternalOvershootXConstraint; + Constraint mScrollMainInternalOvershootYConstraint; + Constraint mScrollMainInternalDeltaConstraint; + Constraint mScrollMainInternalFinalConstraint; + Constraint mScrollMainInternalRelativeConstraint; + Constraint mScrollMainInternalDomainConstraint; + Constraint mScrollMainInternalPrePositionMaxConstraint; +}; + +} // namespace Internal + +} // namespace Toolkit + +} // namespace Dali + +#endif // DALI_TOOLKIT_INTERNAL_SCROLL_VIEW_CONSTRAINTS_H diff --git a/dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-impl.cpp b/dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-impl.cpp index 8ca6855..86cfc56 100644 --- a/dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-impl.cpp +++ b/dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-impl.cpp @@ -43,7 +43,7 @@ //#define ENABLED_SCROLL_STATE_LOGGING #ifdef ENABLED_SCROLL_STATE_LOGGING -#define DALI_LOG_SCROLL_STATE(format, ...) Dali::Integration::Log::LogMessage(Dali::Integration::Log::DebugInfo, "%s:%d " format "\n", __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__) +#define DALI_LOG_SCROLL_STATE(format, ...) Dali::Integration::Log::LogMessageWithFunctionLine(Dali::Integration::Log::DebugInfo, "%s:%d " format "\n", __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__) #else #define DALI_LOG_SCROLL_STATE(format, ...) #endif @@ -55,29 +55,32 @@ // TODO: Orientation. // TODO: upgrade Vector2/3 to support returning Unit vectors, normals, & cross product (dot product is already provided) -using namespace Dali; - namespace { -const float DEFAULT_SLOW_SNAP_ANIMATION_DURATION(0.5f); ///< Default Drag-Release animation time. -const float DEFAULT_FAST_SNAP_ANIMATION_DURATION(0.25f); ///< Default Drag-Flick animation time. -const float DEFAULT_SNAP_OVERSHOOT_DURATION(0.5f); ///< Default Overshoot snapping animation time. -const float DEFAULT_MAX_OVERSHOOT(100.0f); ///< Default maximum allowed overshoot in pixels - -const float DEFAULT_AXIS_AUTO_LOCK_GRADIENT(0.36f); ///< Default Axis-AutoLock gradient threshold. default is 0.36:1 (20 degrees) -const float DEFAULT_FRICTION_COEFFICIENT(1.0f); ///< Default Friction Co-efficient. (in stage diagonals per second) -const float DEFAULT_FLICK_SPEED_COEFFICIENT(1.0f); ///< Default Flick speed coefficient (multiples input touch velocity) -const float DEFAULT_MAX_FLICK_SPEED(3.0f); ///< Default Maximum flick speed. (in stage diagonals per second) - -const Vector2 DEFAULT_MIN_FLICK_DISTANCE(30.0f, 30.0f); ///< minimum distance for pan before flick allowed -const float DEFAULT_MIN_FLICK_SPEED_THRESHOLD(500.0f); ///< Minimum pan speed required for flick in pixels/s -const float FREE_FLICK_SPEED_THRESHOLD = 200.0f; ///< Free-Flick threshold in pixels/ms -const float AUTOLOCK_AXIS_MINIMUM_DISTANCE2 = 100.0f; ///< Auto-lock axis after minimum distance squared. -const float FLICK_ORTHO_ANGLE_RANGE = 75.0f; ///< degrees. (if >45, then supports diagonal flicking) -const Vector2 DEFAULT_WHEEL_SCROLL_DISTANCE_STEP_PROPORTION = Vector2(0.17f, 0.1f); ///< The step of horizontal scroll distance in the proportion of stage size for each wheel event received. -const unsigned long MINIMUM_TIME_BETWEEN_DOWN_AND_UP_FOR_RESET(150u); -const float TOUCH_DOWN_TIMER_INTERVAL = 100.0f; -const float DEFAULT_SCROLL_UPDATE_DISTANCE(30.0f); ///< Default distance to travel in pixels for scroll update signal +using namespace Dali; + +constexpr float DEFAULT_SLOW_SNAP_ANIMATION_DURATION(0.5f); ///< Default Drag-Release animation time. +constexpr float DEFAULT_FAST_SNAP_ANIMATION_DURATION(0.25f); ///< Default Drag-Flick animation time. +constexpr float DEFAULT_SNAP_OVERSHOOT_DURATION(0.5f); ///< Default Overshoot snapping animation time. +constexpr float DEFAULT_MAX_OVERSHOOT(100.0f); ///< Default maximum allowed overshoot in pixels + +constexpr float DEFAULT_AXIS_AUTO_LOCK_GRADIENT(0.36f); ///< Default Axis-AutoLock gradient threshold. default is 0.36:1 (20 degrees) +constexpr float DEFAULT_FRICTION_COEFFICIENT(1.0f); ///< Default Friction Co-efficient. (in stage diagonals per second) +constexpr float DEFAULT_FLICK_SPEED_COEFFICIENT(1.0f); ///< Default Flick speed coefficient (multiples input touch velocity) +constexpr float DEFAULT_MAX_FLICK_SPEED(3.0f); ///< Default Maximum flick speed. (in stage diagonals per second) + +constexpr Dali::Vector2 DEFAULT_MIN_FLICK_DISTANCE(30.0f, 30.0f); ///< minimum distance for pan before flick allowed +constexpr float DEFAULT_MIN_FLICK_SPEED_THRESHOLD(500.0f); ///< Minimum pan speed required for flick in pixels/s + +constexpr float FREE_FLICK_SPEED_THRESHOLD = 200.0f; ///< Free-Flick threshold in pixels/ms +constexpr float AUTOLOCK_AXIS_MINIMUM_DISTANCE2 = 100.0f; ///< Auto-lock axis after minimum distance squared. +constexpr float FLICK_ORTHO_ANGLE_RANGE = 75.0f; ///< degrees. (if >45, then supports diagonal flicking) + +constexpr Dali::Vector2 DEFAULT_WHEEL_SCROLL_DISTANCE_STEP_PROPORTION(0.17f, 0.1f); ///< The step of horizontal scroll distance in the proportion of stage size for each wheel event received. + +constexpr unsigned long MINIMUM_TIME_BETWEEN_DOWN_AND_UP_FOR_RESET(150u); +constexpr float TOUCH_DOWN_TIMER_INTERVAL = 100.0f; +constexpr float DEFAULT_SCROLL_UPDATE_DISTANCE(30.0f); ///< Default distance to travel in pixels for scroll update signal const std::string INTERNAL_MAX_POSITION_PROPERTY_NAME("internalMaxPosition"); @@ -104,7 +107,7 @@ float VectorInDomain(float a, float b, float start, float end, Dali::Toolkit::Di { if(bias == Dali::Toolkit::DIRECTION_BIAS_NONE) { - return ShortestDistanceInDomain(a, b, start, end); + return Dali::ShortestDistanceInDomain(a, b, start, end); } // (a-start + end-b) float size = end - start; @@ -145,22 +148,118 @@ float VectorInDomain(float a, float b, float start, float end, Dali::Toolkit::Di * @param anchor The Anchor point of interest. * @return The position of the Anchor */ -Vector3 GetPositionOfAnchor(Actor& actor, const Vector3& anchor) +Dali::Vector3 GetPositionOfAnchor(Dali::Actor& actor, const Dali::Vector3& anchor) { - Vector3 childPosition = actor.GetCurrentProperty(Actor::Property::POSITION); - Vector3 childAnchor = -actor.GetCurrentProperty(Actor::Property::ANCHOR_POINT) + anchor; - Vector3 childSize = actor.GetCurrentProperty(Actor::Property::SIZE); + Dali::Vector3 childPosition = actor.GetCurrentProperty(Dali::Actor::Property::POSITION); + Dali::Vector3 childAnchor = -actor.GetCurrentProperty(Dali::Actor::Property::ANCHOR_POINT) + anchor; + Dali::Vector3 childSize = actor.GetCurrentProperty(Dali::Actor::Property::SIZE); return childPosition + childAnchor * childSize; } -// AlphaFunctions ///////////////////////////////////////////////////////////////////////////////// +/** + * Returns the closest actor to the given position + * @param[in] actor The scrollview actor + * @param[in] internalActor The internal actor (to ignore) + * @param[in] position The given position + * @param[in] dirX Direction to search in + * @param[in] dirY Direction to search in + * @param[in] dirZ Direction to search in + * @return the closest child actor + */ +using FindDirection = Dali::Toolkit::Internal::ScrollView::FindDirection; -float FinalDefaultAlphaFunction(float offset) +Actor FindClosestActorToPosition( + CustomActor actor, Actor internalActor, const Vector3& position, FindDirection dirX, FindDirection dirY, FindDirection dirZ) { - return offset * 0.5f; + Actor closestChild; + float closestDistance2 = 0.0f; + Vector3 actualPosition = position; + + unsigned int numChildren = actor.GetChildCount(); + + for(unsigned int i = 0; i < numChildren; ++i) + { + Actor child = actor.GetChildAt(i); + + if(internalActor == child) // ignore internal actor. + { + continue; + } + + Vector3 childPosition = GetPositionOfAnchor(child, AnchorPoint::CENTER); + + Vector3 delta = childPosition - actualPosition; + + // X-axis checking (only find Actors to the [dirX] of actualPosition) + if(dirX > FindDirection::All) // != All,None + { + FindDirection deltaH = delta.x > 0 ? FindDirection::Right : FindDirection::Left; + if(dirX != deltaH) + { + continue; + } + } + + // Y-axis checking (only find Actors to the [dirY] of actualPosition) + if(dirY > FindDirection::All) // != All,None + { + FindDirection deltaV = delta.y > 0 ? FindDirection::Down : FindDirection::Up; + if(dirY != deltaV) + { + continue; + } + } + + // Z-axis checking (only find Actors to the [dirZ] of actualPosition) + if(dirZ > FindDirection::All) // != All,None + { + FindDirection deltaV = delta.y > 0 ? FindDirection::In : FindDirection::Out; + if(dirZ != deltaV) + { + continue; + } + } + + // compare child to closest child in terms of distance. + float distance2 = 0.0f; + + // distance2 = the Square of the relevant dimensions of delta + if(dirX != FindDirection::None) + { + distance2 += delta.x * delta.x; + } + + if(dirY != FindDirection::None) + { + distance2 += delta.y * delta.y; + } + + if(dirZ != FindDirection::None) + { + distance2 += delta.z * delta.z; + } + + if(closestChild) // Next time. + { + if(distance2 < closestDistance2) + { + closestChild = child; + closestDistance2 = distance2; + } + } + else // First time. + { + closestChild = child; + closestDistance2 = distance2; + } + } + + return closestChild; } +// AlphaFunctions ///////////////////////////////////////////////////////////////////////////////// + /** * ConstantDecelerationAlphaFunction * Newtoninan distance for constant deceleration @@ -177,54 +276,257 @@ float ConstantDecelerationAlphaFunction(float progress) return progress * 2.0f - progress * progress; } -// Internal Constraints /////////////////////////////////////////////////////////////////////////// - /** - * Internal Relative position Constraint - * Generates the relative position value of the scroll view - * based on the absolute position, and it's relation to the - * scroll domain. This is a value from 0.0f to 1.0f in each - * scroll position axis. + * Clamp a position + * @param[in] size The size to clamp to + * @param[in] rulerX The horizontal ruler + * @param[in] rulerY The vertical ruler + * @param[in,out] position The position to clamp + * @param[out] clamped the clamped state */ -void InternalRelativePositionConstraint(Vector2& relativePosition, const PropertyInputContainer& inputs) +void ClampPosition(const Vector3& size, Dali::Toolkit::RulerPtr rulerX, Dali::Toolkit::RulerPtr rulerY, Vector2& position, Dali::Toolkit::ClampState2D& clamped) { - Vector2 position = -inputs[0]->GetVector2(); - const Vector2& min = inputs[1]->GetVector2(); - const Vector2& max = inputs[2]->GetVector2(); - const Vector3& size = inputs[3]->GetVector3(); - - position.x = WrapInDomain(position.x, min.x, max.x); - position.y = WrapInDomain(position.y, min.y, max.y); - - Vector2 domainSize = (max - min) - size.GetVectorXY(); - - relativePosition.x = domainSize.x > Math::MACHINE_EPSILON_1 ? fabsf((position.x - min.x) / domainSize.x) : 0.0f; - relativePosition.y = domainSize.y > Math::MACHINE_EPSILON_1 ? fabsf((position.y - min.y) / domainSize.y) : 0.0f; + position.x = -rulerX->Clamp(-position.x, size.width, 1.0f, clamped.x); // NOTE: X & Y rulers think in -ve coordinate system. + position.y = -rulerY->Clamp(-position.y, size.height, 1.0f, clamped.y); // That is scrolling RIGHT (e.g. 100.0, 0.0) means moving LEFT. } /** - * Internal scroll domain Constraint - * Generates the scroll domain of the scroll view. + * TODO: In situations where axes are different (X snap, Y free) + * Each axis should really have their own independent animation (time and equation) + * Consider, X axis snapping to nearest grid point (EaseOut over fixed time) + * Consider, Y axis simulating physics to arrive at a point (Physics equation over variable time) + * Currently, the axes have been split however, they both use the same EaseOut equation. + * + * @param[in] scrollView The main scrollview + * @param[in] rulerX The X ruler + * @param[in] rulerY The Y ruler + * @param[in] lockAxis Which axis (if any) is locked. + * @param[in] velocity Current pan velocity + * @param[in] maxOvershoot Maximum overshoot + * @param[in] inAcessibilityPan True if we are currently panning with accessibility + * @param[out] positionSnap The target position of snap animation + * @param[out] positionDuration The duration of the snap animation + * @param[out] alphaFunction The snap animation alpha function + * @param[out] isFlick if we are flicking or not + * @param[out] isFreeFlick if we are free flicking or not */ -void InternalScrollDomainConstraint(Vector2& scrollDomain, const PropertyInputContainer& inputs) +void SnapWithVelocity( + Dali::Toolkit::Internal::ScrollView& scrollView, + Dali::Toolkit::RulerPtr rulerX, + Dali::Toolkit::RulerPtr rulerY, + Dali::Toolkit::Internal::ScrollView::LockAxis lockAxis, + Vector2 velocity, + Vector2 maxOvershoot, + Vector2& positionSnap, + Vector2& positionDuration, + AlphaFunction& alphaFunction, + bool inAccessibilityPan, + bool& isFlick, + bool& isFreeFlick) { - const Vector2& min = inputs[0]->GetVector2(); - const Vector2& max = inputs[1]->GetVector2(); - const Vector3& size = inputs[2]->GetVector3(); + // Animator takes over now, touches are assumed not to interfere. + // And if touches do interfere, then we'll stop animation, update PrePosition + // to current mScroll's properties, and then resume. + // Note: For Flicking this may work a bit different... - scrollDomain = (max - min) - size.GetVectorXY(); -} + float angle = atan2(velocity.y, velocity.x); + float speed2 = velocity.LengthSquared(); + float biasX = 0.5f; + float biasY = 0.5f; + FindDirection horizontal = FindDirection::None; + FindDirection vertical = FindDirection::None; -/** - * Internal maximum scroll position Constraint - * Generates the maximum scroll position of the scroll view. - */ -void InternalPrePositionMaxConstraint(Vector2& scrollMax, const PropertyInputContainer& inputs) -{ - const Vector2& max = inputs[0]->GetVector2(); - const Vector3& size = inputs[1]->GetVector3(); + using LockAxis = Dali::Toolkit::Internal::ScrollView::LockAxis; + + // orthoAngleRange = Angle tolerance within the Exact N,E,S,W direction + // that will be accepted as a general N,E,S,W flick direction. + + const float orthoAngleRange = FLICK_ORTHO_ANGLE_RANGE * M_PI / 180.0f; + const float flickSpeedThreshold2 = scrollView.GetMinimumSpeedForFlick() * scrollView.GetMinimumSpeedForFlick(); + + // Flick logic X Axis + + if(rulerX->IsEnabled() && lockAxis != LockAxis::LockHorizontal) + { + horizontal = FindDirection::All; + + if(speed2 > flickSpeedThreshold2 || // exceeds flick threshold + inAccessibilityPan) // With AccessibilityPan its easier to move between snap positions + { + if((angle >= -orthoAngleRange) && (angle < orthoAngleRange)) // Swiping East + { + biasX = 0.0f, horizontal = FindDirection::Left; + + // This guards against an error where no movement occurs, due to the flick finishing + // before the update-thread has advanced mScrollPostPosition past the the previous snap point. + positionSnap.x += 1.0f; + } + else if((angle >= M_PI - orthoAngleRange) || (angle < -M_PI + orthoAngleRange)) // Swiping West + { + biasX = 1.0f, horizontal = FindDirection::Right; + + // This guards against an error where no movement occurs, due to the flick finishing + // before the update-thread has advanced mScrollPostPosition past the the previous snap point. + positionSnap.x -= 1.0f; + } + } + } + + // Flick logic Y Axis + + if(rulerY->IsEnabled() && lockAxis != LockAxis::LockVertical) + { + vertical = FindDirection::All; + + if(speed2 > flickSpeedThreshold2 || // exceeds flick threshold + inAccessibilityPan) // With AccessibilityPan its easier to move between snap positions + { + if((angle >= M_PI_2 - orthoAngleRange) && (angle < M_PI_2 + orthoAngleRange)) // Swiping South + { + biasY = 0.0f, vertical = FindDirection::Up; + } + else if((angle >= -M_PI_2 - orthoAngleRange) && (angle < -M_PI_2 + orthoAngleRange)) // Swiping North + { + biasY = 1.0f, vertical = FindDirection::Down; + } + } + } + + // isFlick: Whether this gesture is a flick or not. + isFlick = (horizontal != FindDirection::All || vertical != FindDirection::All); + // isFreeFlick: Whether this gesture is a flick under free panning criteria. + isFreeFlick = velocity.LengthSquared() > (FREE_FLICK_SPEED_THRESHOLD * FREE_FLICK_SPEED_THRESHOLD); + + if(isFlick || isFreeFlick) + { + positionDuration = Vector2::ONE * scrollView.GetScrollFlickDuration(); + alphaFunction = scrollView.GetScrollFlickAlphaFunction(); + } + + // Calculate next positionSnap //////////////////////////////////////////////////////////// + + if(scrollView.GetActorAutoSnap()) + { + Vector3 size = scrollView.Self().GetCurrentProperty(Actor::Property::SIZE); + + Actor child = scrollView.FindClosestActorToPosition(Vector3(size.width * 0.5f, size.height * 0.5f, 0.0f), horizontal, vertical); + + if(!child && isFlick) + { + // If we conducted a direction limited search and found no actor, then just snap to the closest actor. + child = scrollView.FindClosestActorToPosition(Vector3(size.width * 0.5f, size.height * 0.5f, 0.0f)); + } + + if(child) + { + Vector2 position = scrollView.Self().GetCurrentProperty(Toolkit::ScrollView::Property::SCROLL_POSITION); + + // Get center-point of the Actor. + Vector3 childPosition = GetPositionOfAnchor(child, AnchorPoint::CENTER); + + if(rulerX->IsEnabled()) + { + positionSnap.x = position.x - childPosition.x + size.width * 0.5f; + } + if(rulerY->IsEnabled()) + { + positionSnap.y = position.y - childPosition.y + size.height * 0.5f; + } + } + } + + Vector2 startPosition = positionSnap; + positionSnap.x = -rulerX->Snap(-positionSnap.x, biasX); // NOTE: X & Y rulers think in -ve coordinate system. + positionSnap.y = -rulerY->Snap(-positionSnap.y, biasY); // That is scrolling RIGHT (e.g. 100.0, 0.0) means moving LEFT. + + Dali::Toolkit::ClampState2D clamped; + Vector3 size = scrollView.Self().GetCurrentProperty(Actor::Property::SIZE); + Vector2 clampDelta(Vector2::ZERO); + ClampPosition(size, rulerX, rulerY, positionSnap, clamped); + + if((rulerX->GetType() == Dali::Toolkit::Ruler::FREE || rulerY->GetType() == Dali::Toolkit::Ruler::FREE) && + isFreeFlick && !scrollView.GetActorAutoSnap()) + { + // Calculate target position based on velocity of flick. + + // a = Deceleration (Set to diagonal stage length * friction coefficient) + // u = Initial Velocity (Flick velocity) + // v = 0 (Final Velocity) + // t = Time (Velocity / Deceleration) + Vector2 stageSize = Stage::GetCurrent().GetSize(); + float stageLength = Vector3(stageSize.x, stageSize.y, 0.0f).Length(); + float a = (stageLength * scrollView.GetFrictionCoefficient()); + Vector3 u = Vector3(velocity.x, velocity.y, 0.0f) * scrollView.GetFlickSpeedCoefficient(); + float speed = u.Length(); + u /= speed; + + // TODO: Change this to a decay function. (faster you flick, the slower it should be) + speed = std::min(speed, stageLength * scrollView.GetMaxFlickSpeed()); + u *= speed; + alphaFunction = ConstantDecelerationAlphaFunction; + + float t = speed / a; + + if(rulerX->IsEnabled() && rulerX->GetType() == Dali::Toolkit::Ruler::FREE) + { + positionSnap.x += t * u.x * 0.5f; + } + + if(rulerY->IsEnabled() && rulerY->GetType() == Dali::Toolkit::Ruler::FREE) + { + positionSnap.y += t * u.y * 0.5f; + } + + clampDelta = positionSnap; + ClampPosition(size, rulerX, rulerY, positionSnap, clamped); + + if((positionSnap - startPosition).LengthSquared() > Math::MACHINE_EPSILON_0) + { + clampDelta -= positionSnap; + clampDelta.x = clampDelta.x > 0.0f ? std::min(clampDelta.x, maxOvershoot.x) : std::max(clampDelta.x, -maxOvershoot.x); + clampDelta.y = clampDelta.y > 0.0f ? std::min(clampDelta.y, maxOvershoot.y) : std::max(clampDelta.y, -maxOvershoot.y); + } + else + { + clampDelta = Vector2::ZERO; + } + + // If Axis is Free and has velocity, then calculate time taken + // to reach target based on velocity in axis. + if(rulerX->IsEnabled() && rulerX->GetType() == Dali::Toolkit::Ruler::FREE) + { + float deltaX = fabsf(startPosition.x - positionSnap.x); + + if(fabsf(u.x) > Math::MACHINE_EPSILON_1) + { + positionDuration.x = fabsf(deltaX / u.x); + } + else + { + positionDuration.x = 0; + } + } + + if(rulerY->IsEnabled() && rulerY->GetType() == Dali::Toolkit::Ruler::FREE) + { + float deltaY = fabsf(startPosition.y - positionSnap.y); + + if(fabsf(u.y) > Math::MACHINE_EPSILON_1) + { + positionDuration.y = fabsf(deltaY / u.y); + } + else + { + positionDuration.y = 0; + } + } + } - scrollMax = max - size.GetVectorXY(); + if(scrollView.IsOvershootEnabled()) + { + // Scroll to the end of the overshoot only when overshoot is enabled. + positionSnap += clampDelta; + } } } // unnamed namespace @@ -277,336 +579,6 @@ DALI_SIGNAL_REGISTRATION(Toolkit, ScrollView, "valueChanged", SIGNAL_SNAP_STARTE DALI_TYPE_REGISTRATION_END() -/** - * Returns whether to lock scrolling to a particular axis - * - * @param[in] panDelta Distance panned since gesture started - * @param[in] currentLockAxis The current lock axis value - * @param[in] lockGradient How quickly to lock to a particular axis - * - * @return The new axis lock state - */ -ScrollView::LockAxis GetLockAxis(const Vector2& panDelta, ScrollView::LockAxis currentLockAxis, float lockGradient) -{ - if(panDelta.LengthSquared() > AUTOLOCK_AXIS_MINIMUM_DISTANCE2 && - currentLockAxis == ScrollView::LockPossible) - { - float dx = fabsf(panDelta.x); - float dy = fabsf(panDelta.y); - if(dx * lockGradient >= dy) - { - // 0.36:1 gradient to the horizontal (deviate < 20 degrees) - currentLockAxis = ScrollView::LockVertical; - } - else if(dy * lockGradient > dx) - { - // 0.36:1 gradient to the vertical (deviate < 20 degrees) - currentLockAxis = ScrollView::LockHorizontal; - } - else - { - currentLockAxis = ScrollView::LockNone; - } - } - return currentLockAxis; -} - -/** - * Internal Pre-Position Property Constraint. - * - * Generates position property based on current position + gesture displacement. - * Or generates position property based on positionX/Y. - * Note: This is the position prior to any clamping at scroll boundaries. - */ -struct InternalPrePositionConstraint -{ - InternalPrePositionConstraint(const Vector2& initialPanPosition, - const Vector2& initialPanMask, - bool axisAutoLock, - float axisAutoLockGradient, - ScrollView::LockAxis initialLockAxis, - const Vector2& maxOvershoot, - const RulerPtr& rulerX, - const RulerPtr& rulerY) - : mLocalStart(initialPanPosition), - mInitialPanMask(initialPanMask), - mMaxOvershoot(maxOvershoot), - mAxisAutoLockGradient(axisAutoLockGradient), - mLockAxis(initialLockAxis), - mAxisAutoLock(axisAutoLock), - mWasPanning(false) - { - const RulerDomain& rulerDomainX = rulerX->GetDomain(); - const RulerDomain& rulerDomainY = rulerY->GetDomain(); - mDomainMin = Vector2(rulerDomainX.min, -rulerDomainY.min); - mDomainMax = Vector2(-rulerDomainX.max, -rulerDomainY.max); - mClampX = rulerDomainX.enabled; - mClampY = rulerDomainY.enabled; - mFixedRulerX = rulerX->GetType() == Ruler::FIXED; - mFixedRulerY = rulerY->GetType() == Ruler::FIXED; - } - - void operator()(Vector2& scrollPostPosition, const PropertyInputContainer& inputs) - { - const Vector2& panPosition = inputs[0]->GetVector2(); - const bool& inGesture = inputs[1]->GetBoolean(); - - // First check if we are within a gesture. - // The ScrollView may have received a start gesture from ::OnPan() - // while the finish gesture is received now in this constraint. - // This gesture must then be rejected as the value will be "old". - // Typically the last value from the end of the last gesture. - // If we are rejecting the gesture, we simply don't modify the constraint target. - if(inGesture) - { - if(!mWasPanning) - { - mPrePosition = scrollPostPosition; - mStartPosition = mPrePosition; - mCurrentPanMask = mInitialPanMask; - mWasPanning = true; - } - - // Calculate Deltas... - const Vector2& currentPosition = panPosition; - Vector2 panDelta(currentPosition - mLocalStart); - - // Axis Auto Lock - locks the panning to the horizontal or vertical axis if the pan - // appears mostly horizontal or mostly vertical respectively... - if(mAxisAutoLock) - { - mLockAxis = GetLockAxis(panDelta, mLockAxis, mAxisAutoLockGradient); - if(mLockAxis == ScrollView::LockVertical) - { - mCurrentPanMask.y = 0.0f; - } - else if(mLockAxis == ScrollView::LockHorizontal) - { - mCurrentPanMask.x = 0.0f; - } - } - - // Restrict deltas based on ruler enable/disable and axis-lock state... - panDelta *= mCurrentPanMask; - - // Perform Position transform based on input deltas... - scrollPostPosition = mPrePosition; - scrollPostPosition += panDelta; - - // if no wrapping then clamp preposition to maximum overshoot amount - const Vector3& size = inputs[2]->GetVector3(); - if(mClampX) - { - float newXPosition = Clamp(scrollPostPosition.x, (mDomainMax.x + size.x) - mMaxOvershoot.x, mDomainMin.x + mMaxOvershoot.x); - if((newXPosition < scrollPostPosition.x - Math::MACHINE_EPSILON_1) || (newXPosition > scrollPostPosition.x + Math::MACHINE_EPSILON_1)) - { - mPrePosition.x = newXPosition; - mLocalStart.x = panPosition.x; - } - scrollPostPosition.x = newXPosition; - } - if(mClampY) - { - float newYPosition = Clamp(scrollPostPosition.y, (mDomainMax.y + size.y) - mMaxOvershoot.y, mDomainMin.y + mMaxOvershoot.y); - if((newYPosition < scrollPostPosition.y - Math::MACHINE_EPSILON_1) || (newYPosition > scrollPostPosition.y + Math::MACHINE_EPSILON_1)) - { - mPrePosition.y = newYPosition; - mLocalStart.y = panPosition.y; - } - scrollPostPosition.y = newYPosition; - } - - // If we are using a fixed ruler in a particular axis, limit the maximum pages scrolled on that axis. - if(mFixedRulerX || mFixedRulerY) - { - // Here we limit the maximum amount that can be moved from the starting position of the gesture to one page. - // We do this only if we have a fixed ruler (on that axis) and the mode is enabled. - // Note: 1.0f is subtracted to keep the value within one page size (otherwise we stray on to the page after). - // Note: A further 1.0f is subtracted to handle a compensation that happens later within the flick handling code in SnapWithVelocity(). - // When a flick is completed, an adjustment of 1.0f is sometimes made to allow for the scenario where: - // A flick finishes before the update thread has advanced the scroll position past the previous snap point. - Vector2 viewPageSizeLimit(size.x - (1.0f + 1.0f), size.y - (1.0f - 1.0f)); - Vector2 minPosition(mStartPosition.x - viewPageSizeLimit.x, mStartPosition.y - viewPageSizeLimit.y); - Vector2 maxPosition(mStartPosition.x + viewPageSizeLimit.x, mStartPosition.y + viewPageSizeLimit.y); - - if(mFixedRulerX) - { - scrollPostPosition.x = Clamp(scrollPostPosition.x, minPosition.x, maxPosition.x); - } - if(mFixedRulerY) - { - scrollPostPosition.y = Clamp(scrollPostPosition.y, minPosition.y, maxPosition.y); - } - } - } - } - - Vector2 mPrePosition; - Vector2 mLocalStart; - Vector2 mStartPosition; ///< The start position of the gesture - used to limit scroll amount (not modified by clamping). - Vector2 mInitialPanMask; ///< Initial pan mask (based on ruler settings). - Vector2 mCurrentPanMask; ///< Current pan mask that can be altered by axis lock mode. - Vector2 mDomainMin; - Vector2 mDomainMax; - Vector2 mMaxOvershoot; - - float mAxisAutoLockGradient; ///< Set by ScrollView - ScrollView::LockAxis mLockAxis; - - bool mAxisAutoLock : 1; ///< Set by ScrollView - bool mWasPanning : 1; - bool mClampX : 1; - bool mClampY : 1; - bool mFixedRulerX : 1; - bool mFixedRulerY : 1; -}; - -/** - * Internal Position Property Constraint. - * - * Generates position property based on pre-position - * Note: This is the position after clamping. - * (uses result of InternalPrePositionConstraint) - */ -struct InternalPositionConstraint -{ - InternalPositionConstraint(const RulerDomain& domainX, const RulerDomain& domainY, bool wrap) - : mDomainMin(-domainX.min, -domainY.min), - mDomainMax(-domainX.max, -domainY.max), - mClampX(domainX.enabled), - mClampY(domainY.enabled), - mWrap(wrap) - { - } - - void operator()(Vector2& position, const PropertyInputContainer& inputs) - { - position = inputs[0]->GetVector2(); - const Vector2& size = inputs[3]->GetVector3().GetVectorXY(); - const Vector2& min = inputs[1]->GetVector2(); - const Vector2& max = inputs[2]->GetVector2(); - - if(mWrap) - { - position.x = -WrapInDomain(-position.x, min.x, max.x); - position.y = -WrapInDomain(-position.y, min.y, max.y); - } - else - { - // clamp post position to domain - position.x = mClampX ? Clamp(position.x, mDomainMax.x + size.x, mDomainMin.x) : position.x; - position.y = mClampY ? Clamp(position.y, mDomainMax.y + size.y, mDomainMin.y) : position.y; - } - } - - Vector2 mDomainMin; - Vector2 mDomainMax; - bool mClampX; - bool mClampY; - bool mWrap; -}; - -/** - * This constraint updates the X overshoot property using the difference - * SCROLL_PRE_POSITION.x and SCROLL_POSITION.x, returning a relative value between 0.0f and 1.0f - */ -struct OvershootXConstraint -{ - OvershootXConstraint(float maxOvershoot) - : mMaxOvershoot(maxOvershoot) - { - } - - void operator()(float& current, const PropertyInputContainer& inputs) - { - if(inputs[2]->GetBoolean()) - { - const Vector2& scrollPrePosition = inputs[0]->GetVector2(); - const Vector2& scrollPostPosition = inputs[1]->GetVector2(); - float newOvershoot = scrollPrePosition.x - scrollPostPosition.x; - current = (newOvershoot > 0.0f ? std::min(newOvershoot, mMaxOvershoot) : std::max(newOvershoot, -mMaxOvershoot)) / mMaxOvershoot; - } - else - { - current = 0.0f; - } - } - - float mMaxOvershoot; -}; - -/** - * This constraint updates the Y overshoot property using the difference - * SCROLL_PRE_POSITION.y and SCROLL_POSITION.y, returning a relative value between 0.0f and 1.0f - */ -struct OvershootYConstraint -{ - OvershootYConstraint(float maxOvershoot) - : mMaxOvershoot(maxOvershoot) - { - } - - void operator()(float& current, const PropertyInputContainer& inputs) - { - if(inputs[2]->GetBoolean()) - { - const Vector2& scrollPrePosition = inputs[0]->GetVector2(); - const Vector2& scrollPostPosition = inputs[1]->GetVector2(); - float newOvershoot = scrollPrePosition.y - scrollPostPosition.y; - current = (newOvershoot > 0.0f ? std::min(newOvershoot, mMaxOvershoot) : std::max(newOvershoot, -mMaxOvershoot)) / mMaxOvershoot; - } - else - { - current = 0.0f; - } - } - - float mMaxOvershoot; -}; - -/** - * Internal Position-Delta Property Constraint. - * - * Generates position-delta property based on scroll-position + scroll-offset properties. - */ -void InternalPositionDeltaConstraint(Vector2& current, const PropertyInputContainer& inputs) -{ - const Vector2& scrollPosition = inputs[0]->GetVector2(); - const Vector2& scrollOffset = inputs[1]->GetVector2(); - - current = scrollPosition + scrollOffset; -} - -/** - * Internal Final Position Constraint - * The position of content is: - * of scroll-position + f(scroll-overshoot) - * where f(...) function defines how overshoot - * should affect final-position. - */ -struct InternalFinalConstraint -{ - InternalFinalConstraint(AlphaFunctionPrototype functionX, - AlphaFunctionPrototype functionY) - : mFunctionX(functionX), - mFunctionY(functionY) - { - } - - void operator()(Vector2& current, const PropertyInputContainer& inputs) - { - const float& overshootx = inputs[1]->GetFloat(); - const float& overshooty = inputs[2]->GetFloat(); - Vector2 offset(mFunctionX(overshootx), - mFunctionY(overshooty)); - - current = inputs[0]->GetVector2() - offset; - } - - AlphaFunctionPrototype mFunctionX; - AlphaFunctionPrototype mFunctionY; -}; - } // namespace /////////////////////////////////////////////////////////////////////////////////////////////////// @@ -702,7 +674,7 @@ void ScrollView::OnInitialize() self.SetProperty(Toolkit::Scrollable::Property::CAN_SCROLL_HORIZONTAL, mCanScrollHorizontal); UpdatePropertyDomain(); - SetInternalConstraints(); + mConstraints.SetInternalConstraints(*this); // Connect wheel event self.WheelEventSignal().Connect(this, &ScrollView::OnWheelEvent); @@ -746,46 +718,6 @@ ScrollView::~ScrollView() DALI_LOG_SCROLL_STATE("[0x%X]", this); } -AlphaFunction ScrollView::GetScrollSnapAlphaFunction() const -{ - return mSnapAlphaFunction; -} - -void ScrollView::SetScrollSnapAlphaFunction(AlphaFunction alpha) -{ - mSnapAlphaFunction = alpha; -} - -AlphaFunction ScrollView::GetScrollFlickAlphaFunction() const -{ - return mFlickAlphaFunction; -} - -void ScrollView::SetScrollFlickAlphaFunction(AlphaFunction alpha) -{ - mFlickAlphaFunction = alpha; -} - -float ScrollView::GetScrollSnapDuration() const -{ - return mSnapDuration; -} - -void ScrollView::SetScrollSnapDuration(float time) -{ - mSnapDuration = time; -} - -float ScrollView::GetScrollFlickDuration() const -{ - return mFlickDuration; -} - -void ScrollView::SetScrollFlickDuration(float time) -{ - mFlickDuration = time; -} - void ScrollView::ApplyEffect(Toolkit::ScrollViewEffect effect) { Dali::Toolkit::ScrollView self = Dali::Toolkit::ScrollView::DownCast(Self()); @@ -858,22 +790,12 @@ void ScrollView::RemoveConstraintsFromChildren() RemoveConstraintsFromBoundActors(); } -const RulerPtr ScrollView::GetRulerX() const -{ - return mRulerX; -} - -const RulerPtr ScrollView::GetRulerY() const -{ - return mRulerY; -} - void ScrollView::SetRulerX(RulerPtr ruler) { mRulerX = ruler; UpdatePropertyDomain(); - UpdateMainInternalConstraint(); + mConstraints.UpdateMainInternalConstraint(*this); } void ScrollView::SetRulerY(RulerPtr ruler) @@ -881,7 +803,7 @@ void ScrollView::SetRulerY(RulerPtr ruler) mRulerY = ruler; UpdatePropertyDomain(); - UpdateMainInternalConstraint(); + mConstraints.UpdateMainInternalConstraint(*this); } void ScrollView::UpdatePropertyDomain() @@ -981,11 +903,6 @@ void ScrollView::UpdatePropertyDomain() } } -bool ScrollView::GetScrollSensitive() -{ - return mSensitive; -} - void ScrollView::SetScrollSensitive(bool sensitive) { Actor self = Self(); @@ -1023,22 +940,7 @@ void ScrollView::SetMaxOvershoot(float overshootX, float overshootY) mMaxOvershoot.y = overshootY; mUserMaxOvershoot = mMaxOvershoot; mDefaultMaxOvershoot = false; - UpdateMainInternalConstraint(); -} - -void ScrollView::SetSnapOvershootAlphaFunction(AlphaFunction alpha) -{ - mSnapOvershootAlphaFunction = alpha; -} - -float ScrollView::GetSnapOvershootDuration() -{ - return mSnapOvershootDuration; -} - -void ScrollView::SetSnapOvershootDuration(float duration) -{ - mSnapOvershootDuration = duration; + mConstraints.UpdateMainInternalConstraint(*this); } bool ScrollView::GetActorAutoSnap() @@ -1046,64 +948,29 @@ bool ScrollView::GetActorAutoSnap() return mActorAutoSnapEnabled; } -void ScrollView::SetActorAutoSnap(bool enable) -{ - mActorAutoSnapEnabled = enable; -} - void ScrollView::SetAutoResize(bool enable) { mAutoResizeContainerEnabled = enable; // TODO: This needs a lot of issues to be addressed before working. } -bool ScrollView::GetWrapMode() const -{ - return mWrapMode; -} - void ScrollView::SetWrapMode(bool enable) { mWrapMode = enable; Self().SetProperty(Toolkit::ScrollView::Property::WRAP, enable); } -int ScrollView::GetScrollUpdateDistance() const -{ - return mScrollUpdateDistance; -} - -void ScrollView::SetScrollUpdateDistance(int distance) -{ - mScrollUpdateDistance = distance; -} - -bool ScrollView::GetAxisAutoLock() const -{ - return mAxisAutoLock; -} - void ScrollView::SetAxisAutoLock(bool enable) { mAxisAutoLock = enable; - UpdateMainInternalConstraint(); -} - -float ScrollView::GetAxisAutoLockGradient() const -{ - return mAxisAutoLockGradient; + mConstraints.UpdateMainInternalConstraint(*this); } void ScrollView::SetAxisAutoLockGradient(float gradient) { DALI_ASSERT_DEBUG(gradient >= 0.0f && gradient <= 1.0f); mAxisAutoLockGradient = gradient; - UpdateMainInternalConstraint(); -} - -float ScrollView::GetFrictionCoefficient() const -{ - return mFrictionCoefficient; + mConstraints.UpdateMainInternalConstraint(*this); } void ScrollView::SetFrictionCoefficient(float friction) @@ -1112,56 +979,6 @@ void ScrollView::SetFrictionCoefficient(float friction) mFrictionCoefficient = friction; } -float ScrollView::GetFlickSpeedCoefficient() const -{ - return mFlickSpeedCoefficient; -} - -void ScrollView::SetFlickSpeedCoefficient(float speed) -{ - mFlickSpeedCoefficient = speed; -} - -Vector2 ScrollView::GetMinimumDistanceForFlick() const -{ - return mMinFlickDistance; -} - -void ScrollView::SetMinimumDistanceForFlick(const Vector2& distance) -{ - mMinFlickDistance = distance; -} - -float ScrollView::GetMinimumSpeedForFlick() const -{ - return mFlickSpeedThreshold; -} - -void ScrollView::SetMinimumSpeedForFlick(float speed) -{ - mFlickSpeedThreshold = speed; -} - -float ScrollView::GetMaxFlickSpeed() const -{ - return mMaxFlickSpeed; -} - -void ScrollView::SetMaxFlickSpeed(float speed) -{ - mMaxFlickSpeed = speed; -} - -void ScrollView::SetWheelScrollDistanceStep(Vector2 step) -{ - mWheelScrollDistanceStep = step; -} - -Vector2 ScrollView::GetWheelScrollDistanceStep() const -{ - return mWheelScrollDistanceStep; -} - unsigned int ScrollView::GetCurrentPage() const { // in case animation is currently taking place. @@ -1229,9 +1046,9 @@ void ScrollView::TransformTo(const Vector2& position, float duration, AlphaFunct mGestureStackDepth = 0; self.SetProperty(Toolkit::ScrollView::Property::PANNING, false); - if(mScrollMainInternalPrePositionConstraint) + if(mConstraints.mScrollMainInternalPrePositionConstraint) { - mScrollMainInternalPrePositionConstraint.Remove(); + mConstraints.mScrollMainInternalPrePositionConstraint.Remove(); } } @@ -1244,408 +1061,126 @@ void ScrollView::TransformTo(const Vector2& position, float duration, AlphaFunct Vector2::ONE * duration, alpha, true, - horizontalBias, - verticalBias, - SNAP); - - if(!animating) - { - // if not animating, then this pan has completed right now. - self.SetProperty(Toolkit::ScrollView::Property::SCROLLING, false); - mScrolling = false; - - // If we have no duration, then in the next update frame, we will be at the position specified as we just set. - // In this scenario, we cannot return the currentScrollPosition as this is out-of-date and should instead return the requested final position - Vector2 completedPosition(currentScrollPosition); - if(duration <= Math::MACHINE_EPSILON_10) - { - completedPosition = position; - } - - DALI_LOG_SCROLL_STATE("[0x%X] mScrollCompletedSignal 2 [%.2f, %.2f]", this, completedPosition.x, completedPosition.y); - SetScrollUpdateNotification(false); - mScrollCompletedSignal.Emit(completedPosition); - } -} - -void ScrollView::ScrollTo(const Vector2& position) -{ - ScrollTo(position, mSnapDuration); -} - -void ScrollView::ScrollTo(const Vector2& position, float duration) -{ - ScrollTo(position, duration, DIRECTION_BIAS_NONE, DIRECTION_BIAS_NONE); -} - -void ScrollView::ScrollTo(const Vector2& position, float duration, AlphaFunction alpha) -{ - ScrollTo(position, duration, alpha, DIRECTION_BIAS_NONE, DIRECTION_BIAS_NONE); -} - -void ScrollView::ScrollTo(const Vector2& position, float duration, DirectionBias horizontalBias, DirectionBias verticalBias) -{ - ScrollTo(position, duration, mSnapAlphaFunction, horizontalBias, verticalBias); -} - -void ScrollView::ScrollTo(const Vector2& position, float duration, AlphaFunction alpha, DirectionBias horizontalBias, DirectionBias verticalBias) -{ - DALI_LOG_SCROLL_STATE("[0x%X] position[%.2f, %.2f] duration[%.2f], bias[%d, %d]", this, position.x, position.y, duration, int(horizontalBias), int(verticalBias)); - TransformTo(position, duration, alpha, horizontalBias, verticalBias); -} - -void ScrollView::ScrollTo(unsigned int page) -{ - ScrollTo(page, mSnapDuration); -} - -void ScrollView::ScrollTo(unsigned int page, float duration, DirectionBias bias) -{ - Vector2 position; - unsigned int volume; - unsigned int libraries; - - // The position to scroll to is continuous and linear - // unless a domain has been enabled on the X axis. - // or if WrapMode has been enabled. - bool carryX = mRulerX->GetDomain().enabled | mWrapMode; - bool carryY = mRulerY->GetDomain().enabled | mWrapMode; - - position.x = mRulerX->GetPositionFromPage(page, volume, carryX); - position.y = mRulerY->GetPositionFromPage(volume, libraries, carryY); - - ScrollTo(position, duration, bias, bias); -} - -void ScrollView::ScrollTo(Actor& actor) -{ - ScrollTo(actor, mSnapDuration); -} - -void ScrollView::ScrollTo(Actor& actor, float duration) -{ - DALI_ASSERT_ALWAYS(actor.GetParent() == Self()); - - Actor self = Self(); - Vector3 size = self.GetCurrentProperty(Actor::Property::SIZE); - Vector3 position = actor.GetCurrentProperty(Actor::Property::POSITION); - Vector2 prePosition = GetPropertyPrePosition(); - position.GetVectorXY() -= prePosition; - - ScrollTo(Vector2(position.x - size.width * 0.5f, position.y - size.height * 0.5f), duration); -} - -Actor ScrollView::FindClosestActor() -{ - Actor self = Self(); - Vector3 size = self.GetCurrentProperty(Actor::Property::SIZE); - - return FindClosestActorToPosition(Vector3(size.width * 0.5f, size.height * 0.5f, 0.0f)); -} - -Actor ScrollView::FindClosestActorToPosition(const Vector3& position, FindDirection dirX, FindDirection dirY, FindDirection dirZ) -{ - Actor closestChild; - float closestDistance2 = 0.0f; - Vector3 actualPosition = position; - - unsigned int numChildren = Self().GetChildCount(); - - for(unsigned int i = 0; i < numChildren; ++i) - { - Actor child = Self().GetChildAt(i); - - if(mInternalActor == child) // ignore internal actor. - { - continue; - } - - Vector3 childPosition = GetPositionOfAnchor(child, AnchorPoint::CENTER); - - Vector3 delta = childPosition - actualPosition; - - // X-axis checking (only find Actors to the [dirX] of actualPosition) - if(dirX > All) // != All,None - { - FindDirection deltaH = delta.x > 0 ? Right : Left; - if(dirX != deltaH) - { - continue; - } - } - - // Y-axis checking (only find Actors to the [dirY] of actualPosition) - if(dirY > All) // != All,None - { - FindDirection deltaV = delta.y > 0 ? Down : Up; - if(dirY != deltaV) - { - continue; - } - } - - // Z-axis checking (only find Actors to the [dirZ] of actualPosition) - if(dirZ > All) // != All,None - { - FindDirection deltaV = delta.y > 0 ? In : Out; - if(dirZ != deltaV) - { - continue; - } - } - - // compare child to closest child in terms of distance. - float distance2 = 0.0f; - - // distance2 = the Square of the relevant dimensions of delta - if(dirX != None) - { - distance2 += delta.x * delta.x; - } - - if(dirY != None) - { - distance2 += delta.y * delta.y; - } - - if(dirZ != None) - { - distance2 += delta.z * delta.z; - } - - if(closestChild) // Next time. - { - if(distance2 < closestDistance2) - { - closestChild = child; - closestDistance2 = distance2; - } - } - else // First time. - { - closestChild = child; - closestDistance2 = distance2; - } - } - - return closestChild; -} - -bool ScrollView::ScrollToSnapPoint() -{ - DALI_LOG_SCROLL_STATE("[0x%X]", this); - Vector2 stationaryVelocity = Vector2(0.0f, 0.0f); - return SnapWithVelocity(stationaryVelocity); -} - -// TODO: In situations where axes are different (X snap, Y free) -// Each axis should really have their own independent animation (time and equation) -// Consider, X axis snapping to nearest grid point (EaseOut over fixed time) -// Consider, Y axis simulating physics to arrive at a point (Physics equation over variable time) -// Currently, the axes have been split however, they both use the same EaseOut equation. -bool ScrollView::SnapWithVelocity(Vector2 velocity) -{ - // Animator takes over now, touches are assumed not to interfere. - // And if touches do interfere, then we'll stop animation, update PrePosition - // to current mScroll's properties, and then resume. - // Note: For Flicking this may work a bit different... - - float angle = atan2(velocity.y, velocity.x); - float speed2 = velocity.LengthSquared(); - AlphaFunction alphaFunction = mSnapAlphaFunction; - Vector2 positionDuration = Vector2::ONE * mSnapDuration; - float biasX = 0.5f; - float biasY = 0.5f; - FindDirection horizontal = None; - FindDirection vertical = None; - - // orthoAngleRange = Angle tolerance within the Exact N,E,S,W direction - // that will be accepted as a general N,E,S,W flick direction. - - const float orthoAngleRange = FLICK_ORTHO_ANGLE_RANGE * M_PI / 180.0f; - const float flickSpeedThreshold2 = mFlickSpeedThreshold * mFlickSpeedThreshold; - - Vector2 positionSnap = mScrollPrePosition; - - // Flick logic X Axis - - if(mRulerX->IsEnabled() && mLockAxis != LockHorizontal) - { - horizontal = All; - - if(speed2 > flickSpeedThreshold2 || // exceeds flick threshold - mInAccessibilityPan) // With AccessibilityPan its easier to move between snap positions - { - if((angle >= -orthoAngleRange) && (angle < orthoAngleRange)) // Swiping East - { - biasX = 0.0f, horizontal = Left; - - // This guards against an error where no movement occurs, due to the flick finishing - // before the update-thread has advanced mScrollPostPosition past the the previous snap point. - positionSnap.x += 1.0f; - } - else if((angle >= M_PI - orthoAngleRange) || (angle < -M_PI + orthoAngleRange)) // Swiping West - { - biasX = 1.0f, horizontal = Right; - - // This guards against an error where no movement occurs, due to the flick finishing - // before the update-thread has advanced mScrollPostPosition past the the previous snap point. - positionSnap.x -= 1.0f; - } - } - } - - // Flick logic Y Axis + horizontalBias, + verticalBias, + SNAP); - if(mRulerY->IsEnabled() && mLockAxis != LockVertical) + if(!animating) { - vertical = All; + // if not animating, then this pan has completed right now. + self.SetProperty(Toolkit::ScrollView::Property::SCROLLING, false); + mScrolling = false; - if(speed2 > flickSpeedThreshold2 || // exceeds flick threshold - mInAccessibilityPan) // With AccessibilityPan its easier to move between snap positions + // If we have no duration, then in the next update frame, we will be at the position specified as we just set. + // In this scenario, we cannot return the currentScrollPosition as this is out-of-date and should instead return the requested final position + Vector2 completedPosition(currentScrollPosition); + if(duration <= Math::MACHINE_EPSILON_10) { - if((angle >= M_PI_2 - orthoAngleRange) && (angle < M_PI_2 + orthoAngleRange)) // Swiping South - { - biasY = 0.0f, vertical = Up; - } - else if((angle >= -M_PI_2 - orthoAngleRange) && (angle < -M_PI_2 + orthoAngleRange)) // Swiping North - { - biasY = 1.0f, vertical = Down; - } + completedPosition = position; } - } - // isFlick: Whether this gesture is a flick or not. - bool isFlick = (horizontal != All || vertical != All); - // isFreeFlick: Whether this gesture is a flick under free panning criteria. - bool isFreeFlick = velocity.LengthSquared() > (FREE_FLICK_SPEED_THRESHOLD * FREE_FLICK_SPEED_THRESHOLD); - - if(isFlick || isFreeFlick) - { - positionDuration = Vector2::ONE * mFlickDuration; - alphaFunction = mFlickAlphaFunction; + DALI_LOG_SCROLL_STATE("[0x%X] mScrollCompletedSignal 2 [%.2f, %.2f]", this, completedPosition.x, completedPosition.y); + SetScrollUpdateNotification(false); + mScrollCompletedSignal.Emit(completedPosition); } +} - // Calculate next positionSnap //////////////////////////////////////////////////////////// - - if(mActorAutoSnapEnabled) - { - Vector3 size = Self().GetCurrentProperty(Actor::Property::SIZE); +void ScrollView::ScrollTo(const Vector2& position) +{ + ScrollTo(position, mSnapDuration); +} - Actor child = FindClosestActorToPosition(Vector3(size.width * 0.5f, size.height * 0.5f, 0.0f), horizontal, vertical); +void ScrollView::ScrollTo(const Vector2& position, float duration) +{ + ScrollTo(position, duration, DIRECTION_BIAS_NONE, DIRECTION_BIAS_NONE); +} - if(!child && isFlick) - { - // If we conducted a direction limited search and found no actor, then just snap to the closest actor. - child = FindClosestActorToPosition(Vector3(size.width * 0.5f, size.height * 0.5f, 0.0f)); - } +void ScrollView::ScrollTo(const Vector2& position, float duration, AlphaFunction alpha) +{ + ScrollTo(position, duration, alpha, DIRECTION_BIAS_NONE, DIRECTION_BIAS_NONE); +} - if(child) - { - Vector2 position = Self().GetCurrentProperty(Toolkit::ScrollView::Property::SCROLL_POSITION); +void ScrollView::ScrollTo(const Vector2& position, float duration, DirectionBias horizontalBias, DirectionBias verticalBias) +{ + ScrollTo(position, duration, mSnapAlphaFunction, horizontalBias, verticalBias); +} - // Get center-point of the Actor. - Vector3 childPosition = GetPositionOfAnchor(child, AnchorPoint::CENTER); +void ScrollView::ScrollTo(const Vector2& position, float duration, AlphaFunction alpha, DirectionBias horizontalBias, DirectionBias verticalBias) +{ + DALI_LOG_SCROLL_STATE("[0x%X] position[%.2f, %.2f] duration[%.2f], bias[%d, %d]", this, position.x, position.y, duration, int(horizontalBias), int(verticalBias)); + TransformTo(position, duration, alpha, horizontalBias, verticalBias); +} - if(mRulerX->IsEnabled()) - { - positionSnap.x = position.x - childPosition.x + size.width * 0.5f; - } - if(mRulerY->IsEnabled()) - { - positionSnap.y = position.y - childPosition.y + size.height * 0.5f; - } - } - } +void ScrollView::ScrollTo(unsigned int page) +{ + ScrollTo(page, mSnapDuration); +} - Vector2 startPosition = positionSnap; - positionSnap.x = -mRulerX->Snap(-positionSnap.x, biasX); // NOTE: X & Y rulers think in -ve coordinate system. - positionSnap.y = -mRulerY->Snap(-positionSnap.y, biasY); // That is scrolling RIGHT (e.g. 100.0, 0.0) means moving LEFT. +void ScrollView::ScrollTo(unsigned int page, float duration, DirectionBias bias) +{ + Vector2 position; + unsigned int volume; + unsigned int libraries; - Vector2 clampDelta(Vector2::ZERO); - ClampPosition(positionSnap); + // The position to scroll to is continuous and linear + // unless a domain has been enabled on the X axis. + // or if WrapMode has been enabled. + bool carryX = mRulerX->GetDomain().enabled | mWrapMode; + bool carryY = mRulerY->GetDomain().enabled | mWrapMode; - if((mRulerX->GetType() == Ruler::FREE || mRulerY->GetType() == Ruler::FREE) && isFreeFlick && !mActorAutoSnapEnabled) - { - // Calculate target position based on velocity of flick. + position.x = mRulerX->GetPositionFromPage(page, volume, carryX); + position.y = mRulerY->GetPositionFromPage(volume, libraries, carryY); - // a = Deceleration (Set to diagonal stage length * friction coefficient) - // u = Initial Velocity (Flick velocity) - // v = 0 (Final Velocity) - // t = Time (Velocity / Deceleration) - Vector2 stageSize = Stage::GetCurrent().GetSize(); - float stageLength = Vector3(stageSize.x, stageSize.y, 0.0f).Length(); - float a = (stageLength * mFrictionCoefficient); - Vector3 u = Vector3(velocity.x, velocity.y, 0.0f) * mFlickSpeedCoefficient; - float speed = u.Length(); - u /= speed; + ScrollTo(position, duration, bias, bias); +} - // TODO: Change this to a decay function. (faster you flick, the slower it should be) - speed = std::min(speed, stageLength * mMaxFlickSpeed); - u *= speed; - alphaFunction = ConstantDecelerationAlphaFunction; +void ScrollView::ScrollTo(Actor& actor) +{ + ScrollTo(actor, mSnapDuration); +} - float t = speed / a; +void ScrollView::ScrollTo(Actor& actor, float duration) +{ + DALI_ASSERT_ALWAYS(actor.GetParent() == Self()); - if(mRulerX->IsEnabled() && mRulerX->GetType() == Ruler::FREE) - { - positionSnap.x += t * u.x * 0.5f; - } + Actor self = Self(); + Vector3 size = self.GetCurrentProperty(Actor::Property::SIZE); + Vector3 position = actor.GetCurrentProperty(Actor::Property::POSITION); + Vector2 prePosition = GetPropertyPrePosition(); + position.GetVectorXY() -= prePosition; - if(mRulerY->IsEnabled() && mRulerY->GetType() == Ruler::FREE) - { - positionSnap.y += t * u.y * 0.5f; - } + ScrollTo(Vector2(position.x - size.width * 0.5f, position.y - size.height * 0.5f), duration); +} - clampDelta = positionSnap; - ClampPosition(positionSnap); - if((positionSnap - startPosition).LengthSquared() > Math::MACHINE_EPSILON_0) - { - clampDelta -= positionSnap; - clampDelta.x = clampDelta.x > 0.0f ? std::min(clampDelta.x, mMaxOvershoot.x) : std::max(clampDelta.x, -mMaxOvershoot.x); - clampDelta.y = clampDelta.y > 0.0f ? std::min(clampDelta.y, mMaxOvershoot.y) : std::max(clampDelta.y, -mMaxOvershoot.y); - } - else - { - clampDelta = Vector2::ZERO; - } +Actor ScrollView::FindClosestActor() +{ + Actor self = Self(); + Vector3 size = self.GetCurrentProperty(Actor::Property::SIZE); - // If Axis is Free and has velocity, then calculate time taken - // to reach target based on velocity in axis. - if(mRulerX->IsEnabled() && mRulerX->GetType() == Ruler::FREE) - { - float deltaX = fabsf(startPosition.x - positionSnap.x); + return FindClosestActorToPosition(Vector3(size.width * 0.5f, size.height * 0.5f, 0.0f)); +} - if(fabsf(u.x) > Math::MACHINE_EPSILON_1) - { - positionDuration.x = fabsf(deltaX / u.x); - } - else - { - positionDuration.x = 0; - } - } +Actor ScrollView::FindClosestActorToPosition(const Vector3& position, FindDirection dirX, FindDirection dirY, FindDirection dirZ) +{ + return ::FindClosestActorToPosition(Self(), mInternalActor, position, dirX, dirY, dirZ); +} - if(mRulerY->IsEnabled() && mRulerY->GetType() == Ruler::FREE) - { - float deltaY = fabsf(startPosition.y - positionSnap.y); +bool ScrollView::ScrollToSnapPoint() +{ + DALI_LOG_SCROLL_STATE("[0x%X]", this); + Vector2 stationaryVelocity = Vector2(0.0f, 0.0f); + return SnapWithVelocity(stationaryVelocity); +} - if(fabsf(u.y) > Math::MACHINE_EPSILON_1) - { - positionDuration.y = fabsf(deltaY / u.y); - } - else - { - positionDuration.y = 0; - } - } - } +bool ScrollView::SnapWithVelocity(Vector2 velocity) +{ + Vector2 positionSnap = mScrollPrePosition; + Vector2 positionDuration = Vector2::ONE * mSnapDuration; + AlphaFunction alphaFunction = mSnapAlphaFunction; + bool isFlick; + bool isFreeFlick; - if(IsOvershootEnabled()) - { - // Scroll to the end of the overshoot only when overshoot is enabled. - positionSnap += clampDelta; - } + ::SnapWithVelocity(*this, mRulerX, mRulerY, mLockAxis, velocity, mMaxOvershoot, positionSnap, positionDuration, alphaFunction, mInAccessibilityPan, isFlick, isFreeFlick); bool animating = AnimateTo(positionSnap, positionDuration, alphaFunction, false, DIRECTION_BIAS_NONE, DIRECTION_BIAS_NONE, isFlick || isFreeFlick ? FLICK : SNAP); @@ -1698,7 +1233,7 @@ bool ScrollView::AnimateTo(const Vector2& position, const Vector2& positionDurat // Position Delta /////////////////////////////////////////////////////// if(positionChanged) { - UpdateMainInternalConstraint(); + mConstraints.UpdateMainInternalConstraint(*this); if(mWrapMode && findShortcuts) { // In Wrap Mode, the shortest distance is a little less intuitive... @@ -1771,7 +1306,7 @@ void ScrollView::EnableScrollOvershoot(bool enable) } } - UpdateMainInternalConstraint(); + mConstraints.UpdateMainInternalConstraint(*this); } void ScrollView::AddOverlay(Actor actor) @@ -1826,7 +1361,7 @@ Toolkit::ScrollView::SnapStartedSignalType& ScrollView::SnapStartedSignal() bool ScrollView::AccessibleImpl::ScrollToChild(Actor child) { auto scrollView = Dali::Toolkit::ScrollView::DownCast(Self()); - if (Toolkit::GetImpl(scrollView).FindClosestActor() == child) + if(Toolkit::GetImpl(scrollView).FindClosestActor() == child) { return false; } @@ -1963,7 +1498,7 @@ void ScrollView::OnSizeSet(const Vector3& size) } } UpdatePropertyDomain(); - UpdateMainInternalConstraint(); + mConstraints.UpdateMainInternalConstraint(*this); if(IsOvershootEnabled()) { mOvershootIndicator->Reset(); @@ -2503,7 +2038,7 @@ void ScrollView::OnPan(const PanGesture& gesture) self.SetProperty(Toolkit::ScrollView::Property::PANNING, true); self.SetProperty(Toolkit::ScrollView::Property::START_PAGE_POSITION, Vector3(position.x, position.y, 0.0f)); - UpdateMainInternalConstraint(); + mConstraints.UpdateMainInternalConstraint(*this); Toolkit::ScrollBar scrollBar = mScrollBar.GetHandle(); if(scrollBar && mTransientScrollBar) { @@ -2546,9 +2081,9 @@ void ScrollView::OnPan(const PanGesture& gesture) mPanning = false; self.SetProperty(Toolkit::ScrollView::Property::PANNING, false); - if(mScrollMainInternalPrePositionConstraint) + if(mConstraints.mScrollMainInternalPrePositionConstraint) { - mScrollMainInternalPrePositionConstraint.Remove(); + mConstraints.mScrollMainInternalPrePositionConstraint.Remove(); } Toolkit::ScrollBar scrollBar = mScrollBar.GetHandle(); @@ -2704,8 +2239,7 @@ void ScrollView::ClampPosition(Vector2& position, ClampState2D& clamped) const { Vector3 size = Self().GetCurrentProperty(Actor::Property::SIZE); - position.x = -mRulerX->Clamp(-position.x, size.width, 1.0f, clamped.x); // NOTE: X & Y rulers think in -ve coordinate system. - position.y = -mRulerY->Clamp(-position.y, size.height, 1.0f, clamped.y); // That is scrolling RIGHT (e.g. 100.0, 0.0) means moving LEFT. + ::ClampPosition(size, mRulerX, mRulerY, position, clamped); } void ScrollView::WrapPosition(Vector2& position) const @@ -2727,168 +2261,6 @@ void ScrollView::WrapPosition(Vector2& position) const } } -void ScrollView::UpdateMainInternalConstraint() -{ - // TODO: Only update the constraints which have changed, rather than remove all and add all again. - // Requires a dali-core ApplyConstraintAt, or a ReplaceConstraint. The former is probably more flexible. - Actor self = Self(); - PanGestureDetector detector(GetPanGestureDetector()); - - if(mScrollMainInternalPositionConstraint) - { - mScrollMainInternalPositionConstraint.Remove(); - mScrollMainInternalDeltaConstraint.Remove(); - mScrollMainInternalFinalConstraint.Remove(); - mScrollMainInternalRelativeConstraint.Remove(); - mScrollMainInternalDomainConstraint.Remove(); - mScrollMainInternalPrePositionMaxConstraint.Remove(); - } - if(mScrollMainInternalPrePositionConstraint) - { - mScrollMainInternalPrePositionConstraint.Remove(); - } - - // TODO: It's probably better to use a local displacement value as this will give a displacement when scrolling just commences - // but we need to make sure than the gesture system gives displacement since last frame (60Hz), not displacement since last touch event (90Hz). - - // 1. First calculate the pre-position (this is the scroll position if no clamping has taken place) - Vector2 initialPanMask = Vector2(mRulerX->IsEnabled() ? 1.0f : 0.0f, mRulerY->IsEnabled() ? 1.0f : 0.0f); - - if(mLockAxis == LockVertical) - { - initialPanMask.y = 0.0f; - } - else if(mLockAxis == LockHorizontal) - { - initialPanMask.x = 0.0f; - } - - if(mPanning) - { - mScrollMainInternalPrePositionConstraint = Constraint::New(self, - Toolkit::ScrollView::Property::SCROLL_PRE_POSITION, - InternalPrePositionConstraint(mPanStartPosition, - initialPanMask, - mAxisAutoLock, - mAxisAutoLockGradient, - mLockAxis, - mMaxOvershoot, - mRulerX, - mRulerY)); - mScrollMainInternalPrePositionConstraint.AddSource(Source(detector, PanGestureDetector::Property::LOCAL_POSITION)); - mScrollMainInternalPrePositionConstraint.AddSource(Source(detector, PanGestureDetector::Property::PANNING)); - mScrollMainInternalPrePositionConstraint.AddSource(Source(self, Actor::Property::SIZE)); - mScrollMainInternalPrePositionConstraint.Apply(); - } - - // 2. Second calculate the clamped position (actual position) - mScrollMainInternalPositionConstraint = Constraint::New(self, - Toolkit::ScrollView::Property::SCROLL_POSITION, - InternalPositionConstraint(mRulerX->GetDomain(), - mRulerY->GetDomain(), - mWrapMode)); - mScrollMainInternalPositionConstraint.AddSource(LocalSource(Toolkit::ScrollView::Property::SCROLL_PRE_POSITION)); - mScrollMainInternalPositionConstraint.AddSource(LocalSource(Toolkit::Scrollable::Property::SCROLL_POSITION_MIN)); - mScrollMainInternalPositionConstraint.AddSource(LocalSource(Toolkit::Scrollable::Property::SCROLL_POSITION_MAX)); - mScrollMainInternalPositionConstraint.AddSource(Source(self, Actor::Property::SIZE)); - mScrollMainInternalPositionConstraint.Apply(); - - mScrollMainInternalDeltaConstraint = Constraint::New(self, Toolkit::ScrollView::Property::SCROLL_POSITION_DELTA, InternalPositionDeltaConstraint); - mScrollMainInternalDeltaConstraint.AddSource(LocalSource(Toolkit::ScrollView::Property::SCROLL_POSITION)); - mScrollMainInternalDeltaConstraint.AddSource(LocalSource(Toolkit::ScrollView::Property::SCROLL_DOMAIN_OFFSET)); - mScrollMainInternalDeltaConstraint.Apply(); - - mScrollMainInternalFinalConstraint = Constraint::New(self, Toolkit::ScrollView::Property::SCROLL_FINAL, InternalFinalConstraint(FinalDefaultAlphaFunction, FinalDefaultAlphaFunction)); - mScrollMainInternalFinalConstraint.AddSource(LocalSource(Toolkit::ScrollView::Property::SCROLL_POSITION)); - mScrollMainInternalFinalConstraint.AddSource(LocalSource(Toolkit::ScrollView::Property::OVERSHOOT_X)); - mScrollMainInternalFinalConstraint.AddSource(LocalSource(Toolkit::ScrollView::Property::OVERSHOOT_Y)); - mScrollMainInternalFinalConstraint.Apply(); - - mScrollMainInternalRelativeConstraint = Constraint::New(self, Toolkit::Scrollable::Property::SCROLL_RELATIVE_POSITION, InternalRelativePositionConstraint); - mScrollMainInternalRelativeConstraint.AddSource(LocalSource(Toolkit::ScrollView::Property::SCROLL_POSITION)); - mScrollMainInternalRelativeConstraint.AddSource(LocalSource(Toolkit::Scrollable::Property::SCROLL_POSITION_MIN)); - mScrollMainInternalRelativeConstraint.AddSource(LocalSource(Toolkit::Scrollable::Property::SCROLL_POSITION_MAX)); - mScrollMainInternalRelativeConstraint.AddSource(LocalSource(Actor::Property::SIZE)); - mScrollMainInternalRelativeConstraint.Apply(); - - mScrollMainInternalDomainConstraint = Constraint::New(self, Toolkit::ScrollView::Property::SCROLL_DOMAIN_SIZE, InternalScrollDomainConstraint); - mScrollMainInternalDomainConstraint.AddSource(LocalSource(Toolkit::Scrollable::Property::SCROLL_POSITION_MIN)); - mScrollMainInternalDomainConstraint.AddSource(LocalSource(Toolkit::Scrollable::Property::SCROLL_POSITION_MAX)); - mScrollMainInternalDomainConstraint.AddSource(LocalSource(Actor::Property::SIZE)); - mScrollMainInternalDomainConstraint.Apply(); - - mScrollMainInternalPrePositionMaxConstraint = Constraint::New(self, Toolkit::ScrollView::Property::SCROLL_PRE_POSITION_MAX, InternalPrePositionMaxConstraint); - mScrollMainInternalPrePositionMaxConstraint.AddSource(LocalSource(Toolkit::Scrollable::Property::SCROLL_POSITION_MAX)); - mScrollMainInternalPrePositionMaxConstraint.AddSource(LocalSource(Actor::Property::SIZE)); - mScrollMainInternalPrePositionMaxConstraint.Apply(); - - // When panning we want to make sure overshoot values are affected by pre position and post position - SetOvershootConstraintsEnabled(!mWrapMode); -} - -void ScrollView::SetOvershootConstraintsEnabled(bool enabled) -{ - Actor self(Self()); - // remove and reset, it may now be in wrong order with the main internal constraints - if(mScrollMainInternalOvershootXConstraint) - { - mScrollMainInternalOvershootXConstraint.Remove(); - mScrollMainInternalOvershootXConstraint.Reset(); - mScrollMainInternalOvershootYConstraint.Remove(); - mScrollMainInternalOvershootYConstraint.Reset(); - } - if(enabled) - { - mScrollMainInternalOvershootXConstraint = Constraint::New(self, Toolkit::ScrollView::Property::OVERSHOOT_X, OvershootXConstraint(mMaxOvershoot.x)); - mScrollMainInternalOvershootXConstraint.AddSource(LocalSource(Toolkit::ScrollView::Property::SCROLL_PRE_POSITION)); - mScrollMainInternalOvershootXConstraint.AddSource(LocalSource(Toolkit::ScrollView::Property::SCROLL_POSITION)); - mScrollMainInternalOvershootXConstraint.AddSource(LocalSource(Toolkit::Scrollable::Property::CAN_SCROLL_HORIZONTAL)); - mScrollMainInternalOvershootXConstraint.Apply(); - - mScrollMainInternalOvershootYConstraint = Constraint::New(self, Toolkit::ScrollView::Property::OVERSHOOT_Y, OvershootYConstraint(mMaxOvershoot.y)); - mScrollMainInternalOvershootYConstraint.AddSource(LocalSource(Toolkit::ScrollView::Property::SCROLL_PRE_POSITION)); - mScrollMainInternalOvershootYConstraint.AddSource(LocalSource(Toolkit::ScrollView::Property::SCROLL_POSITION)); - mScrollMainInternalOvershootYConstraint.AddSource(LocalSource(Toolkit::Scrollable::Property::CAN_SCROLL_VERTICAL)); - mScrollMainInternalOvershootYConstraint.Apply(); - } - else - { - self.SetProperty(Toolkit::ScrollView::Property::OVERSHOOT_X, 0.0f); - self.SetProperty(Toolkit::ScrollView::Property::OVERSHOOT_Y, 0.0f); - } -} - -void ScrollView::SetInternalConstraints() -{ - // Internal constraints (applied to target ScrollBase Actor itself) ///////// - UpdateMainInternalConstraint(); - - // User definable constraints to apply to all child actors ////////////////// - Actor self = Self(); - - // Apply some default constraints to ScrollView & its bound actors - // Movement + Wrap function - - Constraint constraint; - - // MoveActor (scrolling) - constraint = Constraint::New(self, Actor::Property::POSITION, MoveActorConstraint); - constraint.AddSource(Source(self, Toolkit::ScrollView::Property::SCROLL_POSITION)); - constraint.SetRemoveAction(Constraint::DISCARD); - ApplyConstraintToBoundActors(constraint); - - // WrapActor (wrap functionality) - constraint = Constraint::New(self, Actor::Property::POSITION, WrapActorConstraint); - constraint.AddSource(LocalSource(Actor::Property::SCALE)); - constraint.AddSource(LocalSource(Actor::Property::ANCHOR_POINT)); - constraint.AddSource(LocalSource(Actor::Property::SIZE)); - constraint.AddSource(Source(self, Toolkit::Scrollable::Property::SCROLL_POSITION_MIN)); - constraint.AddSource(Source(self, Toolkit::Scrollable::Property::SCROLL_POSITION_MAX)); - constraint.AddSource(Source(self, Toolkit::ScrollView::Property::WRAP)); - constraint.SetRemoveAction(Constraint::DISCARD); - ApplyConstraintToBoundActors(constraint); -} - void ScrollView::SetProperty(BaseObject* object, Property::Index index, const Property::Value& value) { Toolkit::ScrollView scrollView = Toolkit::ScrollView::DownCast(Dali::BaseHandle(object)); @@ -3051,6 +2423,31 @@ void ScrollView::SetScrollMode(const Property::Map& scrollModeMap) SetRulerY(rulerY); } +ScrollView::LockAxis GetLockAxis(const Vector2& panDelta, ScrollView::LockAxis currentLockAxis, float lockGradient) +{ + if(panDelta.LengthSquared() > AUTOLOCK_AXIS_MINIMUM_DISTANCE2 && + currentLockAxis == ScrollView::LockPossible) + { + float dx = fabsf(panDelta.x); + float dy = fabsf(panDelta.y); + if(dx * lockGradient >= dy) + { + // 0.36:1 gradient to the horizontal (deviate < 20 degrees) + currentLockAxis = ScrollView::LockVertical; + } + else if(dy * lockGradient > dx) + { + // 0.36:1 gradient to the vertical (deviate < 20 degrees) + currentLockAxis = ScrollView::LockHorizontal; + } + else + { + currentLockAxis = ScrollView::LockNone; + } + } + return currentLockAxis; +} + } // namespace Internal } // namespace Toolkit diff --git a/dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-impl.h b/dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-impl.h index aee050e..4d871a7 100644 --- a/dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-impl.h +++ b/dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-impl.h @@ -30,6 +30,7 @@ #include #include #include +#include namespace Dali { @@ -103,42 +104,66 @@ public: /** * @copydoc Toolkit::ScrollView::GetScrollSnapAlphaFunction */ - AlphaFunction GetScrollSnapAlphaFunction() const; + AlphaFunction GetScrollSnapAlphaFunction() const + { + return mSnapAlphaFunction; + } /** * @copydoc Toolkit::ScrollView::SetScrollSnapAlphaFunction */ - void SetScrollSnapAlphaFunction(AlphaFunction alpha); + void SetScrollSnapAlphaFunction(AlphaFunction alpha) + { + mSnapAlphaFunction = alpha; + } /** * @copydoc Toolkit::ScrollView::GetScrollFlickAlphaFunction */ - AlphaFunction GetScrollFlickAlphaFunction() const; + AlphaFunction GetScrollFlickAlphaFunction() const + { + return mFlickAlphaFunction; + } /** * @copydoc Toolkit::ScrollView::SetScrollFlickAlphaFunction */ - void SetScrollFlickAlphaFunction(AlphaFunction alpha); + void SetScrollFlickAlphaFunction(AlphaFunction alpha) + { + mFlickAlphaFunction = alpha; + } /** * @copydoc Toolkit::ScrollView::GetScrollSnapDuration */ - float GetScrollSnapDuration() const; + float GetScrollSnapDuration() const + { + return mSnapDuration; + } /** * @copydoc Toolkit::ScrollView::SetScrollSnapDuration */ - void SetScrollSnapDuration(float time); + void SetScrollSnapDuration(float time) + { + mSnapDuration = time; + } /** * @copydoc Toolkit::ScrollView::GetScrollFlickDuration */ - float GetScrollFlickDuration() const; + float GetScrollFlickDuration() const + { + return mFlickDuration; + } /** * @copydoc Toolkit::ScrollView::SetScrollFlickDuration */ - void SetScrollFlickDuration(float time); + void SetScrollFlickDuration(float time) + { + mFlickDuration = time; + } /** * @copydoc Toolkit::ScrollView::ApplyEffect @@ -168,12 +193,18 @@ public: /** * @copydoc Toolkit::ScrollView::GetRulerX */ - const RulerPtr GetRulerX() const; + const RulerPtr GetRulerX() const + { + return mRulerX; + } /** * @copydoc Toolkit::ScrollView::GetRulerY */ - const RulerPtr GetRulerY() const; + const RulerPtr GetRulerY() const + { + return mRulerY; + } /** * @copydoc Toolkit::ScrollView::SetRulerX @@ -190,7 +221,10 @@ public: * * @return whether the touch sensitivity is true or false. */ - bool GetScrollSensitive(); + bool GetScrollSensitive() + { + return mSensitive; + } /** * @copydoc Toolkit::ScrollView::SetScrollSensitive @@ -205,19 +239,28 @@ public: /** * @copydoc Toolkit::ScrollView::SetSnapOvershootAlphaFunction */ - void SetSnapOvershootAlphaFunction(AlphaFunction alpha); + void SetSnapOvershootAlphaFunction(AlphaFunction alpha) + { + mSnapOvershootAlphaFunction = alpha; + } /** * Retrieve the duartion of Snap Overshoot animation * * @return the duration. */ - float GetSnapOvershootDuration(); + float GetSnapOvershootDuration() + { + return mSnapOvershootDuration; + } /** * @copydoc Toolkit::ScrollView::SetSnapOvershootDuration */ - void SetSnapOvershootDuration(float duration); + void SetSnapOvershootDuration(float duration) + { + mSnapOvershootDuration = duration; + } /** * Retrieve whether Actor Auto-Snap mode is enabled or not. @@ -229,7 +272,10 @@ public: /** * @copydoc Toolkit::ScrollView::SetActorAutoSnap */ - void SetActorAutoSnap(bool enable); + void SetActorAutoSnap(bool enable) + { + mActorAutoSnapEnabled = enable; + } /** * Enables or Disables Auto Resizing mode for ScrollView contents. @@ -251,7 +297,10 @@ public: * * @return Wrap Mode Enabled flag. */ - bool GetWrapMode() const; + bool GetWrapMode() const + { + return mWrapMode; + } /** * @copydoc Toolkit::ScrollView::SetWrapMode @@ -261,17 +310,26 @@ public: /** * @copydoc Toolkit::ScrollView::GetScrollupdateDistance */ - int GetScrollUpdateDistance() const; + int GetScrollUpdateDistance() const + { + return mScrollUpdateDistance; + } /** * @copydoc Toolkit::ScrollView::SetScrollUpdateDistance */ - void SetScrollUpdateDistance(int distance); + void SetScrollUpdateDistance(int distance) + { + mScrollUpdateDistance = distance; + } /** * @copydoc Toolkit::ScrollView::GetAxisAutoLock */ - bool GetAxisAutoLock() const; + bool GetAxisAutoLock() const + { + return mAxisAutoLock; + } /** * @copydoc Toolkit::ScrollView::SetAxisAutoLock @@ -281,7 +339,10 @@ public: /** * @copydoc Toolkit::ScrollView::GetAxisAutoLockGradient */ - float GetAxisAutoLockGradient() const; + float GetAxisAutoLockGradient() const + { + return mAxisAutoLockGradient; + } /** * @copydoc Toolkit::ScrollView::SetAxisAutoLockGradient @@ -291,7 +352,10 @@ public: /** * @copydoc Toolkit::ScrollView::GetFrictionCoefficient */ - float GetFrictionCoefficient() const; + float GetFrictionCoefficient() const + { + return mFrictionCoefficient; + } /** * @copydoc Toolkit::ScrollView::SetFrictionCoefficient @@ -301,52 +365,82 @@ public: /** * @copydoc Toolkit::ScrollView::GetFlickSpeedCoefficient */ - float GetFlickSpeedCoefficient() const; + float GetFlickSpeedCoefficient() const + { + return mFlickSpeedCoefficient; + } /** * @copydoc Toolkit::ScrollView::SetFlickSpeedCoefficient */ - void SetFlickSpeedCoefficient(float speed); + void SetFlickSpeedCoefficient(float speed) + { + mFlickSpeedCoefficient = speed; + } /** * @copydoc Toolkit::ScrollView::GetMinimumDistanceForFlick */ - Vector2 GetMinimumDistanceForFlick() const; + Vector2 GetMinimumDistanceForFlick() const + { + return mMinFlickDistance; + } /** * @copydoc Toolkit::ScrollView::SetMinimumDistanceForFlick */ - void SetMinimumDistanceForFlick(const Vector2& distance); + void SetMinimumDistanceForFlick(const Vector2& distance) + { + mMinFlickDistance = distance; + } /** * @copydoc Toolkit::ScrollView::GetMinimumSpeedForFlick */ - float GetMinimumSpeedForFlick() const; + float GetMinimumSpeedForFlick() const + { + return mFlickSpeedThreshold; + } /** * @copydoc Toolkit::ScrollView::SetMinimumSpeedForFlick */ - void SetMinimumSpeedForFlick(float speed); + void SetMinimumSpeedForFlick(float speed) + { + mFlickSpeedThreshold = speed; + } /** * @copydoc Toolkit::ScrollView::GetMaxFlickSpeed */ - float GetMaxFlickSpeed() const; + float GetMaxFlickSpeed() const + { + return mMaxFlickSpeed; + } /** * @copydoc Toolkit::ScrollView::SetMaxFlickSpeed */ - void SetMaxFlickSpeed(float speed); + void SetMaxFlickSpeed(float speed) + { + mMaxFlickSpeed = speed; + } /** * @copydoc Toolkit::ScrollView::GetWheelScrollDistanceStep */ - Vector2 GetWheelScrollDistanceStep() const; + Vector2 GetWheelScrollDistanceStep() const + { + return mWheelScrollDistanceStep; + } /** * @copydoc Toolkit::ScrollView::SetWheelScrollDistanceStep */ - void SetWheelScrollDistanceStep(Vector2 step); + void SetWheelScrollDistanceStep(Vector2 step) + { + mWheelScrollDistanceStep = step; + } /** * @copydoc Toolkit::ScrollView::GetCurrentPage @@ -765,26 +859,6 @@ private: */ void WrapPosition(Vector2& position) const; - /** - * Updates the main internal scroll constraints with new ruler and domain - * values - */ - void UpdateMainInternalConstraint(); - - /** - * Enables/disables the overshoot constraints - * - * @param[in] enabled whether to enable or disable the overshoot constraints - */ - void SetOvershootConstraintsEnabled(bool enabled); - - /** - * Sets internal constraints for this ScrollView. - * Many of these internal constraints are based on properties within - * ScrollView. - */ - void SetInternalConstraints(); - protected: struct AccessibleImpl : public Scrollable::AccessibleImpl { @@ -865,6 +939,8 @@ private: ScrollView& operator=(const ScrollView& rhs); private: + ScrollViewConstraints mConstraints; + unsigned long mTouchDownTime; ///< The touch down time int mGestureStackDepth; ///< How many gestures are currently occuring. @@ -922,17 +998,6 @@ private: Vector2 mWheelScrollDistanceStep; ///< The step of scroll distance in actor coordinates in X and Y axes for each wheel event received. - //ScrollInternalConstraintsPtr mScrollInternalConstraints; - Constraint mScrollMainInternalPrePositionConstraint; - Constraint mScrollMainInternalPositionConstraint; - Constraint mScrollMainInternalOvershootXConstraint; - Constraint mScrollMainInternalOvershootYConstraint; - Constraint mScrollMainInternalDeltaConstraint; - Constraint mScrollMainInternalFinalConstraint; - Constraint mScrollMainInternalRelativeConstraint; - Constraint mScrollMainInternalDomainConstraint; - Constraint mScrollMainInternalPrePositionMaxConstraint; - ScrollOvershootIndicatorPtr mOvershootIndicator; WeakHandle mScrollBar; @@ -953,8 +1018,21 @@ private: bool mCanScrollHorizontal : 1; ///< Local value of our property to check against bool mCanScrollVertical : 1; ///< Local value of our property to check against bool mTransientScrollBar : 1; ///< True if scroll-bar should be automatically show/hidden during/after panning + + friend ScrollViewConstraints; }; +/** + * Returns whether to lock scrolling to a particular axis + * + * @param[in] panDelta Distance panned since gesture started + * @param[in] currentLockAxis The current lock axis value + * @param[in] lockGradient How quickly to lock to a particular axis + * + * @return The new axis lock state + */ +ScrollView::LockAxis GetLockAxis(const Vector2& panDelta, ScrollView::LockAxis currentLockAxis, float lockGradient); + } // namespace Internal // Helpers for public-api forwarding methods diff --git a/dali-toolkit/internal/controls/table-view/table-view-impl.cpp b/dali-toolkit/internal/controls/table-view/table-view-impl.cpp index 4b3e019..9aec5ba 100644 --- a/dali-toolkit/internal/controls/table-view/table-view-impl.cpp +++ b/dali-toolkit/internal/controls/table-view/table-view-impl.cpp @@ -51,7 +51,7 @@ bool FitToChild(Actor actor, Dimension::Type dimension) // currently not called from code so compiler will optimize these away, kept here for future debugging #define TABLEVIEW_TAG "DALI Toolkit::TableView " -#define TV_LOG(fmt, args, ...) Debug::LogMessage(Debug::DebugInfo, TABLEVIEW_TAG fmt, ##args) +#define TV_LOG(fmt, args, ...) Debug::LogMessageWithFunctionLine(Debug::DebugInfo, TABLEVIEW_TAG fmt, ##args) //#define TABLEVIEW_DEBUG 1 #if defined(TABLEVIEW_DEBUG) diff --git a/dali-toolkit/internal/controls/text-controls/common-text-utils.cpp b/dali-toolkit/internal/controls/text-controls/common-text-utils.cpp new file mode 100644 index 0000000..7331f3e --- /dev/null +++ b/dali-toolkit/internal/controls/text-controls/common-text-utils.cpp @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2021 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::Toolkit::Internal +{ +void CommonTextUtils::RenderText( + Actor textActor, + Text::RendererPtr renderer, + Text::ControllerPtr controller, + Text::DecoratorPtr decorator, + float alignmentOffset, + Actor& renderableActor, + Actor& backgroundActor, + Toolkit::Control& stencil, + std::vector& clippingDecorationActors, + Text::Controller::UpdateTextType updateTextType) +{ + Actor newRenderableActor; + + if(Text::Controller::NONE_UPDATED != (Text::Controller::MODEL_UPDATED & updateTextType)) + { + if(renderer) + { + newRenderableActor = renderer->Render(controller->GetView(), + textActor, + Property::INVALID_INDEX, // Animatable property not supported + alignmentOffset, + DepthIndex::CONTENT); + } + + if(renderableActor != newRenderableActor) + { + UnparentAndReset(backgroundActor); + UnparentAndReset(renderableActor); + renderableActor = newRenderableActor; + + if(renderableActor) + { + backgroundActor = controller->CreateBackgroundActor(); + } + } + } + + if(renderableActor) + { + const Vector2& scrollOffset = controller->GetTextModel()->GetScrollPosition(); + + float renderableActorPositionX, renderableActorPositionY; + + if(stencil) + { + renderableActorPositionX = scrollOffset.x + alignmentOffset; + renderableActorPositionY = scrollOffset.y; + } + else + { + Extents padding; + padding = textActor.GetProperty(Toolkit::Control::Property::PADDING); + + // Support Right-To-Left of padding + Dali::LayoutDirection::Type layoutDirection = static_cast(textActor.GetProperty(Dali::Actor::Property::LAYOUT_DIRECTION).Get()); + if(Dali::LayoutDirection::RIGHT_TO_LEFT == layoutDirection) + { + std::swap(padding.start, padding.end); + } + + renderableActorPositionX = scrollOffset.x + alignmentOffset + padding.start; + renderableActorPositionY = scrollOffset.y + padding.top; + } + + renderableActor.SetProperty(Actor::Property::POSITION, Vector2(renderableActorPositionX, renderableActorPositionY)); + + // Make sure the actors are parented correctly with/without clipping + Actor self = stencil ? stencil : textActor; + + Actor highlightActor; + + for(std::vector::iterator it = clippingDecorationActors.begin(), + endIt = clippingDecorationActors.end(); + it != endIt; + ++it) + { + self.Add(*it); + it->LowerToBottom(); + + if(it->GetProperty(Dali::Actor::Property::NAME) == "HighlightActor") + { + highlightActor = *it; + } + } + clippingDecorationActors.clear(); + + self.Add(renderableActor); + + if(backgroundActor) + { + if(decorator && decorator->IsHighlightVisible()) + { + self.Add(backgroundActor); + backgroundActor.SetProperty(Actor::Property::POSITION, Vector2(renderableActorPositionX, renderableActorPositionY)); // In text field's coords. + backgroundActor.LowerBelow(highlightActor); + } + else + { + renderableActor.Add(backgroundActor); + backgroundActor.SetProperty(Actor::Property::POSITION, Vector2(0.0f, 0.0f)); // In renderable actor's coords. + backgroundActor.LowerToBottom(); + } + } + } +} + +} // namespace Dali::Toolkit::Internal diff --git a/dali-toolkit/internal/controls/text-controls/common-text-utils.h b/dali-toolkit/internal/controls/text-controls/common-text-utils.h new file mode 100644 index 0000000..f2eaba7 --- /dev/null +++ b/dali-toolkit/internal/controls/text-controls/common-text-utils.h @@ -0,0 +1,62 @@ +#ifndef DALI_TOOLKIT_INTERNAL_TEXT_CONTROLS_COMMON_TEXT_UTILS_H +#define DALI_TOOLKIT_INTERNAL_TEXT_CONTROLS_COMMON_TEXT_UTILS_H + +/* + * Copyright (c) 2021 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 +#include +#include + +#include + +namespace Dali::Toolkit::Internal +{ +class CommonTextUtils +{ +public: + /** + * Common method to render text, setting up background, foreground actors with decorators/stencil. + * @param[in] textActor The TextEditor or TextField + * @param[in] renderer pointer to the text renderer + * @param[in] controller pointer to the text controller + * @param[in] decorator pointer to the text decorator + * @param[in] alignmentOffset Alignment offset + * @param[in,out] renderableActor Actor for rendering text + * @param[in,out] backgroundActor Actor for rendering background + * @param[in,out] stencil Clipping actor + * @param[in,out] clippingDecorationActors Clipping decoration actors + * @param[in] updateTextType How the text has been updated + */ + static void RenderText( + Actor textActor, + Text::RendererPtr renderer, + Text::ControllerPtr controller, + Text::DecoratorPtr decorator, + float alignmentOffset, + Actor& renderableActor, + Actor& backgroundActor, + Toolkit::Control& stencil, + std::vector& clippingDecorationActors, + Text::Controller::UpdateTextType updateTextType); +}; + +} // namespace Dali::Toolkit::Internal + +#endif //DALI_TOOLKIT_INTERNAL_TEXT_CONTROLS_COMMON_TEXT_UTILS_H diff --git a/dali-toolkit/internal/controls/text-controls/text-editor-impl.cpp b/dali-toolkit/internal/controls/text-controls/text-editor-impl.cpp index 0bdc8c1..0259471 100644 --- a/dali-toolkit/internal/controls/text-controls/text-editor-impl.cpp +++ b/dali-toolkit/internal/controls/text-controls/text-editor-impl.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -31,11 +32,12 @@ #include // INTERNAL INCLUDES -#include #include #include #include #include +#include +#include #include #include #include @@ -48,6 +50,10 @@ using namespace Dali::Toolkit::Text; +#if defined(DEBUG_ENABLED) +Debug::Filter* gTextEditorLogFilter = Debug::Filter::New(Debug::Concise, true, "LOG_TEXT_CONTROLS"); +#endif + namespace Dali { namespace Toolkit @@ -56,10 +62,6 @@ namespace Internal { namespace // unnamed namespace { -#if defined(DEBUG_ENABLED) -Debug::Filter* gLogFilter = Debug::Filter::New(Debug::Concise, true, "LOG_TEXT_CONTROLS"); -#endif - const unsigned int DEFAULT_RENDERING_BACKEND = Dali::Toolkit::DevelText::DEFAULT_RENDERING_BACKEND; const float DEFAULT_SCROLL_SPEED = 1200.f; ///< The default scroll speed for the text editor in pixels/second. } // unnamed namespace @@ -165,22 +167,55 @@ DALI_SIGNAL_REGISTRATION(Toolkit, TextEditor, "selectionCleared", SIGNAL_SE DALI_TYPE_REGISTRATION_END() // clang-format on -const char* const IMAGE_MAP_FILENAME_STRING = "filename"; - -/// Retrieves a filename from a value that is a Property::Map -std::string GetImageFileNameFromPropertyValue(const Property::Value& value) +Toolkit::TextEditor::InputStyle::Mask ConvertInputStyle(Text::InputStyle::Mask inputStyleMask) { - std::string filename; - const Property::Map* map = value.GetMap(); - if(map) + Toolkit::TextEditor::InputStyle::Mask editorInputStyleMask = Toolkit::TextEditor::InputStyle::NONE; + + if(InputStyle::NONE != static_cast(inputStyleMask & InputStyle::INPUT_COLOR)) { - const Property::Value* filenameValue = map->Find(IMAGE_MAP_FILENAME_STRING); - if(filenameValue) - { - filenameValue->Get(filename); - } + editorInputStyleMask = static_cast(editorInputStyleMask | Toolkit::TextEditor::InputStyle::COLOR); + } + if(InputStyle::NONE != static_cast(inputStyleMask & InputStyle::INPUT_FONT_FAMILY)) + { + editorInputStyleMask = static_cast(editorInputStyleMask | Toolkit::TextEditor::InputStyle::FONT_FAMILY); + } + if(InputStyle::NONE != static_cast(inputStyleMask & InputStyle::INPUT_POINT_SIZE)) + { + editorInputStyleMask = static_cast(editorInputStyleMask | Toolkit::TextEditor::InputStyle::POINT_SIZE); + } + if(InputStyle::NONE != static_cast(inputStyleMask & InputStyle::INPUT_FONT_WEIGHT)) + { + editorInputStyleMask = static_cast(editorInputStyleMask | Toolkit::TextEditor::InputStyle::FONT_STYLE); + } + if(InputStyle::NONE != static_cast(inputStyleMask & InputStyle::INPUT_FONT_WIDTH)) + { + editorInputStyleMask = static_cast(editorInputStyleMask | Toolkit::TextEditor::InputStyle::FONT_STYLE); + } + if(InputStyle::NONE != static_cast(inputStyleMask & InputStyle::INPUT_FONT_SLANT)) + { + editorInputStyleMask = static_cast(editorInputStyleMask | Toolkit::TextEditor::InputStyle::FONT_STYLE); + } + if(InputStyle::NONE != static_cast(inputStyleMask & InputStyle::INPUT_LINE_SPACING)) + { + editorInputStyleMask = static_cast(editorInputStyleMask | Toolkit::TextEditor::InputStyle::LINE_SPACING); + } + if(InputStyle::NONE != static_cast(inputStyleMask & InputStyle::INPUT_UNDERLINE)) + { + editorInputStyleMask = static_cast(editorInputStyleMask | Toolkit::TextEditor::InputStyle::UNDERLINE); + } + if(InputStyle::NONE != static_cast(inputStyleMask & InputStyle::INPUT_SHADOW)) + { + editorInputStyleMask = static_cast(editorInputStyleMask | Toolkit::TextEditor::InputStyle::SHADOW); } - return filename; + if(InputStyle::NONE != static_cast(inputStyleMask & InputStyle::INPUT_EMBOSS)) + { + editorInputStyleMask = static_cast(editorInputStyleMask | Toolkit::TextEditor::InputStyle::EMBOSS); + } + if(InputStyle::NONE != static_cast(inputStyleMask & InputStyle::INPUT_OUTLINE)) + { + editorInputStyleMask = static_cast(editorInputStyleMask | Toolkit::TextEditor::InputStyle::OUTLINE); + } + return editorInputStyleMask; } } // namespace @@ -195,652 +230,21 @@ Toolkit::TextEditor TextEditor::New() // Second-phase init of the implementation // This can only be done after the CustomActor connection has been made... - impl->Initialize(); - - return handle; -} - -void TextEditor::SetProperty(BaseObject* object, Property::Index index, const Property::Value& value) -{ - Toolkit::TextEditor textEditor = Toolkit::TextEditor::DownCast(Dali::BaseHandle(object)); - - DALI_LOG_INFO(gLogFilter, Debug::Verbose, "TextEditor SetProperty\n"); - - if(textEditor) - { - TextEditor& impl(GetImpl(textEditor)); - DALI_ASSERT_DEBUG(impl.mController && "No text contoller"); - DALI_ASSERT_DEBUG(impl.mDecorator && "No text decorator"); - - switch(index) - { - case Toolkit::DevelTextEditor::Property::RENDERING_BACKEND: - { - int backend = value.Get(); - DALI_LOG_INFO(gLogFilter, Debug::Verbose, "TextEditor %p RENDERING_BACKEND %d\n", impl.mController.Get(), backend); - - if(impl.mRenderingBackend != backend) - { - impl.mRenderingBackend = backend; - impl.mRenderer.Reset(); - impl.RequestTextRelayout(); - } - break; - } - case Toolkit::TextEditor::Property::TEXT: - { - const std::string& text = value.Get(); - DALI_LOG_INFO(gLogFilter, Debug::General, "TextEditor %p TEXT %s\n", impl.mController.Get(), text.c_str()); - - impl.mController->SetText(text); - break; - } - case Toolkit::TextEditor::Property::TEXT_COLOR: - { - const Vector4& textColor = value.Get(); - DALI_LOG_INFO(gLogFilter, Debug::General, "TextEditor %p TEXT_COLOR %f,%f,%f,%f\n", impl.mController.Get(), textColor.r, textColor.g, textColor.b, textColor.a); - - if(impl.mController->GetDefaultColor() != textColor) - { - impl.mController->SetDefaultColor(textColor); - impl.mController->SetInputColor(textColor); - impl.mRenderer.Reset(); - } - break; - } - case Toolkit::TextEditor::Property::FONT_FAMILY: - { - const std::string& fontFamily = value.Get(); - DALI_LOG_INFO(gLogFilter, Debug::General, "TextEditor %p FONT_FAMILY %s\n", impl.mController.Get(), fontFamily.c_str()); - impl.mController->SetDefaultFontFamily(fontFamily); - break; - } - case Toolkit::TextEditor::Property::FONT_STYLE: - { - SetFontStyleProperty(impl.mController, value, Text::FontStyle::DEFAULT); - break; - } - case Toolkit::TextEditor::Property::POINT_SIZE: - { - const float pointSize = value.Get(); - DALI_LOG_INFO(gLogFilter, Debug::General, "TextEditor %p POINT_SIZE %f\n", impl.mController.Get(), pointSize); - - if(!Equals(impl.mController->GetDefaultFontSize(Text::Controller::POINT_SIZE), pointSize)) - { - impl.mController->SetDefaultFontSize(pointSize, Text::Controller::POINT_SIZE); - } - break; - } - case Toolkit::TextEditor::Property::HORIZONTAL_ALIGNMENT: - { - Text::HorizontalAlignment::Type alignment(static_cast(-1)); // Set to invalid value to ensure a valid mode does get set - if(Text::GetHorizontalAlignmentEnumeration(value, alignment)) - { - DALI_LOG_INFO(gLogFilter, Debug::General, "TextEditor %p HORIZONTAL_ALIGNMENT %d\n", impl.mController.Get(), alignment); - impl.mController->SetHorizontalAlignment(alignment); - } - break; - } - case Toolkit::TextEditor::Property::SCROLL_THRESHOLD: - { - const float threshold = value.Get(); - DALI_LOG_INFO(gLogFilter, Debug::Verbose, "TextEditor %p SCROLL_THRESHOLD %f\n", impl.mController.Get(), threshold); - - impl.mDecorator->SetScrollThreshold(threshold); - break; - } - case Toolkit::TextEditor::Property::SCROLL_SPEED: - { - const float speed = value.Get(); - DALI_LOG_INFO(gLogFilter, Debug::Verbose, "TextEditor %p SCROLL_SPEED %f\n", impl.mController.Get(), speed); - - impl.mDecorator->SetScrollSpeed(speed); - break; - } - case Toolkit::TextEditor::Property::PRIMARY_CURSOR_COLOR: - { - const Vector4& color = value.Get(); - DALI_LOG_INFO(gLogFilter, Debug::General, "TextEditor %p PRIMARY_CURSOR_COLOR %f,%f,%f,%f\n", impl.mController.Get(), color.r, color.g, color.b, color.a); - - impl.mDecorator->SetCursorColor(PRIMARY_CURSOR, color); - impl.RequestTextRelayout(); - break; - } - case Toolkit::TextEditor::Property::SECONDARY_CURSOR_COLOR: - { - const Vector4& color = value.Get(); - DALI_LOG_INFO(gLogFilter, Debug::General, "TextEditor %p SECONDARY_CURSOR_COLOR %f,%f,%f,%f\n", impl.mController.Get(), color.r, color.g, color.b, color.a); - - impl.mDecorator->SetCursorColor(SECONDARY_CURSOR, color); - impl.RequestTextRelayout(); - break; - } - case Toolkit::TextEditor::Property::ENABLE_CURSOR_BLINK: - { - const bool enable = value.Get(); - DALI_LOG_INFO(gLogFilter, Debug::Verbose, "TextEditor %p ENABLE_CURSOR_BLINK %d\n", impl.mController.Get(), enable); - - impl.mController->SetEnableCursorBlink(enable); - impl.RequestTextRelayout(); - break; - } - case Toolkit::TextEditor::Property::CURSOR_BLINK_INTERVAL: - { - const float interval = value.Get(); - DALI_LOG_INFO(gLogFilter, Debug::Verbose, "TextEditor %p CURSOR_BLINK_INTERVAL %f\n", impl.mController.Get(), interval); - - impl.mDecorator->SetCursorBlinkInterval(interval); - break; - } - case Toolkit::TextEditor::Property::CURSOR_BLINK_DURATION: - { - const float duration = value.Get(); - DALI_LOG_INFO(gLogFilter, Debug::Verbose, "TextEditor %p CURSOR_BLINK_DURATION %f\n", impl.mController.Get(), duration); - - impl.mDecorator->SetCursorBlinkDuration(duration); - break; - } - case Toolkit::TextEditor::Property::CURSOR_WIDTH: - { - const int width = value.Get(); - DALI_LOG_INFO(gLogFilter, Debug::Verbose, "TextEditor %p CURSOR_WIDTH %d\n", impl.mController.Get(), width); - - impl.mDecorator->SetCursorWidth(width); - impl.mController->GetLayoutEngine().SetCursorWidth(width); - break; - } - case Toolkit::TextEditor::Property::GRAB_HANDLE_IMAGE: - { - const std::string imageFileName = value.Get(); - DALI_LOG_INFO(gLogFilter, Debug::Verbose, "TextEditor %p GRAB_HANDLE_IMAGE %s\n", impl.mController.Get(), imageFileName.c_str()); - - if(imageFileName.size()) - { - impl.mDecorator->SetHandleImage(GRAB_HANDLE, HANDLE_IMAGE_RELEASED, imageFileName); - impl.RequestTextRelayout(); - } - break; - } - case Toolkit::TextEditor::Property::GRAB_HANDLE_PRESSED_IMAGE: - { - const std::string imageFileName = value.Get(); - DALI_LOG_INFO(gLogFilter, Debug::Verbose, "TextEditor %p GRAB_HANDLE_PRESSED_IMAGE %s\n", impl.mController.Get(), imageFileName.c_str()); - - if(imageFileName.size()) - { - impl.mDecorator->SetHandleImage(GRAB_HANDLE, HANDLE_IMAGE_PRESSED, imageFileName); - impl.RequestTextRelayout(); - } - break; - } - case Toolkit::TextEditor::Property::SELECTION_HANDLE_IMAGE_LEFT: - { - const std::string filename = GetImageFileNameFromPropertyValue(value); - - if(filename.size()) - { - impl.mDecorator->SetHandleImage(LEFT_SELECTION_HANDLE, HANDLE_IMAGE_RELEASED, filename); - impl.RequestTextRelayout(); - } - break; - } - case Toolkit::TextEditor::Property::SELECTION_HANDLE_IMAGE_RIGHT: - { - const std::string filename = GetImageFileNameFromPropertyValue(value); - - if(filename.size()) - { - impl.mDecorator->SetHandleImage(RIGHT_SELECTION_HANDLE, HANDLE_IMAGE_RELEASED, filename); - impl.RequestTextRelayout(); - } - break; - } - case Toolkit::TextEditor::Property::SELECTION_HANDLE_PRESSED_IMAGE_LEFT: - { - const std::string filename = GetImageFileNameFromPropertyValue(value); - - if(filename.size()) - { - impl.mDecorator->SetHandleImage(LEFT_SELECTION_HANDLE, HANDLE_IMAGE_PRESSED, filename); - impl.RequestTextRelayout(); - } - break; - } - case Toolkit::TextEditor::Property::SELECTION_HANDLE_PRESSED_IMAGE_RIGHT: - { - const std::string filename = GetImageFileNameFromPropertyValue(value); - - if(filename.size()) - { - impl.mDecorator->SetHandleImage(RIGHT_SELECTION_HANDLE, HANDLE_IMAGE_PRESSED, filename); - impl.RequestTextRelayout(); - } - break; - } - case Toolkit::TextEditor::Property::SELECTION_HANDLE_MARKER_IMAGE_LEFT: - { - const std::string filename = GetImageFileNameFromPropertyValue(value); - - if(filename.size()) - { - impl.mDecorator->SetHandleImage(LEFT_SELECTION_HANDLE_MARKER, HANDLE_IMAGE_RELEASED, filename); - impl.RequestTextRelayout(); - } - break; - } - case Toolkit::TextEditor::Property::SELECTION_HANDLE_MARKER_IMAGE_RIGHT: - { - const std::string filename = GetImageFileNameFromPropertyValue(value); - - if(filename.size()) - { - impl.mDecorator->SetHandleImage(RIGHT_SELECTION_HANDLE_MARKER, HANDLE_IMAGE_RELEASED, filename); - impl.RequestTextRelayout(); - } - break; - } - case Toolkit::TextEditor::Property::SELECTION_HIGHLIGHT_COLOR: - { - const Vector4 color = value.Get(); - DALI_LOG_INFO(gLogFilter, Debug::General, "TextEditor %p SELECTION_HIGHLIGHT_COLOR %f,%f,%f,%f\n", impl.mController.Get(), color.r, color.g, color.b, color.a); - - impl.mDecorator->SetHighlightColor(color); - impl.RequestTextRelayout(); - break; - } - case Toolkit::TextEditor::Property::DECORATION_BOUNDING_BOX: - { - const Rect& box = value.Get >(); - DALI_LOG_INFO(gLogFilter, Debug::General, "TextEditor %p DECORATION_BOUNDING_BOX %d,%d %dx%d\n", impl.mController.Get(), box.x, box.y, box.width, box.height); - - impl.mDecorator->SetBoundingBox(box); - impl.RequestTextRelayout(); - break; - } - case Toolkit::TextEditor::Property::ENABLE_MARKUP: - { - const bool enableMarkup = value.Get(); - DALI_LOG_INFO(gLogFilter, Debug::General, "TextEditor %p ENABLE_MARKUP %d\n", impl.mController.Get(), enableMarkup); - - impl.mController->SetMarkupProcessorEnabled(enableMarkup); - break; - } - case Toolkit::TextEditor::Property::INPUT_COLOR: - { - const Vector4& inputColor = value.Get(); - DALI_LOG_INFO(gLogFilter, Debug::General, "TextEditor %p INPUT_COLOR %f,%f,%f,%f\n", impl.mController.Get(), inputColor.r, inputColor.g, inputColor.b, inputColor.a); - - impl.mController->SetInputColor(inputColor); - break; - } - case Toolkit::TextEditor::Property::INPUT_FONT_FAMILY: - { - const std::string& fontFamily = value.Get(); - DALI_LOG_INFO(gLogFilter, Debug::General, "TextEditor %p INPUT_FONT_FAMILY %s\n", impl.mController.Get(), fontFamily.c_str()); - impl.mController->SetInputFontFamily(fontFamily); - break; - } - case Toolkit::TextEditor::Property::INPUT_FONT_STYLE: - { - SetFontStyleProperty(impl.mController, value, Text::FontStyle::INPUT); - break; - } - case Toolkit::TextEditor::Property::INPUT_POINT_SIZE: - { - const float pointSize = value.Get(); - DALI_LOG_INFO(gLogFilter, Debug::General, "TextEditor %p INPUT_POINT_SIZE %f\n", impl.mController.Get(), pointSize); - impl.mController->SetInputFontPointSize(pointSize); - break; - } - case Toolkit::TextEditor::Property::LINE_SPACING: - { - const float lineSpacing = value.Get(); - impl.mController->SetDefaultLineSpacing(lineSpacing); - impl.mRenderer.Reset(); - break; - } - case Toolkit::TextEditor::Property::INPUT_LINE_SPACING: - { - const float lineSpacing = value.Get(); - impl.mController->SetInputLineSpacing(lineSpacing); - impl.mRenderer.Reset(); - break; - } - case Toolkit::TextEditor::Property::UNDERLINE: - { - const bool update = SetUnderlineProperties(impl.mController, value, Text::EffectStyle::DEFAULT); - if(update) - { - impl.mRenderer.Reset(); - } - break; - } - case Toolkit::TextEditor::Property::INPUT_UNDERLINE: - { - const bool update = SetUnderlineProperties(impl.mController, value, Text::EffectStyle::INPUT); - if(update) - { - impl.mRenderer.Reset(); - } - break; - } - case Toolkit::TextEditor::Property::SHADOW: - { - const bool update = SetShadowProperties(impl.mController, value, Text::EffectStyle::DEFAULT); - if(update) - { - impl.mRenderer.Reset(); - } - break; - } - case Toolkit::TextEditor::Property::INPUT_SHADOW: - { - const bool update = SetShadowProperties(impl.mController, value, Text::EffectStyle::INPUT); - if(update) - { - impl.mRenderer.Reset(); - } - break; - } - case Toolkit::TextEditor::Property::EMBOSS: - { - const bool update = SetEmbossProperties(impl.mController, value, Text::EffectStyle::DEFAULT); - if(update) - { - impl.mRenderer.Reset(); - } - break; - } - case Toolkit::TextEditor::Property::INPUT_EMBOSS: - { - const bool update = SetEmbossProperties(impl.mController, value, Text::EffectStyle::INPUT); - if(update) - { - impl.mRenderer.Reset(); - } - break; - } - case Toolkit::TextEditor::Property::OUTLINE: - { - const bool update = SetOutlineProperties(impl.mController, value, Text::EffectStyle::DEFAULT); - if(update) - { - impl.mRenderer.Reset(); - } - break; - } - case Toolkit::TextEditor::Property::INPUT_OUTLINE: - { - const bool update = SetOutlineProperties(impl.mController, value, Text::EffectStyle::INPUT); - if(update) - { - impl.mRenderer.Reset(); - } - break; - } - case Toolkit::TextEditor::Property::SMOOTH_SCROLL: - { - const bool enable = value.Get(); - DALI_LOG_INFO(gLogFilter, Debug::Verbose, "TextEditor SMOOTH_SCROLL %d\n", enable); - - impl.mScrollAnimationEnabled = enable; - break; - } - case Toolkit::TextEditor::Property::SMOOTH_SCROLL_DURATION: - { - const float duration = value.Get(); - DALI_LOG_INFO(gLogFilter, Debug::General, "TextEditor SMOOTH_SCROLL_DURATION %f\n", duration); - - impl.mScrollAnimationDuration = duration; - if(impl.mTextVerticalScroller) - { - impl.mTextVerticalScroller->SetDuration(duration); - } - break; - } - case Toolkit::TextEditor::Property::ENABLE_SCROLL_BAR: - { - const bool enable = value.Get(); - DALI_LOG_INFO(gLogFilter, Debug::Verbose, "TextEditor SHOW_SCROLL_BAR %d\n", enable); - - impl.mScrollBarEnabled = enable; - break; - } - case Toolkit::TextEditor::Property::SCROLL_BAR_SHOW_DURATION: - { - const float duration = value.Get(); - DALI_LOG_INFO(gLogFilter, Debug::General, "TextEditor SCROLL_BAR_SHOW_DURATION %f\n", duration); - - impl.mAnimationPeriod.delaySeconds = duration; - break; - } - case Toolkit::TextEditor::Property::SCROLL_BAR_FADE_DURATION: - { - const float duration = value.Get(); - DALI_LOG_INFO(gLogFilter, Debug::General, "TextEditor SCROLL_BAR_FADE_DURATION %f\n", duration); - - impl.mAnimationPeriod.durationSeconds = duration; - break; - } - case Toolkit::TextEditor::Property::PIXEL_SIZE: - { - const float pixelSize = value.Get(); - DALI_LOG_INFO(gLogFilter, Debug::General, "TextEditor %p PIXEL_SIZE %f\n", impl.mController.Get(), pixelSize); - - if(!Equals(impl.mController->GetDefaultFontSize(Text::Controller::PIXEL_SIZE), pixelSize)) - { - impl.mController->SetDefaultFontSize(pixelSize, Text::Controller::PIXEL_SIZE); - } - break; - } - case Toolkit::DevelTextEditor::Property::PLACEHOLDER_TEXT: - { - const std::string& text = value.Get(); - DALI_LOG_INFO(gLogFilter, Debug::General, "TextEditor::OnPropertySet %p PLACEHOLDER_TEXT %s\n", impl.mController.Get(), text.c_str()); - - impl.mController->SetPlaceholderText(Controller::PLACEHOLDER_TYPE_INACTIVE, text); - break; - } - case Toolkit::DevelTextEditor::Property::PLACEHOLDER_TEXT_COLOR: - { - const Vector4& textColor = value.Get(); - DALI_LOG_INFO(gLogFilter, Debug::General, "TextEditor %p PLACEHOLDER_TEXT_COLOR %f,%f,%f,%f\n", impl.mController.Get(), textColor.r, textColor.g, textColor.b, textColor.a); - - if(impl.mController->GetPlaceholderTextColor() != textColor) - { - impl.mController->SetPlaceholderTextColor(textColor); - impl.mRenderer.Reset(); - } - break; - } - case Toolkit::TextEditor::Property::ENABLE_SELECTION: - { - const bool enableSelection = value.Get(); - DALI_LOG_INFO(gLogFilter, Debug::General, "TextEditor %p ENABLE_SELECTION %d\n", impl.mController.Get(), enableSelection); - impl.mController->SetSelectionEnabled(enableSelection); - break; - } - case Toolkit::TextEditor::Property::PLACEHOLDER: - { - const Property::Map* map = value.GetMap(); - if(map) - { - impl.mController->SetPlaceholderProperty(*map); - } - break; - } - case Toolkit::TextEditor::Property::LINE_WRAP_MODE: - { - Text::LineWrap::Mode lineWrapMode(static_cast(-1)); // Set to invalid value to ensure a valid mode does get set - if(GetLineWrapModeEnumeration(value, lineWrapMode)) - { - DALI_LOG_INFO(gLogFilter, Debug::General, "TextEditor %p LineWrap::MODE %d\n", impl.mController.Get(), lineWrapMode); - impl.mController->SetLineWrapMode(lineWrapMode); - } - break; - } - case Toolkit::DevelTextEditor::Property::ENABLE_SHIFT_SELECTION: - { - const bool shiftSelection = value.Get(); - DALI_LOG_INFO(gLogFilter, Debug::General, "TextEditor %p ENABLE_SHIFT_SELECTION %d\n", impl.mController.Get(), shiftSelection); - - impl.mController->SetShiftSelectionEnabled(shiftSelection); - break; - } - case Toolkit::DevelTextEditor::Property::ENABLE_GRAB_HANDLE: - { - const bool grabHandleEnabled = value.Get(); - DALI_LOG_INFO(gLogFilter, Debug::General, "TextEditor %p ENABLE_GRAB_HANDLE %d\n", impl.mController.Get(), grabHandleEnabled); - - impl.mController->SetGrabHandleEnabled(grabHandleEnabled); - break; - } - case Toolkit::DevelTextEditor::Property::MATCH_SYSTEM_LANGUAGE_DIRECTION: - { - impl.mController->SetMatchLayoutDirection(value.Get() ? DevelText::MatchLayoutDirection::LOCALE : DevelText::MatchLayoutDirection::CONTENTS); - break; - } - case Toolkit::DevelTextEditor::Property::MAX_LENGTH: - { - const int max = value.Get(); - DALI_LOG_INFO(gLogFilter, Debug::General, "TextEditor %p MAX_LENGTH %d\n", impl.mController.Get(), max); - - impl.mController->SetMaximumNumberOfCharacters(max); - break; - } - case Toolkit::DevelTextEditor::Property::SELECTED_TEXT_START: - { - uint32_t start = static_cast(value.Get()); - DALI_LOG_INFO(gLogFilter, Debug::General, "TextEditor %p SELECTED_TEXT_START %d\n", impl.mController.Get(), start); - impl.SetTextSelectionRange(&start, nullptr); - break; - } - case Toolkit::DevelTextEditor::Property::SELECTED_TEXT_END: - { - uint32_t end = static_cast(value.Get()); - DALI_LOG_INFO(gLogFilter, Debug::General, "TextEditor %p SELECTED_TEXT_END %d\n", impl.mController.Get(), end); - impl.SetTextSelectionRange(nullptr, &end); - break; - } - case Toolkit::DevelTextEditor::Property::ENABLE_EDITING: - { - const bool editable = value.Get(); - DALI_LOG_INFO(gLogFilter, Debug::General, "TextEditor %p ENABLE_EDITING %d\n", impl.mController.Get(), editable); - impl.SetEditable(editable); - break; - } - case Toolkit::DevelTextEditor::Property::HORIZONTAL_SCROLL_POSITION: - { - float horizontalScroll = value.Get(); - DALI_LOG_INFO(gLogFilter, Debug::General, "TextEditor %p HORIZONTAL_SCROLL_POSITION %d\n", impl.mController.Get(), horizontalScroll); - if(horizontalScroll >= 0.0f) - { - impl.ScrollBy(Vector2(horizontalScroll - impl.GetHorizontalScrollPosition(), 0)); - } - break; - } - case Toolkit::DevelTextEditor::Property::VERTICAL_SCROLL_POSITION: - { - float verticalScroll = value.Get(); - DALI_LOG_INFO(gLogFilter, Debug::General, "TextEditor %p VERTICAL_SCROLL_POSITION %d\n", impl.mController.Get(), verticalScroll); - if(verticalScroll >= 0.0f) - { - impl.ScrollBy(Vector2(0, verticalScroll - impl.GetVerticalScrollPosition())); - } - break; - } - case Toolkit::DevelTextEditor::Property::FONT_SIZE_SCALE: - { - const float scale = value.Get(); - DALI_LOG_INFO(gLogFilter, Debug::General, "TextEditor %p FONT_SIZE_SCALE %f\n", impl.mController.Get(), scale); - - if(!Equals(impl.mController->GetFontSizeScale(), scale)) - { - impl.mController->SetFontSizeScale(scale); - } - break; - } - case Toolkit::DevelTextEditor::Property::PRIMARY_CURSOR_POSITION: - { - uint32_t position = static_cast(value.Get()); - DALI_LOG_INFO(gLogFilter, Debug::General, "TextEditor %p PRIMARY_CURSOR_POSITION %d\n", impl.mController.Get(), position); - if(impl.mController->SetPrimaryCursorPosition(position, impl.HasKeyInputFocus())) - { - impl.SetKeyInputFocus(); - } - break; - } - case Toolkit::DevelTextEditor::Property::GRAB_HANDLE_COLOR: - { - const Vector4 color = value.Get(); - DALI_LOG_INFO(gLogFilter, Debug::General, "TextEditor %p GRAB_HANDLE_COLOR %f,%f,%f,%f\n", impl.mController.Get(), color.r, color.g, color.b, color.a); - - impl.mDecorator->SetHandleColor(color); - impl.RequestTextRelayout(); - break; - } - case Toolkit::DevelTextEditor::Property::ENABLE_GRAB_HANDLE_POPUP: - { - const bool grabHandlePopupEnabled = value.Get(); - DALI_LOG_INFO(gLogFilter, Debug::General, "TextEditor %p ENABLE_GRAB_HANDLE_POPUP %d\n", impl.mController.Get(), grabHandlePopupEnabled); - - impl.mController->SetGrabHandlePopupEnabled(grabHandlePopupEnabled); - break; - } - case Toolkit::DevelTextEditor::Property::INPUT_METHOD_SETTINGS: - { - const Property::Map* map = value.GetMap(); - if(map) - { - impl.mInputMethodOptions.ApplyProperty(*map); - } - impl.mController->SetInputModePassword(impl.mInputMethodOptions.IsPassword()); - - Toolkit::Control control = Toolkit::KeyInputFocusManager::Get().GetCurrentFocusControl(); - if(control == textEditor) - { - impl.mInputMethodContext.ApplyOptions(impl.mInputMethodOptions); - } - break; - } - case Toolkit::DevelTextEditor::Property::INPUT_FILTER: - { - const Property::Map* map = value.GetMap(); - if(map) - { - impl.mController->SetInputFilterOption(*map); - } - break; - } - case Toolkit::DevelTextEditor::Property::ELLIPSIS: - { - const bool ellipsis = value.Get(); - DALI_LOG_INFO(gLogFilter, Debug::General, "TextEditor %p ELLIPSIS %d\n", impl.mController.Get(), ellipsis); + impl->Initialize(); - impl.mController->SetTextElideEnabled(ellipsis); - break; - } - case Toolkit::DevelTextEditor::Property::ELLIPSIS_POSITION: - { - DevelText::EllipsisPosition::Type ellipsisPositionType(static_cast(-1)); // Set to invalid value to ensure a valid mode does get set - if(GetEllipsisPositionTypeEnumeration(value, ellipsisPositionType)) - { - DALI_LOG_INFO(gLogFilter, Debug::General, "TextEditor %p EllipsisPosition::Type %d\n", impl.mController.Get(), ellipsisPositionType); - impl.mController->SetEllipsisPosition(ellipsisPositionType); - } - break; - } - case Toolkit::DevelTextEditor::Property::MIN_LINE_SIZE: - { - const float minLineSize = value.Get(); - DALI_LOG_INFO(gLogFilter, Debug::Verbose, "TextEditor %p MIN_LINE_SIZE %f\n", impl.mController.Get(), minLineSize); + return handle; +} - impl.mController->SetDefaultLineSize(minLineSize); - impl.mRenderer.Reset(); - break; - } - } // switch - } // texteditor +void TextEditor::SetProperty(BaseObject* object, Property::Index index, const Property::Value& value) +{ + Toolkit::TextEditor textEditor = Toolkit::TextEditor::DownCast(Dali::BaseHandle(object)); + + DALI_LOG_INFO(gTextEditorLogFilter, Debug::Verbose, "TextEditor SetProperty\n"); + + if(textEditor) + { + PropertyHandler::SetProperty(textEditor, index, value); + } } Property::Value TextEditor::GetProperty(BaseObject* object, Property::Index index) @@ -851,390 +255,8 @@ Property::Value TextEditor::GetProperty(BaseObject* object, Property::Index inde if(textEditor) { - TextEditor& impl(GetImpl(textEditor)); - DALI_ASSERT_DEBUG(impl.mController && "No text contoller"); - DALI_ASSERT_DEBUG(impl.mDecorator && "No text decorator"); - - switch(index) - { - case Toolkit::DevelTextEditor::Property::RENDERING_BACKEND: - { - value = impl.mRenderingBackend; - break; - } - case Toolkit::TextEditor::Property::TEXT: - { - std::string text; - impl.mController->GetText(text); - DALI_LOG_INFO(gLogFilter, Debug::General, "TextEditor %p returning text: %s\n", impl.mController.Get(), text.c_str()); - value = text; - break; - } - case Toolkit::TextEditor::Property::TEXT_COLOR: - { - value = impl.mController->GetDefaultColor(); - break; - } - case Toolkit::TextEditor::Property::FONT_FAMILY: - { - value = impl.mController->GetDefaultFontFamily(); - break; - } - case Toolkit::TextEditor::Property::FONT_STYLE: - { - GetFontStyleProperty(impl.mController, value, Text::FontStyle::DEFAULT); - break; - } - case Toolkit::TextEditor::Property::POINT_SIZE: - { - value = impl.mController->GetDefaultFontSize(Text::Controller::POINT_SIZE); - break; - } - case Toolkit::TextEditor::Property::HORIZONTAL_ALIGNMENT: - { - const char* name = GetHorizontalAlignmentString(impl.mController->GetHorizontalAlignment()); - if(name) - { - value = std::string(name); - } - break; - } - case Toolkit::TextEditor::Property::SCROLL_THRESHOLD: - { - value = impl.mDecorator->GetScrollThreshold(); - break; - } - case Toolkit::TextEditor::Property::SCROLL_SPEED: - { - value = impl.mDecorator->GetScrollSpeed(); - break; - } - case Toolkit::TextEditor::Property::PRIMARY_CURSOR_COLOR: - { - value = impl.mDecorator->GetColor(PRIMARY_CURSOR); - break; - } - case Toolkit::TextEditor::Property::SECONDARY_CURSOR_COLOR: - { - value = impl.mDecorator->GetColor(SECONDARY_CURSOR); - break; - } - case Toolkit::TextEditor::Property::ENABLE_CURSOR_BLINK: - { - value = impl.mController->GetEnableCursorBlink(); - break; - } - case Toolkit::TextEditor::Property::CURSOR_BLINK_INTERVAL: - { - value = impl.mDecorator->GetCursorBlinkInterval(); - break; - } - case Toolkit::TextEditor::Property::CURSOR_BLINK_DURATION: - { - value = impl.mDecorator->GetCursorBlinkDuration(); - break; - } - case Toolkit::TextEditor::Property::CURSOR_WIDTH: - { - value = impl.mDecorator->GetCursorWidth(); - break; - } - case Toolkit::TextEditor::Property::GRAB_HANDLE_IMAGE: - { - value = impl.mDecorator->GetHandleImage(GRAB_HANDLE, HANDLE_IMAGE_RELEASED); - break; - } - case Toolkit::TextEditor::Property::GRAB_HANDLE_PRESSED_IMAGE: - { - value = impl.mDecorator->GetHandleImage(GRAB_HANDLE, HANDLE_IMAGE_PRESSED); - break; - } - case Toolkit::TextEditor::Property::SELECTION_HANDLE_IMAGE_LEFT: - { - impl.GetHandleImagePropertyValue(value, LEFT_SELECTION_HANDLE, HANDLE_IMAGE_RELEASED); - break; - } - case Toolkit::TextEditor::Property::SELECTION_HANDLE_IMAGE_RIGHT: - { - impl.GetHandleImagePropertyValue(value, RIGHT_SELECTION_HANDLE, HANDLE_IMAGE_RELEASED); - break; - } - case Toolkit::TextEditor::Property::SELECTION_HANDLE_PRESSED_IMAGE_LEFT: - { - impl.GetHandleImagePropertyValue(value, LEFT_SELECTION_HANDLE, HANDLE_IMAGE_PRESSED); - break; - } - case Toolkit::TextEditor::Property::SELECTION_HANDLE_PRESSED_IMAGE_RIGHT: - { - impl.GetHandleImagePropertyValue(value, RIGHT_SELECTION_HANDLE, HANDLE_IMAGE_PRESSED); - break; - } - case Toolkit::TextEditor::Property::SELECTION_HANDLE_MARKER_IMAGE_LEFT: - { - impl.GetHandleImagePropertyValue(value, LEFT_SELECTION_HANDLE_MARKER, HANDLE_IMAGE_RELEASED); - break; - } - case Toolkit::TextEditor::Property::SELECTION_HANDLE_MARKER_IMAGE_RIGHT: - { - impl.GetHandleImagePropertyValue(value, RIGHT_SELECTION_HANDLE_MARKER, HANDLE_IMAGE_RELEASED); - break; - } - case Toolkit::TextEditor::Property::SELECTION_HIGHLIGHT_COLOR: - { - value = impl.mDecorator->GetHighlightColor(); - break; - } - case Toolkit::TextEditor::Property::DECORATION_BOUNDING_BOX: - { - Rect boundingBox; - impl.mDecorator->GetBoundingBox(boundingBox); - value = boundingBox; - break; - } - case Toolkit::TextEditor::Property::ENABLE_MARKUP: - { - value = impl.mController->IsMarkupProcessorEnabled(); - break; - } - case Toolkit::TextEditor::Property::INPUT_COLOR: - { - value = impl.mController->GetInputColor(); - break; - } - case Toolkit::TextEditor::Property::INPUT_FONT_FAMILY: - { - value = impl.mController->GetInputFontFamily(); - break; - } - case Toolkit::TextEditor::Property::INPUT_FONT_STYLE: - { - GetFontStyleProperty(impl.mController, value, Text::FontStyle::INPUT); - break; - } - case Toolkit::TextEditor::Property::INPUT_POINT_SIZE: - { - value = impl.mController->GetInputFontPointSize(); - break; - } - case Toolkit::TextEditor::Property::LINE_SPACING: - { - value = impl.mController->GetDefaultLineSpacing(); - break; - } - case Toolkit::TextEditor::Property::INPUT_LINE_SPACING: - { - value = impl.mController->GetInputLineSpacing(); - break; - } - case Toolkit::TextEditor::Property::UNDERLINE: - { - GetUnderlineProperties(impl.mController, value, Text::EffectStyle::DEFAULT); - break; - } - case Toolkit::TextEditor::Property::INPUT_UNDERLINE: - { - GetUnderlineProperties(impl.mController, value, Text::EffectStyle::INPUT); - break; - } - case Toolkit::TextEditor::Property::SHADOW: - { - GetShadowProperties(impl.mController, value, Text::EffectStyle::DEFAULT); - break; - } - case Toolkit::TextEditor::Property::INPUT_SHADOW: - { - GetShadowProperties(impl.mController, value, Text::EffectStyle::INPUT); - break; - } - case Toolkit::TextEditor::Property::EMBOSS: - { - GetEmbossProperties(impl.mController, value, Text::EffectStyle::DEFAULT); - break; - } - case Toolkit::TextEditor::Property::INPUT_EMBOSS: - { - GetEmbossProperties(impl.mController, value, Text::EffectStyle::INPUT); - break; - } - case Toolkit::TextEditor::Property::OUTLINE: - { - GetOutlineProperties(impl.mController, value, Text::EffectStyle::DEFAULT); - break; - } - case Toolkit::TextEditor::Property::INPUT_OUTLINE: - { - GetOutlineProperties(impl.mController, value, Text::EffectStyle::INPUT); - break; - } - case Toolkit::TextEditor::Property::SMOOTH_SCROLL: - { - value = impl.mScrollAnimationEnabled; - break; - } - case Toolkit::TextEditor::Property::SMOOTH_SCROLL_DURATION: - { - value = impl.mScrollAnimationDuration; - break; - } - case Toolkit::TextEditor::Property::ENABLE_SCROLL_BAR: - { - value = impl.mScrollBarEnabled; - break; - } - case Toolkit::TextEditor::Property::SCROLL_BAR_SHOW_DURATION: - { - value = impl.mAnimationPeriod.delaySeconds; - break; - } - case Toolkit::TextEditor::Property::SCROLL_BAR_FADE_DURATION: - { - value = impl.mAnimationPeriod.durationSeconds; - break; - } - case Toolkit::TextEditor::Property::PIXEL_SIZE: - { - value = impl.mController->GetDefaultFontSize(Text::Controller::PIXEL_SIZE); - break; - } - case Toolkit::TextEditor::Property::LINE_COUNT: - { - float width = textEditor.GetProperty(Actor::Property::SIZE_WIDTH).Get(); - value = impl.mController->GetLineCount(width); - break; - } - case Toolkit::DevelTextEditor::Property::PLACEHOLDER_TEXT: - { - std::string text; - impl.mController->GetPlaceholderText(Controller::PLACEHOLDER_TYPE_INACTIVE, text); - value = text; - break; - } - case Toolkit::DevelTextEditor::Property::PLACEHOLDER_TEXT_COLOR: - { - value = impl.mController->GetPlaceholderTextColor(); - break; - } - case Toolkit::TextEditor::Property::ENABLE_SELECTION: - { - value = impl.mController->IsSelectionEnabled(); - break; - } - case Toolkit::TextEditor::Property::PLACEHOLDER: - { - Property::Map map; - impl.mController->GetPlaceholderProperty(map); - value = map; - break; - } - case Toolkit::TextEditor::Property::LINE_WRAP_MODE: - { - value = impl.mController->GetLineWrapMode(); - break; - } - case Toolkit::DevelTextEditor::Property::ENABLE_SHIFT_SELECTION: - { - value = impl.mController->IsShiftSelectionEnabled(); - break; - } - case Toolkit::DevelTextEditor::Property::ENABLE_GRAB_HANDLE: - { - value = impl.mController->IsGrabHandleEnabled(); - break; - } - case Toolkit::DevelTextEditor::Property::MATCH_SYSTEM_LANGUAGE_DIRECTION: - { - value = impl.mController->GetMatchLayoutDirection() != DevelText::MatchLayoutDirection::CONTENTS; - break; - } - case Toolkit::DevelTextEditor::Property::MAX_LENGTH: - { - value = impl.mController->GetMaximumNumberOfCharacters(); - break; - } - case Toolkit::DevelTextEditor::Property::SELECTED_TEXT: - { - value = impl.mController->GetSelectedText(); - break; - } - case Toolkit::DevelTextEditor::Property::SELECTED_TEXT_START: - { - Uint32Pair range = impl.GetTextSelectionRange(); - value = static_cast(range.first); - break; - } - case Toolkit::DevelTextEditor::Property::SELECTED_TEXT_END: - { - Uint32Pair range = impl.GetTextSelectionRange(); - value = static_cast(range.second); - break; - } - case Toolkit::DevelTextEditor::Property::ENABLE_EDITING: - { - value = impl.IsEditable(); - break; - } - case Toolkit::DevelTextEditor::Property::HORIZONTAL_SCROLL_POSITION: - { - value = impl.GetHorizontalScrollPosition(); - break; - } - case Toolkit::DevelTextEditor::Property::VERTICAL_SCROLL_POSITION: - { - value = impl.GetVerticalScrollPosition(); - break; - } - case Toolkit::DevelTextEditor::Property::FONT_SIZE_SCALE: - { - value = impl.mController->GetFontSizeScale(); - break; - } - case Toolkit::DevelTextEditor::Property::PRIMARY_CURSOR_POSITION: - { - value = static_cast(impl.mController->GetPrimaryCursorPosition()); - break; - } - case Toolkit::DevelTextEditor::Property::GRAB_HANDLE_COLOR: - { - value = impl.mDecorator->GetHandleColor(); - break; - } - case Toolkit::DevelTextEditor::Property::ENABLE_GRAB_HANDLE_POPUP: - { - value = impl.mController->IsGrabHandlePopupEnabled(); - break; - } - case Toolkit::DevelTextEditor::Property::INPUT_METHOD_SETTINGS: - { - Property::Map map; - impl.mInputMethodOptions.RetrieveProperty(map); - value = map; - break; - } - case Toolkit::DevelTextEditor::Property::INPUT_FILTER: - { - Property::Map map; - impl.mController->GetInputFilterOption(map); - value = map; - break; - } - case Toolkit::DevelTextEditor::Property::ELLIPSIS: - { - value = impl.mController->IsTextElideEnabled(); - break; - } - case Toolkit::DevelTextEditor::Property::ELLIPSIS_POSITION: - { - value = impl.mController->GetEllipsisPosition(); - break; - } - case Toolkit::DevelTextEditor::Property::MIN_LINE_SIZE: - { - value = impl.mController->GetDefaultLineSize(); - break; - } - } //switch + value = PropertyHandler::GetProperty(textEditor, index); } - return value; } @@ -1550,13 +572,13 @@ void TextEditor::OnInitialize() void TextEditor::OnStyleChange(Toolkit::StyleManager styleManager, StyleChange::Type change) { - DALI_LOG_INFO(gLogFilter, Debug::Verbose, "TextEditor::OnStyleChange\n"); + DALI_LOG_INFO(gTextEditorLogFilter, Debug::Verbose, "TextEditor::OnStyleChange\n"); switch(change) { case StyleChange::DEFAULT_FONT_CHANGE: { - DALI_LOG_INFO(gLogFilter, Debug::Verbose, "TextEditor::OnStyleChange DEFAULT_FONT_CHANGE\n"); + DALI_LOG_INFO(gTextEditorLogFilter, Debug::Verbose, "TextEditor::OnStyleChange DEFAULT_FONT_CHANGE\n"); const std::string& newFont = GetImpl(styleManager).GetDefaultFontFamily(); // Property system did not set the font so should update it. mController->UpdateAfterFontChange(newFont); @@ -1610,7 +632,7 @@ void TextEditor::ResizeActor(Actor& actor, const Vector2& size) void TextEditor::OnRelayout(const Vector2& size, RelayoutContainer& container) { - DALI_LOG_INFO(gLogFilter, Debug::Verbose, "TextEditor OnRelayout\n"); + DALI_LOG_INFO(gTextEditorLogFilter, Debug::Verbose, "TextEditor OnRelayout\n"); Actor self = Self(); @@ -1649,7 +671,7 @@ void TextEditor::OnRelayout(const Vector2& size, RelayoutContainer& container) if((Text::Controller::NONE_UPDATED != updateTextType) || !mRenderer) { - DALI_LOG_INFO(gLogFilter, Debug::Verbose, "TextEditor::OnRelayout %p Displaying new contents\n", mController.Get()); + DALI_LOG_INFO(gTextEditorLogFilter, Debug::Verbose, "TextEditor::OnRelayout %p Displaying new contents\n", mController.Get()); if(mDecorator && (Text::Controller::NONE_UPDATED != (Text::Controller::DECORATOR_UPDATED & updateTextType))) @@ -1702,100 +724,9 @@ void TextEditor::OnRelayout(const Vector2& size, RelayoutContainer& container) void TextEditor::RenderText(Text::Controller::UpdateTextType updateTextType) { - Actor renderableActor; - - if(Text::Controller::NONE_UPDATED != (Text::Controller::MODEL_UPDATED & updateTextType)) - { - if(mRenderer) - { - Dali::Toolkit::TextEditor handle = Dali::Toolkit::TextEditor(GetOwner()); - - renderableActor = mRenderer->Render(mController->GetView(), - handle, - Property::INVALID_INDEX, // Animatable property not supported - mAlignmentOffset, - DepthIndex::CONTENT); - } - - if(renderableActor != mRenderableActor) - { - UnparentAndReset(mBackgroundActor); - UnparentAndReset(mRenderableActor); - mRenderableActor = renderableActor; - - if(mRenderableActor) - { - mBackgroundActor = mController->CreateBackgroundActor(); - } - } - } - + CommonTextUtils::RenderText(Self(), mRenderer, mController, mDecorator, mAlignmentOffset, mRenderableActor, mBackgroundActor, mStencil, mClippingDecorationActors, updateTextType); if(mRenderableActor) { - const Vector2& scrollOffset = mController->GetTextModel()->GetScrollPosition(); - - float renderableActorPositionX, renderableActorPositionY; - - if(mStencil) - { - renderableActorPositionX = scrollOffset.x + mAlignmentOffset; - renderableActorPositionY = scrollOffset.y; - } - else - { - Extents padding; - padding = Self().GetProperty(Toolkit::Control::Property::PADDING); - - // Support Right-To-Left of padding - Dali::LayoutDirection::Type layoutDirection = static_cast(Self().GetProperty(Dali::Actor::Property::LAYOUT_DIRECTION).Get()); - if(Dali::LayoutDirection::RIGHT_TO_LEFT == layoutDirection) - { - std::swap(padding.start, padding.end); - } - - renderableActorPositionX = scrollOffset.x + mAlignmentOffset + padding.start; - renderableActorPositionY = scrollOffset.y + padding.top; - } - - mRenderableActor.SetProperty(Actor::Property::POSITION, Vector2(renderableActorPositionX, renderableActorPositionY)); - // Make sure the actors are parented correctly with/without clipping - Actor self = mStencil ? mStencil : Self(); - - Actor highlightActor; - - for(std::vector::iterator it = mClippingDecorationActors.begin(), - endIt = mClippingDecorationActors.end(); - it != endIt; - ++it) - { - self.Add(*it); - it->LowerToBottom(); - - if(it->GetProperty(Dali::Actor::Property::NAME) == "HighlightActor") - { - highlightActor = *it; - } - } - mClippingDecorationActors.clear(); - - self.Add(mRenderableActor); - - if(mBackgroundActor) - { - if(mDecorator && mDecorator->IsHighlightVisible()) - { - self.Add(mBackgroundActor); - mBackgroundActor.SetProperty(Actor::Property::POSITION, Vector2(renderableActorPositionX, renderableActorPositionY)); // In text field's coords. - mBackgroundActor.LowerBelow(highlightActor); - } - else - { - mRenderableActor.Add(mBackgroundActor); - mBackgroundActor.SetProperty(Actor::Property::POSITION, Vector2(0.0f, 0.0f)); // In renderable actor's coords. - mBackgroundActor.LowerToBottom(); - } - } - ApplyScrollPosition(); } UpdateScrollBar(); @@ -1803,7 +734,7 @@ void TextEditor::RenderText(Text::Controller::UpdateTextType updateTextType) void TextEditor::OnKeyInputFocusGained() { - DALI_LOG_INFO(gLogFilter, Debug::Verbose, "TextEditor::OnKeyInputFocusGained %p\n", mController.Get()); + DALI_LOG_INFO(gTextEditorLogFilter, Debug::Verbose, "TextEditor::OnKeyInputFocusGained %p\n", mController.Get()); if(mInputMethodContext && IsEditable()) { // All input panel properties, such as layout, return key type, and input hint, should be set before input panel activates (or shows). @@ -1834,7 +765,7 @@ void TextEditor::OnKeyInputFocusGained() void TextEditor::OnKeyInputFocusLost() { - DALI_LOG_INFO(gLogFilter, Debug::Verbose, "TextEditor:OnKeyInputFocusLost %p\n", mController.Get()); + DALI_LOG_INFO(gTextEditorLogFilter, Debug::Verbose, "TextEditor:OnKeyInputFocusLost %p\n", mController.Get()); if(mInputMethodContext) { mInputMethodContext.StatusChangedSignal().Disconnect(this, &TextEditor::KeyboardStatusChanged); @@ -1867,7 +798,7 @@ bool TextEditor::OnAccessibilityActivated() void TextEditor::OnTap(const TapGesture& gesture) { - DALI_LOG_INFO(gLogFilter, Debug::Verbose, "TextEditor::OnTap %p\n", mController.Get()); + DALI_LOG_INFO(gTextEditorLogFilter, Debug::Verbose, "TextEditor::OnTap %p\n", mController.Get()); if(mInputMethodContext && IsEditable()) { mInputMethodContext.Activate(); @@ -1903,7 +834,7 @@ void TextEditor::OnLongPress(const LongPressGesture& gesture) bool TextEditor::OnKeyEvent(const KeyEvent& event) { - DALI_LOG_INFO(gLogFilter, Debug::Verbose, "TextEditor::OnKeyEvent %p keyCode %d\n", mController.Get(), event.GetKeyCode()); + DALI_LOG_INFO(gTextEditorLogFilter, Debug::Verbose, "TextEditor::OnKeyEvent %p keyCode %d\n", mController.Get(), event.GetKeyCode()); if(Dali::DALI_KEY_ESCAPE == event.GetKeyCode() && mController->ShouldClearFocusOnEscape()) { @@ -1982,55 +913,7 @@ void TextEditor::MaxLengthReached() void TextEditor::InputStyleChanged(Text::InputStyle::Mask inputStyleMask) { Dali::Toolkit::TextEditor handle(GetOwner()); - - Toolkit::TextEditor::InputStyle::Mask editorInputStyleMask = Toolkit::TextEditor::InputStyle::NONE; - - if(InputStyle::NONE != static_cast(inputStyleMask & InputStyle::INPUT_COLOR)) - { - editorInputStyleMask = static_cast(editorInputStyleMask | Toolkit::TextEditor::InputStyle::COLOR); - } - if(InputStyle::NONE != static_cast(inputStyleMask & InputStyle::INPUT_FONT_FAMILY)) - { - editorInputStyleMask = static_cast(editorInputStyleMask | Toolkit::TextEditor::InputStyle::FONT_FAMILY); - } - if(InputStyle::NONE != static_cast(inputStyleMask & InputStyle::INPUT_POINT_SIZE)) - { - editorInputStyleMask = static_cast(editorInputStyleMask | Toolkit::TextEditor::InputStyle::POINT_SIZE); - } - if(InputStyle::NONE != static_cast(inputStyleMask & InputStyle::INPUT_FONT_WEIGHT)) - { - editorInputStyleMask = static_cast(editorInputStyleMask | Toolkit::TextEditor::InputStyle::FONT_STYLE); - } - if(InputStyle::NONE != static_cast(inputStyleMask & InputStyle::INPUT_FONT_WIDTH)) - { - editorInputStyleMask = static_cast(editorInputStyleMask | Toolkit::TextEditor::InputStyle::FONT_STYLE); - } - if(InputStyle::NONE != static_cast(inputStyleMask & InputStyle::INPUT_FONT_SLANT)) - { - editorInputStyleMask = static_cast(editorInputStyleMask | Toolkit::TextEditor::InputStyle::FONT_STYLE); - } - if(InputStyle::NONE != static_cast(inputStyleMask & InputStyle::INPUT_LINE_SPACING)) - { - editorInputStyleMask = static_cast(editorInputStyleMask | Toolkit::TextEditor::InputStyle::LINE_SPACING); - } - if(InputStyle::NONE != static_cast(inputStyleMask & InputStyle::INPUT_UNDERLINE)) - { - editorInputStyleMask = static_cast(editorInputStyleMask | Toolkit::TextEditor::InputStyle::UNDERLINE); - } - if(InputStyle::NONE != static_cast(inputStyleMask & InputStyle::INPUT_SHADOW)) - { - editorInputStyleMask = static_cast(editorInputStyleMask | Toolkit::TextEditor::InputStyle::SHADOW); - } - if(InputStyle::NONE != static_cast(inputStyleMask & InputStyle::INPUT_EMBOSS)) - { - editorInputStyleMask = static_cast(editorInputStyleMask | Toolkit::TextEditor::InputStyle::EMBOSS); - } - if(InputStyle::NONE != static_cast(inputStyleMask & InputStyle::INPUT_OUTLINE)) - { - editorInputStyleMask = static_cast(editorInputStyleMask | Toolkit::TextEditor::InputStyle::OUTLINE); - } - - mInputStyleChangedSignal.Emit(handle, editorInputStyleMask); + mInputStyleChangedSignal.Emit(handle, ConvertInputStyle(inputStyleMask)); } void TextEditor::AnchorClicked(const std::string& href) @@ -2248,7 +1131,7 @@ void TextEditor::OnSceneConnect(Dali::Actor actor) InputMethodContext::CallbackData TextEditor::OnInputMethodContextEvent(Dali::InputMethodContext& inputMethodContext, const InputMethodContext::EventData& inputMethodContextEvent) { - DALI_LOG_INFO(gLogFilter, Debug::Verbose, "TextEditor::OnInputMethodContextEvent %p eventName %d\n", mController.Get(), inputMethodContextEvent.eventName); + DALI_LOG_INFO(gTextEditorLogFilter, Debug::Verbose, "TextEditor::OnInputMethodContextEvent %p eventName %d\n", mController.Get(), inputMethodContextEvent.eventName); return mController->OnInputMethodContextEvent(inputMethodContext, inputMethodContextEvent); } @@ -2257,8 +1140,9 @@ void TextEditor::GetHandleImagePropertyValue(Property::Value& value, Text::Handl if(mDecorator) { Property::Map map; - map[IMAGE_MAP_FILENAME_STRING] = mDecorator->GetHandleImage(handleType, handleImageType); - value = map; + map[TextEditor::PropertyHandler::IMAGE_MAP_FILENAME_STRING] = mDecorator->GetHandleImage(handleType, handleImageType); + + value = map; } } @@ -2269,7 +1153,7 @@ void TextEditor::OnClipboardTextSelected(ClipboardEventNotifier& clipboard) void TextEditor::KeyboardStatusChanged(bool keyboardShown) { - DALI_LOG_INFO(gLogFilter, Debug::Verbose, "TextEditor::KeyboardStatusChanged %p keyboardShown %d\n", mController.Get(), keyboardShown); + DALI_LOG_INFO(gTextEditorLogFilter, Debug::Verbose, "TextEditor::KeyboardStatusChanged %p keyboardShown %d\n", mController.Get(), keyboardShown); // Just hide the grab handle when keyboard is hidden. if(!keyboardShown) diff --git a/dali-toolkit/internal/controls/text-controls/text-editor-impl.h b/dali-toolkit/internal/controls/text-controls/text-editor-impl.h index bc28781..8c5d7be 100644 --- a/dali-toolkit/internal/controls/text-controls/text-editor-impl.h +++ b/dali-toolkit/internal/controls/text-controls/text-editor-impl.h @@ -522,6 +522,8 @@ private: // Data uint32_t mOldSelectionStart; uint32_t mOldSelectionEnd; + struct PropertyHandler; + /** * @brief This structure is to connect TextEditor with Accessible functions. */ diff --git a/dali-toolkit/internal/controls/text-controls/text-editor-property-handler.cpp b/dali-toolkit/internal/controls/text-controls/text-editor-property-handler.cpp new file mode 100644 index 0000000..62dfbda --- /dev/null +++ b/dali-toolkit/internal/controls/text-controls/text-editor-property-handler.cpp @@ -0,0 +1,1081 @@ +/* + * Copyright (c) 2021 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 +#include +#include +#include +#include +#include + +#if defined(DEBUG_ENABLED) +extern Debug::Filter* gTextEditorLogFilter; +#endif + +namespace Dali::Toolkit::Internal +{ +const char* const TextEditor::PropertyHandler::IMAGE_MAP_FILENAME_STRING{"filename"}; + +/// Retrieves a filename from a value that is a Property::Map +std::string TextEditor::PropertyHandler::GetImageFileNameFromPropertyValue(const Property::Value& value) +{ + std::string filename; + const Property::Map* map = value.GetMap(); + if(map) + { + const Property::Value* filenameValue = map->Find(TextEditor::PropertyHandler::IMAGE_MAP_FILENAME_STRING); + if(filenameValue) + { + filenameValue->Get(filename); + } + } + return filename; +} + +void TextEditor::PropertyHandler::SetProperty(Toolkit::TextEditor textEditor, Property::Index index, const Property::Value& value) +{ + TextEditor& impl(GetImpl(textEditor)); + DALI_ASSERT_DEBUG(impl.mController && "No text controller"); + DALI_ASSERT_DEBUG(impl.mDecorator && "No text decorator"); + + switch(index) + { + case Toolkit::DevelTextEditor::Property::RENDERING_BACKEND: + { + int backend = value.Get(); + DALI_LOG_INFO(gTextEditorLogFilter, Debug::Verbose, "TextEditor %p RENDERING_BACKEND %d\n", impl.mController.Get(), backend); + + if(impl.mRenderingBackend != backend) + { + impl.mRenderingBackend = backend; + impl.mRenderer.Reset(); + impl.RequestTextRelayout(); + } + break; + } + case Toolkit::TextEditor::Property::TEXT: + { + const std::string& text = value.Get(); + DALI_LOG_INFO(gTextEditorLogFilter, Debug::General, "TextEditor %p TEXT %s\n", impl.mController.Get(), text.c_str()); + + impl.mController->SetText(text); + break; + } + case Toolkit::TextEditor::Property::TEXT_COLOR: + { + const Vector4& textColor = value.Get(); + DALI_LOG_INFO(gTextEditorLogFilter, Debug::General, "TextEditor %p TEXT_COLOR %f,%f,%f,%f\n", impl.mController.Get(), textColor.r, textColor.g, textColor.b, textColor.a); + + if(impl.mController->GetDefaultColor() != textColor) + { + impl.mController->SetDefaultColor(textColor); + impl.mController->SetInputColor(textColor); + impl.mRenderer.Reset(); + } + break; + } + case Toolkit::TextEditor::Property::FONT_FAMILY: + { + const std::string& fontFamily = value.Get(); + DALI_LOG_INFO(gTextEditorLogFilter, Debug::General, "TextEditor %p FONT_FAMILY %s\n", impl.mController.Get(), fontFamily.c_str()); + impl.mController->SetDefaultFontFamily(fontFamily); + break; + } + case Toolkit::TextEditor::Property::FONT_STYLE: + { + SetFontStyleProperty(impl.mController, value, Text::FontStyle::DEFAULT); + break; + } + case Toolkit::TextEditor::Property::POINT_SIZE: + { + const float pointSize = value.Get(); + DALI_LOG_INFO(gTextEditorLogFilter, Debug::General, "TextEditor %p POINT_SIZE %f\n", impl.mController.Get(), pointSize); + + if(!Equals(impl.mController->GetDefaultFontSize(Text::Controller::POINT_SIZE), pointSize)) + { + impl.mController->SetDefaultFontSize(pointSize, Text::Controller::POINT_SIZE); + } + break; + } + case Toolkit::TextEditor::Property::HORIZONTAL_ALIGNMENT: + { + Text::HorizontalAlignment::Type alignment(static_cast(-1)); // Set to invalid value to ensure a valid mode does get set + if(Text::GetHorizontalAlignmentEnumeration(value, alignment)) + { + DALI_LOG_INFO(gTextEditorLogFilter, Debug::General, "TextEditor %p HORIZONTAL_ALIGNMENT %d\n", impl.mController.Get(), alignment); + impl.mController->SetHorizontalAlignment(alignment); + } + break; + } + case Toolkit::TextEditor::Property::SCROLL_THRESHOLD: + { + const float threshold = value.Get(); + DALI_LOG_INFO(gTextEditorLogFilter, Debug::Verbose, "TextEditor %p SCROLL_THRESHOLD %f\n", impl.mController.Get(), threshold); + + impl.mDecorator->SetScrollThreshold(threshold); + break; + } + case Toolkit::TextEditor::Property::SCROLL_SPEED: + { + const float speed = value.Get(); + DALI_LOG_INFO(gTextEditorLogFilter, Debug::Verbose, "TextEditor %p SCROLL_SPEED %f\n", impl.mController.Get(), speed); + + impl.mDecorator->SetScrollSpeed(speed); + break; + } + case Toolkit::TextEditor::Property::PRIMARY_CURSOR_COLOR: + { + const Vector4& color = value.Get(); + DALI_LOG_INFO(gTextEditorLogFilter, Debug::General, "TextEditor %p PRIMARY_CURSOR_COLOR %f,%f,%f,%f\n", impl.mController.Get(), color.r, color.g, color.b, color.a); + + impl.mDecorator->SetCursorColor(Toolkit::Text::PRIMARY_CURSOR, color); + impl.RequestTextRelayout(); + break; + } + case Toolkit::TextEditor::Property::SECONDARY_CURSOR_COLOR: + { + const Vector4& color = value.Get(); + DALI_LOG_INFO(gTextEditorLogFilter, Debug::General, "TextEditor %p SECONDARY_CURSOR_COLOR %f,%f,%f,%f\n", impl.mController.Get(), color.r, color.g, color.b, color.a); + + impl.mDecorator->SetCursorColor(Toolkit::Text::SECONDARY_CURSOR, color); + impl.RequestTextRelayout(); + break; + } + case Toolkit::TextEditor::Property::ENABLE_CURSOR_BLINK: + { + const bool enable = value.Get(); + DALI_LOG_INFO(gTextEditorLogFilter, Debug::Verbose, "TextEditor %p ENABLE_CURSOR_BLINK %d\n", impl.mController.Get(), enable); + + impl.mController->SetEnableCursorBlink(enable); + impl.RequestTextRelayout(); + break; + } + case Toolkit::TextEditor::Property::CURSOR_BLINK_INTERVAL: + { + const float interval = value.Get(); + DALI_LOG_INFO(gTextEditorLogFilter, Debug::Verbose, "TextEditor %p CURSOR_BLINK_INTERVAL %f\n", impl.mController.Get(), interval); + + impl.mDecorator->SetCursorBlinkInterval(interval); + break; + } + case Toolkit::TextEditor::Property::CURSOR_BLINK_DURATION: + { + const float duration = value.Get(); + DALI_LOG_INFO(gTextEditorLogFilter, Debug::Verbose, "TextEditor %p CURSOR_BLINK_DURATION %f\n", impl.mController.Get(), duration); + + impl.mDecorator->SetCursorBlinkDuration(duration); + break; + } + case Toolkit::TextEditor::Property::CURSOR_WIDTH: + { + const int width = value.Get(); + DALI_LOG_INFO(gTextEditorLogFilter, Debug::Verbose, "TextEditor %p CURSOR_WIDTH %d\n", impl.mController.Get(), width); + + impl.mDecorator->SetCursorWidth(width); + impl.mController->GetLayoutEngine().SetCursorWidth(width); + break; + } + case Toolkit::TextEditor::Property::GRAB_HANDLE_IMAGE: + { + const std::string imageFileName = value.Get(); + DALI_LOG_INFO(gTextEditorLogFilter, Debug::Verbose, "TextEditor %p GRAB_HANDLE_IMAGE %s\n", impl.mController.Get(), imageFileName.c_str()); + + if(imageFileName.size()) + { + impl.mDecorator->SetHandleImage(Toolkit::Text::GRAB_HANDLE, Toolkit::Text::HANDLE_IMAGE_RELEASED, imageFileName); + impl.RequestTextRelayout(); + } + break; + } + case Toolkit::TextEditor::Property::GRAB_HANDLE_PRESSED_IMAGE: + { + const std::string imageFileName = value.Get(); + DALI_LOG_INFO(gTextEditorLogFilter, Debug::Verbose, "TextEditor %p GRAB_HANDLE_PRESSED_IMAGE %s\n", impl.mController.Get(), imageFileName.c_str()); + + if(imageFileName.size()) + { + impl.mDecorator->SetHandleImage(Toolkit::Text::GRAB_HANDLE, Toolkit::Text::HANDLE_IMAGE_PRESSED, imageFileName); + impl.RequestTextRelayout(); + } + break; + } + case Toolkit::TextEditor::Property::SELECTION_HANDLE_IMAGE_LEFT: + { + const std::string filename = GetImageFileNameFromPropertyValue(value); + + if(filename.size()) + { + impl.mDecorator->SetHandleImage(Toolkit::Text::LEFT_SELECTION_HANDLE, Toolkit::Text::HANDLE_IMAGE_RELEASED, filename); + impl.RequestTextRelayout(); + } + break; + } + case Toolkit::TextEditor::Property::SELECTION_HANDLE_IMAGE_RIGHT: + { + const std::string filename = GetImageFileNameFromPropertyValue(value); + + if(filename.size()) + { + impl.mDecorator->SetHandleImage(Toolkit::Text::RIGHT_SELECTION_HANDLE, Toolkit::Text::HANDLE_IMAGE_RELEASED, filename); + impl.RequestTextRelayout(); + } + break; + } + case Toolkit::TextEditor::Property::SELECTION_HANDLE_PRESSED_IMAGE_LEFT: + { + const std::string filename = GetImageFileNameFromPropertyValue(value); + + if(filename.size()) + { + impl.mDecorator->SetHandleImage(Toolkit::Text::LEFT_SELECTION_HANDLE, Toolkit::Text::HANDLE_IMAGE_PRESSED, filename); + impl.RequestTextRelayout(); + } + break; + } + case Toolkit::TextEditor::Property::SELECTION_HANDLE_PRESSED_IMAGE_RIGHT: + { + const std::string filename = GetImageFileNameFromPropertyValue(value); + + if(filename.size()) + { + impl.mDecorator->SetHandleImage(Toolkit::Text::RIGHT_SELECTION_HANDLE, Toolkit::Text::HANDLE_IMAGE_PRESSED, filename); + impl.RequestTextRelayout(); + } + break; + } + case Toolkit::TextEditor::Property::SELECTION_HANDLE_MARKER_IMAGE_LEFT: + { + const std::string filename = GetImageFileNameFromPropertyValue(value); + + if(filename.size()) + { + impl.mDecorator->SetHandleImage(Toolkit::Text::LEFT_SELECTION_HANDLE_MARKER, + Toolkit::Text::HANDLE_IMAGE_RELEASED, + filename); + impl.RequestTextRelayout(); + } + break; + } + case Toolkit::TextEditor::Property::SELECTION_HANDLE_MARKER_IMAGE_RIGHT: + { + const std::string filename = GetImageFileNameFromPropertyValue(value); + + if(filename.size()) + { + impl.mDecorator->SetHandleImage(Toolkit::Text::RIGHT_SELECTION_HANDLE_MARKER, + Toolkit::Text::HANDLE_IMAGE_RELEASED, + filename); + impl.RequestTextRelayout(); + } + break; + } + case Toolkit::TextEditor::Property::SELECTION_HIGHLIGHT_COLOR: + { + const Vector4 color = value.Get(); + DALI_LOG_INFO(gTextEditorLogFilter, Debug::General, "TextEditor %p SELECTION_HIGHLIGHT_COLOR %f,%f,%f,%f\n", impl.mController.Get(), color.r, color.g, color.b, color.a); + + impl.mDecorator->SetHighlightColor(color); + impl.RequestTextRelayout(); + break; + } + case Toolkit::TextEditor::Property::DECORATION_BOUNDING_BOX: + { + const Rect& box = value.Get >(); + DALI_LOG_INFO(gTextEditorLogFilter, Debug::General, "TextEditor %p DECORATION_BOUNDING_BOX %d,%d %dx%d\n", impl.mController.Get(), box.x, box.y, box.width, box.height); + + impl.mDecorator->SetBoundingBox(box); + impl.RequestTextRelayout(); + break; + } + case Toolkit::TextEditor::Property::ENABLE_MARKUP: + { + const bool enableMarkup = value.Get(); + DALI_LOG_INFO(gTextEditorLogFilter, Debug::General, "TextEditor %p ENABLE_MARKUP %d\n", impl.mController.Get(), enableMarkup); + + impl.mController->SetMarkupProcessorEnabled(enableMarkup); + break; + } + case Toolkit::TextEditor::Property::INPUT_COLOR: + { + const Vector4& inputColor = value.Get(); + DALI_LOG_INFO(gTextEditorLogFilter, Debug::General, "TextEditor %p INPUT_COLOR %f,%f,%f,%f\n", impl.mController.Get(), inputColor.r, inputColor.g, inputColor.b, inputColor.a); + + impl.mController->SetInputColor(inputColor); + break; + } + case Toolkit::TextEditor::Property::INPUT_FONT_FAMILY: + { + const std::string& fontFamily = value.Get(); + DALI_LOG_INFO(gTextEditorLogFilter, Debug::General, "TextEditor %p INPUT_FONT_FAMILY %s\n", impl.mController.Get(), fontFamily.c_str()); + impl.mController->SetInputFontFamily(fontFamily); + break; + } + case Toolkit::TextEditor::Property::INPUT_FONT_STYLE: + { + SetFontStyleProperty(impl.mController, value, Text::FontStyle::INPUT); + break; + } + case Toolkit::TextEditor::Property::INPUT_POINT_SIZE: + { + const float pointSize = value.Get(); + DALI_LOG_INFO(gTextEditorLogFilter, Debug::General, "TextEditor %p INPUT_POINT_SIZE %f\n", impl.mController.Get(), pointSize); + impl.mController->SetInputFontPointSize(pointSize); + break; + } + case Toolkit::TextEditor::Property::LINE_SPACING: + { + const float lineSpacing = value.Get(); + impl.mController->SetDefaultLineSpacing(lineSpacing); + impl.mRenderer.Reset(); + break; + } + case Toolkit::TextEditor::Property::INPUT_LINE_SPACING: + { + const float lineSpacing = value.Get(); + impl.mController->SetInputLineSpacing(lineSpacing); + impl.mRenderer.Reset(); + break; + } + case Toolkit::TextEditor::Property::UNDERLINE: + { + const bool update = SetUnderlineProperties(impl.mController, value, Text::EffectStyle::DEFAULT); + if(update) + { + impl.mRenderer.Reset(); + } + break; + } + case Toolkit::TextEditor::Property::INPUT_UNDERLINE: + { + const bool update = SetUnderlineProperties(impl.mController, value, Text::EffectStyle::INPUT); + if(update) + { + impl.mRenderer.Reset(); + } + break; + } + case Toolkit::TextEditor::Property::SHADOW: + { + const bool update = SetShadowProperties(impl.mController, value, Text::EffectStyle::DEFAULT); + if(update) + { + impl.mRenderer.Reset(); + } + break; + } + case Toolkit::TextEditor::Property::INPUT_SHADOW: + { + const bool update = SetShadowProperties(impl.mController, value, Text::EffectStyle::INPUT); + if(update) + { + impl.mRenderer.Reset(); + } + break; + } + case Toolkit::TextEditor::Property::EMBOSS: + { + const bool update = SetEmbossProperties(impl.mController, value, Text::EffectStyle::DEFAULT); + if(update) + { + impl.mRenderer.Reset(); + } + break; + } + case Toolkit::TextEditor::Property::INPUT_EMBOSS: + { + const bool update = SetEmbossProperties(impl.mController, value, Text::EffectStyle::INPUT); + if(update) + { + impl.mRenderer.Reset(); + } + break; + } + case Toolkit::TextEditor::Property::OUTLINE: + { + const bool update = SetOutlineProperties(impl.mController, value, Text::EffectStyle::DEFAULT); + if(update) + { + impl.mRenderer.Reset(); + } + break; + } + case Toolkit::TextEditor::Property::INPUT_OUTLINE: + { + const bool update = SetOutlineProperties(impl.mController, value, Text::EffectStyle::INPUT); + if(update) + { + impl.mRenderer.Reset(); + } + break; + } + case Toolkit::TextEditor::Property::SMOOTH_SCROLL: + { + const bool enable = value.Get(); + DALI_LOG_INFO(gTextEditorLogFilter, Debug::Verbose, "TextEditor SMOOTH_SCROLL %d\n", enable); + + impl.mScrollAnimationEnabled = enable; + break; + } + case Toolkit::TextEditor::Property::SMOOTH_SCROLL_DURATION: + { + const float duration = value.Get(); + DALI_LOG_INFO(gTextEditorLogFilter, Debug::General, "TextEditor SMOOTH_SCROLL_DURATION %f\n", duration); + + impl.mScrollAnimationDuration = duration; + if(impl.mTextVerticalScroller) + { + impl.mTextVerticalScroller->SetDuration(duration); + } + break; + } + case Toolkit::TextEditor::Property::ENABLE_SCROLL_BAR: + { + const bool enable = value.Get(); + DALI_LOG_INFO(gTextEditorLogFilter, Debug::Verbose, "TextEditor SHOW_SCROLL_BAR %d\n", enable); + + impl.mScrollBarEnabled = enable; + break; + } + case Toolkit::TextEditor::Property::SCROLL_BAR_SHOW_DURATION: + { + const float duration = value.Get(); + DALI_LOG_INFO(gTextEditorLogFilter, Debug::General, "TextEditor SCROLL_BAR_SHOW_DURATION %f\n", duration); + + impl.mAnimationPeriod.delaySeconds = duration; + break; + } + case Toolkit::TextEditor::Property::SCROLL_BAR_FADE_DURATION: + { + const float duration = value.Get(); + DALI_LOG_INFO(gTextEditorLogFilter, Debug::General, "TextEditor SCROLL_BAR_FADE_DURATION %f\n", duration); + + impl.mAnimationPeriod.durationSeconds = duration; + break; + } + case Toolkit::TextEditor::Property::PIXEL_SIZE: + { + const float pixelSize = value.Get(); + DALI_LOG_INFO(gTextEditorLogFilter, Debug::General, "TextEditor %p PIXEL_SIZE %f\n", impl.mController.Get(), pixelSize); + + if(!Equals(impl.mController->GetDefaultFontSize(Text::Controller::PIXEL_SIZE), pixelSize)) + { + impl.mController->SetDefaultFontSize(pixelSize, Text::Controller::PIXEL_SIZE); + } + break; + } + case Toolkit::DevelTextEditor::Property::PLACEHOLDER_TEXT: + { + const std::string& text = value.Get(); + DALI_LOG_INFO(gTextEditorLogFilter, Debug::General, "TextEditor::OnPropertySet %p PLACEHOLDER_TEXT %s\n", impl.mController.Get(), text.c_str()); + + impl.mController->SetPlaceholderText(Text::Controller::PLACEHOLDER_TYPE_INACTIVE, text); + break; + } + case Toolkit::DevelTextEditor::Property::PLACEHOLDER_TEXT_COLOR: + { + const Vector4& textColor = value.Get(); + DALI_LOG_INFO(gTextEditorLogFilter, Debug::General, "TextEditor %p PLACEHOLDER_TEXT_COLOR %f,%f,%f,%f\n", impl.mController.Get(), textColor.r, textColor.g, textColor.b, textColor.a); + + if(impl.mController->GetPlaceholderTextColor() != textColor) + { + impl.mController->SetPlaceholderTextColor(textColor); + impl.mRenderer.Reset(); + } + break; + } + case Toolkit::TextEditor::Property::ENABLE_SELECTION: + { + const bool enableSelection = value.Get(); + DALI_LOG_INFO(gTextEditorLogFilter, Debug::General, "TextEditor %p ENABLE_SELECTION %d\n", impl.mController.Get(), enableSelection); + impl.mController->SetSelectionEnabled(enableSelection); + break; + } + case Toolkit::TextEditor::Property::PLACEHOLDER: + { + const Property::Map* map = value.GetMap(); + if(map) + { + impl.mController->SetPlaceholderProperty(*map); + } + break; + } + case Toolkit::TextEditor::Property::LINE_WRAP_MODE: + { + Text::LineWrap::Mode lineWrapMode(static_cast(-1)); // Set to invalid value to ensure a valid mode does get set + if(Toolkit::Text::GetLineWrapModeEnumeration(value, lineWrapMode)) + { + DALI_LOG_INFO(gTextEditorLogFilter, Debug::General, "TextEditor %p LineWrap::MODE %d\n", impl.mController.Get(), lineWrapMode); + impl.mController->SetLineWrapMode(lineWrapMode); + } + break; + } + case Toolkit::DevelTextEditor::Property::ENABLE_SHIFT_SELECTION: + { + const bool shiftSelection = value.Get(); + DALI_LOG_INFO(gTextEditorLogFilter, Debug::General, "TextEditor %p ENABLE_SHIFT_SELECTION %d\n", impl.mController.Get(), shiftSelection); + + impl.mController->SetShiftSelectionEnabled(shiftSelection); + break; + } + case Toolkit::DevelTextEditor::Property::ENABLE_GRAB_HANDLE: + { + const bool grabHandleEnabled = value.Get(); + DALI_LOG_INFO(gTextEditorLogFilter, Debug::General, "TextEditor %p ENABLE_GRAB_HANDLE %d\n", impl.mController.Get(), grabHandleEnabled); + + impl.mController->SetGrabHandleEnabled(grabHandleEnabled); + break; + } + case Toolkit::DevelTextEditor::Property::MATCH_SYSTEM_LANGUAGE_DIRECTION: + { + impl.mController->SetMatchLayoutDirection(value.Get() ? DevelText::MatchLayoutDirection::LOCALE : DevelText::MatchLayoutDirection::CONTENTS); + break; + } + case Toolkit::DevelTextEditor::Property::MAX_LENGTH: + { + const int max = value.Get(); + DALI_LOG_INFO(gTextEditorLogFilter, Debug::General, "TextEditor %p MAX_LENGTH %d\n", impl.mController.Get(), max); + + impl.mController->SetMaximumNumberOfCharacters(max); + break; + } + case Toolkit::DevelTextEditor::Property::SELECTED_TEXT_START: + { + uint32_t start = static_cast(value.Get()); + DALI_LOG_INFO(gTextEditorLogFilter, Debug::General, "TextEditor %p SELECTED_TEXT_START %d\n", impl.mController.Get(), start); + impl.SetTextSelectionRange(&start, nullptr); + break; + } + case Toolkit::DevelTextEditor::Property::SELECTED_TEXT_END: + { + uint32_t end = static_cast(value.Get()); + DALI_LOG_INFO(gTextEditorLogFilter, Debug::General, "TextEditor %p SELECTED_TEXT_END %d\n", impl.mController.Get(), end); + impl.SetTextSelectionRange(nullptr, &end); + break; + } + case Toolkit::DevelTextEditor::Property::ENABLE_EDITING: + { + const bool editable = value.Get(); + DALI_LOG_INFO(gTextEditorLogFilter, Debug::General, "TextEditor %p ENABLE_EDITING %d\n", impl.mController.Get(), editable); + impl.SetEditable(editable); + break; + } + case Toolkit::DevelTextEditor::Property::HORIZONTAL_SCROLL_POSITION: + { + float horizontalScroll = value.Get(); + DALI_LOG_INFO(gTextEditorLogFilter, Debug::General, "TextEditor %p HORIZONTAL_SCROLL_POSITION %d\n", impl.mController.Get(), horizontalScroll); + if(horizontalScroll >= 0.0f) + { + impl.ScrollBy(Vector2(horizontalScroll - impl.GetHorizontalScrollPosition(), 0)); + } + break; + } + case Toolkit::DevelTextEditor::Property::VERTICAL_SCROLL_POSITION: + { + float verticalScroll = value.Get(); + DALI_LOG_INFO(gTextEditorLogFilter, Debug::General, "TextEditor %p VERTICAL_SCROLL_POSITION %d\n", impl.mController.Get(), verticalScroll); + if(verticalScroll >= 0.0f) + { + impl.ScrollBy(Vector2(0, verticalScroll - impl.GetVerticalScrollPosition())); + } + break; + } + case Toolkit::DevelTextEditor::Property::FONT_SIZE_SCALE: + { + const float scale = value.Get(); + DALI_LOG_INFO(gTextEditorLogFilter, Debug::General, "TextEditor %p FONT_SIZE_SCALE %f\n", impl.mController.Get(), scale); + + if(!Equals(impl.mController->GetFontSizeScale(), scale)) + { + impl.mController->SetFontSizeScale(scale); + } + break; + } + case Toolkit::DevelTextEditor::Property::PRIMARY_CURSOR_POSITION: + { + uint32_t position = static_cast(value.Get()); + DALI_LOG_INFO(gTextEditorLogFilter, Debug::General, "TextEditor %p PRIMARY_CURSOR_POSITION %d\n", impl.mController.Get(), position); + if(impl.mController->SetPrimaryCursorPosition(position, impl.HasKeyInputFocus())) + { + impl.SetKeyInputFocus(); + } + break; + } + case Toolkit::DevelTextEditor::Property::GRAB_HANDLE_COLOR: + { + const Vector4 color = value.Get(); + DALI_LOG_INFO(gTextEditorLogFilter, Debug::General, "TextEditor %p GRAB_HANDLE_COLOR %f,%f,%f,%f\n", impl.mController.Get(), color.r, color.g, color.b, color.a); + + impl.mDecorator->SetHandleColor(color); + impl.RequestTextRelayout(); + break; + } + case Toolkit::DevelTextEditor::Property::ENABLE_GRAB_HANDLE_POPUP: + { + const bool grabHandlePopupEnabled = value.Get(); + DALI_LOG_INFO(gTextEditorLogFilter, Debug::General, "TextEditor %p ENABLE_GRAB_HANDLE_POPUP %d\n", impl.mController.Get(), grabHandlePopupEnabled); + + impl.mController->SetGrabHandlePopupEnabled(grabHandlePopupEnabled); + break; + } + case Toolkit::DevelTextEditor::Property::INPUT_METHOD_SETTINGS: + { + const Property::Map* map = value.GetMap(); + if(map) + { + impl.mInputMethodOptions.ApplyProperty(*map); + } + impl.mController->SetInputModePassword(impl.mInputMethodOptions.IsPassword()); + + Toolkit::Control control = Toolkit::KeyInputFocusManager::Get().GetCurrentFocusControl(); + if(control == textEditor) + { + impl.mInputMethodContext.ApplyOptions(impl.mInputMethodOptions); + } + break; + } + case Toolkit::DevelTextEditor::Property::INPUT_FILTER: + { + const Property::Map* map = value.GetMap(); + if(map) + { + impl.mController->SetInputFilterOption(*map); + } + break; + } + case Toolkit::DevelTextEditor::Property::ELLIPSIS: + { + const bool ellipsis = value.Get(); + DALI_LOG_INFO(gTextEditorLogFilter, Debug::General, "TextEditor %p ELLIPSIS %d\n", impl.mController.Get(), ellipsis); + + impl.mController->SetTextElideEnabled(ellipsis); + break; + } + case Toolkit::DevelTextEditor::Property::ELLIPSIS_POSITION: + { + DevelText::EllipsisPosition::Type ellipsisPositionType(static_cast(-1)); // Set to invalid value to ensure a valid mode does get set + if(Text::GetEllipsisPositionTypeEnumeration(value, ellipsisPositionType)) + { + DALI_LOG_INFO(gTextEditorLogFilter, Debug::General, "TextEditor %p EllipsisPosition::Type %d\n", impl.mController.Get(), ellipsisPositionType); + impl.mController->SetEllipsisPosition(ellipsisPositionType); + } + break; + } + case Toolkit::DevelTextEditor::Property::MIN_LINE_SIZE: + { + const float minLineSize = value.Get(); + DALI_LOG_INFO(gTextEditorLogFilter, Debug::Verbose, "TextEditor %p MIN_LINE_SIZE %f\n", impl.mController.Get(), minLineSize); + + impl.mController->SetDefaultLineSize(minLineSize); + impl.mRenderer.Reset(); + break; + } + } +} + +Property::Value TextEditor::PropertyHandler::GetProperty(Toolkit::TextEditor textEditor, Property::Index index) +{ + Property::Value value; + TextEditor& impl(GetImpl(textEditor)); + DALI_ASSERT_DEBUG(impl.mController && "No text controller"); + DALI_ASSERT_DEBUG(impl.mDecorator && "No text decorator"); + + switch(index) + { + case Toolkit::DevelTextEditor::Property::RENDERING_BACKEND: + { + value = impl.mRenderingBackend; + break; + } + case Toolkit::TextEditor::Property::TEXT: + { + std::string text; + impl.mController->GetText(text); + DALI_LOG_INFO(gTextEditorLogFilter, Debug::General, "TextEditor %p returning text: %s\n", impl.mController.Get(), text.c_str()); + value = text; + break; + } + case Toolkit::TextEditor::Property::TEXT_COLOR: + { + value = impl.mController->GetDefaultColor(); + break; + } + case Toolkit::TextEditor::Property::FONT_FAMILY: + { + value = impl.mController->GetDefaultFontFamily(); + break; + } + case Toolkit::TextEditor::Property::FONT_STYLE: + { + GetFontStyleProperty(impl.mController, value, Text::FontStyle::DEFAULT); + break; + } + case Toolkit::TextEditor::Property::POINT_SIZE: + { + value = impl.mController->GetDefaultFontSize(Text::Controller::POINT_SIZE); + break; + } + case Toolkit::TextEditor::Property::HORIZONTAL_ALIGNMENT: + { + const char* name = Text::GetHorizontalAlignmentString(impl.mController->GetHorizontalAlignment()); + if(name) + { + value = std::string(name); + } + break; + } + case Toolkit::TextEditor::Property::SCROLL_THRESHOLD: + { + value = impl.mDecorator->GetScrollThreshold(); + break; + } + case Toolkit::TextEditor::Property::SCROLL_SPEED: + { + value = impl.mDecorator->GetScrollSpeed(); + break; + } + case Toolkit::TextEditor::Property::PRIMARY_CURSOR_COLOR: + { + value = impl.mDecorator->GetColor(Text::PRIMARY_CURSOR); + break; + } + case Toolkit::TextEditor::Property::SECONDARY_CURSOR_COLOR: + { + value = impl.mDecorator->GetColor(Text::SECONDARY_CURSOR); + break; + } + case Toolkit::TextEditor::Property::ENABLE_CURSOR_BLINK: + { + value = impl.mController->GetEnableCursorBlink(); + break; + } + case Toolkit::TextEditor::Property::CURSOR_BLINK_INTERVAL: + { + value = impl.mDecorator->GetCursorBlinkInterval(); + break; + } + case Toolkit::TextEditor::Property::CURSOR_BLINK_DURATION: + { + value = impl.mDecorator->GetCursorBlinkDuration(); + break; + } + case Toolkit::TextEditor::Property::CURSOR_WIDTH: + { + value = impl.mDecorator->GetCursorWidth(); + break; + } + case Toolkit::TextEditor::Property::GRAB_HANDLE_IMAGE: + { + value = impl.mDecorator->GetHandleImage(Text::GRAB_HANDLE, Text::HANDLE_IMAGE_RELEASED); + break; + } + case Toolkit::TextEditor::Property::GRAB_HANDLE_PRESSED_IMAGE: + { + value = impl.mDecorator->GetHandleImage(Text::GRAB_HANDLE, Text::HANDLE_IMAGE_PRESSED); + break; + } + case Toolkit::TextEditor::Property::SELECTION_HANDLE_IMAGE_LEFT: + { + impl.GetHandleImagePropertyValue(value, Text::LEFT_SELECTION_HANDLE, Text::HANDLE_IMAGE_RELEASED); + break; + } + case Toolkit::TextEditor::Property::SELECTION_HANDLE_IMAGE_RIGHT: + { + impl.GetHandleImagePropertyValue(value, Text::RIGHT_SELECTION_HANDLE, Text::HANDLE_IMAGE_RELEASED); + break; + } + case Toolkit::TextEditor::Property::SELECTION_HANDLE_PRESSED_IMAGE_LEFT: + { + impl.GetHandleImagePropertyValue(value, Text::LEFT_SELECTION_HANDLE, Text::HANDLE_IMAGE_PRESSED); + break; + } + case Toolkit::TextEditor::Property::SELECTION_HANDLE_PRESSED_IMAGE_RIGHT: + { + impl.GetHandleImagePropertyValue(value, Text::RIGHT_SELECTION_HANDLE, Text::HANDLE_IMAGE_PRESSED); + break; + } + case Toolkit::TextEditor::Property::SELECTION_HANDLE_MARKER_IMAGE_LEFT: + { + impl.GetHandleImagePropertyValue(value, Text::LEFT_SELECTION_HANDLE_MARKER, Text::HANDLE_IMAGE_RELEASED); + break; + } + case Toolkit::TextEditor::Property::SELECTION_HANDLE_MARKER_IMAGE_RIGHT: + { + impl.GetHandleImagePropertyValue(value, Text::RIGHT_SELECTION_HANDLE_MARKER, Text::HANDLE_IMAGE_RELEASED); + break; + } + case Toolkit::TextEditor::Property::SELECTION_HIGHLIGHT_COLOR: + { + value = impl.mDecorator->GetHighlightColor(); + break; + } + case Toolkit::TextEditor::Property::DECORATION_BOUNDING_BOX: + { + Rect boundingBox; + impl.mDecorator->GetBoundingBox(boundingBox); + value = boundingBox; + break; + } + case Toolkit::TextEditor::Property::ENABLE_MARKUP: + { + value = impl.mController->IsMarkupProcessorEnabled(); + break; + } + case Toolkit::TextEditor::Property::INPUT_COLOR: + { + value = impl.mController->GetInputColor(); + break; + } + case Toolkit::TextEditor::Property::INPUT_FONT_FAMILY: + { + value = impl.mController->GetInputFontFamily(); + break; + } + case Toolkit::TextEditor::Property::INPUT_FONT_STYLE: + { + GetFontStyleProperty(impl.mController, value, Text::FontStyle::INPUT); + break; + } + case Toolkit::TextEditor::Property::INPUT_POINT_SIZE: + { + value = impl.mController->GetInputFontPointSize(); + break; + } + case Toolkit::TextEditor::Property::LINE_SPACING: + { + value = impl.mController->GetDefaultLineSpacing(); + break; + } + case Toolkit::TextEditor::Property::INPUT_LINE_SPACING: + { + value = impl.mController->GetInputLineSpacing(); + break; + } + case Toolkit::TextEditor::Property::UNDERLINE: + { + GetUnderlineProperties(impl.mController, value, Text::EffectStyle::DEFAULT); + break; + } + case Toolkit::TextEditor::Property::INPUT_UNDERLINE: + { + GetUnderlineProperties(impl.mController, value, Text::EffectStyle::INPUT); + break; + } + case Toolkit::TextEditor::Property::SHADOW: + { + GetShadowProperties(impl.mController, value, Text::EffectStyle::DEFAULT); + break; + } + case Toolkit::TextEditor::Property::INPUT_SHADOW: + { + GetShadowProperties(impl.mController, value, Text::EffectStyle::INPUT); + break; + } + case Toolkit::TextEditor::Property::EMBOSS: + { + GetEmbossProperties(impl.mController, value, Text::EffectStyle::DEFAULT); + break; + } + case Toolkit::TextEditor::Property::INPUT_EMBOSS: + { + GetEmbossProperties(impl.mController, value, Text::EffectStyle::INPUT); + break; + } + case Toolkit::TextEditor::Property::OUTLINE: + { + GetOutlineProperties(impl.mController, value, Text::EffectStyle::DEFAULT); + break; + } + case Toolkit::TextEditor::Property::INPUT_OUTLINE: + { + GetOutlineProperties(impl.mController, value, Text::EffectStyle::INPUT); + break; + } + case Toolkit::TextEditor::Property::SMOOTH_SCROLL: + { + value = impl.mScrollAnimationEnabled; + break; + } + case Toolkit::TextEditor::Property::SMOOTH_SCROLL_DURATION: + { + value = impl.mScrollAnimationDuration; + break; + } + case Toolkit::TextEditor::Property::ENABLE_SCROLL_BAR: + { + value = impl.mScrollBarEnabled; + break; + } + case Toolkit::TextEditor::Property::SCROLL_BAR_SHOW_DURATION: + { + value = impl.mAnimationPeriod.delaySeconds; + break; + } + case Toolkit::TextEditor::Property::SCROLL_BAR_FADE_DURATION: + { + value = impl.mAnimationPeriod.durationSeconds; + break; + } + case Toolkit::TextEditor::Property::PIXEL_SIZE: + { + value = impl.mController->GetDefaultFontSize(Text::Controller::PIXEL_SIZE); + break; + } + case Toolkit::TextEditor::Property::LINE_COUNT: + { + float width = textEditor.GetProperty(Actor::Property::SIZE_WIDTH).Get(); + value = impl.mController->GetLineCount(width); + break; + } + case Toolkit::DevelTextEditor::Property::PLACEHOLDER_TEXT: + { + std::string text; + impl.mController->GetPlaceholderText(Text::Controller::PLACEHOLDER_TYPE_INACTIVE, text); + value = text; + break; + } + case Toolkit::DevelTextEditor::Property::PLACEHOLDER_TEXT_COLOR: + { + value = impl.mController->GetPlaceholderTextColor(); + break; + } + case Toolkit::TextEditor::Property::ENABLE_SELECTION: + { + value = impl.mController->IsSelectionEnabled(); + break; + } + case Toolkit::TextEditor::Property::PLACEHOLDER: + { + Property::Map map; + impl.mController->GetPlaceholderProperty(map); + value = map; + break; + } + case Toolkit::TextEditor::Property::LINE_WRAP_MODE: + { + value = impl.mController->GetLineWrapMode(); + break; + } + case Toolkit::DevelTextEditor::Property::ENABLE_SHIFT_SELECTION: + { + value = impl.mController->IsShiftSelectionEnabled(); + break; + } + case Toolkit::DevelTextEditor::Property::ENABLE_GRAB_HANDLE: + { + value = impl.mController->IsGrabHandleEnabled(); + break; + } + case Toolkit::DevelTextEditor::Property::MATCH_SYSTEM_LANGUAGE_DIRECTION: + { + value = impl.mController->GetMatchLayoutDirection() != DevelText::MatchLayoutDirection::CONTENTS; + break; + } + case Toolkit::DevelTextEditor::Property::MAX_LENGTH: + { + value = impl.mController->GetMaximumNumberOfCharacters(); + break; + } + case Toolkit::DevelTextEditor::Property::SELECTED_TEXT: + { + value = impl.mController->GetSelectedText(); + break; + } + case Toolkit::DevelTextEditor::Property::SELECTED_TEXT_START: + { + Uint32Pair range = impl.GetTextSelectionRange(); + value = static_cast(range.first); + break; + } + case Toolkit::DevelTextEditor::Property::SELECTED_TEXT_END: + { + Uint32Pair range = impl.GetTextSelectionRange(); + value = static_cast(range.second); + break; + } + case Toolkit::DevelTextEditor::Property::ENABLE_EDITING: + { + value = impl.IsEditable(); + break; + } + case Toolkit::DevelTextEditor::Property::HORIZONTAL_SCROLL_POSITION: + { + value = impl.GetHorizontalScrollPosition(); + break; + } + case Toolkit::DevelTextEditor::Property::VERTICAL_SCROLL_POSITION: + { + value = impl.GetVerticalScrollPosition(); + break; + } + case Toolkit::DevelTextEditor::Property::FONT_SIZE_SCALE: + { + value = impl.mController->GetFontSizeScale(); + break; + } + case Toolkit::DevelTextEditor::Property::PRIMARY_CURSOR_POSITION: + { + value = static_cast(impl.mController->GetPrimaryCursorPosition()); + break; + } + case Toolkit::DevelTextEditor::Property::GRAB_HANDLE_COLOR: + { + value = impl.mDecorator->GetHandleColor(); + break; + } + case Toolkit::DevelTextEditor::Property::ENABLE_GRAB_HANDLE_POPUP: + { + value = impl.mController->IsGrabHandlePopupEnabled(); + break; + } + case Toolkit::DevelTextEditor::Property::INPUT_METHOD_SETTINGS: + { + Property::Map map; + impl.mInputMethodOptions.RetrieveProperty(map); + value = map; + break; + } + case Toolkit::DevelTextEditor::Property::INPUT_FILTER: + { + Property::Map map; + impl.mController->GetInputFilterOption(map); + value = map; + break; + } + case Toolkit::DevelTextEditor::Property::ELLIPSIS: + { + value = impl.mController->IsTextElideEnabled(); + break; + } + case Toolkit::DevelTextEditor::Property::ELLIPSIS_POSITION: + { + value = impl.mController->GetEllipsisPosition(); + break; + } + case Toolkit::DevelTextEditor::Property::MIN_LINE_SIZE: + { + value = impl.mController->GetDefaultLineSize(); + break; + } + } //switch + return value; +} + +} // namespace Dali::Toolkit::Internal diff --git a/dali-toolkit/internal/controls/text-controls/text-editor-property-handler.h b/dali-toolkit/internal/controls/text-controls/text-editor-property-handler.h new file mode 100644 index 0000000..2664f4d --- /dev/null +++ b/dali-toolkit/internal/controls/text-controls/text-editor-property-handler.h @@ -0,0 +1,61 @@ +#ifndef DALI_TOOLKIT_INTERNAL_TEXT_EDITOR_PROPERTY_HANDLER_H +#define DALI_TOOLKIT_INTERNAL_TEXT_EDITOR_PROPERTY_HANDLER_H + +/* + * Copyright (c) 2021 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 + +namespace Dali::Toolkit::Internal +{ +/** + * Class to manage properties for the TextEditor + */ +struct TextEditor::PropertyHandler +{ + static const char* const IMAGE_MAP_FILENAME_STRING; //<<< "filename" key for image map + + /** + * Set properties on the text editor / controller / decorator + * + * @param[in] textEditor The handle for the text editor + * @param[in] index The property index of the property to set + * @param[in] value The value to set + */ + static void SetProperty(Toolkit::TextEditor textEditor, Property::Index index, const Property::Value& value); + + /** + * Get properties from the text editor / controller / decorator + * + * @param[in] textEditor The handle for the text editor + * @param[in] index The property index of the property to set + * @return the value + */ + static Property::Value GetProperty(Toolkit::TextEditor textEditor, Property::Index index); + +private: + /** + * Method to extract "filename" value from a Property::Map + * + * @param[in] The property value containing the Property::Map + * @return The resulting "filename" value if present + */ + static std::string GetImageFileNameFromPropertyValue(const Property::Value& value); +}; + +} // namespace Dali::Toolkit::Internal + +#endif //DALI_TOOLKIT_INTERNAL_TEXT_EDITOR_PROPERTY_HANDLER_H diff --git a/dali-toolkit/internal/controls/text-controls/text-field-impl.cpp b/dali-toolkit/internal/controls/text-controls/text-field-impl.cpp index 32beca1..fe01e46 100644 --- a/dali-toolkit/internal/controls/text-controls/text-field-impl.cpp +++ b/dali-toolkit/internal/controls/text-controls/text-field-impl.cpp @@ -24,17 +24,19 @@ #include #include #include +#include #include #include #include #include // INTERNAL INCLUDES -#include #include #include #include #include +#include +#include #include #include #include @@ -48,6 +50,10 @@ using namespace Dali::Toolkit::Text; +#if defined(DEBUG_ENABLED) +Debug::Filter* gTextFieldLogFilter = Debug::Filter::New(Debug::Concise, true, "LOG_TEXT_CONTROLS"); +#endif + namespace Dali { namespace Toolkit @@ -56,10 +62,6 @@ namespace Internal { namespace // unnamed namespace { -#if defined(DEBUG_ENABLED) -Debug::Filter* gLogFilter = Debug::Filter::New(Debug::Concise, true, "LOG_TEXT_CONTROLS"); -#endif - const unsigned int DEFAULT_RENDERING_BACKEND = Dali::Toolkit::DevelText::DEFAULT_RENDERING_BACKEND; } // unnamed namespace @@ -152,22 +154,51 @@ DALI_SIGNAL_REGISTRATION(Toolkit, TextField, "selectionCleared", SIGNAL_SEL DALI_TYPE_REGISTRATION_END() // clang-format on -const char* const IMAGE_MAP_FILENAME_STRING = "filename"; - -/// Retrieves a filename from a value that is a Property::Map -std::string GetImageFileNameFromPropertyValue(const Property::Value& value) +Toolkit::TextField::InputStyle::Mask ConvertInputStyle(Text::InputStyle::Mask inputStyleMask) { - std::string filename; - const Property::Map* map = value.GetMap(); - if(map) + Toolkit::TextField::InputStyle::Mask fieldInputStyleMask = Toolkit::TextField::InputStyle::NONE; + + if(InputStyle::NONE != static_cast(inputStyleMask & InputStyle::INPUT_COLOR)) { - const Property::Value* filenameValue = map->Find(IMAGE_MAP_FILENAME_STRING); - if(filenameValue) - { - filenameValue->Get(filename); - } + fieldInputStyleMask = static_cast(fieldInputStyleMask | Toolkit::TextField::InputStyle::COLOR); + } + if(InputStyle::NONE != static_cast(inputStyleMask & InputStyle::INPUT_FONT_FAMILY)) + { + fieldInputStyleMask = static_cast(fieldInputStyleMask | Toolkit::TextField::InputStyle::FONT_FAMILY); + } + if(InputStyle::NONE != static_cast(inputStyleMask & InputStyle::INPUT_POINT_SIZE)) + { + fieldInputStyleMask = static_cast(fieldInputStyleMask | Toolkit::TextField::InputStyle::POINT_SIZE); + } + if(InputStyle::NONE != static_cast(inputStyleMask & InputStyle::INPUT_FONT_WEIGHT)) + { + fieldInputStyleMask = static_cast(fieldInputStyleMask | Toolkit::TextField::InputStyle::FONT_STYLE); + } + if(InputStyle::NONE != static_cast(inputStyleMask & InputStyle::INPUT_FONT_WIDTH)) + { + fieldInputStyleMask = static_cast(fieldInputStyleMask | Toolkit::TextField::InputStyle::FONT_STYLE); + } + if(InputStyle::NONE != static_cast(inputStyleMask & InputStyle::INPUT_FONT_SLANT)) + { + fieldInputStyleMask = static_cast(fieldInputStyleMask | Toolkit::TextField::InputStyle::FONT_STYLE); + } + if(InputStyle::NONE != static_cast(inputStyleMask & InputStyle::INPUT_UNDERLINE)) + { + fieldInputStyleMask = static_cast(fieldInputStyleMask | Toolkit::TextField::InputStyle::UNDERLINE); + } + if(InputStyle::NONE != static_cast(inputStyleMask & InputStyle::INPUT_SHADOW)) + { + fieldInputStyleMask = static_cast(fieldInputStyleMask | Toolkit::TextField::InputStyle::SHADOW); + } + if(InputStyle::NONE != static_cast(inputStyleMask & InputStyle::INPUT_EMBOSS)) + { + fieldInputStyleMask = static_cast(fieldInputStyleMask | Toolkit::TextField::InputStyle::EMBOSS); + } + if(InputStyle::NONE != static_cast(inputStyleMask & InputStyle::INPUT_OUTLINE)) + { + fieldInputStyleMask = static_cast(fieldInputStyleMask | Toolkit::TextField::InputStyle::OUTLINE); } - return filename; + return fieldInputStyleMask; } } // namespace @@ -191,606 +222,12 @@ void TextField::SetProperty(BaseObject* object, Property::Index index, const Pro { Toolkit::TextField textField = Toolkit::TextField::DownCast(Dali::BaseHandle(object)); - DALI_LOG_INFO(gLogFilter, Debug::Verbose, "TextField SetProperty\n"); + DALI_LOG_INFO(gTextFieldLogFilter, Debug::Verbose, "TextField SetProperty\n"); if(textField) { - TextField& impl(GetImpl(textField)); - DALI_ASSERT_DEBUG(impl.mController && "No text contoller"); - DALI_ASSERT_DEBUG(impl.mDecorator && "No text decorator"); - - switch(index) - { - case Toolkit::DevelTextField::Property::RENDERING_BACKEND: - { - int backend = value.Get(); - DALI_LOG_INFO(gLogFilter, Debug::Verbose, "TextField %p RENDERING_BACKEND %d\n", impl.mController.Get(), backend); - -#ifndef ENABLE_VECTOR_BASED_TEXT_RENDERING - if(DevelText::RENDERING_VECTOR_BASED == backend) - { - backend = TextAbstraction::BITMAP_GLYPH; // Fallback to bitmap-based rendering - } -#endif - if(impl.mRenderingBackend != backend) - { - impl.mRenderingBackend = backend; - impl.mRenderer.Reset(); - - // When using the vector-based rendering, the size of the GLyphs are different - TextAbstraction::GlyphType glyphType = (DevelText::RENDERING_VECTOR_BASED == impl.mRenderingBackend) ? TextAbstraction::VECTOR_GLYPH : TextAbstraction::BITMAP_GLYPH; - impl.mController->SetGlyphType(glyphType); - } - break; - } - case Toolkit::TextField::Property::TEXT: - { - const std::string& text = value.Get(); - DALI_LOG_INFO(gLogFilter, Debug::General, "TextField %p TEXT %s\n", impl.mController.Get(), text.c_str()); - - impl.mController->SetText(text); - break; - } - case Toolkit::TextField::Property::PLACEHOLDER_TEXT: - { - const std::string& text = value.Get(); - DALI_LOG_INFO(gLogFilter, Debug::General, "TextField %p PLACEHOLDER_TEXT %s\n", impl.mController.Get(), text.c_str()); - - impl.mController->SetPlaceholderText(Controller::PLACEHOLDER_TYPE_INACTIVE, text); - break; - } - case Toolkit::TextField::Property::PLACEHOLDER_TEXT_FOCUSED: - { - const std::string& text = value.Get(); - DALI_LOG_INFO(gLogFilter, Debug::General, "TextField %p PLACEHOLDER_TEXT_FOCUSED %s\n", impl.mController.Get(), text.c_str()); - - impl.mController->SetPlaceholderText(Controller::PLACEHOLDER_TYPE_ACTIVE, text); - break; - } - case Toolkit::TextField::Property::FONT_FAMILY: - { - const std::string& fontFamily = value.Get(); - DALI_LOG_INFO(gLogFilter, Debug::General, "TextField %p FONT_FAMILY %s\n", impl.mController.Get(), fontFamily.c_str()); - impl.mController->SetDefaultFontFamily(fontFamily); - break; - } - case Toolkit::TextField::Property::FONT_STYLE: - { - SetFontStyleProperty(impl.mController, value, Text::FontStyle::DEFAULT); - break; - } - case Toolkit::TextField::Property::POINT_SIZE: - { - const float pointSize = value.Get(); - DALI_LOG_INFO(gLogFilter, Debug::General, "TextField %p POINT_SIZE %f\n", impl.mController.Get(), pointSize); - - if(!Equals(impl.mController->GetDefaultFontSize(Text::Controller::POINT_SIZE), pointSize)) - { - impl.mController->SetDefaultFontSize(pointSize, Text::Controller::POINT_SIZE); - } - break; - } - case Toolkit::TextField::Property::MAX_LENGTH: - { - const int max = value.Get(); - DALI_LOG_INFO(gLogFilter, Debug::General, "TextField %p MAX_LENGTH %d\n", impl.mController.Get(), max); - - impl.mController->SetMaximumNumberOfCharacters(max); - break; - } - case Toolkit::TextField::Property::EXCEED_POLICY: - { - impl.mExceedPolicy = value.Get(); - - if(Dali::Toolkit::TextField::EXCEED_POLICY_CLIP == impl.mExceedPolicy) - { - impl.EnableClipping(); - } - else - { - UnparentAndReset(impl.mStencil); - } - impl.RequestTextRelayout(); - break; - } - case Toolkit::TextField::Property::HORIZONTAL_ALIGNMENT: - { - Text::HorizontalAlignment::Type alignment(static_cast(-1)); // Set to invalid value to ensure a valid mode does get set - if(GetHorizontalAlignmentEnumeration(value, alignment)) - { - DALI_LOG_INFO(gLogFilter, Debug::General, "TextField %p HORIZONTAL_ALIGNMENT %d\n", impl.mController.Get(), alignment); - impl.mController->SetHorizontalAlignment(alignment); - } - break; - } - case Toolkit::TextField::Property::VERTICAL_ALIGNMENT: - { - Toolkit::Text::VerticalAlignment::Type alignment(static_cast(-1)); // Set to invalid value to ensure a valid mode does get set - if(GetVerticalAlignmentEnumeration(value, alignment)) - { - impl.mController->SetVerticalAlignment(alignment); - DALI_LOG_INFO(gLogFilter, Debug::General, "TextField %p VERTICAL_ALIGNMENT %d\n", impl.mController.Get(), alignment); - } - break; - } - case Toolkit::TextField::Property::TEXT_COLOR: - { - const Vector4& textColor = value.Get(); - DALI_LOG_INFO(gLogFilter, Debug::General, "TextField %p TEXT_COLOR %f,%f,%f,%f\n", impl.mController.Get(), textColor.r, textColor.g, textColor.b, textColor.a); - - if(impl.mController->GetDefaultColor() != textColor) - { - impl.mController->SetDefaultColor(textColor); - impl.mController->SetInputColor(textColor); - impl.mRenderer.Reset(); - } - break; - } - case Toolkit::TextField::Property::PLACEHOLDER_TEXT_COLOR: - { - const Vector4& textColor = value.Get(); - DALI_LOG_INFO(gLogFilter, Debug::General, "TextField %p PLACEHOLDER_TEXT_COLOR %f,%f,%f,%f\n", impl.mController.Get(), textColor.r, textColor.g, textColor.b, textColor.a); - - if(impl.mController->GetPlaceholderTextColor() != textColor) - { - impl.mController->SetPlaceholderTextColor(textColor); - impl.mRenderer.Reset(); - } - break; - } - case Toolkit::TextField::Property::PRIMARY_CURSOR_COLOR: - { - const Vector4& color = value.Get(); - DALI_LOG_INFO(gLogFilter, Debug::General, "TextField %p PRIMARY_CURSOR_COLOR %f,%f,%f,%f\n", impl.mController.Get(), color.r, color.g, color.b, color.a); - - impl.mDecorator->SetCursorColor(PRIMARY_CURSOR, color); - impl.RequestTextRelayout(); - break; - } - case Toolkit::TextField::Property::SECONDARY_CURSOR_COLOR: - { - const Vector4& color = value.Get(); - DALI_LOG_INFO(gLogFilter, Debug::General, "TextField %p SECONDARY_CURSOR_COLOR %f,%f,%f,%f\n", impl.mController.Get(), color.r, color.g, color.b, color.a); - - impl.mDecorator->SetCursorColor(SECONDARY_CURSOR, color); - impl.RequestTextRelayout(); - break; - } - case Toolkit::TextField::Property::ENABLE_CURSOR_BLINK: - { - const bool enable = value.Get(); - DALI_LOG_INFO(gLogFilter, Debug::Verbose, "TextField %p ENABLE_CURSOR_BLINK %d\n", impl.mController.Get(), enable); - - impl.mController->SetEnableCursorBlink(enable); - impl.RequestTextRelayout(); - break; - } - case Toolkit::TextField::Property::CURSOR_BLINK_INTERVAL: - { - const float interval = value.Get(); - DALI_LOG_INFO(gLogFilter, Debug::Verbose, "TextField %p CURSOR_BLINK_INTERVAL %f\n", impl.mController.Get(), interval); - - impl.mDecorator->SetCursorBlinkInterval(interval); - break; - } - case Toolkit::TextField::Property::CURSOR_BLINK_DURATION: - { - const float duration = value.Get(); - DALI_LOG_INFO(gLogFilter, Debug::Verbose, "TextField %p CURSOR_BLINK_DURATION %f\n", impl.mController.Get(), duration); - - impl.mDecorator->SetCursorBlinkDuration(duration); - break; - } - case Toolkit::TextField::Property::CURSOR_WIDTH: - { - const int width = value.Get(); - DALI_LOG_INFO(gLogFilter, Debug::Verbose, "TextField %p CURSOR_WIDTH %d\n", impl.mController.Get(), width); - - impl.mDecorator->SetCursorWidth(width); - impl.mController->GetLayoutEngine().SetCursorWidth(width); - break; - } - case Toolkit::TextField::Property::GRAB_HANDLE_IMAGE: - { - const std::string imageFileName = value.Get(); - DALI_LOG_INFO(gLogFilter, Debug::Verbose, "TextField %p GRAB_HANDLE_IMAGE %s\n", impl.mController.Get(), imageFileName.c_str()); - - if(imageFileName.size()) - { - impl.mDecorator->SetHandleImage(GRAB_HANDLE, HANDLE_IMAGE_RELEASED, imageFileName); - impl.RequestTextRelayout(); - } - break; - } - case Toolkit::TextField::Property::GRAB_HANDLE_PRESSED_IMAGE: - { - const std::string imageFileName = value.Get(); - DALI_LOG_INFO(gLogFilter, Debug::Verbose, "TextField %p GRAB_HANDLE_PRESSED_IMAGE %s\n", impl.mController.Get(), imageFileName.c_str()); - - if(imageFileName.size()) - { - impl.mDecorator->SetHandleImage(GRAB_HANDLE, HANDLE_IMAGE_PRESSED, imageFileName); - impl.RequestTextRelayout(); - } - break; - } - case Toolkit::TextField::Property::SCROLL_THRESHOLD: - { - const float threshold = value.Get(); - DALI_LOG_INFO(gLogFilter, Debug::Verbose, "TextField %p SCROLL_THRESHOLD %f\n", impl.mController.Get(), threshold); - - impl.mDecorator->SetScrollThreshold(threshold); - break; - } - case Toolkit::TextField::Property::SCROLL_SPEED: - { - const float speed = value.Get(); - DALI_LOG_INFO(gLogFilter, Debug::Verbose, "TextField %p SCROLL_SPEED %f\n", impl.mController.Get(), speed); - - impl.mDecorator->SetScrollSpeed(speed); - break; - } - case Toolkit::TextField::Property::SELECTION_HANDLE_IMAGE_LEFT: - { - const std::string filename = GetImageFileNameFromPropertyValue(value); - - if(filename.size()) - { - impl.mDecorator->SetHandleImage(LEFT_SELECTION_HANDLE, HANDLE_IMAGE_RELEASED, filename); - impl.RequestTextRelayout(); - } - break; - } - case Toolkit::TextField::Property::SELECTION_HANDLE_IMAGE_RIGHT: - { - const std::string filename = GetImageFileNameFromPropertyValue(value); - - if(filename.size()) - { - impl.mDecorator->SetHandleImage(RIGHT_SELECTION_HANDLE, HANDLE_IMAGE_RELEASED, filename); - impl.RequestTextRelayout(); - } - break; - } - case Toolkit::TextField::Property::SELECTION_HANDLE_PRESSED_IMAGE_LEFT: - { - const std::string filename = GetImageFileNameFromPropertyValue(value); - - if(filename.size()) - { - impl.mDecorator->SetHandleImage(LEFT_SELECTION_HANDLE, HANDLE_IMAGE_PRESSED, filename); - impl.RequestTextRelayout(); - } - break; - } - case Toolkit::TextField::Property::SELECTION_HANDLE_PRESSED_IMAGE_RIGHT: - { - const std::string filename = GetImageFileNameFromPropertyValue(value); - - if(filename.size()) - { - impl.mDecorator->SetHandleImage(RIGHT_SELECTION_HANDLE, HANDLE_IMAGE_PRESSED, filename); - impl.RequestTextRelayout(); - } - break; - } - case Toolkit::TextField::Property::SELECTION_HANDLE_MARKER_IMAGE_LEFT: - { - const std::string filename = GetImageFileNameFromPropertyValue(value); - - if(filename.size()) - { - impl.mDecorator->SetHandleImage(LEFT_SELECTION_HANDLE_MARKER, HANDLE_IMAGE_RELEASED, filename); - impl.RequestTextRelayout(); - } - break; - } - case Toolkit::TextField::Property::SELECTION_HANDLE_MARKER_IMAGE_RIGHT: - { - const std::string filename = GetImageFileNameFromPropertyValue(value); - - if(filename.size()) - { - impl.mDecorator->SetHandleImage(RIGHT_SELECTION_HANDLE_MARKER, HANDLE_IMAGE_RELEASED, filename); - impl.RequestTextRelayout(); - } - break; - } - case Toolkit::TextField::Property::SELECTION_HIGHLIGHT_COLOR: - { - const Vector4 color = value.Get(); - DALI_LOG_INFO(gLogFilter, Debug::General, "TextField %p SELECTION_HIGHLIGHT_COLOR %f,%f,%f,%f\n", impl.mController.Get(), color.r, color.g, color.b, color.a); - - impl.mDecorator->SetHighlightColor(color); - impl.RequestTextRelayout(); - break; - } - case Toolkit::TextField::Property::DECORATION_BOUNDING_BOX: - { - const Rect box = value.Get >(); - DALI_LOG_INFO(gLogFilter, Debug::General, "TextField %p DECORATION_BOUNDING_BOX %d,%d %dx%d\n", impl.mController.Get(), box.x, box.y, box.width, box.height); - - impl.mDecorator->SetBoundingBox(box); - impl.RequestTextRelayout(); - break; - } - case Toolkit::TextField::Property::INPUT_METHOD_SETTINGS: - { - const Property::Map* map = value.GetMap(); - if(map) - { - impl.mInputMethodOptions.ApplyProperty(*map); - } - impl.mController->SetInputModePassword(impl.mInputMethodOptions.IsPassword()); - - Toolkit::Control control = Toolkit::KeyInputFocusManager::Get().GetCurrentFocusControl(); - if(control == textField) - { - impl.mInputMethodContext.ApplyOptions(impl.mInputMethodOptions); - } - break; - } - case Toolkit::TextField::Property::INPUT_COLOR: - { - const Vector4 inputColor = value.Get(); - DALI_LOG_INFO(gLogFilter, Debug::General, "TextField %p INPUT_COLOR %f,%f,%f,%f\n", impl.mController.Get(), inputColor.r, inputColor.g, inputColor.b, inputColor.a); - - impl.mController->SetInputColor(inputColor); - break; - } - case Toolkit::TextField::Property::ENABLE_MARKUP: - { - const bool enableMarkup = value.Get(); - DALI_LOG_INFO(gLogFilter, Debug::General, "TextField %p ENABLE_MARKUP %d\n", impl.mController.Get(), enableMarkup); - - impl.mController->SetMarkupProcessorEnabled(enableMarkup); - break; - } - case Toolkit::TextField::Property::INPUT_FONT_FAMILY: - { - const std::string& fontFamily = value.Get(); - DALI_LOG_INFO(gLogFilter, Debug::General, "TextField %p INPUT_FONT_FAMILY %s\n", impl.mController.Get(), fontFamily.c_str()); - impl.mController->SetInputFontFamily(fontFamily); - break; - } - case Toolkit::TextField::Property::INPUT_FONT_STYLE: - { - SetFontStyleProperty(impl.mController, value, Text::FontStyle::INPUT); - break; - } - case Toolkit::TextField::Property::INPUT_POINT_SIZE: - { - const float pointSize = value.Get(); - DALI_LOG_INFO(gLogFilter, Debug::General, "TextField %p INPUT_POINT_SIZE %f\n", impl.mController.Get(), pointSize); - impl.mController->SetInputFontPointSize(pointSize); - break; - } - case Toolkit::TextField::Property::UNDERLINE: - { - const bool update = SetUnderlineProperties(impl.mController, value, Text::EffectStyle::DEFAULT); - if(update) - { - impl.mRenderer.Reset(); - } - break; - } - case Toolkit::TextField::Property::INPUT_UNDERLINE: - { - const bool update = SetUnderlineProperties(impl.mController, value, Text::EffectStyle::INPUT); - if(update) - { - impl.mRenderer.Reset(); - } - break; - } - case Toolkit::TextField::Property::SHADOW: - { - const bool update = SetShadowProperties(impl.mController, value, Text::EffectStyle::DEFAULT); - if(update) - { - impl.mRenderer.Reset(); - } - break; - } - case Toolkit::TextField::Property::INPUT_SHADOW: - { - const bool update = SetShadowProperties(impl.mController, value, Text::EffectStyle::INPUT); - if(update) - { - impl.mRenderer.Reset(); - } - break; - } - case Toolkit::TextField::Property::EMBOSS: - { - const bool update = SetEmbossProperties(impl.mController, value, Text::EffectStyle::DEFAULT); - if(update) - { - impl.mRenderer.Reset(); - } - break; - } - case Toolkit::TextField::Property::INPUT_EMBOSS: - { - const bool update = SetEmbossProperties(impl.mController, value, Text::EffectStyle::INPUT); - if(update) - { - impl.mRenderer.Reset(); - } - break; - } - case Toolkit::TextField::Property::OUTLINE: - { - const bool update = SetOutlineProperties(impl.mController, value, Text::EffectStyle::DEFAULT); - if(update) - { - impl.mRenderer.Reset(); - } - break; - } - case Toolkit::TextField::Property::INPUT_OUTLINE: - { - const bool update = SetOutlineProperties(impl.mController, value, Text::EffectStyle::INPUT); - if(update) - { - impl.mRenderer.Reset(); - } - break; - } - case Toolkit::TextField::Property::HIDDEN_INPUT_SETTINGS: - { - const Property::Map* map = value.GetMap(); - if(map) - { - impl.mController->SetHiddenInputOption(*map); - } - break; - } - case Toolkit::TextField::Property::PIXEL_SIZE: - { - const float pixelSize = value.Get(); - DALI_LOG_INFO(gLogFilter, Debug::General, "TextField %p PIXEL_SIZE %f\n", impl.mController.Get(), pixelSize); - - if(!Equals(impl.mController->GetDefaultFontSize(Text::Controller::PIXEL_SIZE), pixelSize)) - { - impl.mController->SetDefaultFontSize(pixelSize, Text::Controller::PIXEL_SIZE); - } - break; - } - case Toolkit::TextField::Property::ENABLE_SELECTION: - { - const bool enableSelection = value.Get(); - DALI_LOG_INFO(gLogFilter, Debug::General, "TextField %p ENABLE_SELECTION %d\n", impl.mController.Get(), enableSelection); - impl.mController->SetSelectionEnabled(enableSelection); - break; - } - case Toolkit::TextField::Property::PLACEHOLDER: - { - const Property::Map* map = value.GetMap(); - if(map) - { - impl.mController->SetPlaceholderProperty(*map); - } - break; - } - case Toolkit::TextField::Property::ELLIPSIS: - { - const bool ellipsis = value.Get(); - DALI_LOG_INFO(gLogFilter, Debug::General, "TextField %p ELLIPSIS %d\n", impl.mController.Get(), ellipsis); - - impl.mController->SetTextElideEnabled(ellipsis); - break; - } - case Toolkit::DevelTextField::Property::ENABLE_SHIFT_SELECTION: - { - const bool shiftSelection = value.Get(); - DALI_LOG_INFO(gLogFilter, Debug::General, "TextField %p ENABLE_SHIFT_SELECTION %d\n", impl.mController.Get(), shiftSelection); - - impl.mController->SetShiftSelectionEnabled(shiftSelection); - break; - } - case Toolkit::DevelTextField::Property::ENABLE_GRAB_HANDLE: - { - const bool grabHandleEnabled = value.Get(); - DALI_LOG_INFO(gLogFilter, Debug::General, "TextField %p ENABLE_GRAB_HANDLE %d\n", impl.mController.Get(), grabHandleEnabled); - - impl.mController->SetGrabHandleEnabled(grabHandleEnabled); - break; - } - case Toolkit::DevelTextField::Property::MATCH_SYSTEM_LANGUAGE_DIRECTION: - { - impl.mController->SetMatchLayoutDirection(value.Get() ? DevelText::MatchLayoutDirection::LOCALE : DevelText::MatchLayoutDirection::CONTENTS); - break; - } - case Toolkit::DevelTextField::Property::ENABLE_GRAB_HANDLE_POPUP: - { - const bool grabHandlePopupEnabled = value.Get(); - DALI_LOG_INFO(gLogFilter, Debug::General, "TextField %p ENABLE_GRAB_HANDLE_POPUP %d\n", impl.mController.Get(), grabHandlePopupEnabled); - - impl.mController->SetGrabHandlePopupEnabled(grabHandlePopupEnabled); - break; - } - case Toolkit::DevelTextField::Property::BACKGROUND: - { - const Vector4 backgroundColor = value.Get(); - DALI_LOG_INFO(gLogFilter, Debug::General, "TextField %p BACKGROUND %f,%f,%f,%f\n", impl.mController.Get(), backgroundColor.r, backgroundColor.g, backgroundColor.b, backgroundColor.a); - - impl.mController->SetBackgroundEnabled(true); - impl.mController->SetBackgroundColor(backgroundColor); - break; - } - case Toolkit::DevelTextField::Property::SELECTED_TEXT_START: - { - uint32_t start = static_cast(value.Get()); - DALI_LOG_INFO(gLogFilter, Debug::General, "TextField %p SELECTED_TEXT_START %d\n", impl.mController.Get(), start); - impl.SetTextSelectionRange(&start, nullptr); - break; - } - case Toolkit::DevelTextField::Property::SELECTED_TEXT_END: - { - uint32_t end = static_cast(value.Get()); - DALI_LOG_INFO(gLogFilter, Debug::General, "TextField %p SELECTED_TEXT_END %d\n", impl.mController.Get(), end); - impl.SetTextSelectionRange(nullptr, &end); - break; - } - case Toolkit::DevelTextField::Property::ENABLE_EDITING: - { - const bool editable = value.Get(); - DALI_LOG_INFO(gLogFilter, Debug::General, "TextField %p ENABLE_EDITING %d\n", impl.mController.Get(), editable); - impl.SetEditable(editable); - break; - } - case Toolkit::DevelTextField::Property::FONT_SIZE_SCALE: - { - const float scale = value.Get(); - DALI_LOG_INFO(gLogFilter, Debug::General, "TextField %p FONT_SIZE_SCALE %f\n", impl.mController.Get(), scale); - - if(!Equals(impl.mController->GetFontSizeScale(), scale)) - { - impl.mController->SetFontSizeScale(scale); - } - break; - } - case Toolkit::DevelTextField::Property::PRIMARY_CURSOR_POSITION: - { - uint32_t position = static_cast(value.Get()); - DALI_LOG_INFO(gLogFilter, Debug::General, "TextField %p PRIMARY_CURSOR_POSITION %d\n", impl.mController.Get(), position); - if(impl.mController->SetPrimaryCursorPosition(position, impl.HasKeyInputFocus())) - { - impl.SetKeyInputFocus(); - } - break; - } - case Toolkit::DevelTextField::Property::GRAB_HANDLE_COLOR: - { - const Vector4 color = value.Get(); - DALI_LOG_INFO(gLogFilter, Debug::General, "TextField %p GRAB_HANDLE_COLOR %f,%f,%f,%f\n", impl.mController.Get(), color.r, color.g, color.b, color.a); - - impl.mDecorator->SetHandleColor(color); - impl.RequestTextRelayout(); - break; - } - case Toolkit::DevelTextField::Property::INPUT_FILTER: - { - const Property::Map* map = value.GetMap(); - if(map) - { - impl.mController->SetInputFilterOption(*map); - } - break; - } - case Toolkit::DevelTextField::Property::ELLIPSIS_POSITION: - { - DevelText::EllipsisPosition::Type ellipsisPositionType(static_cast(-1)); // Set to invalid value to ensure a valid mode does get set - if(GetEllipsisPositionTypeEnumeration(value, ellipsisPositionType)) - { - DALI_LOG_INFO(gLogFilter, Debug::General, "TextField %p EllipsisPosition::Type %d\n", impl.mController.Get(), ellipsisPositionType); - impl.mController->SetEllipsisPosition(ellipsisPositionType); - } - break; - } - } // switch - } // textfield + PropertyHandler::SetProperty(textField, index, value); + } } Property::Value TextField::GetProperty(BaseObject* object, Property::Index index) @@ -801,362 +238,7 @@ Property::Value TextField::GetProperty(BaseObject* object, Property::Index index if(textField) { - TextField& impl(GetImpl(textField)); - DALI_ASSERT_DEBUG(impl.mController && "No text contoller"); - DALI_ASSERT_DEBUG(impl.mDecorator && "No text decorator"); - - switch(index) - { - case Toolkit::DevelTextField::Property::RENDERING_BACKEND: - { - value = impl.mRenderingBackend; - break; - } - case Toolkit::TextField::Property::TEXT: - { - std::string text; - impl.mController->GetText(text); - DALI_LOG_INFO(gLogFilter, Debug::General, "TextField %p returning text: %s\n", impl.mController.Get(), text.c_str()); - value = text; - break; - } - case Toolkit::TextField::Property::PLACEHOLDER_TEXT: - { - std::string text; - impl.mController->GetPlaceholderText(Controller::PLACEHOLDER_TYPE_INACTIVE, text); - value = text; - break; - } - case Toolkit::TextField::Property::PLACEHOLDER_TEXT_FOCUSED: - { - std::string text; - impl.mController->GetPlaceholderText(Controller::PLACEHOLDER_TYPE_ACTIVE, text); - value = text; - break; - } - case Toolkit::TextField::Property::FONT_FAMILY: - { - value = impl.mController->GetDefaultFontFamily(); - break; - } - case Toolkit::TextField::Property::FONT_STYLE: - { - GetFontStyleProperty(impl.mController, value, Text::FontStyle::DEFAULT); - break; - } - case Toolkit::TextField::Property::POINT_SIZE: - { - value = impl.mController->GetDefaultFontSize(Text::Controller::POINT_SIZE); - break; - } - case Toolkit::TextField::Property::MAX_LENGTH: - { - value = impl.mController->GetMaximumNumberOfCharacters(); - break; - } - case Toolkit::TextField::Property::EXCEED_POLICY: - { - value = impl.mExceedPolicy; - break; - } - case Toolkit::TextField::Property::HORIZONTAL_ALIGNMENT: - { - const char* name = Text::GetHorizontalAlignmentString(impl.mController->GetHorizontalAlignment()); - - if(name) - { - value = std::string(name); - } - break; - } - case Toolkit::TextField::Property::VERTICAL_ALIGNMENT: - { - const char* name = Text::GetVerticalAlignmentString(impl.mController->GetVerticalAlignment()); - - if(name) - { - value = std::string(name); - } - break; - } - case Toolkit::TextField::Property::TEXT_COLOR: - { - value = impl.mController->GetDefaultColor(); - break; - } - case Toolkit::TextField::Property::PLACEHOLDER_TEXT_COLOR: - { - value = impl.mController->GetPlaceholderTextColor(); - break; - } - case Toolkit::TextField::Property::PRIMARY_CURSOR_COLOR: - { - value = impl.mDecorator->GetColor(PRIMARY_CURSOR); - break; - } - case Toolkit::TextField::Property::SECONDARY_CURSOR_COLOR: - { - value = impl.mDecorator->GetColor(SECONDARY_CURSOR); - break; - } - case Toolkit::TextField::Property::ENABLE_CURSOR_BLINK: - { - value = impl.mController->GetEnableCursorBlink(); - break; - } - case Toolkit::TextField::Property::CURSOR_BLINK_INTERVAL: - { - value = impl.mDecorator->GetCursorBlinkInterval(); - break; - } - case Toolkit::TextField::Property::CURSOR_BLINK_DURATION: - { - value = impl.mDecorator->GetCursorBlinkDuration(); - break; - } - case Toolkit::TextField::Property::CURSOR_WIDTH: - { - value = impl.mDecorator->GetCursorWidth(); - break; - } - case Toolkit::TextField::Property::GRAB_HANDLE_IMAGE: - { - value = impl.mDecorator->GetHandleImage(GRAB_HANDLE, HANDLE_IMAGE_RELEASED); - break; - } - case Toolkit::TextField::Property::GRAB_HANDLE_PRESSED_IMAGE: - { - value = impl.mDecorator->GetHandleImage(GRAB_HANDLE, HANDLE_IMAGE_PRESSED); - break; - } - case Toolkit::TextField::Property::SCROLL_THRESHOLD: - { - value = impl.mDecorator->GetScrollThreshold(); - break; - } - case Toolkit::TextField::Property::SCROLL_SPEED: - { - value = impl.mDecorator->GetScrollSpeed(); - break; - } - case Toolkit::TextField::Property::SELECTION_HANDLE_IMAGE_LEFT: - { - impl.GetHandleImagePropertyValue(value, LEFT_SELECTION_HANDLE, HANDLE_IMAGE_RELEASED); - break; - } - case Toolkit::TextField::Property::SELECTION_HANDLE_IMAGE_RIGHT: - { - impl.GetHandleImagePropertyValue(value, RIGHT_SELECTION_HANDLE, HANDLE_IMAGE_RELEASED); - break; - } - case Toolkit::TextField::Property::SELECTION_HANDLE_PRESSED_IMAGE_LEFT: - { - impl.GetHandleImagePropertyValue(value, LEFT_SELECTION_HANDLE, HANDLE_IMAGE_PRESSED); - break; - } - case Toolkit::TextField::Property::SELECTION_HANDLE_PRESSED_IMAGE_RIGHT: - { - impl.GetHandleImagePropertyValue(value, RIGHT_SELECTION_HANDLE, HANDLE_IMAGE_PRESSED); - break; - } - case Toolkit::TextField::Property::SELECTION_HANDLE_MARKER_IMAGE_LEFT: - { - impl.GetHandleImagePropertyValue(value, LEFT_SELECTION_HANDLE_MARKER, HANDLE_IMAGE_RELEASED); - break; - } - case Toolkit::TextField::Property::SELECTION_HANDLE_MARKER_IMAGE_RIGHT: - { - impl.GetHandleImagePropertyValue(value, RIGHT_SELECTION_HANDLE_MARKER, HANDLE_IMAGE_RELEASED); - break; - } - case Toolkit::TextField::Property::SELECTION_HIGHLIGHT_COLOR: - { - value = impl.mDecorator->GetHighlightColor(); - break; - } - case Toolkit::TextField::Property::DECORATION_BOUNDING_BOX: - { - Rect boundingBox; - impl.mDecorator->GetBoundingBox(boundingBox); - value = boundingBox; - break; - } - case Toolkit::TextField::Property::INPUT_METHOD_SETTINGS: - { - Property::Map map; - impl.mInputMethodOptions.RetrieveProperty(map); - value = map; - break; - } - case Toolkit::TextField::Property::INPUT_COLOR: - { - value = impl.mController->GetInputColor(); - break; - } - case Toolkit::TextField::Property::ENABLE_MARKUP: - { - value = impl.mController->IsMarkupProcessorEnabled(); - break; - } - case Toolkit::TextField::Property::INPUT_FONT_FAMILY: - { - value = impl.mController->GetInputFontFamily(); - break; - } - case Toolkit::TextField::Property::INPUT_FONT_STYLE: - { - GetFontStyleProperty(impl.mController, value, Text::FontStyle::INPUT); - break; - } - case Toolkit::TextField::Property::INPUT_POINT_SIZE: - { - value = impl.mController->GetInputFontPointSize(); - break; - } - case Toolkit::TextField::Property::UNDERLINE: - { - GetUnderlineProperties(impl.mController, value, Text::EffectStyle::DEFAULT); - break; - } - case Toolkit::TextField::Property::INPUT_UNDERLINE: - { - GetUnderlineProperties(impl.mController, value, Text::EffectStyle::INPUT); - break; - } - case Toolkit::TextField::Property::SHADOW: - { - GetShadowProperties(impl.mController, value, Text::EffectStyle::DEFAULT); - break; - } - case Toolkit::TextField::Property::INPUT_SHADOW: - { - GetShadowProperties(impl.mController, value, Text::EffectStyle::INPUT); - break; - } - case Toolkit::TextField::Property::EMBOSS: - { - GetEmbossProperties(impl.mController, value, Text::EffectStyle::DEFAULT); - break; - } - case Toolkit::TextField::Property::INPUT_EMBOSS: - { - GetEmbossProperties(impl.mController, value, Text::EffectStyle::INPUT); - break; - } - case Toolkit::TextField::Property::OUTLINE: - { - GetOutlineProperties(impl.mController, value, Text::EffectStyle::DEFAULT); - break; - } - case Toolkit::TextField::Property::INPUT_OUTLINE: - { - GetOutlineProperties(impl.mController, value, Text::EffectStyle::INPUT); - break; - } - case Toolkit::TextField::Property::HIDDEN_INPUT_SETTINGS: - { - Property::Map map; - impl.mController->GetHiddenInputOption(map); - value = map; - break; - } - case Toolkit::TextField::Property::PIXEL_SIZE: - { - value = impl.mController->GetDefaultFontSize(Text::Controller::PIXEL_SIZE); - break; - } - case Toolkit::TextField::Property::ENABLE_SELECTION: - { - value = impl.mController->IsSelectionEnabled(); - break; - } - case Toolkit::TextField::Property::PLACEHOLDER: - { - Property::Map map; - impl.mController->GetPlaceholderProperty(map); - value = map; - break; - } - case Toolkit::TextField::Property::ELLIPSIS: - { - value = impl.mController->IsTextElideEnabled(); - break; - } - case Toolkit::DevelTextField::Property::ENABLE_SHIFT_SELECTION: - { - value = impl.mController->IsShiftSelectionEnabled(); - break; - } - case Toolkit::DevelTextField::Property::ENABLE_GRAB_HANDLE: - { - value = impl.mController->IsGrabHandleEnabled(); - break; - } - case Toolkit::DevelTextField::Property::MATCH_SYSTEM_LANGUAGE_DIRECTION: - { - value = impl.mController->GetMatchLayoutDirection() != DevelText::MatchLayoutDirection::CONTENTS; - break; - } - case Toolkit::DevelTextField::Property::ENABLE_GRAB_HANDLE_POPUP: - { - value = impl.mController->IsGrabHandlePopupEnabled(); - break; - } - case Toolkit::DevelTextField::Property::BACKGROUND: - { - value = impl.mController->GetBackgroundColor(); - break; - } - case Toolkit::DevelTextField::Property::SELECTED_TEXT: - { - value = impl.mController->GetSelectedText(); - break; - } - case Toolkit::DevelTextField::Property::SELECTED_TEXT_START: - { - Uint32Pair range = impl.GetTextSelectionRange(); - value = static_cast(range.first); - break; - } - case Toolkit::DevelTextField::Property::SELECTED_TEXT_END: - { - Uint32Pair range = impl.GetTextSelectionRange(); - value = static_cast(range.second); - break; - } - case Toolkit::DevelTextField::Property::ENABLE_EDITING: - { - value = impl.IsEditable(); - break; - } - case Toolkit::DevelTextField::Property::FONT_SIZE_SCALE: - { - value = impl.mController->GetFontSizeScale(); - break; - } - case Toolkit::DevelTextField::Property::PRIMARY_CURSOR_POSITION: - { - value = static_cast(impl.mController->GetPrimaryCursorPosition()); - break; - } - case Toolkit::DevelTextField::Property::GRAB_HANDLE_COLOR: - { - value = impl.mDecorator->GetHandleColor(); - break; - } - case Toolkit::DevelTextField::Property::INPUT_FILTER: - { - Property::Map map; - impl.mController->GetInputFilterOption(map); - value = map; - break; - } - case Toolkit::DevelTextField::Property::ELLIPSIS_POSITION: - { - value = impl.mController->GetEllipsisPosition(); - break; - } - } //switch + value = PropertyHandler::GetProperty(textField, index); } return value; @@ -1441,13 +523,13 @@ void TextField::OnInitialize() void TextField::OnStyleChange(Toolkit::StyleManager styleManager, StyleChange::Type change) { - DALI_LOG_INFO(gLogFilter, Debug::Verbose, "TextField::OnStyleChange\n"); + DALI_LOG_INFO(gTextFieldLogFilter, Debug::Verbose, "TextField::OnStyleChange\n"); switch(change) { case StyleChange::DEFAULT_FONT_CHANGE: { - DALI_LOG_INFO(gLogFilter, Debug::Verbose, "TextField::OnStyleChange DEFAULT_FONT_CHANGE\n"); + DALI_LOG_INFO(gTextFieldLogFilter, Debug::Verbose, "TextField::OnStyleChange DEFAULT_FONT_CHANGE\n"); const std::string& newFont = GetImpl(styleManager).GetDefaultFontFamily(); // Property system did not set the font so should update it. mController->UpdateAfterFontChange(newFont); @@ -1501,7 +583,7 @@ void TextField::ResizeActor(Actor& actor, const Vector2& size) void TextField::OnRelayout(const Vector2& size, RelayoutContainer& container) { - DALI_LOG_INFO(gLogFilter, Debug::Verbose, "TextField OnRelayout\n"); + DALI_LOG_INFO(gTextFieldLogFilter, Debug::Verbose, "TextField OnRelayout\n"); Actor self = Self(); @@ -1540,7 +622,7 @@ void TextField::OnRelayout(const Vector2& size, RelayoutContainer& container) if((Text::Controller::NONE_UPDATED != updateTextType) || !mRenderer) { - DALI_LOG_INFO(gLogFilter, Debug::Verbose, "TextField::OnRelayout %p Displaying new contents\n", mController.Get()); + DALI_LOG_INFO(gTextFieldLogFilter, Debug::Verbose, "TextField::OnRelayout %p Displaying new contents\n", mController.Get()); if(mDecorator && (Text::Controller::NONE_UPDATED != (Text::Controller::DECORATOR_UPDATED & updateTextType))) @@ -1598,106 +680,12 @@ Text::ControllerPtr TextField::GetTextController() void TextField::RenderText(Text::Controller::UpdateTextType updateTextType) { - Actor renderableActor; - - if(Text::Controller::NONE_UPDATED != (Text::Controller::MODEL_UPDATED & updateTextType)) - { - if(mRenderer) - { - Dali::Toolkit::TextField handle = Dali::Toolkit::TextField(GetOwner()); - - renderableActor = mRenderer->Render(mController->GetView(), - handle, - Property::INVALID_INDEX, // Animatable property not supported - mAlignmentOffset, - DepthIndex::CONTENT); - } - - if(renderableActor != mRenderableActor) - { - UnparentAndReset(mBackgroundActor); - UnparentAndReset(mRenderableActor); - mRenderableActor = renderableActor; - - if(mRenderableActor) - { - mBackgroundActor = mController->CreateBackgroundActor(); - } - } - } - - if(mRenderableActor) - { - const Vector2& scrollOffset = mController->GetTextModel()->GetScrollPosition(); - - float renderableActorPositionX, renderableActorPositionY; - - if(mStencil) - { - renderableActorPositionX = scrollOffset.x + mAlignmentOffset; - renderableActorPositionY = scrollOffset.y; - } - else - { - Extents padding; - padding = Self().GetProperty(Toolkit::Control::Property::PADDING); - - // Support Right-To-Left of padding - Dali::LayoutDirection::Type layoutDirection = static_cast(Self().GetProperty(Dali::Actor::Property::LAYOUT_DIRECTION).Get()); - if(Dali::LayoutDirection::RIGHT_TO_LEFT == layoutDirection) - { - std::swap(padding.start, padding.end); - } - - renderableActorPositionX = scrollOffset.x + mAlignmentOffset + padding.start; - renderableActorPositionY = scrollOffset.y + padding.top; - } - - mRenderableActor.SetProperty(Actor::Property::POSITION, Vector2(renderableActorPositionX, renderableActorPositionY)); - - // Make sure the actors are parented correctly with/without clipping - Actor self = mStencil ? mStencil : Self(); - - Actor highlightActor; - - for(std::vector::iterator it = mClippingDecorationActors.begin(), - endIt = mClippingDecorationActors.end(); - it != endIt; - ++it) - { - self.Add(*it); - it->LowerToBottom(); - - if(it->GetProperty(Dali::Actor::Property::NAME) == "HighlightActor") - { - highlightActor = *it; - } - } - mClippingDecorationActors.clear(); - - self.Add(mRenderableActor); - - if(mBackgroundActor) - { - if(mDecorator && mDecorator->IsHighlightVisible()) - { - self.Add(mBackgroundActor); - mBackgroundActor.SetProperty(Actor::Property::POSITION, Vector2(renderableActorPositionX, renderableActorPositionY)); // In text field's coords. - mBackgroundActor.LowerBelow(highlightActor); - } - else - { - mRenderableActor.Add(mBackgroundActor); - mBackgroundActor.SetProperty(Actor::Property::POSITION, Vector2(0.0f, 0.0f)); // In renderable actor's coords. - mBackgroundActor.LowerToBottom(); - } - } - } + CommonTextUtils::RenderText(Self(), mRenderer, mController, mDecorator, mAlignmentOffset, mRenderableActor, mBackgroundActor, mStencil, mClippingDecorationActors, updateTextType); } void TextField::OnKeyInputFocusGained() { - DALI_LOG_INFO(gLogFilter, Debug::Verbose, "TextField::OnKeyInputFocusGained %p\n", mController.Get()); + DALI_LOG_INFO(gTextFieldLogFilter, Debug::Verbose, "TextField::OnKeyInputFocusGained %p\n", mController.Get()); if(mInputMethodContext && IsEditable()) { // All input panel properties, such as layout, return key type, and input hint, should be set before input panel activates (or shows). @@ -1728,7 +716,7 @@ void TextField::OnKeyInputFocusGained() void TextField::OnKeyInputFocusLost() { - DALI_LOG_INFO(gLogFilter, Debug::Verbose, "TextField:OnKeyInputFocusLost %p\n", mController.Get()); + DALI_LOG_INFO(gTextFieldLogFilter, Debug::Verbose, "TextField:OnKeyInputFocusLost %p\n", mController.Get()); if(mInputMethodContext) { mInputMethodContext.StatusChangedSignal().Disconnect(this, &TextField::KeyboardStatusChanged); @@ -1760,7 +748,7 @@ bool TextField::OnAccessibilityActivated() void TextField::OnTap(const TapGesture& gesture) { - DALI_LOG_INFO(gLogFilter, Debug::Verbose, "TextField::OnTap %p\n", mController.Get()); + DALI_LOG_INFO(gTextFieldLogFilter, Debug::Verbose, "TextField::OnTap %p\n", mController.Get()); if(mInputMethodContext && IsEditable()) { mInputMethodContext.Activate(); @@ -1796,7 +784,7 @@ void TextField::OnLongPress(const LongPressGesture& gesture) bool TextField::OnKeyEvent(const KeyEvent& event) { - DALI_LOG_INFO(gLogFilter, Debug::Verbose, "TextField::OnKeyEvent %p keyCode %d\n", mController.Get(), event.GetKeyCode()); + DALI_LOG_INFO(gTextFieldLogFilter, Debug::Verbose, "TextField::OnKeyEvent %p keyCode %d\n", mController.Get(), event.GetKeyCode()); if(Dali::DALI_KEY_ESCAPE == event.GetKeyCode() && mController->ShouldClearFocusOnEscape()) { @@ -1894,51 +882,7 @@ void TextField::MaxLengthReached() void TextField::InputStyleChanged(Text::InputStyle::Mask inputStyleMask) { Dali::Toolkit::TextField handle(GetOwner()); - - Toolkit::TextField::InputStyle::Mask fieldInputStyleMask = Toolkit::TextField::InputStyle::NONE; - - if(InputStyle::NONE != static_cast(inputStyleMask & InputStyle::INPUT_COLOR)) - { - fieldInputStyleMask = static_cast(fieldInputStyleMask | Toolkit::TextField::InputStyle::COLOR); - } - if(InputStyle::NONE != static_cast(inputStyleMask & InputStyle::INPUT_FONT_FAMILY)) - { - fieldInputStyleMask = static_cast(fieldInputStyleMask | Toolkit::TextField::InputStyle::FONT_FAMILY); - } - if(InputStyle::NONE != static_cast(inputStyleMask & InputStyle::INPUT_POINT_SIZE)) - { - fieldInputStyleMask = static_cast(fieldInputStyleMask | Toolkit::TextField::InputStyle::POINT_SIZE); - } - if(InputStyle::NONE != static_cast(inputStyleMask & InputStyle::INPUT_FONT_WEIGHT)) - { - fieldInputStyleMask = static_cast(fieldInputStyleMask | Toolkit::TextField::InputStyle::FONT_STYLE); - } - if(InputStyle::NONE != static_cast(inputStyleMask & InputStyle::INPUT_FONT_WIDTH)) - { - fieldInputStyleMask = static_cast(fieldInputStyleMask | Toolkit::TextField::InputStyle::FONT_STYLE); - } - if(InputStyle::NONE != static_cast(inputStyleMask & InputStyle::INPUT_FONT_SLANT)) - { - fieldInputStyleMask = static_cast(fieldInputStyleMask | Toolkit::TextField::InputStyle::FONT_STYLE); - } - if(InputStyle::NONE != static_cast(inputStyleMask & InputStyle::INPUT_UNDERLINE)) - { - fieldInputStyleMask = static_cast(fieldInputStyleMask | Toolkit::TextField::InputStyle::UNDERLINE); - } - if(InputStyle::NONE != static_cast(inputStyleMask & InputStyle::INPUT_SHADOW)) - { - fieldInputStyleMask = static_cast(fieldInputStyleMask | Toolkit::TextField::InputStyle::SHADOW); - } - if(InputStyle::NONE != static_cast(inputStyleMask & InputStyle::INPUT_EMBOSS)) - { - fieldInputStyleMask = static_cast(fieldInputStyleMask | Toolkit::TextField::InputStyle::EMBOSS); - } - if(InputStyle::NONE != static_cast(inputStyleMask & InputStyle::INPUT_OUTLINE)) - { - fieldInputStyleMask = static_cast(fieldInputStyleMask | Toolkit::TextField::InputStyle::OUTLINE); - } - - mInputStyleChangedSignal.Emit(handle, fieldInputStyleMask); + mInputStyleChangedSignal.Emit(handle, ConvertInputStyle(inputStyleMask)); } void TextField::AnchorClicked(const std::string& href) @@ -2041,7 +985,7 @@ void TextField::OnSceneConnect(Dali::Actor actor) InputMethodContext::CallbackData TextField::OnInputMethodContextEvent(Dali::InputMethodContext& inputMethodContext, const InputMethodContext::EventData& inputMethodContextEvent) { - DALI_LOG_INFO(gLogFilter, Debug::Verbose, "TextField::OnInputMethodContextEvent %p eventName %d\n", mController.Get(), inputMethodContextEvent.eventName); + DALI_LOG_INFO(gTextFieldLogFilter, Debug::Verbose, "TextField::OnInputMethodContextEvent %p eventName %d\n", mController.Get(), inputMethodContextEvent.eventName); return mController->OnInputMethodContextEvent(inputMethodContext, inputMethodContextEvent); } @@ -2050,8 +994,9 @@ void TextField::GetHandleImagePropertyValue(Property::Value& value, Text::Handle if(mDecorator) { Property::Map map; - map[IMAGE_MAP_FILENAME_STRING] = mDecorator->GetHandleImage(handleType, handleImageType); - value = map; + map[PropertyHandler::IMAGE_MAP_FILENAME_STRING] = mDecorator->GetHandleImage(handleType, handleImageType); + + value = map; } } @@ -2083,7 +1028,7 @@ void TextField::OnClipboardTextSelected(ClipboardEventNotifier& clipboard) void TextField::KeyboardStatusChanged(bool keyboardShown) { - DALI_LOG_INFO(gLogFilter, Debug::Verbose, "TextField::KeyboardStatusChanged %p keyboardShown %d\n", mController.Get(), keyboardShown); + DALI_LOG_INFO(gTextFieldLogFilter, Debug::Verbose, "TextField::KeyboardStatusChanged %p keyboardShown %d\n", mController.Get(), keyboardShown); // Just hide the grab handle when keyboard is hidden. if(!keyboardShown) diff --git a/dali-toolkit/internal/controls/text-controls/text-field-impl.h b/dali-toolkit/internal/controls/text-controls/text-field-impl.h index 0472aa8..b65e953 100644 --- a/dali-toolkit/internal/controls/text-controls/text-field-impl.h +++ b/dali-toolkit/internal/controls/text-controls/text-field-impl.h @@ -470,6 +470,8 @@ private: // Data uint32_t mOldSelectionEnd; protected: + struct PropertyHandler; + /** * @brief This structure is to connect TextField with Accessible functions. */ diff --git a/dali-toolkit/internal/controls/text-controls/text-field-property-handler.cpp b/dali-toolkit/internal/controls/text-controls/text-field-property-handler.cpp new file mode 100644 index 0000000..04a5082 --- /dev/null +++ b/dali-toolkit/internal/controls/text-controls/text-field-property-handler.cpp @@ -0,0 +1,1021 @@ +/* + * Copyright (c) 2021 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 +#include +#include +#include +#include +#include +#include + +#if defined(DEBUG_ENABLED) +extern Debug::Filter* gTextFieldLogFilter; +#endif + +namespace Dali::Toolkit::Internal +{ +const char* const TextField::PropertyHandler::IMAGE_MAP_FILENAME_STRING{"filename"}; + +/// Retrieves a filename from a value that is a Property::Map +std::string TextField::PropertyHandler::GetImageFileNameFromPropertyValue(const Property::Value& value) +{ + std::string filename; + const Property::Map* map = value.GetMap(); + if(map) + { + const Property::Value* filenameValue = map->Find(TextField::PropertyHandler::IMAGE_MAP_FILENAME_STRING); + if(filenameValue) + { + filenameValue->Get(filename); + } + } + return filename; +} + +void TextField::PropertyHandler::SetProperty(Toolkit::TextField textField, Property::Index index, const Property::Value& value) +{ + TextField& impl(GetImpl(textField)); + DALI_ASSERT_DEBUG(impl.mController && "No text controller"); + DALI_ASSERT_DEBUG(impl.mDecorator && "No text decorator"); + + switch(index) + { + case Toolkit::DevelTextField::Property::RENDERING_BACKEND: + { + int backend = value.Get(); + DALI_LOG_INFO(gTextFieldLogFilter, Debug::Verbose, "TextField %p RENDERING_BACKEND %d\n", impl.mController.Get(), backend); + +#ifndef ENABLE_VECTOR_BASED_TEXT_RENDERING + if(DevelText::RENDERING_VECTOR_BASED == backend) + { + backend = TextAbstraction::BITMAP_GLYPH; // Fallback to bitmap-based rendering + } +#endif + if(impl.mRenderingBackend != backend) + { + impl.mRenderingBackend = backend; + impl.mRenderer.Reset(); + + // When using the vector-based rendering, the size of the GLyphs are different + TextAbstraction::GlyphType glyphType = (DevelText::RENDERING_VECTOR_BASED == impl.mRenderingBackend) ? TextAbstraction::VECTOR_GLYPH : TextAbstraction::BITMAP_GLYPH; + impl.mController->SetGlyphType(glyphType); + } + break; + } + case Toolkit::TextField::Property::TEXT: + { + const std::string& text = value.Get(); + DALI_LOG_INFO(gTextFieldLogFilter, Debug::General, "TextField %p TEXT %s\n", impl.mController.Get(), text.c_str()); + + impl.mController->SetText(text); + break; + } + + case Toolkit::TextField::Property::PLACEHOLDER_TEXT: + { + const std::string& text = value.Get(); + DALI_LOG_INFO(gTextFieldLogFilter, Debug::General, "TextField %p PLACEHOLDER_TEXT %s\n", impl.mController.Get(), text.c_str()); + + impl.mController->SetPlaceholderText(Text::Controller::PLACEHOLDER_TYPE_INACTIVE, text); + break; + } + case Toolkit::TextField::Property::PLACEHOLDER_TEXT_FOCUSED: + { + const std::string& text = value.Get(); + DALI_LOG_INFO(gTextFieldLogFilter, Debug::General, "TextField %p PLACEHOLDER_TEXT_FOCUSED %s\n", impl.mController.Get(), text.c_str()); + + impl.mController->SetPlaceholderText(Text::Controller::PLACEHOLDER_TYPE_ACTIVE, text); + break; + } + case Toolkit::TextField::Property::FONT_FAMILY: + { + const std::string& fontFamily = value.Get(); + DALI_LOG_INFO(gTextFieldLogFilter, Debug::General, "TextField %p FONT_FAMILY %s\n", impl.mController.Get(), fontFamily.c_str()); + impl.mController->SetDefaultFontFamily(fontFamily); + break; + } + case Toolkit::TextField::Property::FONT_STYLE: + { + SetFontStyleProperty(impl.mController, value, Text::FontStyle::DEFAULT); + break; + } + case Toolkit::TextField::Property::POINT_SIZE: + { + const float pointSize = value.Get(); + DALI_LOG_INFO(gTextFieldLogFilter, Debug::General, "TextField %p POINT_SIZE %f\n", impl.mController.Get(), pointSize); + + if(!Equals(impl.mController->GetDefaultFontSize(Text::Controller::POINT_SIZE), pointSize)) + { + impl.mController->SetDefaultFontSize(pointSize, Text::Controller::POINT_SIZE); + } + break; + } + case Toolkit::TextField::Property::MAX_LENGTH: + { + const int max = value.Get(); + DALI_LOG_INFO(gTextFieldLogFilter, Debug::General, "TextField %p MAX_LENGTH %d\n", impl.mController.Get(), max); + + impl.mController->SetMaximumNumberOfCharacters(max); + break; + } + case Toolkit::TextField::Property::EXCEED_POLICY: + { + impl.mExceedPolicy = value.Get(); + + if(Dali::Toolkit::TextField::EXCEED_POLICY_CLIP == impl.mExceedPolicy) + { + impl.EnableClipping(); + } + else + { + UnparentAndReset(impl.mStencil); + } + impl.RequestTextRelayout(); + break; + } + + case Toolkit::TextField::Property::HORIZONTAL_ALIGNMENT: + { + Text::HorizontalAlignment::Type alignment(static_cast(-1)); // Set to invalid value to ensure a valid mode does get set + if(Text::GetHorizontalAlignmentEnumeration(value, alignment)) + { + DALI_LOG_INFO(gTextFieldLogFilter, Debug::General, "TextField %p HORIZONTAL_ALIGNMENT %d\n", impl.mController.Get(), alignment); + impl.mController->SetHorizontalAlignment(alignment); + } + break; + } + case Toolkit::TextField::Property::VERTICAL_ALIGNMENT: + { + Toolkit::Text::VerticalAlignment::Type alignment(static_cast(-1)); // Set to invalid value to ensure a valid mode does get set + if(Text::GetVerticalAlignmentEnumeration(value, alignment)) + { + impl.mController->SetVerticalAlignment(alignment); + DALI_LOG_INFO(gTextFieldLogFilter, Debug::General, "TextField %p VERTICAL_ALIGNMENT %d\n", impl.mController.Get(), alignment); + } + break; + } + case Toolkit::TextField::Property::TEXT_COLOR: + { + const Vector4& textColor = value.Get(); + DALI_LOG_INFO(gTextFieldLogFilter, Debug::General, "TextField %p TEXT_COLOR %f,%f,%f,%f\n", impl.mController.Get(), textColor.r, textColor.g, textColor.b, textColor.a); + + if(impl.mController->GetDefaultColor() != textColor) + { + impl.mController->SetDefaultColor(textColor); + impl.mController->SetInputColor(textColor); + impl.mRenderer.Reset(); + } + break; + } + case Toolkit::TextField::Property::PLACEHOLDER_TEXT_COLOR: + { + const Vector4& textColor = value.Get(); + DALI_LOG_INFO(gTextFieldLogFilter, Debug::General, "TextField %p PLACEHOLDER_TEXT_COLOR %f,%f,%f,%f\n", impl.mController.Get(), textColor.r, textColor.g, textColor.b, textColor.a); + + if(impl.mController->GetPlaceholderTextColor() != textColor) + { + impl.mController->SetPlaceholderTextColor(textColor); + impl.mRenderer.Reset(); + } + break; + } + case Toolkit::TextField::Property::PRIMARY_CURSOR_COLOR: + { + const Vector4& color = value.Get(); + DALI_LOG_INFO(gTextFieldLogFilter, Debug::General, "TextField %p PRIMARY_CURSOR_COLOR %f,%f,%f,%f\n", impl.mController.Get(), color.r, color.g, color.b, color.a); + + impl.mDecorator->SetCursorColor(Toolkit::Text::PRIMARY_CURSOR, color); + impl.RequestTextRelayout(); + break; + } + case Toolkit::TextField::Property::SECONDARY_CURSOR_COLOR: + { + const Vector4& color = value.Get(); + DALI_LOG_INFO(gTextFieldLogFilter, Debug::General, "TextField %p SECONDARY_CURSOR_COLOR %f,%f,%f,%f\n", impl.mController.Get(), color.r, color.g, color.b, color.a); + + impl.mDecorator->SetCursorColor(Toolkit::Text::SECONDARY_CURSOR, color); + impl.RequestTextRelayout(); + break; + } + case Toolkit::TextField::Property::ENABLE_CURSOR_BLINK: + { + const bool enable = value.Get(); + DALI_LOG_INFO(gTextFieldLogFilter, Debug::Verbose, "TextField %p ENABLE_CURSOR_BLINK %d\n", impl.mController.Get(), enable); + + impl.mController->SetEnableCursorBlink(enable); + impl.RequestTextRelayout(); + break; + } + case Toolkit::TextField::Property::CURSOR_BLINK_INTERVAL: + { + const float interval = value.Get(); + DALI_LOG_INFO(gTextFieldLogFilter, Debug::Verbose, "TextField %p CURSOR_BLINK_INTERVAL %f\n", impl.mController.Get(), interval); + + impl.mDecorator->SetCursorBlinkInterval(interval); + break; + } + case Toolkit::TextField::Property::CURSOR_BLINK_DURATION: + { + const float duration = value.Get(); + DALI_LOG_INFO(gTextFieldLogFilter, Debug::Verbose, "TextField %p CURSOR_BLINK_DURATION %f\n", impl.mController.Get(), duration); + + impl.mDecorator->SetCursorBlinkDuration(duration); + break; + } + case Toolkit::TextField::Property::CURSOR_WIDTH: + { + const int width = value.Get(); + DALI_LOG_INFO(gTextFieldLogFilter, Debug::Verbose, "TextField %p CURSOR_WIDTH %d\n", impl.mController.Get(), width); + + impl.mDecorator->SetCursorWidth(width); + impl.mController->GetLayoutEngine().SetCursorWidth(width); + break; + } + case Toolkit::TextField::Property::GRAB_HANDLE_IMAGE: + { + const std::string imageFileName = value.Get(); + DALI_LOG_INFO(gTextFieldLogFilter, Debug::Verbose, "TextField %p GRAB_HANDLE_IMAGE %s\n", impl.mController.Get(), imageFileName.c_str()); + + if(imageFileName.size()) + { + impl.mDecorator->SetHandleImage(Toolkit::Text::GRAB_HANDLE, Toolkit::Text::HANDLE_IMAGE_RELEASED, imageFileName); + impl.RequestTextRelayout(); + } + break; + } + case Toolkit::TextField::Property::GRAB_HANDLE_PRESSED_IMAGE: + { + const std::string imageFileName = value.Get(); + DALI_LOG_INFO(gTextFieldLogFilter, Debug::Verbose, "TextField %p GRAB_HANDLE_PRESSED_IMAGE %s\n", impl.mController.Get(), imageFileName.c_str()); + + if(imageFileName.size()) + { + impl.mDecorator->SetHandleImage(Toolkit::Text::GRAB_HANDLE, Toolkit::Text::HANDLE_IMAGE_PRESSED, imageFileName); + impl.RequestTextRelayout(); + } + break; + } + case Toolkit::TextField::Property::SCROLL_THRESHOLD: + { + const float threshold = value.Get(); + DALI_LOG_INFO(gTextFieldLogFilter, Debug::Verbose, "TextField %p SCROLL_THRESHOLD %f\n", impl.mController.Get(), threshold); + + impl.mDecorator->SetScrollThreshold(threshold); + break; + } + case Toolkit::TextField::Property::SCROLL_SPEED: + { + const float speed = value.Get(); + DALI_LOG_INFO(gTextFieldLogFilter, Debug::Verbose, "TextField %p SCROLL_SPEED %f\n", impl.mController.Get(), speed); + + impl.mDecorator->SetScrollSpeed(speed); + break; + } + case Toolkit::TextField::Property::SELECTION_HANDLE_IMAGE_LEFT: + { + const std::string filename = GetImageFileNameFromPropertyValue(value); + + if(filename.size()) + { + impl.mDecorator->SetHandleImage(Toolkit::Text::LEFT_SELECTION_HANDLE, Toolkit::Text::HANDLE_IMAGE_RELEASED, filename); + impl.RequestTextRelayout(); + } + break; + } + case Toolkit::TextField::Property::SELECTION_HANDLE_IMAGE_RIGHT: + { + const std::string filename = GetImageFileNameFromPropertyValue(value); + + if(filename.size()) + { + impl.mDecorator->SetHandleImage(Toolkit::Text::RIGHT_SELECTION_HANDLE, Toolkit::Text::HANDLE_IMAGE_RELEASED, filename); + impl.RequestTextRelayout(); + } + break; + } + case Toolkit::TextField::Property::SELECTION_HANDLE_PRESSED_IMAGE_LEFT: + { + const std::string filename = GetImageFileNameFromPropertyValue(value); + + if(filename.size()) + { + impl.mDecorator->SetHandleImage(Toolkit::Text::LEFT_SELECTION_HANDLE, Toolkit::Text::HANDLE_IMAGE_PRESSED, filename); + impl.RequestTextRelayout(); + } + break; + } + case Toolkit::TextField::Property::SELECTION_HANDLE_PRESSED_IMAGE_RIGHT: + { + const std::string filename = GetImageFileNameFromPropertyValue(value); + + if(filename.size()) + { + impl.mDecorator->SetHandleImage(Toolkit::Text::RIGHT_SELECTION_HANDLE, Toolkit::Text::HANDLE_IMAGE_PRESSED, filename); + impl.RequestTextRelayout(); + } + break; + } + case Toolkit::TextField::Property::SELECTION_HANDLE_MARKER_IMAGE_LEFT: + { + const std::string filename = GetImageFileNameFromPropertyValue(value); + + if(filename.size()) + { + impl.mDecorator->SetHandleImage(Toolkit::Text::LEFT_SELECTION_HANDLE_MARKER, + Toolkit::Text::HANDLE_IMAGE_RELEASED, + filename); + impl.RequestTextRelayout(); + } + break; + } + case Toolkit::TextField::Property::SELECTION_HANDLE_MARKER_IMAGE_RIGHT: + { + const std::string filename = GetImageFileNameFromPropertyValue(value); + + if(filename.size()) + { + impl.mDecorator->SetHandleImage(Toolkit::Text::RIGHT_SELECTION_HANDLE_MARKER, + Toolkit::Text::HANDLE_IMAGE_RELEASED, + filename); + impl.RequestTextRelayout(); + } + break; + } + case Toolkit::TextField::Property::SELECTION_HIGHLIGHT_COLOR: + { + const Vector4 color = value.Get(); + DALI_LOG_INFO(gTextFieldLogFilter, Debug::General, "TextField %p SELECTION_HIGHLIGHT_COLOR %f,%f,%f,%f\n", impl.mController.Get(), color.r, color.g, color.b, color.a); + + impl.mDecorator->SetHighlightColor(color); + impl.RequestTextRelayout(); + break; + } + case Toolkit::TextField::Property::DECORATION_BOUNDING_BOX: + { + const Rect& box = value.Get >(); + DALI_LOG_INFO(gTextFieldLogFilter, Debug::General, "TextField %p DECORATION_BOUNDING_BOX %d,%d %dx%d\n", impl.mController.Get(), box.x, box.y, box.width, box.height); + + impl.mDecorator->SetBoundingBox(box); + impl.RequestTextRelayout(); + break; + } + case Toolkit::TextField::Property::INPUT_METHOD_SETTINGS: + { + const Property::Map* map = value.GetMap(); + if(map) + { + impl.mInputMethodOptions.ApplyProperty(*map); + } + impl.mController->SetInputModePassword(impl.mInputMethodOptions.IsPassword()); + + Toolkit::Control control = Toolkit::KeyInputFocusManager::Get().GetCurrentFocusControl(); + if(control == textField) + { + impl.mInputMethodContext.ApplyOptions(impl.mInputMethodOptions); + } + break; + } + case Toolkit::TextField::Property::INPUT_COLOR: + { + const Vector4& inputColor = value.Get(); + DALI_LOG_INFO(gTextFieldLogFilter, Debug::General, "TextField %p INPUT_COLOR %f,%f,%f,%f\n", impl.mController.Get(), inputColor.r, inputColor.g, inputColor.b, inputColor.a); + + impl.mController->SetInputColor(inputColor); + break; + } + case Toolkit::TextField::Property::ENABLE_MARKUP: + { + const bool enableMarkup = value.Get(); + DALI_LOG_INFO(gTextFieldLogFilter, Debug::General, "TextField %p ENABLE_MARKUP %d\n", impl.mController.Get(), enableMarkup); + + impl.mController->SetMarkupProcessorEnabled(enableMarkup); + break; + } + case Toolkit::TextField::Property::INPUT_FONT_FAMILY: + { + const std::string& fontFamily = value.Get(); + DALI_LOG_INFO(gTextFieldLogFilter, Debug::General, "TextField %p INPUT_FONT_FAMILY %s\n", impl.mController.Get(), fontFamily.c_str()); + impl.mController->SetInputFontFamily(fontFamily); + break; + } + case Toolkit::TextField::Property::INPUT_FONT_STYLE: + { + SetFontStyleProperty(impl.mController, value, Text::FontStyle::INPUT); + break; + } + case Toolkit::TextField::Property::INPUT_POINT_SIZE: + { + const float pointSize = value.Get(); + DALI_LOG_INFO(gTextFieldLogFilter, Debug::General, "TextField %p INPUT_POINT_SIZE %f\n", impl.mController.Get(), pointSize); + impl.mController->SetInputFontPointSize(pointSize); + break; + } + case Toolkit::TextField::Property::UNDERLINE: + { + const bool update = SetUnderlineProperties(impl.mController, value, Text::EffectStyle::DEFAULT); + if(update) + { + impl.mRenderer.Reset(); + } + break; + } + case Toolkit::TextField::Property::INPUT_UNDERLINE: + { + const bool update = SetUnderlineProperties(impl.mController, value, Text::EffectStyle::INPUT); + if(update) + { + impl.mRenderer.Reset(); + } + break; + } + case Toolkit::TextField::Property::SHADOW: + { + const bool update = SetShadowProperties(impl.mController, value, Text::EffectStyle::DEFAULT); + if(update) + { + impl.mRenderer.Reset(); + } + break; + } + case Toolkit::TextField::Property::INPUT_SHADOW: + { + const bool update = SetShadowProperties(impl.mController, value, Text::EffectStyle::INPUT); + if(update) + { + impl.mRenderer.Reset(); + } + break; + } + case Toolkit::TextField::Property::EMBOSS: + { + const bool update = SetEmbossProperties(impl.mController, value, Text::EffectStyle::DEFAULT); + if(update) + { + impl.mRenderer.Reset(); + } + break; + } + case Toolkit::TextField::Property::INPUT_EMBOSS: + { + const bool update = SetEmbossProperties(impl.mController, value, Text::EffectStyle::INPUT); + if(update) + { + impl.mRenderer.Reset(); + } + break; + } + case Toolkit::TextField::Property::OUTLINE: + { + const bool update = SetOutlineProperties(impl.mController, value, Text::EffectStyle::DEFAULT); + if(update) + { + impl.mRenderer.Reset(); + } + break; + } + case Toolkit::TextField::Property::INPUT_OUTLINE: + { + const bool update = SetOutlineProperties(impl.mController, value, Text::EffectStyle::INPUT); + if(update) + { + impl.mRenderer.Reset(); + } + break; + } + case Toolkit::TextField::Property::HIDDEN_INPUT_SETTINGS: + { + const Property::Map* map = value.GetMap(); + if(map) + { + impl.mController->SetHiddenInputOption(*map); + } + break; + } + case Toolkit::TextField::Property::PIXEL_SIZE: + { + const float pixelSize = value.Get(); + DALI_LOG_INFO(gTextFieldLogFilter, Debug::General, "TextField %p PIXEL_SIZE %f\n", impl.mController.Get(), pixelSize); + + if(!Equals(impl.mController->GetDefaultFontSize(Text::Controller::PIXEL_SIZE), pixelSize)) + { + impl.mController->SetDefaultFontSize(pixelSize, Text::Controller::PIXEL_SIZE); + } + break; + } + case Toolkit::TextField::Property::ENABLE_SELECTION: + { + const bool enableSelection = value.Get(); + DALI_LOG_INFO(gTextFieldLogFilter, Debug::General, "TextField %p ENABLE_SELECTION %d\n", impl.mController.Get(), enableSelection); + impl.mController->SetSelectionEnabled(enableSelection); + break; + } + case Toolkit::TextField::Property::PLACEHOLDER: + { + const Property::Map* map = value.GetMap(); + if(map) + { + impl.mController->SetPlaceholderProperty(*map); + } + break; + } + case Toolkit::TextField::Property::ELLIPSIS: + { + const bool ellipsis = value.Get(); + DALI_LOG_INFO(gTextFieldLogFilter, Debug::General, "TextField %p ELLIPSIS %d\n", impl.mController.Get(), ellipsis); + + impl.mController->SetTextElideEnabled(ellipsis); + break; + } + case Toolkit::DevelTextField::Property::ENABLE_SHIFT_SELECTION: + { + const bool shiftSelection = value.Get(); + DALI_LOG_INFO(gTextFieldLogFilter, Debug::General, "TextField %p ENABLE_SHIFT_SELECTION %d\n", impl.mController.Get(), shiftSelection); + + impl.mController->SetShiftSelectionEnabled(shiftSelection); + break; + } + case Toolkit::DevelTextField::Property::ENABLE_GRAB_HANDLE: + { + const bool grabHandleEnabled = value.Get(); + DALI_LOG_INFO(gTextFieldLogFilter, Debug::General, "TextField %p ENABLE_GRAB_HANDLE %d\n", impl.mController.Get(), grabHandleEnabled); + + impl.mController->SetGrabHandleEnabled(grabHandleEnabled); + break; + } + case Toolkit::DevelTextField::Property::MATCH_SYSTEM_LANGUAGE_DIRECTION: + { + impl.mController->SetMatchLayoutDirection(value.Get() ? DevelText::MatchLayoutDirection::LOCALE : DevelText::MatchLayoutDirection::CONTENTS); + break; + } + case Toolkit::DevelTextField::Property::ENABLE_GRAB_HANDLE_POPUP: + { + const bool grabHandlePopupEnabled = value.Get(); + DALI_LOG_INFO(gTextFieldLogFilter, Debug::General, "TextField %p ENABLE_GRAB_HANDLE_POPUP %d\n", impl.mController.Get(), grabHandlePopupEnabled); + + impl.mController->SetGrabHandlePopupEnabled(grabHandlePopupEnabled); + break; + } + case Toolkit::DevelTextField::Property::BACKGROUND: + { + const Vector4 backgroundColor = value.Get(); + DALI_LOG_INFO(gTextFieldLogFilter, Debug::General, "TextField %p BACKGROUND %f,%f,%f,%f\n", impl.mController.Get(), backgroundColor.r, backgroundColor.g, backgroundColor.b, backgroundColor.a); + + impl.mController->SetBackgroundEnabled(true); + impl.mController->SetBackgroundColor(backgroundColor); + break; + } + case Toolkit::DevelTextField::Property::SELECTED_TEXT_START: + { + uint32_t start = static_cast(value.Get()); + DALI_LOG_INFO(gTextFieldLogFilter, Debug::General, "TextField %p SELECTED_TEXT_START %d\n", impl.mController.Get(), start); + impl.SetTextSelectionRange(&start, nullptr); + break; + } + case Toolkit::DevelTextField::Property::SELECTED_TEXT_END: + { + uint32_t end = static_cast(value.Get()); + DALI_LOG_INFO(gTextFieldLogFilter, Debug::General, "TextField %p SELECTED_TEXT_END %d\n", impl.mController.Get(), end); + impl.SetTextSelectionRange(nullptr, &end); + break; + } + case Toolkit::DevelTextField::Property::ENABLE_EDITING: + { + const bool editable = value.Get(); + DALI_LOG_INFO(gTextFieldLogFilter, Debug::General, "TextField %p ENABLE_EDITING %d\n", impl.mController.Get(), editable); + impl.SetEditable(editable); + break; + } + case Toolkit::DevelTextField::Property::FONT_SIZE_SCALE: + { + const float scale = value.Get(); + DALI_LOG_INFO(gTextFieldLogFilter, Debug::General, "TextField %p FONT_SIZE_SCALE %f\n", impl.mController.Get(), scale); + + if(!Equals(impl.mController->GetFontSizeScale(), scale)) + { + impl.mController->SetFontSizeScale(scale); + } + break; + } + case Toolkit::DevelTextField::Property::PRIMARY_CURSOR_POSITION: + { + uint32_t position = static_cast(value.Get()); + DALI_LOG_INFO(gTextFieldLogFilter, Debug::General, "TextField %p PRIMARY_CURSOR_POSITION %d\n", impl.mController.Get(), position); + if(impl.mController->SetPrimaryCursorPosition(position, impl.HasKeyInputFocus())) + { + impl.SetKeyInputFocus(); + } + break; + } + case Toolkit::DevelTextField::Property::GRAB_HANDLE_COLOR: + { + const Vector4 color = value.Get(); + DALI_LOG_INFO(gTextFieldLogFilter, Debug::General, "TextField %p GRAB_HANDLE_COLOR %f,%f,%f,%f\n", impl.mController.Get(), color.r, color.g, color.b, color.a); + + impl.mDecorator->SetHandleColor(color); + impl.RequestTextRelayout(); + break; + } + + case Toolkit::DevelTextField::Property::INPUT_FILTER: + { + const Property::Map* map = value.GetMap(); + if(map) + { + impl.mController->SetInputFilterOption(*map); + } + break; + } + case Toolkit::DevelTextField::Property::ELLIPSIS_POSITION: + { + DevelText::EllipsisPosition::Type ellipsisPositionType(static_cast(-1)); // Set to invalid value to ensure a valid mode does get set + if(Text::GetEllipsisPositionTypeEnumeration(value, ellipsisPositionType)) + { + DALI_LOG_INFO(gTextFieldLogFilter, Debug::General, "TextField %p EllipsisPosition::Type %d\n", impl.mController.Get(), ellipsisPositionType); + impl.mController->SetEllipsisPosition(ellipsisPositionType); + } + break; + } + } +} + +Property::Value TextField::PropertyHandler::GetProperty(Toolkit::TextField textField, Property::Index index) +{ + Property::Value value; + TextField& impl(GetImpl(textField)); + DALI_ASSERT_DEBUG(impl.mController && "No text controller"); + DALI_ASSERT_DEBUG(impl.mDecorator && "No text decorator"); + + switch(index) + { + case Toolkit::DevelTextField::Property::RENDERING_BACKEND: + { + value = impl.mRenderingBackend; + break; + } + case Toolkit::TextField::Property::TEXT: + { + std::string text; + impl.mController->GetText(text); + DALI_LOG_INFO(gTextFieldLogFilter, Debug::General, "TextField %p returning text: %s\n", impl.mController.Get(), text.c_str()); + value = text; + break; + } + case Toolkit::TextField::Property::PLACEHOLDER_TEXT: + { + std::string text; + impl.mController->GetPlaceholderText(Text::Controller::PLACEHOLDER_TYPE_INACTIVE, text); + value = text; + break; + } + case Toolkit::TextField::Property::PLACEHOLDER_TEXT_FOCUSED: + { + std::string text; + impl.mController->GetPlaceholderText(Text::Controller::PLACEHOLDER_TYPE_ACTIVE, text); + value = text; + break; + } + case Toolkit::TextField::Property::FONT_FAMILY: + { + value = impl.mController->GetDefaultFontFamily(); + break; + } + case Toolkit::TextField::Property::FONT_STYLE: + { + GetFontStyleProperty(impl.mController, value, Text::FontStyle::DEFAULT); + break; + } + case Toolkit::TextField::Property::POINT_SIZE: + { + value = impl.mController->GetDefaultFontSize(Text::Controller::POINT_SIZE); + break; + } + case Toolkit::TextField::Property::MAX_LENGTH: + { + value = impl.mController->GetMaximumNumberOfCharacters(); + break; + } + case Toolkit::TextField::Property::EXCEED_POLICY: + { + value = impl.mExceedPolicy; + break; + } + case Toolkit::TextField::Property::HORIZONTAL_ALIGNMENT: + { + const char* name = Text::GetHorizontalAlignmentString(impl.mController->GetHorizontalAlignment()); + if(name) + { + value = std::string(name); + } + break; + } + case Toolkit::TextField::Property::VERTICAL_ALIGNMENT: + { + const char* name = Text::GetVerticalAlignmentString(impl.mController->GetVerticalAlignment()); + + if(name) + { + value = std::string(name); + } + break; + } + case Toolkit::TextField::Property::TEXT_COLOR: + { + value = impl.mController->GetDefaultColor(); + break; + } + case Toolkit::TextField::Property::PLACEHOLDER_TEXT_COLOR: + { + value = impl.mController->GetPlaceholderTextColor(); + break; + } + case Toolkit::TextField::Property::PRIMARY_CURSOR_COLOR: + { + value = impl.mDecorator->GetColor(Text::PRIMARY_CURSOR); + break; + } + case Toolkit::TextField::Property::SECONDARY_CURSOR_COLOR: + { + value = impl.mDecorator->GetColor(Text::SECONDARY_CURSOR); + break; + } + case Toolkit::TextField::Property::ENABLE_CURSOR_BLINK: + { + value = impl.mController->GetEnableCursorBlink(); + break; + } + case Toolkit::TextField::Property::CURSOR_BLINK_INTERVAL: + { + value = impl.mDecorator->GetCursorBlinkInterval(); + break; + } + case Toolkit::TextField::Property::CURSOR_BLINK_DURATION: + { + value = impl.mDecorator->GetCursorBlinkDuration(); + break; + } + case Toolkit::TextField::Property::CURSOR_WIDTH: + { + value = impl.mDecorator->GetCursorWidth(); + break; + } + case Toolkit::TextField::Property::GRAB_HANDLE_IMAGE: + { + value = impl.mDecorator->GetHandleImage(Text::GRAB_HANDLE, Text::HANDLE_IMAGE_RELEASED); + break; + } + case Toolkit::TextField::Property::GRAB_HANDLE_PRESSED_IMAGE: + { + value = impl.mDecorator->GetHandleImage(Text::GRAB_HANDLE, Text::HANDLE_IMAGE_PRESSED); + break; + } + case Toolkit::TextField::Property::SCROLL_THRESHOLD: + { + value = impl.mDecorator->GetScrollThreshold(); + break; + } + case Toolkit::TextField::Property::SCROLL_SPEED: + { + value = impl.mDecorator->GetScrollSpeed(); + break; + } + case Toolkit::TextField::Property::SELECTION_HANDLE_IMAGE_LEFT: + { + impl.GetHandleImagePropertyValue(value, Text::LEFT_SELECTION_HANDLE, Text::HANDLE_IMAGE_RELEASED); + break; + } + case Toolkit::TextField::Property::SELECTION_HANDLE_IMAGE_RIGHT: + { + impl.GetHandleImagePropertyValue(value, Text::RIGHT_SELECTION_HANDLE, Text::HANDLE_IMAGE_RELEASED); + break; + } + case Toolkit::TextField::Property::SELECTION_HANDLE_PRESSED_IMAGE_LEFT: + { + impl.GetHandleImagePropertyValue(value, Text::LEFT_SELECTION_HANDLE, Text::HANDLE_IMAGE_PRESSED); + break; + } + case Toolkit::TextField::Property::SELECTION_HANDLE_PRESSED_IMAGE_RIGHT: + { + impl.GetHandleImagePropertyValue(value, Text::RIGHT_SELECTION_HANDLE, Text::HANDLE_IMAGE_PRESSED); + break; + } + case Toolkit::TextField::Property::SELECTION_HANDLE_MARKER_IMAGE_LEFT: + { + impl.GetHandleImagePropertyValue(value, Text::LEFT_SELECTION_HANDLE_MARKER, Text::HANDLE_IMAGE_RELEASED); + break; + } + case Toolkit::TextField::Property::SELECTION_HANDLE_MARKER_IMAGE_RIGHT: + { + impl.GetHandleImagePropertyValue(value, Text::RIGHT_SELECTION_HANDLE_MARKER, Text::HANDLE_IMAGE_RELEASED); + break; + } + case Toolkit::TextField::Property::SELECTION_HIGHLIGHT_COLOR: + { + value = impl.mDecorator->GetHighlightColor(); + break; + } + case Toolkit::TextField::Property::DECORATION_BOUNDING_BOX: + { + Rect boundingBox; + impl.mDecorator->GetBoundingBox(boundingBox); + value = boundingBox; + break; + } + case Toolkit::TextField::Property::INPUT_METHOD_SETTINGS: + { + Property::Map map; + impl.mInputMethodOptions.RetrieveProperty(map); + value = map; + break; + } + case Toolkit::TextField::Property::INPUT_COLOR: + { + value = impl.mController->GetInputColor(); + break; + } + case Toolkit::TextField::Property::ENABLE_MARKUP: + { + value = impl.mController->IsMarkupProcessorEnabled(); + break; + } + case Toolkit::TextField::Property::INPUT_FONT_FAMILY: + { + value = impl.mController->GetInputFontFamily(); + break; + } + case Toolkit::TextField::Property::INPUT_FONT_STYLE: + { + GetFontStyleProperty(impl.mController, value, Text::FontStyle::INPUT); + break; + } + case Toolkit::TextField::Property::INPUT_POINT_SIZE: + { + value = impl.mController->GetInputFontPointSize(); + break; + } + case Toolkit::TextField::Property::UNDERLINE: + { + GetUnderlineProperties(impl.mController, value, Text::EffectStyle::DEFAULT); + break; + } + case Toolkit::TextField::Property::INPUT_UNDERLINE: + { + GetUnderlineProperties(impl.mController, value, Text::EffectStyle::INPUT); + break; + } + case Toolkit::TextField::Property::SHADOW: + { + GetShadowProperties(impl.mController, value, Text::EffectStyle::DEFAULT); + break; + } + case Toolkit::TextField::Property::INPUT_SHADOW: + { + GetShadowProperties(impl.mController, value, Text::EffectStyle::INPUT); + break; + } + case Toolkit::TextField::Property::EMBOSS: + { + GetEmbossProperties(impl.mController, value, Text::EffectStyle::DEFAULT); + break; + } + case Toolkit::TextField::Property::INPUT_EMBOSS: + { + GetEmbossProperties(impl.mController, value, Text::EffectStyle::INPUT); + break; + } + case Toolkit::TextField::Property::OUTLINE: + { + GetOutlineProperties(impl.mController, value, Text::EffectStyle::DEFAULT); + break; + } + case Toolkit::TextField::Property::INPUT_OUTLINE: + { + GetOutlineProperties(impl.mController, value, Text::EffectStyle::INPUT); + break; + } + case Toolkit::TextField::Property::HIDDEN_INPUT_SETTINGS: + { + Property::Map map; + impl.mController->GetHiddenInputOption(map); + value = map; + break; + } + case Toolkit::TextField::Property::PIXEL_SIZE: + { + value = impl.mController->GetDefaultFontSize(Text::Controller::PIXEL_SIZE); + break; + } + case Toolkit::TextField::Property::ENABLE_SELECTION: + { + value = impl.mController->IsSelectionEnabled(); + break; + } + case Toolkit::TextField::Property::PLACEHOLDER: + { + Property::Map map; + impl.mController->GetPlaceholderProperty(map); + value = map; + break; + } + case Toolkit::TextField::Property::ELLIPSIS: + { + value = impl.mController->IsTextElideEnabled(); + break; + } + case Toolkit::DevelTextField::Property::ENABLE_SHIFT_SELECTION: + { + value = impl.mController->IsShiftSelectionEnabled(); + break; + } + case Toolkit::DevelTextField::Property::ENABLE_GRAB_HANDLE: + { + value = impl.mController->IsGrabHandleEnabled(); + break; + } + case Toolkit::DevelTextField::Property::MATCH_SYSTEM_LANGUAGE_DIRECTION: + { + value = impl.mController->GetMatchLayoutDirection() != DevelText::MatchLayoutDirection::CONTENTS; + break; + } + case Toolkit::DevelTextField::Property::ENABLE_GRAB_HANDLE_POPUP: + { + value = impl.mController->IsGrabHandlePopupEnabled(); + break; + } + case Toolkit::DevelTextField::Property::BACKGROUND: + { + value = impl.mController->GetBackgroundColor(); + break; + } + case Toolkit::DevelTextField::Property::SELECTED_TEXT: + { + value = impl.mController->GetSelectedText(); + break; + } + case Toolkit::DevelTextField::Property::SELECTED_TEXT_START: + { + Uint32Pair range = impl.GetTextSelectionRange(); + value = static_cast(range.first); + break; + } + case Toolkit::DevelTextField::Property::SELECTED_TEXT_END: + { + Uint32Pair range = impl.GetTextSelectionRange(); + value = static_cast(range.second); + break; + } + case Toolkit::DevelTextField::Property::ENABLE_EDITING: + { + value = impl.IsEditable(); + break; + } + case Toolkit::DevelTextField::Property::FONT_SIZE_SCALE: + { + value = impl.mController->GetFontSizeScale(); + break; + } + case Toolkit::DevelTextField::Property::PRIMARY_CURSOR_POSITION: + { + value = static_cast(impl.mController->GetPrimaryCursorPosition()); + break; + } + case Toolkit::DevelTextField::Property::GRAB_HANDLE_COLOR: + { + value = impl.mDecorator->GetHandleColor(); + break; + } + case Toolkit::DevelTextField::Property::INPUT_FILTER: + { + Property::Map map; + impl.mController->GetInputFilterOption(map); + value = map; + break; + } + case Toolkit::DevelTextField::Property::ELLIPSIS_POSITION: + { + value = impl.mController->GetEllipsisPosition(); + break; + } + } //switch + return value; +} + +} // namespace Dali::Toolkit::Internal diff --git a/dali-toolkit/internal/controls/text-controls/text-field-property-handler.h b/dali-toolkit/internal/controls/text-controls/text-field-property-handler.h new file mode 100644 index 0000000..f7b5c53 --- /dev/null +++ b/dali-toolkit/internal/controls/text-controls/text-field-property-handler.h @@ -0,0 +1,61 @@ +#ifndef DALI_TOOLKIT_INTERNAL_TEXT_FIELD_PROPERTY_HANDLER_H +#define DALI_TOOLKIT_INTERNAL_TEXT_FIELD_PROPERTY_HANDLER_H + +/* + * Copyright (c) 2021 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 + +namespace Dali::Toolkit::Internal +{ +/** + * Class to manage properties for the TextField + */ +struct TextField::PropertyHandler +{ + static const char* const IMAGE_MAP_FILENAME_STRING; //<<< "filename" key for image map + + /** + * Set properties on the text field / controller / decorator + * + * @param[in] textField The handle for the text field + * @param[in] index The property index of the property to set + * @param[in] value The value to set + */ + static void SetProperty(Toolkit::TextField textField, Property::Index index, const Property::Value& value); + + /** + * Get properties from the text field / controller / decorator + * + * @param[in] textField The handle for the text field + * @param[in] index The property index of the property to set + * @return the value + */ + static Property::Value GetProperty(Toolkit::TextField textField, Property::Index index); + +private: + /** + * Method to extract "filename" value from a Property::Map + * + * @param[in] The property value containing the Property::Map + * @return The resulting "filename" value if present + */ + static std::string GetImageFileNameFromPropertyValue(const Property::Value& value); +}; + +} // namespace Dali::Toolkit::Internal + +#endif //DALI_TOOLKIT_INTERNAL_TEXT_FIELD_PROPERTY_HANDLER_H diff --git a/dali-toolkit/internal/file.list b/dali-toolkit/internal/file.list index f1aa866..3229006 100644 --- a/dali-toolkit/internal/file.list +++ b/dali-toolkit/internal/file.list @@ -92,6 +92,7 @@ SET( toolkit_src_files ${toolkit_src_dir}/controls/scrollable/scroll-view/scroll-overshoot-indicator-impl.cpp ${toolkit_src_dir}/controls/scrollable/scroll-view/scroll-view-effect-impl.cpp ${toolkit_src_dir}/controls/scrollable/scroll-view/scroll-view-impl.cpp + ${toolkit_src_dir}/controls/scrollable/scroll-view/scroll-view-impl-constraints.cpp ${toolkit_src_dir}/controls/scrollable/scroll-view/scroll-view-page-path-effect-impl.cpp ${toolkit_src_dir}/controls/scene3d-view/scene3d-view-impl.cpp ${toolkit_src_dir}/controls/scene3d-view/gltf-loader.cpp @@ -99,8 +100,11 @@ SET( toolkit_src_files ${toolkit_src_dir}/controls/slider/slider-impl.cpp ${toolkit_src_dir}/controls/super-blur-view/super-blur-view-impl.cpp ${toolkit_src_dir}/controls/table-view/table-view-impl.cpp + ${toolkit_src_dir}/controls/text-controls/common-text-utils.cpp ${toolkit_src_dir}/controls/text-controls/text-editor-impl.cpp + ${toolkit_src_dir}/controls/text-controls/text-editor-property-handler.cpp ${toolkit_src_dir}/controls/text-controls/text-field-impl.cpp + ${toolkit_src_dir}/controls/text-controls/text-field-property-handler.cpp ${toolkit_src_dir}/controls/text-controls/text-label-impl.cpp ${toolkit_src_dir}/controls/text-controls/text-selection-popup-impl.cpp ${toolkit_src_dir}/controls/text-controls/text-selection-toolbar-impl.cpp @@ -155,6 +159,7 @@ SET( toolkit_src_files ${toolkit_src_dir}/text/text-controller-event-handler.cpp ${toolkit_src_dir}/text/text-controller-impl.cpp ${toolkit_src_dir}/text/text-controller-impl-event-handler.cpp + ${toolkit_src_dir}/text/text-controller-impl-model-updater.cpp ${toolkit_src_dir}/text/text-controller-input-font-handler.cpp ${toolkit_src_dir}/text/text-controller-placeholder-handler.cpp ${toolkit_src_dir}/text/text-controller-relayouter.cpp diff --git a/dali-toolkit/internal/graphics/shaders/color-visual-shader.frag b/dali-toolkit/internal/graphics/shaders/color-visual-shader.frag index 13be4df..3e3d19d 100644 --- a/dali-toolkit/internal/graphics/shaders/color-visual-shader.frag +++ b/dali-toolkit/internal/graphics/shaders/color-visual-shader.frag @@ -241,18 +241,18 @@ mediump float calculateBlurOpacity() // solve (v.x - x)^2 + (v.y - x)^2 = (cr / cy * x)^2 #if IS_REQUIRED_ROUNDED_CORNER - // NOTE : lowspec HW cannot calculate here. need to reduce numeric error - mediump float A = (cr * cr - 2.0 * cy * cy); - mediump float B = cy * (v.x + v.y); - mediump float V = dot(v,v); - mediump float D = B * B + A * V; + // Note : lowspec HW cannot calculate here. need to reduce numeric error + highp float A = (cr * cr - 2.0 * cy * cy); + highp float B = cy * (v.x + v.y); + highp float V = dot(v,v); + highp float D = B * B + A * V; potential = V * (cr + cy) / (sqrt(D) + B); #else // We can simplify this value cause cy = 0.8 * blurRadius, cr = 1.2 * blurRadius // potential = 5.0*(sqrt(4.0*(v.x+v.y)^2 + dot(v,v)) - 2.0*(v.x+v.y)); // = 10.0*(v.x+v.y) * (sqrt(1.0 + (length(v) / (2.0*(v.x+v.y)))^2) - 1.0); // = 10.0*(v.x+v.y) * (sqrt(1.25 - x + x^2) - 1.0); - // ~= 10.0*(v.x+v.y) * (0.11803399 - 0.44721360x + 0.35777088x^2 - 0.14310x^3 + O(x^4)) (Taylor series) + // ~= 10.0*(v.x+v.y) * (0.11803399 - 0.44721360x + 0.35777088x^2 - 0.14310x^3 + O(x^5)) (Taylor series) // ~= -1.0557281 * (v.x + v.y) + 2.236068 * length(v) - ~~~ (here, x <= 0.5 * (1.0 - sqrt(0.5)) < 0.1464467) // Note : This simplify need cause we should use it on lowspec HW. mediump float x = 0.5 * (1.0 - length(v) / (v.x + v.y)); diff --git a/dali-toolkit/internal/text/multi-language-support-impl.cpp b/dali-toolkit/internal/text/multi-language-support-impl.cpp index a0e6ae5..82470f8 100644 --- a/dali-toolkit/internal/text/multi-language-support-impl.cpp +++ b/dali-toolkit/internal/text/multi-language-support-impl.cpp @@ -228,7 +228,8 @@ void MultilanguageSupport::SetScripts(const Vector& text, // Check if whether is right to left markup and Keeps true if the previous value was true. currentScriptRun.isRightToLeft = currentScriptRun.isRightToLeft || TextAbstraction::IsRightToLeftMark(character); - if(TextAbstraction::EMOJI == currentScriptRun.script) + // ZWJ, ZWNJ between emojis should be treated as EMOJI. + if(TextAbstraction::EMOJI == currentScriptRun.script && !(TextAbstraction::IsZeroWidthJoiner(character) || TextAbstraction::IsZeroWidthNonJoiner(character))) { // Emojis doesn't mix well with characters common to all scripts. Insert the emoji run. scripts.Insert(scripts.Begin() + scriptIndex, currentScriptRun); @@ -444,7 +445,8 @@ void MultilanguageSupport::ValidateFonts(const Vector& Vector::ConstIterator scriptRunEndIt = scripts.End(); bool isNewParagraphCharacter = false; - bool isPreviousEmojiScript = false; + bool isPreviousEmojiScript = false; + FontId previousEmojiFontId = 0u; CharacterIndex lastCharacter = startIndex + numberOfCharacters; for(Length index = startIndex; index < lastCharacter; ++index) @@ -535,6 +537,16 @@ void MultilanguageSupport::ValidateFonts(const Vector& currentFontRun.isBoldRequired = false; } + // ZWJ, ZWNJ between emojis should use the previous emoji font. + if(isEmojiScript && (TextAbstraction::IsZeroWidthJoiner(character) || TextAbstraction::IsZeroWidthNonJoiner(character))) + { + if(0u != previousEmojiFontId) + { + fontId = previousEmojiFontId; + isValidFont = true; + } + } + // If the given font is not valid, it means either: // - there is no cached font for the current script yet or, // - the user has set a different font than the default one for the current script or, @@ -647,6 +659,15 @@ void MultilanguageSupport::ValidateFonts(const Vector& } // !isValidFont (2) } // !isValidFont (1) + // Store the font id when the first character is an emoji. + if(isEmojiScript && !isPreviousEmojiScript) + { + if(0u != fontId) + { + previousEmojiFontId = fontId; + } + } + #ifdef DEBUG_ENABLED { Dali::TextAbstraction::FontDescription description; diff --git a/dali-toolkit/internal/text/rendering/view-model.cpp b/dali-toolkit/internal/text/rendering/view-model.cpp index 35c0a87..2187487 100644 --- a/dali-toolkit/internal/text/rendering/view-model.cpp +++ b/dali-toolkit/internal/text/rendering/view-model.cpp @@ -449,7 +449,7 @@ void ViewModel::ElideGlyphs() // Need to reshape the glyph as the font may be different in size. const GlyphInfo& ellipsisGlyph = fontClient.GetEllipsisGlyph(fontClient.GetPointSize(glyphToRemove.fontId)); - if(!firstPenSet) + if(!firstPenSet || EqualsZero(glyphToRemove.advance)) { const Vector2& position = *(elidedPositionsBuffer + indexOfEllipsis); diff --git a/dali-toolkit/internal/text/text-controller-impl-model-updater.cpp b/dali-toolkit/internal/text/text-controller-impl-model-updater.cpp new file mode 100644 index 0000000..1ce7516 --- /dev/null +++ b/dali-toolkit/internal/text/text-controller-impl-model-updater.cpp @@ -0,0 +1,589 @@ +/* + * Copyright (c) 2021 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. + * + */ + +// CLASS HEADER +#include + +// EXTERNAL INCLUDES +#include + +// INTERNAL INCLUDES +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Dali::Toolkit::Text +{ + +namespace +{ +#if defined(DEBUG_ENABLED) +Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, true, "LOG_TEXT_CONTROLS"); +#endif + +// The relative luminance of a color is defined as (L = 0.2126 * R + 0.7152 * G + 0.0722 * B) +// based on W3C Recommendations (https://www.w3.org/TR/WCAG20/) +constexpr float BRIGHTNESS_THRESHOLD = 0.179f; +constexpr float CONSTANT_R = 0.2126f; +constexpr float CONSTANT_G = 0.7152f; +constexpr float CONSTANT_B = 0.0722f; +constexpr Dali::Vector4 BLACK(0.f, 0.f, 0.f, 1.f); +constexpr Dali::Vector4 WHITE(1.f, 1.f, 1.f, 1.f); +constexpr Dali::Vector4 LIGHT_BLUE(0.75f, 0.96f, 1.f, 1.f); +constexpr Dali::Vector4 BACKGROUND_SUB4(0.58f, 0.87f, 0.96f, 1.f); +constexpr Dali::Vector4 BACKGROUND_SUB5(0.83f, 0.94f, 0.98f, 1.f); +constexpr Dali::Vector4 BACKGROUND_SUB6(1.f, 0.5f, 0.5f, 1.f); +constexpr Dali::Vector4 BACKGROUND_SUB7(1.f, 0.8f, 0.8f, 1.f); +} // namespace + +bool ControllerImplModelUpdater::Update(Controller::Impl& impl, OperationsMask operationsRequired) +{ + DALI_LOG_INFO(gLogFilter, Debug::General, "Controller::UpdateModel\n"); + + // Calculate the operations to be done. + const OperationsMask operations = static_cast(impl.mOperationsPending & operationsRequired); + + if(Controller::NO_OPERATION == operations) + { + // Nothing to do if no operations are pending and required. + return false; + } + + Vector& srcCharacters = impl.mModel->mLogicalModel->mText; + Vector displayCharacters; + bool useHiddenText = false; + if(impl.mHiddenInput && impl.mEventData != nullptr && !impl.mEventData->mIsShowingPlaceholderText) + { + impl.mHiddenInput->Substitute(srcCharacters, displayCharacters); + useHiddenText = true; + } + + Vector& utf32Characters = useHiddenText ? displayCharacters : srcCharacters; + const Length numberOfCharacters = utf32Characters.Count(); + + // Index to the first character of the first paragraph to be updated. + CharacterIndex startIndex = 0u; + // Number of characters of the paragraphs to be removed. + Length paragraphCharacters = 0u; + + impl.CalculateTextUpdateIndices(paragraphCharacters); + + // Check whether the indices for updating the text is valid + if(numberOfCharacters > 0u && + (impl.mTextUpdateInfo.mParagraphCharacterIndex > numberOfCharacters || + impl.mTextUpdateInfo.mRequestedNumberOfCharacters > numberOfCharacters)) + { + std::string currentText; + Utf32ToUtf8(impl.mModel->mLogicalModel->mText.Begin(), numberOfCharacters, currentText); + + DALI_LOG_ERROR("Controller::Impl::UpdateModel: mTextUpdateInfo has invalid indices\n"); + DALI_LOG_ERROR("Number of characters: %d, current text is: %s\n", numberOfCharacters, currentText.c_str()); + + // Dump mTextUpdateInfo + DALI_LOG_ERROR("Dump mTextUpdateInfo:\n"); + DALI_LOG_ERROR(" mTextUpdateInfo.mCharacterIndex = %u\n", impl.mTextUpdateInfo.mCharacterIndex); + DALI_LOG_ERROR(" mTextUpdateInfo.mNumberOfCharactersToRemove = %u\n", impl.mTextUpdateInfo.mNumberOfCharactersToRemove); + DALI_LOG_ERROR(" mTextUpdateInfo.mNumberOfCharactersToAdd = %u\n", impl.mTextUpdateInfo.mNumberOfCharactersToAdd); + DALI_LOG_ERROR(" mTextUpdateInfo.mPreviousNumberOfCharacters = %u\n", impl.mTextUpdateInfo.mPreviousNumberOfCharacters); + DALI_LOG_ERROR(" mTextUpdateInfo.mParagraphCharacterIndex = %u\n", impl.mTextUpdateInfo.mParagraphCharacterIndex); + DALI_LOG_ERROR(" mTextUpdateInfo.mRequestedNumberOfCharacters = %u\n", impl.mTextUpdateInfo.mRequestedNumberOfCharacters); + DALI_LOG_ERROR(" mTextUpdateInfo.mStartGlyphIndex = %u\n", impl.mTextUpdateInfo.mStartGlyphIndex); + DALI_LOG_ERROR(" mTextUpdateInfo.mStartLineIndex = %u\n", impl.mTextUpdateInfo.mStartLineIndex); + DALI_LOG_ERROR(" mTextUpdateInfo.mEstimatedNumberOfLines = %u\n", impl.mTextUpdateInfo.mEstimatedNumberOfLines); + DALI_LOG_ERROR(" mTextUpdateInfo.mClearAll = %d\n", impl.mTextUpdateInfo.mClearAll); + DALI_LOG_ERROR(" mTextUpdateInfo.mFullRelayoutNeeded = %d\n", impl.mTextUpdateInfo.mFullRelayoutNeeded); + DALI_LOG_ERROR(" mTextUpdateInfo.mIsLastCharacterNewParagraph = %d\n", impl.mTextUpdateInfo.mIsLastCharacterNewParagraph); + + return false; + } + + startIndex = impl.mTextUpdateInfo.mParagraphCharacterIndex; + + if(impl.mTextUpdateInfo.mClearAll || + (0u != paragraphCharacters)) + { + impl.ClearModelData(startIndex, startIndex + ((paragraphCharacters > 0u) ? paragraphCharacters - 1u : 0u), operations); + } + + impl.mTextUpdateInfo.mClearAll = false; + + // Whether the model is updated. + bool updated = false; + + Vector& lineBreakInfo = impl.mModel->mLogicalModel->mLineBreakInfo; + const Length requestedNumberOfCharacters = impl.mTextUpdateInfo.mRequestedNumberOfCharacters; + + if(Controller::NO_OPERATION != (Controller::GET_LINE_BREAKS & operations)) + { + // Retrieves the line break info. The line break info is used to split the text in 'paragraphs' to + // calculate the bidirectional info for each 'paragraph'. + // It's also used to layout the text (where it should be a new line) or to shape the text (text in different lines + // is not shaped together). + lineBreakInfo.Resize(numberOfCharacters, TextAbstraction::LINE_NO_BREAK); + + SetLineBreakInfo(utf32Characters, + startIndex, + requestedNumberOfCharacters, + lineBreakInfo); + + if(impl.mModel->mLineWrapMode == ((Text::LineWrap::Mode)DevelText::LineWrap::HYPHENATION) || + impl.mModel->mLineWrapMode == ((Text::LineWrap::Mode)DevelText::LineWrap::MIXED)) + { + CharacterIndex end = startIndex + requestedNumberOfCharacters; + LineBreakInfo* lineBreakInfoBuffer = lineBreakInfo.Begin(); + + for(CharacterIndex index = startIndex; index < end; index++) + { + CharacterIndex wordEnd = index; + while((*(lineBreakInfoBuffer + wordEnd) != TextAbstraction::LINE_ALLOW_BREAK) && (*(lineBreakInfoBuffer + wordEnd) != TextAbstraction::LINE_MUST_BREAK)) + { + wordEnd++; + } + + if((wordEnd + 1) == end) // add last char + { + wordEnd++; + } + + Vector hyphens = GetWordHyphens(utf32Characters.Begin() + index, wordEnd - index, nullptr); + + for(CharacterIndex i = 0; i < (wordEnd - index); i++) + { + if(hyphens[i]) + { + *(lineBreakInfoBuffer + index + i) = TextAbstraction::LINE_HYPHENATION_BREAK; + } + } + + index = wordEnd; + } + } + + // Create the paragraph info. + impl.mModel->mLogicalModel->CreateParagraphInfo(startIndex, + requestedNumberOfCharacters); + updated = true; + } + + const bool getScripts = Controller::NO_OPERATION != (Controller::GET_SCRIPTS & operations); + const bool validateFonts = Controller::NO_OPERATION != (Controller::VALIDATE_FONTS & operations); + + Vector& scripts = impl.mModel->mLogicalModel->mScriptRuns; + Vector& validFonts = impl.mModel->mLogicalModel->mFontRuns; + + if(getScripts || validateFonts) + { + // Validates the fonts assigned by the application or assigns default ones. + // It makes sure all the characters are going to be rendered by the correct font. + MultilanguageSupport multilanguageSupport = MultilanguageSupport::Get(); + + if(getScripts) + { + // Retrieves the scripts used in the text. + multilanguageSupport.SetScripts(utf32Characters, + startIndex, + requestedNumberOfCharacters, + scripts); + } + + if(validateFonts) + { + // Validate the fonts set through the mark-up string. + Vector& fontDescriptionRuns = impl.mModel->mLogicalModel->mFontDescriptionRuns; + + // Get the default font's description. + TextAbstraction::FontDescription defaultFontDescription; + TextAbstraction::PointSize26Dot6 defaultPointSize = TextAbstraction::FontClient::DEFAULT_POINT_SIZE * impl.mFontSizeScale; + + //Get the number of points per one unit of point-size + uint32_t numberOfPointsPerOneUnitOfPointSize = impl.mFontClient.GetNumberOfPointsPerOneUnitOfPointSize(); + + if(impl.IsShowingPlaceholderText() && impl.mEventData && (nullptr != impl.mEventData->mPlaceholderFont)) + { + // If the placeholder font is set specifically, only placeholder font is changed. + defaultFontDescription = impl.mEventData->mPlaceholderFont->mFontDescription; + if(impl.mEventData->mPlaceholderFont->sizeDefined) + { + defaultPointSize = impl.mEventData->mPlaceholderFont->mDefaultPointSize * impl.mFontSizeScale * numberOfPointsPerOneUnitOfPointSize; + } + } + else if(nullptr != impl.mFontDefaults) + { + // Set the normal font and the placeholder font. + defaultFontDescription = impl.mFontDefaults->mFontDescription; + + if(impl.mTextFitEnabled) + { + defaultPointSize = impl.mFontDefaults->mFitPointSize * numberOfPointsPerOneUnitOfPointSize; + } + else + { + defaultPointSize = impl.mFontDefaults->mDefaultPointSize * impl.mFontSizeScale * numberOfPointsPerOneUnitOfPointSize; + } + } + + // Validates the fonts. If there is a character with no assigned font it sets a default one. + // After this call, fonts are validated. + multilanguageSupport.ValidateFonts(utf32Characters, + scripts, + fontDescriptionRuns, + defaultFontDescription, + defaultPointSize, + startIndex, + requestedNumberOfCharacters, + validFonts); + } + updated = true; + } + + Vector mirroredUtf32Characters; + bool textMirrored = false; + const Length numberOfParagraphs = impl.mModel->mLogicalModel->mParagraphInfo.Count(); + if(Controller::NO_OPERATION != (Controller::BIDI_INFO & operations)) + { + Vector& bidirectionalInfo = impl.mModel->mLogicalModel->mBidirectionalParagraphInfo; + bidirectionalInfo.Reserve(numberOfParagraphs); + + // Calculates the bidirectional info for the whole paragraph if it contains right to left scripts. + SetBidirectionalInfo(utf32Characters, + scripts, + lineBreakInfo, + startIndex, + requestedNumberOfCharacters, + bidirectionalInfo, + (impl.mModel->mMatchLayoutDirection != DevelText::MatchLayoutDirection::CONTENTS), + impl.mLayoutDirection); + + if(0u != bidirectionalInfo.Count()) + { + // Only set the character directions if there is right to left characters. + Vector& directions = impl.mModel->mLogicalModel->mCharacterDirections; + GetCharactersDirection(bidirectionalInfo, + numberOfCharacters, + startIndex, + requestedNumberOfCharacters, + directions); + + // This paragraph has right to left text. Some characters may need to be mirrored. + // TODO: consider if the mirrored string can be stored as well. + + textMirrored = GetMirroredText(utf32Characters, + directions, + bidirectionalInfo, + startIndex, + requestedNumberOfCharacters, + mirroredUtf32Characters); + } + else + { + // There is no right to left characters. Clear the directions vector. + impl.mModel->mLogicalModel->mCharacterDirections.Clear(); + } + updated = true; + } + + Vector& glyphs = impl.mModel->mVisualModel->mGlyphs; + Vector& glyphsToCharactersMap = impl.mModel->mVisualModel->mGlyphsToCharacters; + Vector& charactersPerGlyph = impl.mModel->mVisualModel->mCharactersPerGlyph; + Vector newParagraphGlyphs; + newParagraphGlyphs.Reserve(numberOfParagraphs); + + const Length currentNumberOfGlyphs = glyphs.Count(); + if(Controller::NO_OPERATION != (Controller::SHAPE_TEXT & operations)) + { + const Vector& textToShape = textMirrored ? mirroredUtf32Characters : utf32Characters; + // Shapes the text. + ShapeText(textToShape, + lineBreakInfo, + scripts, + validFonts, + startIndex, + impl.mTextUpdateInfo.mStartGlyphIndex, + requestedNumberOfCharacters, + glyphs, + glyphsToCharactersMap, + charactersPerGlyph, + newParagraphGlyphs); + + // Create the 'number of glyphs' per character and the glyph to character conversion tables. + impl.mModel->mVisualModel->CreateGlyphsPerCharacterTable(startIndex, impl.mTextUpdateInfo.mStartGlyphIndex, requestedNumberOfCharacters); + impl.mModel->mVisualModel->CreateCharacterToGlyphTable(startIndex, impl.mTextUpdateInfo.mStartGlyphIndex, requestedNumberOfCharacters); + + updated = true; + } + + const Length numberOfGlyphs = glyphs.Count() - currentNumberOfGlyphs; + + if(Controller::NO_OPERATION != (Controller::GET_GLYPH_METRICS & operations)) + { + GlyphInfo* glyphsBuffer = glyphs.Begin(); + impl.mMetrics->GetGlyphMetrics(glyphsBuffer + impl.mTextUpdateInfo.mStartGlyphIndex, numberOfGlyphs); + + // Update the width and advance of all new paragraph characters. + for(Vector::ConstIterator it = newParagraphGlyphs.Begin(), endIt = newParagraphGlyphs.End(); it != endIt; ++it) + { + const GlyphIndex index = *it; + GlyphInfo& glyph = *(glyphsBuffer + index); + + glyph.xBearing = 0.f; + glyph.width = 0.f; + glyph.advance = 0.f; + } + updated = true; + } + + if((nullptr != impl.mEventData) && + impl.mEventData->mPreEditFlag && + (0u != impl.mModel->mVisualModel->mCharactersToGlyph.Count())) + { + Dali::InputMethodContext::PreEditAttributeDataContainer attrs; + impl.mEventData->mInputMethodContext.GetPreeditStyle(attrs); + Dali::InputMethodContext::PreeditStyle type = Dali::InputMethodContext::PreeditStyle::NONE; + + // Check the type of preedit and run it. + for(Dali::InputMethodContext::PreEditAttributeDataContainer::Iterator it = attrs.Begin(), endIt = attrs.End(); it != endIt; it++) + { + Dali::InputMethodContext::PreeditAttributeData attrData = *it; + DALI_LOG_INFO(gLogFilter, Debug::General, "Controller::UpdateModel PreeditStyle type : %d start %d end %d \n", attrData.preeditType, attrData.startIndex, attrData.endIndex); + type = attrData.preeditType; + + // Check the number of commit characters for the start position. + unsigned int numberOfCommit = impl.mEventData->mPrimaryCursorPosition - impl.mEventData->mPreEditLength; + Length numberOfIndices = attrData.endIndex - attrData.startIndex; + + switch(type) + { + case Dali::InputMethodContext::PreeditStyle::UNDERLINE: + { + // Add the underline for the pre-edit text. + GlyphRun underlineRun; + underlineRun.glyphIndex = attrData.startIndex + numberOfCommit; + underlineRun.numberOfGlyphs = numberOfIndices; + impl.mModel->mVisualModel->mUnderlineRuns.PushBack(underlineRun); + + //Mark-up processor case + if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled()) + { + impl.CopyUnderlinedFromLogicalToVisualModels(false); + } + break; + } + case Dali::InputMethodContext::PreeditStyle::REVERSE: + { + Vector4 textColor = impl.mModel->mVisualModel->GetTextColor(); + ColorRun backgroundColorRun; + backgroundColorRun.characterRun.characterIndex = attrData.startIndex + numberOfCommit; + backgroundColorRun.characterRun.numberOfCharacters = numberOfIndices; + backgroundColorRun.color = textColor; + impl.mModel->mLogicalModel->mBackgroundColorRuns.PushBack(backgroundColorRun); + + Vector4 backgroundColor = impl.mModel->mVisualModel->GetBackgroundColor(); + if(backgroundColor.a == 0) // There is no text background color. + { + // Try use the control's background color. + if(nullptr != impl.mEditableControlInterface) + { + impl.mEditableControlInterface->GetControlBackgroundColor(backgroundColor); + if(backgroundColor.a == 0) // There is no control background color. + { + // Determines black or white color according to text color. + // Based on W3C Recommendations (https://www.w3.org/TR/WCAG20/) + float L = CONSTANT_R * textColor.r + CONSTANT_G * textColor.g + CONSTANT_B * textColor.b; + backgroundColor = L > BRIGHTNESS_THRESHOLD ? BLACK : WHITE; + } + } + } + + Vector colorRuns; + colorRuns.Resize(1u); + ColorRun& colorRun = *(colorRuns.Begin()); + colorRun.color = backgroundColor; + colorRun.characterRun.characterIndex = attrData.startIndex + numberOfCommit; + colorRun.characterRun.numberOfCharacters = numberOfIndices; + impl.mModel->mLogicalModel->mColorRuns.PushBack(colorRun); + + //Mark-up processor case + if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled()) + { + impl.CopyUnderlinedFromLogicalToVisualModels(false); + } + break; + } + case Dali::InputMethodContext::PreeditStyle::HIGHLIGHT: + { + ColorRun backgroundColorRun; + backgroundColorRun.characterRun.characterIndex = attrData.startIndex + numberOfCommit; + backgroundColorRun.characterRun.numberOfCharacters = numberOfIndices; + backgroundColorRun.color = LIGHT_BLUE; + impl.mModel->mLogicalModel->mBackgroundColorRuns.PushBack(backgroundColorRun); + + //Mark-up processor case + if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled()) + { + impl.CopyUnderlinedFromLogicalToVisualModels(false); + } + break; + } + case Dali::InputMethodContext::PreeditStyle::CUSTOM_PLATFORM_STYLE_1: + { + // CUSTOM_PLATFORM_STYLE_1 should be drawn with background and underline together. + ColorRun backgroundColorRun; + backgroundColorRun.characterRun.characterIndex = attrData.startIndex + numberOfCommit; + backgroundColorRun.characterRun.numberOfCharacters = numberOfIndices; + backgroundColorRun.color = BACKGROUND_SUB4; + impl.mModel->mLogicalModel->mBackgroundColorRuns.PushBack(backgroundColorRun); + + GlyphRun underlineRun; + underlineRun.glyphIndex = attrData.startIndex + numberOfCommit; + underlineRun.numberOfGlyphs = numberOfIndices; + impl.mModel->mVisualModel->mUnderlineRuns.PushBack(underlineRun); + + //Mark-up processor case + if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled()) + { + impl.CopyUnderlinedFromLogicalToVisualModels(false); + } + break; + } + case Dali::InputMethodContext::PreeditStyle::CUSTOM_PLATFORM_STYLE_2: + { + // CUSTOM_PLATFORM_STYLE_2 should be drawn with background and underline together. + ColorRun backgroundColorRun; + backgroundColorRun.characterRun.characterIndex = attrData.startIndex + numberOfCommit; + backgroundColorRun.characterRun.numberOfCharacters = numberOfIndices; + backgroundColorRun.color = BACKGROUND_SUB5; + impl.mModel->mLogicalModel->mBackgroundColorRuns.PushBack(backgroundColorRun); + + GlyphRun underlineRun; + underlineRun.glyphIndex = attrData.startIndex + numberOfCommit; + underlineRun.numberOfGlyphs = numberOfIndices; + impl.mModel->mVisualModel->mUnderlineRuns.PushBack(underlineRun); + + //Mark-up processor case + if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled()) + { + impl.CopyUnderlinedFromLogicalToVisualModels(false); + } + break; + } + case Dali::InputMethodContext::PreeditStyle::CUSTOM_PLATFORM_STYLE_3: + { + // CUSTOM_PLATFORM_STYLE_3 should be drawn with background and underline together. + ColorRun backgroundColorRun; + backgroundColorRun.characterRun.characterIndex = attrData.startIndex + numberOfCommit; + backgroundColorRun.characterRun.numberOfCharacters = numberOfIndices; + backgroundColorRun.color = BACKGROUND_SUB6; + impl.mModel->mLogicalModel->mBackgroundColorRuns.PushBack(backgroundColorRun); + + GlyphRun underlineRun; + underlineRun.glyphIndex = attrData.startIndex + numberOfCommit; + underlineRun.numberOfGlyphs = numberOfIndices; + impl.mModel->mVisualModel->mUnderlineRuns.PushBack(underlineRun); + + //Mark-up processor case + if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled()) + { + impl.CopyUnderlinedFromLogicalToVisualModels(false); + } + break; + } + case Dali::InputMethodContext::PreeditStyle::CUSTOM_PLATFORM_STYLE_4: + { + // CUSTOM_PLATFORM_STYLE_4 should be drawn with background and underline together. + ColorRun backgroundColorRun; + backgroundColorRun.characterRun.characterIndex = attrData.startIndex + numberOfCommit; + backgroundColorRun.characterRun.numberOfCharacters = numberOfIndices; + backgroundColorRun.color = BACKGROUND_SUB7; + impl.mModel->mLogicalModel->mBackgroundColorRuns.PushBack(backgroundColorRun); + + GlyphRun underlineRun; + underlineRun.glyphIndex = attrData.startIndex + numberOfCommit; + underlineRun.numberOfGlyphs = numberOfIndices; + impl.mModel->mVisualModel->mUnderlineRuns.PushBack(underlineRun); + + //Mark-up processor case + if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled()) + { + impl.CopyUnderlinedFromLogicalToVisualModels(false); + } + break; + } + case Dali::InputMethodContext::PreeditStyle::NONE: + default: + { + break; + } + } + } + attrs.Clear(); + updated = true; + } + + if(Controller::NO_OPERATION != (Controller::COLOR & operations)) + { + // Set the color runs in glyphs. + SetColorSegmentationInfo(impl.mModel->mLogicalModel->mColorRuns, + impl.mModel->mVisualModel->mCharactersToGlyph, + impl.mModel->mVisualModel->mGlyphsPerCharacter, + startIndex, + impl.mTextUpdateInfo.mStartGlyphIndex, + requestedNumberOfCharacters, + impl.mModel->mVisualModel->mColors, + impl.mModel->mVisualModel->mColorIndices); + + // Set the background color runs in glyphs. + SetColorSegmentationInfo(impl.mModel->mLogicalModel->mBackgroundColorRuns, + impl.mModel->mVisualModel->mCharactersToGlyph, + impl.mModel->mVisualModel->mGlyphsPerCharacter, + startIndex, + impl.mTextUpdateInfo.mStartGlyphIndex, + requestedNumberOfCharacters, + impl.mModel->mVisualModel->mBackgroundColors, + impl.mModel->mVisualModel->mBackgroundColorIndices); + + updated = true; + } + + if((Controller::NO_OPERATION != (Controller::SHAPE_TEXT & operations)) && + !((nullptr != impl.mEventData) && + impl.mEventData->mPreEditFlag && + (0u != impl.mModel->mVisualModel->mCharactersToGlyph.Count()))) + { + //Mark-up processor case + if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled()) + { + impl.CopyUnderlinedFromLogicalToVisualModels(true); + } + + updated = true; + } + + // The estimated number of lines. Used to avoid reallocations when layouting. + impl.mTextUpdateInfo.mEstimatedNumberOfLines = std::max(impl.mModel->mVisualModel->mLines.Count(), impl.mModel->mLogicalModel->mParagraphInfo.Count()); + + // Set the previous number of characters for the next time the text is updated. + impl.mTextUpdateInfo.mPreviousNumberOfCharacters = numberOfCharacters; + + return updated; +} + +} // namespace Dali::Toolkit::Text diff --git a/dali-toolkit/internal/text/text-controller-impl-model-updater.h b/dali-toolkit/internal/text/text-controller-impl-model-updater.h new file mode 100644 index 0000000..2c5dd8c --- /dev/null +++ b/dali-toolkit/internal/text/text-controller-impl-model-updater.h @@ -0,0 +1,46 @@ +#ifndef DALI_TOOLKIT_TEXT_CONTROLLER_IMPL_MODEL_UPDATER_H +#define DALI_TOOLKIT_TEXT_CONTROLLER_IMPL_MODEL_UPDATER_H + +/* + * Copyright (c) 2021 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. + * + */ + +// INTERNAL INCLUDES +#include + +namespace Dali::Toolkit::Text +{ + +/** + * Contains methods for updating the models in the TextController + */ +struct ControllerImplModelUpdater +{ + using OperationsMask = Controller::OperationsMask; + + /** + * @brief Updates the logical and visual models. Updates the style runs in the visual model when the text's styles changes. + * + * @param[in] impl A reference to the Controller::Impl class + * @param[in] operationsRequired The operations required + * @return true if mode has been modified. + */ + static bool Update(Controller::Impl& impl, OperationsMask operationsRequired); +}; + +} // namespace Dali::Toolkit::Text + +#endif // DALI_TOOLKIT_TEXT_CONTROLLER_IMPL_MODEL_UPDATER_H diff --git a/dali-toolkit/internal/text/text-controller-impl.cpp b/dali-toolkit/internal/text/text-controller-impl.cpp index 045fb8a..2edca46 100644 --- a/dali-toolkit/internal/text/text-controller-impl.cpp +++ b/dali-toolkit/internal/text/text-controller-impl.cpp @@ -25,16 +25,11 @@ // INTERNAL INCLUDES #include #include -#include #include -#include #include -#include -#include -#include -#include #include #include +#include #include #include #include @@ -60,28 +55,82 @@ struct BackgroundMesh Vector mIndices; ///< container of indices }; -// The relative luminance of a color is defined as (L = 0.2126 * R + 0.7152 * G + 0.0722 * B) -// based on W3C Recommendations (https://www.w3.org/TR/WCAG20/) -const float BRIGHTNESS_THRESHOLD = 0.179f; -const float CONSTANT_R = 0.2126f; -const float CONSTANT_G = 0.7152f; -const float CONSTANT_B = 0.0722f; -const Dali::Vector4 BLACK(0.f, 0.f, 0.f, 1.f); -const Dali::Vector4 WHITE(1.f, 1.f, 1.f, 1.f); -const Dali::Vector4 LIGHT_BLUE(0.75f, 0.96f, 1.f, 1.f); -const Dali::Vector4 BACKGROUND_SUB4(0.58f, 0.87f, 0.96f, 1.f); -const Dali::Vector4 BACKGROUND_SUB5(0.83f, 0.94f, 0.98f, 1.f); -const Dali::Vector4 BACKGROUND_SUB6(1.f, 0.5f, 0.5f, 1.f); -const Dali::Vector4 BACKGROUND_SUB7(1.f, 0.8f, 0.8f, 1.f); - } // namespace -namespace Dali +namespace Dali::Toolkit::Text { -namespace Toolkit + +namespace { -namespace Text + +void SetDefaultInputStyle(InputStyle& inputStyle, const FontDefaults* const fontDefaults, const Vector4& textColor) { + // Sets the default text's color. + inputStyle.textColor = textColor; + inputStyle.isDefaultColor = true; + + inputStyle.familyName.clear(); + inputStyle.weight = TextAbstraction::FontWeight::NORMAL; + inputStyle.width = TextAbstraction::FontWidth::NORMAL; + inputStyle.slant = TextAbstraction::FontSlant::NORMAL; + inputStyle.size = 0.f; + + inputStyle.lineSpacing = 0.f; + + inputStyle.underlineProperties.clear(); + inputStyle.shadowProperties.clear(); + inputStyle.embossProperties.clear(); + inputStyle.outlineProperties.clear(); + + inputStyle.isFamilyDefined = false; + inputStyle.isWeightDefined = false; + inputStyle.isWidthDefined = false; + inputStyle.isSlantDefined = false; + inputStyle.isSizeDefined = false; + + inputStyle.isLineSpacingDefined = false; + + inputStyle.isUnderlineDefined = false; + inputStyle.isShadowDefined = false; + inputStyle.isEmbossDefined = false; + inputStyle.isOutlineDefined = false; + + // Sets the default font's family name, weight, width, slant and size. + if(fontDefaults) + { + if(fontDefaults->familyDefined) + { + inputStyle.familyName = fontDefaults->mFontDescription.family; + inputStyle.isFamilyDefined = true; + } + + if(fontDefaults->weightDefined) + { + inputStyle.weight = fontDefaults->mFontDescription.weight; + inputStyle.isWeightDefined = true; + } + + if(fontDefaults->widthDefined) + { + inputStyle.width = fontDefaults->mFontDescription.width; + inputStyle.isWidthDefined = true; + } + + if(fontDefaults->slantDefined) + { + inputStyle.slant = fontDefaults->mFontDescription.slant; + inputStyle.isSlantDefined = true; + } + + if(fontDefaults->sizeDefined) + { + inputStyle.size = fontDefaults->mDefaultPointSize; + inputStyle.isSizeDefined = true; + } + } +} +} // unnamed Namespace + EventData::EventData(DecoratorPtr decorator, InputMethodContext& inputMethodContext) : mDecorator(decorator), mInputMethodContext(inputMethodContext), @@ -588,600 +637,12 @@ void Controller::Impl::ClearModelData(CharacterIndex startIndex, CharacterIndex bool Controller::Impl::UpdateModel(OperationsMask operationsRequired) { - DALI_LOG_INFO(gLogFilter, Debug::General, "Controller::UpdateModel\n"); - - // Calculate the operations to be done. - const OperationsMask operations = static_cast(mOperationsPending & operationsRequired); - - if(NO_OPERATION == operations) - { - // Nothing to do if no operations are pending and required. - return false; - } - - Vector& srcCharacters = mModel->mLogicalModel->mText; - Vector displayCharacters; - bool useHiddenText = false; - if(mHiddenInput && mEventData != nullptr && !mEventData->mIsShowingPlaceholderText) - { - mHiddenInput->Substitute(srcCharacters, displayCharacters); - useHiddenText = true; - } - - Vector& utf32Characters = useHiddenText ? displayCharacters : srcCharacters; - const Length numberOfCharacters = utf32Characters.Count(); - - // Index to the first character of the first paragraph to be updated. - CharacterIndex startIndex = 0u; - // Number of characters of the paragraphs to be removed. - Length paragraphCharacters = 0u; - - CalculateTextUpdateIndices(paragraphCharacters); - - // Check whether the indices for updating the text is valid - if(numberOfCharacters > 0u && - (mTextUpdateInfo.mParagraphCharacterIndex > numberOfCharacters || - mTextUpdateInfo.mRequestedNumberOfCharacters > numberOfCharacters)) - { - std::string currentText; - Utf32ToUtf8(mModel->mLogicalModel->mText.Begin(), numberOfCharacters, currentText); - - DALI_LOG_ERROR("Controller::Impl::UpdateModel: mTextUpdateInfo has invalid indices\n"); - DALI_LOG_ERROR("Number of characters: %d, current text is: %s\n", numberOfCharacters, currentText.c_str()); - - // Dump mTextUpdateInfo - DALI_LOG_ERROR("Dump mTextUpdateInfo:\n"); - DALI_LOG_ERROR(" mTextUpdateInfo.mCharacterIndex = %u\n", mTextUpdateInfo.mCharacterIndex); - DALI_LOG_ERROR(" mTextUpdateInfo.mNumberOfCharactersToRemove = %u\n", mTextUpdateInfo.mNumberOfCharactersToRemove); - DALI_LOG_ERROR(" mTextUpdateInfo.mNumberOfCharactersToAdd = %u\n", mTextUpdateInfo.mNumberOfCharactersToAdd); - DALI_LOG_ERROR(" mTextUpdateInfo.mPreviousNumberOfCharacters = %u\n", mTextUpdateInfo.mPreviousNumberOfCharacters); - DALI_LOG_ERROR(" mTextUpdateInfo.mParagraphCharacterIndex = %u\n", mTextUpdateInfo.mParagraphCharacterIndex); - DALI_LOG_ERROR(" mTextUpdateInfo.mRequestedNumberOfCharacters = %u\n", mTextUpdateInfo.mRequestedNumberOfCharacters); - DALI_LOG_ERROR(" mTextUpdateInfo.mStartGlyphIndex = %u\n", mTextUpdateInfo.mStartGlyphIndex); - DALI_LOG_ERROR(" mTextUpdateInfo.mStartLineIndex = %u\n", mTextUpdateInfo.mStartLineIndex); - DALI_LOG_ERROR(" mTextUpdateInfo.mEstimatedNumberOfLines = %u\n", mTextUpdateInfo.mEstimatedNumberOfLines); - DALI_LOG_ERROR(" mTextUpdateInfo.mClearAll = %d\n", mTextUpdateInfo.mClearAll); - DALI_LOG_ERROR(" mTextUpdateInfo.mFullRelayoutNeeded = %d\n", mTextUpdateInfo.mFullRelayoutNeeded); - DALI_LOG_ERROR(" mTextUpdateInfo.mIsLastCharacterNewParagraph = %d\n", mTextUpdateInfo.mIsLastCharacterNewParagraph); - - return false; - } - - startIndex = mTextUpdateInfo.mParagraphCharacterIndex; - - if(mTextUpdateInfo.mClearAll || - (0u != paragraphCharacters)) - { - ClearModelData(startIndex, startIndex + ((paragraphCharacters > 0u) ? paragraphCharacters - 1u : 0u), operations); - } - - mTextUpdateInfo.mClearAll = false; - - // Whether the model is updated. - bool updated = false; - - Vector& lineBreakInfo = mModel->mLogicalModel->mLineBreakInfo; - const Length requestedNumberOfCharacters = mTextUpdateInfo.mRequestedNumberOfCharacters; - - if(NO_OPERATION != (GET_LINE_BREAKS & operations)) - { - // Retrieves the line break info. The line break info is used to split the text in 'paragraphs' to - // calculate the bidirectional info for each 'paragraph'. - // It's also used to layout the text (where it should be a new line) or to shape the text (text in different lines - // is not shaped together). - lineBreakInfo.Resize(numberOfCharacters, TextAbstraction::LINE_NO_BREAK); - - SetLineBreakInfo(utf32Characters, - startIndex, - requestedNumberOfCharacters, - lineBreakInfo); - - if(mModel->mLineWrapMode == ((Text::LineWrap::Mode)DevelText::LineWrap::HYPHENATION) || - mModel->mLineWrapMode == ((Text::LineWrap::Mode)DevelText::LineWrap::MIXED)) - { - CharacterIndex end = startIndex + requestedNumberOfCharacters; - LineBreakInfo* lineBreakInfoBuffer = lineBreakInfo.Begin(); - - for(CharacterIndex index = startIndex; index < end; index++) - { - CharacterIndex wordEnd = index; - while((*(lineBreakInfoBuffer + wordEnd) != TextAbstraction::LINE_ALLOW_BREAK) && (*(lineBreakInfoBuffer + wordEnd) != TextAbstraction::LINE_MUST_BREAK)) - { - wordEnd++; - } - - if((wordEnd + 1) == end) // add last char - { - wordEnd++; - } - - Vector hyphens = GetWordHyphens(utf32Characters.Begin() + index, wordEnd - index, nullptr); - - for(CharacterIndex i = 0; i < (wordEnd - index); i++) - { - if(hyphens[i]) - { - *(lineBreakInfoBuffer + index + i) = TextAbstraction::LINE_HYPHENATION_BREAK; - } - } - - index = wordEnd; - } - } - - // Create the paragraph info. - mModel->mLogicalModel->CreateParagraphInfo(startIndex, - requestedNumberOfCharacters); - updated = true; - } - - const bool getScripts = NO_OPERATION != (GET_SCRIPTS & operations); - const bool validateFonts = NO_OPERATION != (VALIDATE_FONTS & operations); - - Vector& scripts = mModel->mLogicalModel->mScriptRuns; - Vector& validFonts = mModel->mLogicalModel->mFontRuns; - - if(getScripts || validateFonts) - { - // Validates the fonts assigned by the application or assigns default ones. - // It makes sure all the characters are going to be rendered by the correct font. - MultilanguageSupport multilanguageSupport = MultilanguageSupport::Get(); - - if(getScripts) - { - // Retrieves the scripts used in the text. - multilanguageSupport.SetScripts(utf32Characters, - startIndex, - requestedNumberOfCharacters, - scripts); - } - - if(validateFonts) - { - // Validate the fonts set through the mark-up string. - Vector& fontDescriptionRuns = mModel->mLogicalModel->mFontDescriptionRuns; - - // Get the default font's description. - TextAbstraction::FontDescription defaultFontDescription; - TextAbstraction::PointSize26Dot6 defaultPointSize = TextAbstraction::FontClient::DEFAULT_POINT_SIZE * mFontSizeScale; - - //Get the number of points per one unit of point-size - uint32_t numberOfPointsPerOneUnitOfPointSize = mFontClient.GetNumberOfPointsPerOneUnitOfPointSize(); - - if(IsShowingPlaceholderText() && mEventData && (nullptr != mEventData->mPlaceholderFont)) - { - // If the placeholder font is set specifically, only placeholder font is changed. - defaultFontDescription = mEventData->mPlaceholderFont->mFontDescription; - if(mEventData->mPlaceholderFont->sizeDefined) - { - defaultPointSize = mEventData->mPlaceholderFont->mDefaultPointSize * mFontSizeScale * numberOfPointsPerOneUnitOfPointSize; - } - } - else if(nullptr != mFontDefaults) - { - // Set the normal font and the placeholder font. - defaultFontDescription = mFontDefaults->mFontDescription; - - if(mTextFitEnabled) - { - defaultPointSize = mFontDefaults->mFitPointSize * numberOfPointsPerOneUnitOfPointSize; - } - else - { - defaultPointSize = mFontDefaults->mDefaultPointSize * mFontSizeScale * numberOfPointsPerOneUnitOfPointSize; - } - } - - // Validates the fonts. If there is a character with no assigned font it sets a default one. - // After this call, fonts are validated. - multilanguageSupport.ValidateFonts(utf32Characters, - scripts, - fontDescriptionRuns, - defaultFontDescription, - defaultPointSize, - startIndex, - requestedNumberOfCharacters, - validFonts); - } - updated = true; - } - - Vector mirroredUtf32Characters; - bool textMirrored = false; - const Length numberOfParagraphs = mModel->mLogicalModel->mParagraphInfo.Count(); - if(NO_OPERATION != (BIDI_INFO & operations)) - { - Vector& bidirectionalInfo = mModel->mLogicalModel->mBidirectionalParagraphInfo; - bidirectionalInfo.Reserve(numberOfParagraphs); - - // Calculates the bidirectional info for the whole paragraph if it contains right to left scripts. - SetBidirectionalInfo(utf32Characters, - scripts, - lineBreakInfo, - startIndex, - requestedNumberOfCharacters, - bidirectionalInfo, - (mModel->mMatchLayoutDirection != DevelText::MatchLayoutDirection::CONTENTS), - mLayoutDirection); - - if(0u != bidirectionalInfo.Count()) - { - // Only set the character directions if there is right to left characters. - Vector& directions = mModel->mLogicalModel->mCharacterDirections; - GetCharactersDirection(bidirectionalInfo, - numberOfCharacters, - startIndex, - requestedNumberOfCharacters, - directions); - - // This paragraph has right to left text. Some characters may need to be mirrored. - // TODO: consider if the mirrored string can be stored as well. - - textMirrored = GetMirroredText(utf32Characters, - directions, - bidirectionalInfo, - startIndex, - requestedNumberOfCharacters, - mirroredUtf32Characters); - } - else - { - // There is no right to left characters. Clear the directions vector. - mModel->mLogicalModel->mCharacterDirections.Clear(); - } - updated = true; - } - - Vector& glyphs = mModel->mVisualModel->mGlyphs; - Vector& glyphsToCharactersMap = mModel->mVisualModel->mGlyphsToCharacters; - Vector& charactersPerGlyph = mModel->mVisualModel->mCharactersPerGlyph; - Vector newParagraphGlyphs; - newParagraphGlyphs.Reserve(numberOfParagraphs); - - const Length currentNumberOfGlyphs = glyphs.Count(); - if(NO_OPERATION != (SHAPE_TEXT & operations)) - { - const Vector& textToShape = textMirrored ? mirroredUtf32Characters : utf32Characters; - // Shapes the text. - ShapeText(textToShape, - lineBreakInfo, - scripts, - validFonts, - startIndex, - mTextUpdateInfo.mStartGlyphIndex, - requestedNumberOfCharacters, - glyphs, - glyphsToCharactersMap, - charactersPerGlyph, - newParagraphGlyphs); - - // Create the 'number of glyphs' per character and the glyph to character conversion tables. - mModel->mVisualModel->CreateGlyphsPerCharacterTable(startIndex, mTextUpdateInfo.mStartGlyphIndex, requestedNumberOfCharacters); - mModel->mVisualModel->CreateCharacterToGlyphTable(startIndex, mTextUpdateInfo.mStartGlyphIndex, requestedNumberOfCharacters); - - updated = true; - } - - const Length numberOfGlyphs = glyphs.Count() - currentNumberOfGlyphs; - - if(NO_OPERATION != (GET_GLYPH_METRICS & operations)) - { - GlyphInfo* glyphsBuffer = glyphs.Begin(); - mMetrics->GetGlyphMetrics(glyphsBuffer + mTextUpdateInfo.mStartGlyphIndex, numberOfGlyphs); - - // Update the width and advance of all new paragraph characters. - for(Vector::ConstIterator it = newParagraphGlyphs.Begin(), endIt = newParagraphGlyphs.End(); it != endIt; ++it) - { - const GlyphIndex index = *it; - GlyphInfo& glyph = *(glyphsBuffer + index); - - glyph.xBearing = 0.f; - glyph.width = 0.f; - glyph.advance = 0.f; - } - updated = true; - } - - if((nullptr != mEventData) && - mEventData->mPreEditFlag && - (0u != mModel->mVisualModel->mCharactersToGlyph.Count())) - { - Dali::InputMethodContext::PreEditAttributeDataContainer attrs; - mEventData->mInputMethodContext.GetPreeditStyle(attrs); - Dali::InputMethodContext::PreeditStyle type = Dali::InputMethodContext::PreeditStyle::NONE; - - // Check the type of preedit and run it. - for(Dali::InputMethodContext::PreEditAttributeDataContainer::Iterator it = attrs.Begin(), endIt = attrs.End(); it != endIt; it++) - { - Dali::InputMethodContext::PreeditAttributeData attrData = *it; - DALI_LOG_INFO(gLogFilter, Debug::General, "Controller::UpdateModel PreeditStyle type : %d start %d end %d \n", attrData.preeditType, attrData.startIndex, attrData.endIndex); - type = attrData.preeditType; - - // Check the number of commit characters for the start position. - unsigned int numberOfCommit = mEventData->mPrimaryCursorPosition - mEventData->mPreEditLength; - Length numberOfIndices = attrData.endIndex - attrData.startIndex; - - switch(type) - { - case Dali::InputMethodContext::PreeditStyle::UNDERLINE: - { - // Add the underline for the pre-edit text. - GlyphRun underlineRun; - underlineRun.glyphIndex = attrData.startIndex + numberOfCommit; - underlineRun.numberOfGlyphs = numberOfIndices; - mModel->mVisualModel->mUnderlineRuns.PushBack(underlineRun); - - //Mark-up processor case - if(mModel->mVisualModel->IsMarkupProcessorEnabled()) - { - CopyUnderlinedFromLogicalToVisualModels(false); - } - break; - } - case Dali::InputMethodContext::PreeditStyle::REVERSE: - { - Vector4 textColor = mModel->mVisualModel->GetTextColor(); - ColorRun backgroundColorRun; - backgroundColorRun.characterRun.characterIndex = attrData.startIndex + numberOfCommit; - backgroundColorRun.characterRun.numberOfCharacters = numberOfIndices; - backgroundColorRun.color = textColor; - mModel->mLogicalModel->mBackgroundColorRuns.PushBack(backgroundColorRun); - - Vector4 backgroundColor = mModel->mVisualModel->GetBackgroundColor(); - if(backgroundColor.a == 0) // There is no text background color. - { - // Try use the control's background color. - if(nullptr != mEditableControlInterface) - { - mEditableControlInterface->GetControlBackgroundColor(backgroundColor); - if(backgroundColor.a == 0) // There is no control background color. - { - // Determines black or white color according to text color. - // Based on W3C Recommendations (https://www.w3.org/TR/WCAG20/) - float L = CONSTANT_R * textColor.r + CONSTANT_G * textColor.g + CONSTANT_B * textColor.b; - backgroundColor = L > BRIGHTNESS_THRESHOLD ? BLACK : WHITE; - } - } - } - - Vector colorRuns; - colorRuns.Resize(1u); - ColorRun& colorRun = *(colorRuns.Begin()); - colorRun.color = backgroundColor; - colorRun.characterRun.characterIndex = attrData.startIndex + numberOfCommit; - colorRun.characterRun.numberOfCharacters = numberOfIndices; - mModel->mLogicalModel->mColorRuns.PushBack(colorRun); - - //Mark-up processor case - if(mModel->mVisualModel->IsMarkupProcessorEnabled()) - { - CopyUnderlinedFromLogicalToVisualModels(false); - } - break; - } - case Dali::InputMethodContext::PreeditStyle::HIGHLIGHT: - { - ColorRun backgroundColorRun; - backgroundColorRun.characterRun.characterIndex = attrData.startIndex + numberOfCommit; - backgroundColorRun.characterRun.numberOfCharacters = numberOfIndices; - backgroundColorRun.color = LIGHT_BLUE; - mModel->mLogicalModel->mBackgroundColorRuns.PushBack(backgroundColorRun); - - //Mark-up processor case - if(mModel->mVisualModel->IsMarkupProcessorEnabled()) - { - CopyUnderlinedFromLogicalToVisualModels(false); - } - break; - } - case Dali::InputMethodContext::PreeditStyle::CUSTOM_PLATFORM_STYLE_1: - { - // CUSTOM_PLATFORM_STYLE_1 should be drawn with background and underline together. - ColorRun backgroundColorRun; - backgroundColorRun.characterRun.characterIndex = attrData.startIndex + numberOfCommit; - backgroundColorRun.characterRun.numberOfCharacters = numberOfIndices; - backgroundColorRun.color = BACKGROUND_SUB4; - mModel->mLogicalModel->mBackgroundColorRuns.PushBack(backgroundColorRun); - - GlyphRun underlineRun; - underlineRun.glyphIndex = attrData.startIndex + numberOfCommit; - underlineRun.numberOfGlyphs = numberOfIndices; - mModel->mVisualModel->mUnderlineRuns.PushBack(underlineRun); - - //Mark-up processor case - if(mModel->mVisualModel->IsMarkupProcessorEnabled()) - { - CopyUnderlinedFromLogicalToVisualModels(false); - } - break; - } - case Dali::InputMethodContext::PreeditStyle::CUSTOM_PLATFORM_STYLE_2: - { - // CUSTOM_PLATFORM_STYLE_2 should be drawn with background and underline together. - ColorRun backgroundColorRun; - backgroundColorRun.characterRun.characterIndex = attrData.startIndex + numberOfCommit; - backgroundColorRun.characterRun.numberOfCharacters = numberOfIndices; - backgroundColorRun.color = BACKGROUND_SUB5; - mModel->mLogicalModel->mBackgroundColorRuns.PushBack(backgroundColorRun); - - GlyphRun underlineRun; - underlineRun.glyphIndex = attrData.startIndex + numberOfCommit; - underlineRun.numberOfGlyphs = numberOfIndices; - mModel->mVisualModel->mUnderlineRuns.PushBack(underlineRun); - - //Mark-up processor case - if(mModel->mVisualModel->IsMarkupProcessorEnabled()) - { - CopyUnderlinedFromLogicalToVisualModels(false); - } - break; - } - case Dali::InputMethodContext::PreeditStyle::CUSTOM_PLATFORM_STYLE_3: - { - // CUSTOM_PLATFORM_STYLE_3 should be drawn with background and underline together. - ColorRun backgroundColorRun; - backgroundColorRun.characterRun.characterIndex = attrData.startIndex + numberOfCommit; - backgroundColorRun.characterRun.numberOfCharacters = numberOfIndices; - backgroundColorRun.color = BACKGROUND_SUB6; - mModel->mLogicalModel->mBackgroundColorRuns.PushBack(backgroundColorRun); - - GlyphRun underlineRun; - underlineRun.glyphIndex = attrData.startIndex + numberOfCommit; - underlineRun.numberOfGlyphs = numberOfIndices; - mModel->mVisualModel->mUnderlineRuns.PushBack(underlineRun); - - //Mark-up processor case - if(mModel->mVisualModel->IsMarkupProcessorEnabled()) - { - CopyUnderlinedFromLogicalToVisualModels(false); - } - break; - } - case Dali::InputMethodContext::PreeditStyle::CUSTOM_PLATFORM_STYLE_4: - { - // CUSTOM_PLATFORM_STYLE_4 should be drawn with background and underline together. - ColorRun backgroundColorRun; - backgroundColorRun.characterRun.characterIndex = attrData.startIndex + numberOfCommit; - backgroundColorRun.characterRun.numberOfCharacters = numberOfIndices; - backgroundColorRun.color = BACKGROUND_SUB7; - mModel->mLogicalModel->mBackgroundColorRuns.PushBack(backgroundColorRun); - - GlyphRun underlineRun; - underlineRun.glyphIndex = attrData.startIndex + numberOfCommit; - underlineRun.numberOfGlyphs = numberOfIndices; - mModel->mVisualModel->mUnderlineRuns.PushBack(underlineRun); - - //Mark-up processor case - if(mModel->mVisualModel->IsMarkupProcessorEnabled()) - { - CopyUnderlinedFromLogicalToVisualModels(false); - } - break; - } - case Dali::InputMethodContext::PreeditStyle::NONE: - default: - { - break; - } - } - } - attrs.Clear(); - updated = true; - } - - if(NO_OPERATION != (COLOR & operations)) - { - // Set the color runs in glyphs. - SetColorSegmentationInfo(mModel->mLogicalModel->mColorRuns, - mModel->mVisualModel->mCharactersToGlyph, - mModel->mVisualModel->mGlyphsPerCharacter, - startIndex, - mTextUpdateInfo.mStartGlyphIndex, - requestedNumberOfCharacters, - mModel->mVisualModel->mColors, - mModel->mVisualModel->mColorIndices); - - // Set the background color runs in glyphs. - SetColorSegmentationInfo(mModel->mLogicalModel->mBackgroundColorRuns, - mModel->mVisualModel->mCharactersToGlyph, - mModel->mVisualModel->mGlyphsPerCharacter, - startIndex, - mTextUpdateInfo.mStartGlyphIndex, - requestedNumberOfCharacters, - mModel->mVisualModel->mBackgroundColors, - mModel->mVisualModel->mBackgroundColorIndices); - - updated = true; - } - - if((NO_OPERATION != (SHAPE_TEXT & operations)) && - !((nullptr != mEventData) && - mEventData->mPreEditFlag && - (0u != mModel->mVisualModel->mCharactersToGlyph.Count()))) - { - //Mark-up processor case - if(mModel->mVisualModel->IsMarkupProcessorEnabled()) - { - CopyUnderlinedFromLogicalToVisualModels(true); - } - - updated = true; - } - - // The estimated number of lines. Used to avoid reallocations when layouting. - mTextUpdateInfo.mEstimatedNumberOfLines = std::max(mModel->mVisualModel->mLines.Count(), mModel->mLogicalModel->mParagraphInfo.Count()); - - // Set the previous number of characters for the next time the text is updated. - mTextUpdateInfo.mPreviousNumberOfCharacters = numberOfCharacters; - - return updated; + return ControllerImplModelUpdater::Update(*this, operationsRequired); } void Controller::Impl::RetrieveDefaultInputStyle(InputStyle& inputStyle) { - // Sets the default text's color. - inputStyle.textColor = mTextColor; - inputStyle.isDefaultColor = true; - - inputStyle.familyName.clear(); - inputStyle.weight = TextAbstraction::FontWeight::NORMAL; - inputStyle.width = TextAbstraction::FontWidth::NORMAL; - inputStyle.slant = TextAbstraction::FontSlant::NORMAL; - inputStyle.size = 0.f; - - inputStyle.lineSpacing = 0.f; - - inputStyle.underlineProperties.clear(); - inputStyle.shadowProperties.clear(); - inputStyle.embossProperties.clear(); - inputStyle.outlineProperties.clear(); - - inputStyle.isFamilyDefined = false; - inputStyle.isWeightDefined = false; - inputStyle.isWidthDefined = false; - inputStyle.isSlantDefined = false; - inputStyle.isSizeDefined = false; - - inputStyle.isLineSpacingDefined = false; - - inputStyle.isUnderlineDefined = false; - inputStyle.isShadowDefined = false; - inputStyle.isEmbossDefined = false; - inputStyle.isOutlineDefined = false; - - // Sets the default font's family name, weight, width, slant and size. - if(mFontDefaults) - { - if(mFontDefaults->familyDefined) - { - inputStyle.familyName = mFontDefaults->mFontDescription.family; - inputStyle.isFamilyDefined = true; - } - - if(mFontDefaults->weightDefined) - { - inputStyle.weight = mFontDefaults->mFontDescription.weight; - inputStyle.isWeightDefined = true; - } - - if(mFontDefaults->widthDefined) - { - inputStyle.width = mFontDefaults->mFontDescription.width; - inputStyle.isWidthDefined = true; - } - - if(mFontDefaults->slantDefined) - { - inputStyle.slant = mFontDefaults->mFontDescription.slant; - inputStyle.isSlantDefined = true; - } - - if(mFontDefaults->sizeDefined) - { - inputStyle.size = mFontDefaults->mDefaultPointSize; - inputStyle.isSizeDefined = true; - } - } + SetDefaultInputStyle(inputStyle, mFontDefaults, mTextColor); } float Controller::Impl::GetDefaultFontLineHeight() @@ -2125,7 +1586,7 @@ Actor Controller::Impl::CreateBackgroundActor() const Vector2 textSize = mView.GetLayoutSize(); - const float offsetX = textSize.width * 0.5f; + const float offsetX = alignmentOffset + textSize.width * 0.5f; const float offsetY = textSize.height * 0.5f; const Vector4* const backgroundColorsBuffer = mView.GetBackgroundColors(); @@ -2297,8 +1758,4 @@ void Controller::Impl::CopyUnderlinedFromLogicalToVisualModels(bool shouldClearP } } -} // namespace Text - -} // namespace Toolkit - -} // namespace Dali +} // namespace Dali::Toolkit::Text diff --git a/dali-toolkit/internal/text/text-controller-impl.h b/dali-toolkit/internal/text/text-controller-impl.h index 02fbff8..0c6297f 100644 --- a/dali-toolkit/internal/text/text-controller-impl.h +++ b/dali-toolkit/internal/text/text-controller-impl.h @@ -46,6 +46,7 @@ const float DEFAULT_FONT_SIZE_SCALE = 1.f; struct CursorInfo; struct FontDefaults; struct ControllerImplEventHandler; +struct ControllerImplModelUpdater; struct SelectionHandleController; class SelectableControlInterface; @@ -845,6 +846,7 @@ public: private: friend ControllerImplEventHandler; + friend ControllerImplModelUpdater; friend SelectionHandleController; }; diff --git a/dali-toolkit/internal/text/text-controller.cpp b/dali-toolkit/internal/text/text-controller.cpp index 30c6e04..6e4d361 100644 --- a/dali-toolkit/internal/text/text-controller.cpp +++ b/dali-toolkit/internal/text/text-controller.cpp @@ -46,48 +46,76 @@ constexpr float MAX_FLOAT = std::numeric_limits::max(); const std::string EMPTY_STRING(""); -int ConvertPixelToPint(float pixel) +template +void EnsureCreated(Type*& object) { - unsigned int horizontalDpi = 0u; - unsigned int verticalDpi = 0u; - Dali::TextAbstraction::FontClient fontClient = Dali::TextAbstraction::FontClient::Get(); - fontClient.GetDpi(horizontalDpi, verticalDpi); - - return (pixel * 72.f) / static_cast(horizontalDpi); + if(!object) + { + object = new Type(); + } } -} // namespace +template +void EnsureCreated(std::unique_ptr& object) +{ + if(!object) + { + object = std::unique_ptr(new Type()); + } +} -namespace Dali +template +void EnsureCreated(Type*& object, Arg1 arg1) { -namespace Toolkit + if(!object) + { + object = new Type(arg1); + } +} + +template +void EnsureCreated(Type*& object, Arg1 arg1, Arg2 arg2) { -namespace Text + if(!object) + { + object = new Type(arg1, arg2); + } +} + +float GetDpi() { -// public : Constructor. + unsigned int horizontalDpi = 0u; + unsigned int verticalDpi = 0u; + Dali::TextAbstraction::FontClient fontClient = Dali::TextAbstraction::FontClient::Get(); + fontClient.GetDpi(horizontalDpi, verticalDpi); + return static_cast(horizontalDpi); +} -ControllerPtr Controller::New() +float ConvertPixelToPoint(float pixel) { - return ControllerPtr(new Controller()); + return pixel * 72.0f / GetDpi(); } -ControllerPtr Controller::New(ControlInterface* controlInterface) +float ConvertPointToPixel(float point) { - return ControllerPtr(new Controller(controlInterface)); + // Pixel size = Point size * DPI / 72.f + return point * GetDpi() / 72.0f; } -ControllerPtr Controller::New(ControlInterface* controlInterface, - EditableControlInterface* editableControlInterface, - SelectableControlInterface* selectableControlInterface, - AnchorControlInterface* anchorControlInterface) +void UpdateCursorPosition(Dali::Toolkit::Text::EventData* eventData) { - return ControllerPtr(new Controller(controlInterface, - editableControlInterface, - selectableControlInterface, - anchorControlInterface)); + if(eventData && Dali::Toolkit::Text::EventData::IsEditingState(eventData->mState)) + { + // Update the cursor position if it's in editing mode + eventData->mDecoratorUpdated = true; + eventData->mUpdateCursorPosition = true; // Cursor position should be updated when the font size is updated. + } } -// public : Configure the text controller. +} // namespace + +namespace Dali::Toolkit::Text +{ void Controller::EnableTextInput(DecoratorPtr decorator, InputMethodContext& inputMethodContext) { @@ -100,10 +128,7 @@ void Controller::EnableTextInput(DecoratorPtr decorator, InputMethodContext& inp return; } - if(NULL == mImpl->mEventData) - { - mImpl->mEventData = new EventData(decorator, inputMethodContext); - } + EnsureCreated(mImpl->mEventData, decorator, inputMethodContext); } void Controller::SetGlyphType(TextAbstraction::GlyphType glyphType) @@ -147,24 +172,20 @@ void Controller::SetAutoScrollEnabled(bool enable) if(mImpl->mLayoutEngine.GetLayout() == Layout::Engine::SINGLE_LINE_BOX) { + mImpl->mOperationsPending = static_cast(mImpl->mOperationsPending | + LAYOUT | + ALIGN | + UPDATE_LAYOUT_SIZE | + REORDER); + if(enable) { DALI_LOG_INFO(gLogFilter, Debug::General, "Controller::SetAutoScrollEnabled for SINGLE_LINE_BOX\n"); - mImpl->mOperationsPending = static_cast(mImpl->mOperationsPending | - LAYOUT | - ALIGN | - UPDATE_LAYOUT_SIZE | - UPDATE_DIRECTION | - REORDER); + mImpl->mOperationsPending = static_cast(mImpl->mOperationsPending | UPDATE_DIRECTION); } else { DALI_LOG_INFO(gLogFilter, Debug::General, "Controller::SetAutoScrollEnabled Disabling autoscroll\n"); - mImpl->mOperationsPending = static_cast(mImpl->mOperationsPending | - LAYOUT | - ALIGN | - UPDATE_LAYOUT_SIZE | - REORDER); } mImpl->mIsAutoScrollEnabled = enable; @@ -192,62 +213,42 @@ CharacterDirection Controller::GetAutoScrollDirection() const float Controller::GetAutoScrollLineAlignment() const { float offset = 0.f; - - if(mImpl->mModel->mVisualModel && - (0u != mImpl->mModel->mVisualModel->mLines.Count())) + if(mImpl->mModel->mVisualModel && (0u != mImpl->mModel->mVisualModel->mLines.Count())) { offset = (*mImpl->mModel->mVisualModel->mLines.Begin()).alignmentOffset; } - return offset; } void Controller::SetHorizontalScrollEnabled(bool enable) { - if((NULL != mImpl->mEventData) && - mImpl->mEventData->mDecorator) + if(mImpl->mEventData && mImpl->mEventData->mDecorator) { mImpl->mEventData->mDecorator->SetHorizontalScrollEnabled(enable); } } + bool Controller::IsHorizontalScrollEnabled() const { - if((NULL != mImpl->mEventData) && - mImpl->mEventData->mDecorator) - { - return mImpl->mEventData->mDecorator->IsHorizontalScrollEnabled(); - } - - return false; + return mImpl->mEventData && mImpl->mEventData->mDecorator && mImpl->mEventData->mDecorator->IsHorizontalScrollEnabled(); } void Controller::SetVerticalScrollEnabled(bool enable) { - if((NULL != mImpl->mEventData) && - mImpl->mEventData->mDecorator) + if(mImpl->mEventData && mImpl->mEventData->mDecorator) { - if(mImpl->mEventData->mDecorator) - { - mImpl->mEventData->mDecorator->SetVerticalScrollEnabled(enable); - } + mImpl->mEventData->mDecorator->SetVerticalScrollEnabled(enable); } } bool Controller::IsVerticalScrollEnabled() const { - if((NULL != mImpl->mEventData) && - mImpl->mEventData->mDecorator) - { - return mImpl->mEventData->mDecorator->IsVerticalScrollEnabled(); - } - - return false; + return mImpl->mEventData && mImpl->mEventData->mDecorator && mImpl->mEventData->mDecorator->IsVerticalScrollEnabled(); } void Controller::SetSmoothHandlePanEnabled(bool enable) { - if((NULL != mImpl->mEventData) && - mImpl->mEventData->mDecorator) + if(mImpl->mEventData && mImpl->mEventData->mDecorator) { mImpl->mEventData->mDecorator->SetSmoothHandlePanEnabled(enable); } @@ -255,13 +256,7 @@ void Controller::SetSmoothHandlePanEnabled(bool enable) bool Controller::IsSmoothHandlePanEnabled() const { - if((NULL != mImpl->mEventData) && - mImpl->mEventData->mDecorator) - { - return mImpl->mEventData->mDecorator->IsSmoothHandlePanEnabled(); - } - - return false; + return mImpl->mEventData && mImpl->mEventData->mDecorator && mImpl->mEventData->mDecorator->IsSmoothHandlePanEnabled(); } void Controller::SetMaximumNumberOfCharacters(Length maxCharacters) @@ -278,12 +273,11 @@ void Controller::SetEnableCursorBlink(bool enable) { DALI_ASSERT_DEBUG(NULL != mImpl->mEventData && "TextInput disabled"); - if(NULL != mImpl->mEventData) + if(mImpl->mEventData) { mImpl->mEventData->mCursorBlinkEnabled = enable; - if(!enable && - mImpl->mEventData->mDecorator) + if(!enable && mImpl->mEventData->mDecorator) { mImpl->mEventData->mDecorator->StopCursorBlink(); } @@ -292,12 +286,7 @@ void Controller::SetEnableCursorBlink(bool enable) bool Controller::GetEnableCursorBlink() const { - if(NULL != mImpl->mEventData) - { - return mImpl->mEventData->mCursorBlinkEnabled; - } - - return false; + return mImpl->mEventData && mImpl->mEventData->mCursorBlinkEnabled; } void Controller::SetMultiLineEnabled(bool enable) @@ -367,9 +356,7 @@ void Controller::SetVerticalAlignment(VerticalAlignment::Type alignment) { // Set the alignment. mImpl->mModel->mVerticalAlignment = alignment; - mImpl->mOperationsPending = static_cast(mImpl->mOperationsPending | ALIGN); - mImpl->RequestRelayout(); } } @@ -484,19 +471,7 @@ bool Controller::IsTextFitEnabled() const void Controller::SetTextFitMinSize(float minSize, FontSizeType type) { - switch(type) - { - case POINT_SIZE: - { - mImpl->mTextFitMinSize = minSize; - break; - } - case PIXEL_SIZE: - { - mImpl->mTextFitMinSize = ConvertPixelToPint(minSize); - break; - } - } + mImpl->mTextFitMinSize = (type == POINT_SIZE) ? minSize : ConvertPixelToPoint(minSize); } float Controller::GetTextFitMinSize() const @@ -506,19 +481,7 @@ float Controller::GetTextFitMinSize() const void Controller::SetTextFitMaxSize(float maxSize, FontSizeType type) { - switch(type) - { - case POINT_SIZE: - { - mImpl->mTextFitMaxSize = maxSize; - break; - } - case PIXEL_SIZE: - { - mImpl->mTextFitMaxSize = ConvertPixelToPint(maxSize); - break; - } - } + mImpl->mTextFitMaxSize = (type == POINT_SIZE) ? maxSize : ConvertPixelToPoint(maxSize); } float Controller::GetTextFitMaxSize() const @@ -528,19 +491,7 @@ float Controller::GetTextFitMaxSize() const void Controller::SetTextFitStepSize(float step, FontSizeType type) { - switch(type) - { - case POINT_SIZE: - { - mImpl->mTextFitStepSize = step; - break; - } - case PIXEL_SIZE: - { - mImpl->mTextFitStepSize = ConvertPixelToPint(step); - break; - } - } + mImpl->mTextFitStepSize = (type == POINT_SIZE) ? step : ConvertPixelToPoint(step); } float Controller::GetTextFitStepSize() const @@ -608,8 +559,6 @@ bool Controller::IsGrabHandlePopupEnabled() const return mImpl->mEventData->mGrabHandlePopupEnabled; } -// public : Update - void Controller::SetText(const std::string& text) { TextUpdater::SetText(*this, text); @@ -678,28 +627,16 @@ void Controller::SendSelectionToClipboard(bool deleteAfterSending) mImpl->SendSelectionToClipboard(deleteAfterSending); } -// public : Default style & Input style - void Controller::SetDefaultFontFamily(const std::string& defaultFontFamily) { - if(NULL == mImpl->mFontDefaults) - { - mImpl->mFontDefaults = new FontDefaults(); - } + EnsureCreated(mImpl->mFontDefaults); mImpl->mFontDefaults->mFontDescription.family = defaultFontFamily; DALI_LOG_INFO(gLogFilter, Debug::General, "Controller::SetDefaultFontFamily %s\n", defaultFontFamily.c_str()); mImpl->mFontDefaults->familyDefined = !defaultFontFamily.empty(); - if(mImpl->mEventData) - { - // Update the cursor position if it's in editing mode - if(EventData::IsEditingState(mImpl->mEventData->mState)) - { - mImpl->mEventData->mDecoratorUpdated = true; - mImpl->mEventData->mUpdateCursorPosition = true; // Cursor position should be updated when the font family is updated. - } - } + // Update the cursor position if it's in editing mode + UpdateCursorPosition(mImpl->mEventData); // Clear the font-specific data ClearFontData(); @@ -709,12 +646,7 @@ void Controller::SetDefaultFontFamily(const std::string& defaultFontFamily) const std::string& Controller::GetDefaultFontFamily() const { - if(NULL != mImpl->mFontDefaults) - { - return mImpl->mFontDefaults->mFontDescription.family; - } - - return EMPTY_STRING; + return mImpl->mFontDefaults ? mImpl->mFontDefaults->mFontDescription.family : EMPTY_STRING; } void Controller::SetPlaceholderFontFamily(const std::string& placeholderTextFontFamily) @@ -729,23 +661,13 @@ const std::string& Controller::GetPlaceholderFontFamily() const void Controller::SetDefaultFontWeight(FontWeight weight) { - if(NULL == mImpl->mFontDefaults) - { - mImpl->mFontDefaults = new FontDefaults(); - } + EnsureCreated(mImpl->mFontDefaults); mImpl->mFontDefaults->mFontDescription.weight = weight; mImpl->mFontDefaults->weightDefined = true; - if(mImpl->mEventData) - { - // Update the cursor position if it's in editing mode - if(EventData::IsEditingState(mImpl->mEventData->mState)) - { - mImpl->mEventData->mDecoratorUpdated = true; - mImpl->mEventData->mUpdateCursorPosition = true; // Cursor position should be updated when the font weight is updated. - } - } + // Update the cursor position if it's in editing mode + UpdateCursorPosition(mImpl->mEventData); // Clear the font-specific data ClearFontData(); @@ -755,22 +677,12 @@ void Controller::SetDefaultFontWeight(FontWeight weight) bool Controller::IsDefaultFontWeightDefined() const { - if(NULL != mImpl->mFontDefaults) - { - return mImpl->mFontDefaults->weightDefined; - } - - return false; + return mImpl->mFontDefaults && mImpl->mFontDefaults->weightDefined; } FontWeight Controller::GetDefaultFontWeight() const { - if(NULL != mImpl->mFontDefaults) - { - return mImpl->mFontDefaults->mFontDescription.weight; - } - - return TextAbstraction::FontWeight::NORMAL; + return mImpl->mFontDefaults ? mImpl->mFontDefaults->mFontDescription.weight : TextAbstraction::FontWeight::NORMAL; } void Controller::SetPlaceholderTextFontWeight(FontWeight weight) @@ -781,7 +693,6 @@ void Controller::SetPlaceholderTextFontWeight(FontWeight weight) bool Controller::IsPlaceholderTextFontWeightDefined() const { return PlaceholderHandler::IsPlaceholderTextFontWeightDefined(*this); - ; } FontWeight Controller::GetPlaceholderTextFontWeight() const @@ -791,23 +702,13 @@ FontWeight Controller::GetPlaceholderTextFontWeight() const void Controller::SetDefaultFontWidth(FontWidth width) { - if(NULL == mImpl->mFontDefaults) - { - mImpl->mFontDefaults = new FontDefaults(); - } + EnsureCreated(mImpl->mFontDefaults); mImpl->mFontDefaults->mFontDescription.width = width; mImpl->mFontDefaults->widthDefined = true; - if(mImpl->mEventData) - { - // Update the cursor position if it's in editing mode - if(EventData::IsEditingState(mImpl->mEventData->mState)) - { - mImpl->mEventData->mDecoratorUpdated = true; - mImpl->mEventData->mUpdateCursorPosition = true; // Cursor position should be updated when the font width is updated. - } - } + // Update the cursor position if it's in editing mode + UpdateCursorPosition(mImpl->mEventData); // Clear the font-specific data ClearFontData(); @@ -817,22 +718,12 @@ void Controller::SetDefaultFontWidth(FontWidth width) bool Controller::IsDefaultFontWidthDefined() const { - if(NULL != mImpl->mFontDefaults) - { - return mImpl->mFontDefaults->widthDefined; - } - - return false; + return mImpl->mFontDefaults && mImpl->mFontDefaults->widthDefined; } FontWidth Controller::GetDefaultFontWidth() const { - if(NULL != mImpl->mFontDefaults) - { - return mImpl->mFontDefaults->mFontDescription.width; - } - - return TextAbstraction::FontWidth::NORMAL; + return mImpl->mFontDefaults ? mImpl->mFontDefaults->mFontDescription.width : TextAbstraction::FontWidth::NORMAL; } void Controller::SetPlaceholderTextFontWidth(FontWidth width) @@ -852,23 +743,13 @@ FontWidth Controller::GetPlaceholderTextFontWidth() const void Controller::SetDefaultFontSlant(FontSlant slant) { - if(NULL == mImpl->mFontDefaults) - { - mImpl->mFontDefaults = new FontDefaults(); - } + EnsureCreated(mImpl->mFontDefaults); mImpl->mFontDefaults->mFontDescription.slant = slant; mImpl->mFontDefaults->slantDefined = true; - if(mImpl->mEventData) - { - // Update the cursor position if it's in editing mode - if(EventData::IsEditingState(mImpl->mEventData->mState)) - { - mImpl->mEventData->mDecoratorUpdated = true; - mImpl->mEventData->mUpdateCursorPosition = true; // Cursor position should be updated when the font slant is updated. - } - } + // Update the cursor position if it's in editing mode + UpdateCursorPosition(mImpl->mEventData); // Clear the font-specific data ClearFontData(); @@ -878,21 +759,12 @@ void Controller::SetDefaultFontSlant(FontSlant slant) bool Controller::IsDefaultFontSlantDefined() const { - if(NULL != mImpl->mFontDefaults) - { - return mImpl->mFontDefaults->slantDefined; - } - return false; + return mImpl->mFontDefaults && mImpl->mFontDefaults->slantDefined; } FontSlant Controller::GetDefaultFontSlant() const { - if(NULL != mImpl->mFontDefaults) - { - return mImpl->mFontDefaults->mFontDescription.slant; - } - - return TextAbstraction::FontSlant::NORMAL; + return mImpl->mFontDefaults ? mImpl->mFontDefaults->mFontDescription.slant : TextAbstraction::FontSlant::NORMAL; } void Controller::SetPlaceholderTextFontSlant(FontSlant slant) @@ -914,15 +786,8 @@ void Controller::SetFontSizeScale(float scale) { mImpl->mFontSizeScale = scale; - if(mImpl->mEventData) - { - // Update the cursor position if it's in editing mode - if(EventData::IsEditingState(mImpl->mEventData->mState)) - { - mImpl->mEventData->mDecoratorUpdated = true; - mImpl->mEventData->mUpdateCursorPosition = true; // Cursor position should be updated when the font size is updated. - } - } + // Update the cursor position if it's in editing mode + UpdateCursorPosition(mImpl->mEventData); // Clear the font-specific data ClearFontData(); @@ -932,52 +797,18 @@ void Controller::SetFontSizeScale(float scale) float Controller::GetFontSizeScale() const { - if(nullptr != mImpl->mFontDefaults) - { - return mImpl->mFontSizeScale; - } - - return 1.f; + return mImpl->mFontDefaults ? mImpl->mFontSizeScale : 1.0f; } void Controller::SetDefaultFontSize(float fontSize, FontSizeType type) { - if(NULL == mImpl->mFontDefaults) - { - mImpl->mFontDefaults = new FontDefaults(); - } + EnsureCreated(mImpl->mFontDefaults); - switch(type) - { - case POINT_SIZE: - { - mImpl->mFontDefaults->mDefaultPointSize = fontSize; - mImpl->mFontDefaults->sizeDefined = true; - break; - } - case PIXEL_SIZE: - { - // Point size = Pixel size * 72.f / DPI - unsigned int horizontalDpi = 0u; - unsigned int verticalDpi = 0u; - TextAbstraction::FontClient fontClient = TextAbstraction::FontClient::Get(); - fontClient.GetDpi(horizontalDpi, verticalDpi); - - mImpl->mFontDefaults->mDefaultPointSize = (fontSize * 72.f) / static_cast(horizontalDpi); - mImpl->mFontDefaults->sizeDefined = true; - break; - } - } + mImpl->mFontDefaults->mDefaultPointSize = (type == POINT_SIZE) ? fontSize : ConvertPixelToPoint(fontSize); + mImpl->mFontDefaults->sizeDefined = true; - if(mImpl->mEventData) - { - // Update the cursor position if it's in editing mode - if(EventData::IsEditingState(mImpl->mEventData->mState)) - { - mImpl->mEventData->mDecoratorUpdated = true; - mImpl->mEventData->mUpdateCursorPosition = true; // Cursor position should be updated when the font size is updated. - } - } + // Update the cursor position if it's in editing mode + UpdateCursorPosition(mImpl->mEventData); // Clear the font-specific data ClearFontData(); @@ -987,32 +818,11 @@ void Controller::SetDefaultFontSize(float fontSize, FontSizeType type) float Controller::GetDefaultFontSize(FontSizeType type) const { - float value = 0.0f; - if(NULL != mImpl->mFontDefaults) + if(mImpl->mFontDefaults) { - switch(type) - { - case POINT_SIZE: - { - value = mImpl->mFontDefaults->mDefaultPointSize; - break; - } - case PIXEL_SIZE: - { - // Pixel size = Point size * DPI / 72.f - unsigned int horizontalDpi = 0u; - unsigned int verticalDpi = 0u; - TextAbstraction::FontClient fontClient = TextAbstraction::FontClient::Get(); - fontClient.GetDpi(horizontalDpi, verticalDpi); - - value = mImpl->mFontDefaults->mDefaultPointSize * static_cast(horizontalDpi) / 72.f; - break; - } - } - return value; + return (type == POINT_SIZE) ? mImpl->mFontDefaults->mDefaultPointSize : ConvertPointToPixel(mImpl->mFontDefaults->mDefaultPointSize); } - - return value; + return 0.0f; } void Controller::SetPlaceholderTextFontSize(float fontSize, FontSizeType type) @@ -1032,11 +842,8 @@ void Controller::SetDefaultColor(const Vector4& color) if(!mImpl->IsShowingPlaceholderText()) { mImpl->mModel->mVisualModel->SetTextColor(color); - mImpl->mModel->mLogicalModel->mColorRuns.Clear(); - mImpl->mOperationsPending = static_cast(mImpl->mOperationsPending | COLOR); - mImpl->RequestRelayout(); } } @@ -1059,7 +866,6 @@ const Vector4& Controller::GetPlaceholderTextColor() const void Controller::SetShadowOffset(const Vector2& shadowOffset) { mImpl->mModel->mVisualModel->SetShadowOffset(shadowOffset); - mImpl->RequestRelayout(); } @@ -1071,7 +877,6 @@ const Vector2& Controller::GetShadowOffset() const void Controller::SetShadowColor(const Vector4& shadowColor) { mImpl->mModel->mVisualModel->SetShadowColor(shadowColor); - mImpl->RequestRelayout(); } @@ -1085,7 +890,6 @@ void Controller::SetShadowBlurRadius(const float& shadowBlurRadius) if(fabsf(GetShadowBlurRadius() - shadowBlurRadius) > Math::MACHINE_EPSILON_1) { mImpl->mModel->mVisualModel->SetShadowBlurRadius(shadowBlurRadius); - mImpl->RequestRelayout(); } } @@ -1098,7 +902,6 @@ const float& Controller::GetShadowBlurRadius() const void Controller::SetUnderlineColor(const Vector4& color) { mImpl->mModel->mVisualModel->SetUnderlineColor(color); - mImpl->RequestRelayout(); } @@ -1110,7 +913,6 @@ const Vector4& Controller::GetUnderlineColor() const void Controller::SetUnderlineEnabled(bool enabled) { mImpl->mModel->mVisualModel->SetUnderlineEnabled(enabled); - mImpl->RequestRelayout(); } @@ -1122,7 +924,6 @@ bool Controller::IsUnderlineEnabled() const void Controller::SetUnderlineHeight(float height) { mImpl->mModel->mVisualModel->SetUnderlineHeight(height); - mImpl->RequestRelayout(); } @@ -1134,7 +935,6 @@ float Controller::GetUnderlineHeight() const void Controller::SetOutlineColor(const Vector4& color) { mImpl->mModel->mVisualModel->SetOutlineColor(color); - mImpl->RequestRelayout(); } @@ -1146,7 +946,6 @@ const Vector4& Controller::GetOutlineColor() const void Controller::SetOutlineWidth(uint16_t width) { mImpl->mModel->mVisualModel->SetOutlineWidth(width); - mImpl->RequestRelayout(); } @@ -1158,7 +957,6 @@ uint16_t Controller::GetOutlineWidth() const void Controller::SetBackgroundColor(const Vector4& color) { mImpl->mModel->mVisualModel->SetBackgroundColor(color); - mImpl->RequestRelayout(); } @@ -1170,7 +968,6 @@ const Vector4& Controller::GetBackgroundColor() const void Controller::SetBackgroundEnabled(bool enabled) { mImpl->mModel->mVisualModel->SetBackgroundEnabled(enabled); - mImpl->RequestRelayout(); } @@ -1181,42 +978,24 @@ bool Controller::IsBackgroundEnabled() const void Controller::SetDefaultEmbossProperties(const std::string& embossProperties) { - if(NULL == mImpl->mEmbossDefaults) - { - mImpl->mEmbossDefaults = new EmbossDefaults(); - } - + EnsureCreated(mImpl->mEmbossDefaults); mImpl->mEmbossDefaults->properties = embossProperties; } const std::string& Controller::GetDefaultEmbossProperties() const { - if(NULL != mImpl->mEmbossDefaults) - { - return mImpl->mEmbossDefaults->properties; - } - - return EMPTY_STRING; + return mImpl->mEmbossDefaults ? mImpl->mEmbossDefaults->properties : EMPTY_STRING; } void Controller::SetDefaultOutlineProperties(const std::string& outlineProperties) { - if(NULL == mImpl->mOutlineDefaults) - { - mImpl->mOutlineDefaults = new OutlineDefaults(); - } - + EnsureCreated(mImpl->mOutlineDefaults); mImpl->mOutlineDefaults->properties = outlineProperties; } const std::string& Controller::GetDefaultOutlineProperties() const { - if(NULL != mImpl->mOutlineDefaults) - { - return mImpl->mOutlineDefaults->properties; - } - - return EMPTY_STRING; + return mImpl->mOutlineDefaults ? mImpl->mOutlineDefaults->properties : EMPTY_STRING; } void Controller::RelayoutForNewLineSize() @@ -1228,7 +1007,7 @@ void Controller::RelayoutForNewLineSize() mImpl->mOperationsPending = static_cast(mImpl->mOperationsPending | LAYOUT); //remove selection - if((mImpl->mEventData != nullptr) && (mImpl->mEventData->mState == EventData::SELECTING)) + if(mImpl->mEventData && mImpl->mEventData->mState == EventData::SELECTING) { mImpl->ChangeState(EventData::EDITING); } @@ -1274,7 +1053,7 @@ float Controller::GetDefaultLineSize() const void Controller::SetInputColor(const Vector4& color) { - if(NULL != mImpl->mEventData) + if(mImpl->mEventData) { mImpl->mEventData->mInputStyle.textColor = color; mImpl->mEventData->mInputStyle.isDefaultColor = false; @@ -1318,13 +1097,8 @@ void Controller::SetInputColor(const Vector4& color) const Vector4& Controller::GetInputColor() const { - if(NULL != mImpl->mEventData) - { - return mImpl->mEventData->mInputStyle.textColor; - } - - // Return the default text's color if there is no EventData. - return mImpl->mTextColor; + // Return event text input color if we have it, otherwise just return the default text's color + return mImpl->mEventData ? mImpl->mEventData->mInputStyle.textColor : mImpl->mTextColor; } void Controller::SetInputFontFamily(const std::string& fontFamily) @@ -1394,7 +1168,7 @@ float Controller::GetInputFontPointSize() const void Controller::SetInputLineSpacing(float lineSpacing) { - if(NULL != mImpl->mEventData) + if(mImpl->mEventData) { mImpl->mEventData->mInputStyle.lineSpacing = lineSpacing; mImpl->mEventData->mInputStyle.isLineSpacingDefined = true; @@ -1403,17 +1177,12 @@ void Controller::SetInputLineSpacing(float lineSpacing) float Controller::GetInputLineSpacing() const { - if(NULL != mImpl->mEventData) - { - return mImpl->mEventData->mInputStyle.lineSpacing; - } - - return 0.f; + return mImpl->mEventData ? mImpl->mEventData->mInputStyle.lineSpacing : 0.0f; } void Controller::SetInputShadowProperties(const std::string& shadowProperties) { - if(NULL != mImpl->mEventData) + if(mImpl->mEventData) { mImpl->mEventData->mInputStyle.shadowProperties = shadowProperties; } @@ -1421,17 +1190,12 @@ void Controller::SetInputShadowProperties(const std::string& shadowProperties) const std::string& Controller::GetInputShadowProperties() const { - if(NULL != mImpl->mEventData) - { - return mImpl->mEventData->mInputStyle.shadowProperties; - } - - return EMPTY_STRING; + return mImpl->mEventData ? mImpl->mEventData->mInputStyle.shadowProperties : EMPTY_STRING; } void Controller::SetInputUnderlineProperties(const std::string& underlineProperties) { - if(NULL != mImpl->mEventData) + if(mImpl->mEventData) { mImpl->mEventData->mInputStyle.underlineProperties = underlineProperties; } @@ -1439,17 +1203,12 @@ void Controller::SetInputUnderlineProperties(const std::string& underlinePropert const std::string& Controller::GetInputUnderlineProperties() const { - if(NULL != mImpl->mEventData) - { - return mImpl->mEventData->mInputStyle.underlineProperties; - } - - return EMPTY_STRING; + return mImpl->mEventData ? mImpl->mEventData->mInputStyle.underlineProperties : EMPTY_STRING; } void Controller::SetInputEmbossProperties(const std::string& embossProperties) { - if(NULL != mImpl->mEventData) + if(mImpl->mEventData) { mImpl->mEventData->mInputStyle.embossProperties = embossProperties; } @@ -1457,17 +1216,12 @@ void Controller::SetInputEmbossProperties(const std::string& embossProperties) const std::string& Controller::GetInputEmbossProperties() const { - if(NULL != mImpl->mEventData) - { - return mImpl->mEventData->mInputStyle.embossProperties; - } - - return GetDefaultEmbossProperties(); + return mImpl->mEventData ? mImpl->mEventData->mInputStyle.embossProperties : GetDefaultEmbossProperties(); } void Controller::SetInputOutlineProperties(const std::string& outlineProperties) { - if(NULL != mImpl->mEventData) + if(mImpl->mEventData) { mImpl->mEventData->mInputStyle.outlineProperties = outlineProperties; } @@ -1475,17 +1229,12 @@ void Controller::SetInputOutlineProperties(const std::string& outlineProperties) const std::string& Controller::GetInputOutlineProperties() const { - if(NULL != mImpl->mEventData) - { - return mImpl->mEventData->mInputStyle.outlineProperties; - } - - return GetDefaultOutlineProperties(); + return mImpl->mEventData ? mImpl->mEventData->mInputStyle.outlineProperties : GetDefaultOutlineProperties(); } void Controller::SetInputModePassword(bool passwordInput) { - if(NULL != mImpl->mEventData) + if(mImpl->mEventData) { mImpl->mEventData->mPasswordInput = passwordInput; } @@ -1493,16 +1242,12 @@ void Controller::SetInputModePassword(bool passwordInput) bool Controller::IsInputModePassword() { - if(NULL != mImpl->mEventData) - { - return mImpl->mEventData->mPasswordInput; - } - return false; + return mImpl->mEventData && mImpl->mEventData->mPasswordInput; } void Controller::SetNoTextDoubleTapAction(NoTextTap::Action action) { - if(NULL != mImpl->mEventData) + if(mImpl->mEventData) { mImpl->mEventData->mDoubleTapAction = action; } @@ -1510,19 +1255,12 @@ void Controller::SetNoTextDoubleTapAction(NoTextTap::Action action) Controller::NoTextTap::Action Controller::GetNoTextDoubleTapAction() const { - NoTextTap::Action action = NoTextTap::NO_ACTION; - - if(NULL != mImpl->mEventData) - { - action = mImpl->mEventData->mDoubleTapAction; - } - - return action; + return mImpl->mEventData ? mImpl->mEventData->mDoubleTapAction : NoTextTap::NO_ACTION; } void Controller::SetNoTextLongPressAction(NoTextTap::Action action) { - if(NULL != mImpl->mEventData) + if(mImpl->mEventData) { mImpl->mEventData->mLongPressAction = action; } @@ -1530,14 +1268,7 @@ void Controller::SetNoTextLongPressAction(NoTextTap::Action action) Controller::NoTextTap::Action Controller::GetNoTextLongPressAction() const { - NoTextTap::Action action = NoTextTap::NO_ACTION; - - if(NULL != mImpl->mEventData) - { - action = mImpl->mEventData->mLongPressAction; - } - - return action; + return mImpl->mEventData ? mImpl->mEventData->mLongPressAction : NoTextTap::NO_ACTION; } bool Controller::IsUnderlineSetByString() @@ -1580,8 +1311,6 @@ void Controller::FontStyleSetByString(bool setByString) mImpl->mFontStyleSetByString = setByString; } -// public : Queries & retrieves. - Layout::Engine& Controller::GetLayoutEngine() { return mImpl->mLayoutEngine; @@ -1615,8 +1344,7 @@ float Controller::GetHeightForWidth(float width) int Controller::GetLineCount(float width) { GetHeightForWidth(width); - int numberofLines = mImpl->mModel->GetNumberOfLines(); - return numberofLines; + return mImpl->mModel->GetNumberOfLines(); } const ModelInterface* const Controller::GetTextModel() const @@ -1650,16 +1378,13 @@ bool Controller::GetTextScrollInfo(float& scrollPosition, float& controlHeight, void Controller::SetHiddenInputOption(const Property::Map& options) { - if(NULL == mImpl->mHiddenInput) - { - mImpl->mHiddenInput = new HiddenText(this); - } + EnsureCreated(mImpl->mHiddenInput, this); mImpl->mHiddenInput->SetProperties(options); } void Controller::GetHiddenInputOption(Property::Map& options) { - if(NULL != mImpl->mHiddenInput) + if(mImpl->mHiddenInput) { mImpl->mHiddenInput->GetProperties(options); } @@ -1667,16 +1392,13 @@ void Controller::GetHiddenInputOption(Property::Map& options) void Controller::SetInputFilterOption(const Property::Map& options) { - if(!mImpl->mInputFilter) - { - mImpl->mInputFilter = std::unique_ptr(new InputFilter()); - } + EnsureCreated(mImpl->mInputFilter); mImpl->mInputFilter->SetProperties(options); } void Controller::GetInputFilterOption(Property::Map& options) { - if(NULL != mImpl->mInputFilter) + if(mImpl->mInputFilter) { mImpl->mInputFilter->GetProperties(options); } @@ -1757,8 +1479,6 @@ void Controller::SetEllipsisPosition(Toolkit::DevelText::EllipsisPosition::Type mImpl->mModel->mVisualModel->SetEllipsisPosition(ellipsisPosition); } -// public : Relayout. - Controller::UpdateTextType Controller::Relayout(const Size& size, Dali::LayoutDirection::Type layoutDirection) { return Relayouter::Relayout(*this, size, layoutDirection); @@ -1769,8 +1489,6 @@ void Controller::RequestRelayout() mImpl->RequestRelayout(); } -// public : Input style change signals. - bool Controller::IsInputStyleChangedSignalsQueueEmpty() { return (NULL == mImpl->mEventData) || (0u == mImpl->mEventData->mInputStyleChangedQueue.Count()); @@ -1778,31 +1496,20 @@ bool Controller::IsInputStyleChangedSignalsQueueEmpty() void Controller::ProcessInputStyleChangedSignals() { - if(NULL == mImpl->mEventData) - { - // Nothing to do. - return; - } - - for(Vector::ConstIterator it = mImpl->mEventData->mInputStyleChangedQueue.Begin(), - endIt = mImpl->mEventData->mInputStyleChangedQueue.End(); - it != endIt; - ++it) + if(mImpl->mEventData) { - const InputStyle::Mask mask = *it; - - if(NULL != mImpl->mEditableControlInterface) + if(mImpl->mEditableControlInterface) { - // Emit the input style changed signal. - mImpl->mEditableControlInterface->InputStyleChanged(mask); + // Emit the input style changed signal for each mask + std::for_each(mImpl->mEventData->mInputStyleChangedQueue.begin(), + mImpl->mEventData->mInputStyleChangedQueue.end(), + [&](const auto mask) { mImpl->mEditableControlInterface->InputStyleChanged(mask); } ); } - } - mImpl->mEventData->mInputStyleChangedQueue.Clear(); + mImpl->mEventData->mInputStyleChangedQueue.Clear(); + } } -// public : Text-input Event Queuing. - void Controller::KeyboardFocusGainEvent() { EventHandler::KeyboardFocusGainEvent(*this); @@ -1933,7 +1640,7 @@ string Controller::CutText() if(!IsEditable()) { - return ""; + return EMPTY_STRING; } mImpl->SendSelectionToClipboard(true); // Synchronous call to modify text @@ -1976,8 +1683,6 @@ void Controller::PasteClipboardItemEvent() EventHandler::PasteClipboardItemEvent(*this); } -// protected : Inherit from Text::Decorator::ControllerInterface. - void Controller::GetTargetSize(Vector2& targetSize) { targetSize = mImpl->mModel->mVisualModel->mControlSize; @@ -1985,7 +1690,7 @@ void Controller::GetTargetSize(Vector2& targetSize) void Controller::AddDecoration(Actor& actor, bool needsClipping) { - if(NULL != mImpl->mEditableControlInterface) + if(mImpl->mEditableControlInterface) { mImpl->mEditableControlInterface->AddDecoration(actor, needsClipping); } @@ -2037,22 +1742,14 @@ void Controller::ScrollBy(Vector2 scroll) float Controller::GetHorizontalScrollPosition() { - if(mImpl->mEventData) - { - //scroll values are negative internally so we convert them to positive numbers - return -mImpl->mModel->mScrollPosition.x; - } - return 0; + // Scroll values are negative internally so we convert them to positive numbers + return mImpl->mEventData ? -mImpl->mModel->mScrollPosition.x : 0.0f; } float Controller::GetVerticalScrollPosition() { - if(mImpl->mEventData) - { - //scroll values are negative internally so we convert them to positive numbers - return -mImpl->mModel->mScrollPosition.y; - } - return 0; + // Scroll values are negative internally so we convert them to positive numbers + return mImpl->mEventData ? -mImpl->mModel->mScrollPosition.y : 0.0f; } void Controller::DecorationEvent(HandleType handleType, HandleState state, float x, float y) @@ -2060,8 +1757,6 @@ void Controller::DecorationEvent(HandleType handleType, HandleState state, float EventHandler::DecorationEvent(*this, handleType, state, x, y); } -// protected : Inherit from TextSelectionPopup::TextPopupButtonCallbackInterface. - void Controller::TextPopupButtonTouched(Dali::Toolkit::TextSelectionPopup::Buttons button) { EventHandler::TextPopupButtonTouched(*this, button); @@ -2076,8 +1771,6 @@ void Controller::DisplayTimeExpired() mImpl->RequestRelayout(); } -// private : Update. - void Controller::InsertText(const std::string& text, Controller::InsertType type) { TextUpdater::InsertText(*this, text, type); @@ -2088,9 +1781,7 @@ void Controller::PasteText(const std::string& stringToPaste) TextUpdater::PasteText(*this, stringToPaste); } -bool Controller::RemoveText(int cursorOffset, - int numberOfCharacters, - UpdateInputStyleType type) +bool Controller::RemoveText(int cursorOffset, int numberOfCharacters, UpdateInputStyleType type) { return TextUpdater::RemoveText(*this, cursorOffset, numberOfCharacters, type); } @@ -2100,24 +1791,17 @@ bool Controller::RemoveSelectedText() return TextUpdater::RemoveSelectedText(*this); } -void Controller::InsertTextAnchor(int numberOfCharacters, - CharacterIndex previousCursorIndex) +void Controller::InsertTextAnchor(int numberOfCharacters, CharacterIndex previousCursorIndex) { TextUpdater::InsertTextAnchor(*this, numberOfCharacters, previousCursorIndex); } -void Controller::RemoveTextAnchor(int cursorOffset, - int numberOfCharacters, - CharacterIndex previousCursorIndex) +void Controller::RemoveTextAnchor(int cursorOffset, int numberOfCharacters, CharacterIndex previousCursorIndex) { TextUpdater::RemoveTextAnchor(*this, cursorOffset, numberOfCharacters, previousCursorIndex); } -// private : Relayout. - -bool Controller::DoRelayout(const Size& size, - OperationsMask operationsRequired, - Size& layoutSize) +bool Controller::DoRelayout(const Size& size, OperationsMask operationsRequired, Size& layoutSize) { return Relayouter::DoRelayout(*this, size, operationsRequired, layoutSize); } @@ -2127,8 +1811,6 @@ void Controller::CalculateVerticalOffset(const Size& controlSize) Relayouter::CalculateVerticalOffset(*this, controlSize); } -// private : Events. - void Controller::ProcessModifyEvents() { EventHandler::ProcessModifyEvents(*this); @@ -2224,7 +1906,7 @@ CharacterIndex Controller::GetCursorPosition() void Controller::ResetScrollPosition() { - if(NULL != mImpl->mEventData) + if(mImpl->mEventData) { // Reset the scroll position. mImpl->mModel->mScrollPosition = Vector2::ZERO; @@ -2252,18 +1934,6 @@ Actor Controller::CreateBackgroundActor() return mImpl->CreateBackgroundActor(); } -// private : Private contructors & copy operator. - -Controller::Controller() -: Controller(nullptr, nullptr, nullptr, nullptr) -{ -} - -Controller::Controller(ControlInterface* controlInterface) -: Controller(controlInterface, nullptr, nullptr, nullptr) -{ -} - Controller::Controller(ControlInterface* controlInterface, EditableControlInterface* editableControlInterface, SelectableControlInterface* selectableControlInterface, @@ -2272,17 +1942,9 @@ Controller::Controller(ControlInterface* controlInterface, { } -// The copy constructor and operator are left unimplemented. - -// protected : Destructor. - Controller::~Controller() { delete mImpl; } -} // namespace Text - -} // namespace Toolkit - -} // namespace Dali +} // namespace Dali::Toolkit::Text diff --git a/dali-toolkit/internal/text/text-controller.h b/dali-toolkit/internal/text/text-controller.h index 9302cf5..3240384 100644 --- a/dali-toolkit/internal/text/text-controller.h +++ b/dali-toolkit/internal/text/text-controller.h @@ -35,11 +35,7 @@ #include #include -namespace Dali -{ -namespace Toolkit -{ -namespace Text +namespace Dali::Toolkit::Text { class Controller; class ControlInterface; @@ -170,7 +166,10 @@ public: // Constructor. * * @return A pointer to a new Controller. */ - static ControllerPtr New(); + static ControllerPtr New() + { + return ControllerPtr(new Controller()); + } /** * @brief Create a new instance of a Controller. @@ -179,7 +178,10 @@ public: // Constructor. * * @return A pointer to a new Controller. */ - static ControllerPtr New(ControlInterface* controlInterface); + static ControllerPtr New(ControlInterface* controlInterface) + { + return ControllerPtr(new Controller(controlInterface)); + } /** * @brief Create a new instance of a Controller. @@ -194,7 +196,13 @@ public: // Constructor. static ControllerPtr New(ControlInterface* controlInterface, EditableControlInterface* editableControlInterface, SelectableControlInterface* selectableControlInterface, - AnchorControlInterface* anchorControlInterface); + AnchorControlInterface* anchorControlInterface) + { + return ControllerPtr(new Controller(controlInterface, + editableControlInterface, + selectableControlInterface, + anchorControlInterface)); + } public: // Configure the text controller. /** @@ -1897,12 +1905,18 @@ private: // Private contructors & copy operator. /** * @brief Private constructor. */ - Controller(); + Controller() + : Controller(nullptr, nullptr, nullptr, nullptr) + { + } /** * @brief Private constructor. */ - Controller(ControlInterface* controlInterface); + Controller(ControlInterface* controlInterface) + : Controller(controlInterface, nullptr, nullptr, nullptr) + { + } /** * @brief Private constructor. @@ -1912,11 +1926,8 @@ private: // Private contructors & copy operator. SelectableControlInterface* selectableControlInterface, AnchorControlInterface* anchorControlInterface); - // Undefined - Controller(const Controller& handle); - - // Undefined - Controller& operator=(const Controller& handle); + Controller(const Controller& handle) = delete; + Controller& operator=(const Controller& handle) = delete; protected: // Destructor. /** @@ -1937,10 +1948,6 @@ private: Impl* mImpl; }; -} // namespace Text - -} // namespace Toolkit - -} // namespace Dali +} // namespace Dali::Toolkit::Text #endif // DALI_TOOLKIT_TEXT_CONTROLLER_H diff --git a/dali-toolkit/internal/transition/transition-base-impl.cpp b/dali-toolkit/internal/transition/transition-base-impl.cpp index f8aed47..5ee926e 100644 --- a/dali-toolkit/internal/transition/transition-base-impl.cpp +++ b/dali-toolkit/internal/transition/transition-base-impl.cpp @@ -208,22 +208,18 @@ void TransitionBase::SetAnimation() return; } - // If this transition is not a transition from a Control to another Control - // and a transition effect to appear with delay, - // the mTarget should not be shown until delay seconds. - if(!IsPairTransition() && mIsAppearingTransition && mAnimation && mTimePeriod.delaySeconds > Dali::Math::MACHINE_EPSILON_10) - { - Dali::KeyFrames initialKeyframes = Dali::KeyFrames::New(); - initialKeyframes.Add(0.0f, OPACITY_TRANSPARENT); - initialKeyframes.Add(1.0f, OPACITY_TRANSPARENT); - mAnimation.AnimateBetween(Property(mTarget, Dali::Actor::Property::OPACITY), initialKeyframes, TimePeriod(mTimePeriod.delaySeconds)); - } - for(uint32_t i = 0; i < mStartPropertyMap.Count(); ++i) { Property::Value* finishValue = mFinishPropertyMap.Find(mStartPropertyMap.GetKeyAt(i).indexKey); if(finishValue) { + // If this transition is appearing transition, this property keeps start value during delay. + // If multiple transitions are applied to this Control and others run before this transition, + // this property should keep start value until this transition starts. + if(!IsPairTransition() && IsAppearingTransition() && mTimePeriod.delaySeconds > Dali::Math::MACHINE_EPSILON_10) + { + mTarget.SetProperty(mStartPropertyMap.GetKeyAt(i).indexKey, mStartPropertyMap.GetValue(i)); + } AnimateBetween(mTarget, mStartPropertyMap.GetKeyAt(i).indexKey, mStartPropertyMap.GetValue(i), *finishValue); } } diff --git a/dali-toolkit/internal/transition/transition-base-impl.h b/dali-toolkit/internal/transition/transition-base-impl.h index 409eb60..b194e52 100644 --- a/dali-toolkit/internal/transition/transition-base-impl.h +++ b/dali-toolkit/internal/transition/transition-base-impl.h @@ -101,6 +101,30 @@ public: mIsAppearingTransition = appearingTransition; } + /** + * @brief Returns whether this transition is appearing transition or not + */ + bool IsAppearingTransition() const + { + return mIsAppearingTransition; + } + + /** + * @brief Returns whether this transition is a transition from a Control to another Control or effect to appearing or disappearing. + */ + bool IsPairTransition() const + { + return mIsPairTransition; + } + + /** + * @brief Returns target which will be transition. + */ + const Dali::Toolkit::Control GetTarget() const + { + return mTarget; + } + protected: /** @@ -159,14 +183,6 @@ protected: } /** - * @brief Returns whether this transition is appearing transition or not - */ - bool IsAppearingTransition() const - { - return mIsAppearingTransition; - } - - /** * @brief Set whether this transition is a transition from a Control to another Control or effect to appearing or disappearing. * @param[in] pairTransition True if this transition is appearing transition. */ @@ -175,14 +191,6 @@ protected: mIsPairTransition = pairTransition; } - /** - * @brief Returns whether this transition is a transition from a Control to another Control or effect to appearing or disappearing. - */ - bool IsPairTransition() const - { - return mIsPairTransition; - } - protected: /** * Construct a new TransitionBase. diff --git a/dali-toolkit/internal/transition/transition-impl.cpp b/dali-toolkit/internal/transition/transition-impl.cpp index 2cbd14d..78ba8db 100644 --- a/dali-toolkit/internal/transition/transition-impl.cpp +++ b/dali-toolkit/internal/transition/transition-impl.cpp @@ -27,6 +27,7 @@ // INTERNAL INCLUDES #include +#include namespace Dali { @@ -37,10 +38,9 @@ namespace Internal namespace { const Dali::AlphaFunction DEFAULT_ALPHA_FUNCTION(Dali::AlphaFunction::DEFAULT); - } // anonymous namespace -TransitionPtr Transition::New(Dali::Toolkit::Control source, Dali::Toolkit::Control destination, TimePeriod timePeriod) +TransitionPtr Transition::New(Dali::Toolkit::Control source, Dali::Toolkit::Control destination, bool useDestinationTarget, TimePeriod timePeriod) { float delaySeconds = timePeriod.delaySeconds; if(delaySeconds < 0.0f) @@ -56,7 +56,7 @@ TransitionPtr Transition::New(Dali::Toolkit::Control source, Dali::Toolkit::Cont durationSeconds = 0.0f; } - TransitionPtr transition = new Transition(source, destination, TimePeriod(delaySeconds, durationSeconds)); + TransitionPtr transition = new Transition(source, destination, useDestinationTarget, TimePeriod(delaySeconds, durationSeconds)); // Second-phase construction transition->Initialize(); @@ -64,12 +64,14 @@ TransitionPtr Transition::New(Dali::Toolkit::Control source, Dali::Toolkit::Cont return transition; } -Transition::Transition(Dali::Toolkit::Control source, Dali::Toolkit::Control destination, TimePeriod timePeriod) +Transition::Transition(Dali::Toolkit::Control source, Dali::Toolkit::Control destination, bool useDestinationTarget, TimePeriod timePeriod) : TransitionBase(), + mUseDestinationTarget(useDestinationTarget), + mOriginalSize(), mSourceControl(source), mDestinationControl(destination) { - SetTarget(destination); + SetTarget(mUseDestinationTarget ? destination : source); SetTimePeriod(timePeriod); SetPairTransition(true); } @@ -90,16 +92,15 @@ void Transition::OnPlay() } //Make startPropertyMap and finishPropertyMap to use for property animation. - Matrix sourceWorldTransform = sourceControl[Dali::Actor::Property::WORLD_MATRIX]; + Matrix sourceWorldTransform = GetWorldTransform(sourceControl); Vector3 sourcePosition, sourceScale; Quaternion sourceOrientation; sourceWorldTransform.GetTransformComponents(sourcePosition, sourceOrientation, sourceScale); - Vector3 destinationPosition = destinationControl[Dali::Actor::Property::POSITION]; - Vector3 destinationScale = destinationControl[Dali::Actor::Property::SCALE]; - Quaternion destinationOrientation = destinationControl[Dali::Actor::Property::ORIENTATION]; - Vector4 targetColor = destinationControl[Dali::Actor::Property::COLOR]; - Vector3 targetSize = destinationControl[Dali::Actor::Property::SIZE]; + Matrix destinationWorldTransform = GetWorldTransform(destinationControl); + Vector3 destinationPosition, destinationScale; + Quaternion destinationOrientation; + destinationWorldTransform.GetTransformComponents(destinationPosition, destinationOrientation, destinationScale); Property::Map startPropertyMap; Property::Map finishPropertyMap; @@ -114,29 +115,36 @@ void Transition::OnPlay() startPropertyMap.Insert(Dali::Actor::Property::SCALE, sourceScale); finishPropertyMap.Insert(Dali::Actor::Property::SCALE, destinationScale); - Vector4 sourceColor = sourceControl.GetCurrentProperty(Dali::Actor::Property::WORLD_COLOR); + Vector4 sourceColor = GetWorldColor(sourceControl); + Vector4 destinationColor = GetWorldColor(destinationControl); startPropertyMap.Insert(Dali::Actor::Property::COLOR, sourceColor); - finishPropertyMap.Insert(Dali::Actor::Property::COLOR, targetColor); + finishPropertyMap.Insert(Dali::Actor::Property::COLOR, destinationColor); // Set animation for other properties if source and destination is different. - Vector3 sourceSize = sourceControl.GetCurrentProperty(Dali::Actor::Property::SIZE); - if(sourceSize != targetSize) + Vector3 sourceSize = sourceControl[Dali::Actor::Property::SIZE]; + Vector3 destinationSize = destinationControl[Dali::Actor::Property::SIZE]; + if(sourceSize != destinationSize) { startPropertyMap.Insert(Dali::Actor::Property::SIZE, sourceSize); - finishPropertyMap.Insert(Dali::Actor::Property::SIZE, targetSize); + finishPropertyMap.Insert(Dali::Actor::Property::SIZE, destinationSize); + if(!mUseDestinationTarget) + { + mOriginalSize = GetTargetControl().GetProperty(Dali::Actor::Property::SIZE); + } } SetStartPropertyMap(startPropertyMap); SetFinishPropertyMap(finishPropertyMap); // source View becomes transparent during transition. + Dali::Toolkit::Control waitingControl = GetWaitingControl(); if(IsTransitionWithChild()) { - sourceControl[Dali::Actor::Property::VISIBLE] = false; + waitingControl[Dali::Actor::Property::VISIBLE] = false; } else { - GetImplementation(sourceControl).SetTransparent(true); + GetImplementation(waitingControl).SetTransparent(true); } Dali::Animation animation = GetAnimation(); @@ -145,27 +153,82 @@ void Transition::OnPlay() DALI_LOG_ERROR("animation is still not initialized\n"); return; } - Dali::Toolkit::DevelControl::CreateTransitions(destinationControl, animation, sourceControl, GetAlphaFunction(), GetTimePeriod()); + + mOriginalVisualProperties.clear(); + std::vector> destinationVisualProperties; + Dali::Toolkit::Control targetControl = GetTargetControl(); + Internal::Control& internalControl = Toolkit::Internal::GetImplementation(targetControl); + Internal::Control::Impl& controlDataImpl = Toolkit::Internal::Control::Impl::Get(internalControl); + controlDataImpl.CreateTransitions(mOriginalVisualProperties, destinationVisualProperties, sourceControl, destinationControl); + + for(uint32_t index = 0; index < mOriginalVisualProperties.size(); ++index) + { + Dali::Property::Map source = mOriginalVisualProperties[index].second; + Dali::Property::Map destination = destinationVisualProperties[index].second; + for(size_t i = 0; i < source.Count(); ++i) + { + Dali::Property property = DevelControl::GetVisualProperty(targetControl, mOriginalVisualProperties[index].first, source.GetKeyAt(i)); + if(GetTimePeriod().delaySeconds > 0.0f) + { + Dali::KeyFrames initialKeyframes = Dali::KeyFrames::New(); + initialKeyframes.Add(0.0f, source.GetValue(i)); + animation.AnimateBetween(property, initialKeyframes, TimePeriod(GetTimePeriod().delaySeconds)); + } + Dali::KeyFrames keyframes = Dali::KeyFrames::New(); + keyframes.Add(0.0f, source.GetValue(i)); + keyframes.Add(1.0f, destination.GetValue(i)); + animation.AnimateBetween(property, keyframes, GetAlphaFunction(), GetTimePeriod()); + } + } } void Transition::OnFinished() { - Dali::Toolkit::Control sourceControl = mSourceControl.GetHandle(); - if(!sourceControl) + Dali::Toolkit::Control waitingControl = GetWaitingControl(); + if(!waitingControl) { return; } + if(!mUseDestinationTarget) + { + Dali::Toolkit::Control target = GetTargetControl(); + Dali::Animation resetAnimation = Dali::Animation::New(0.0f); + if(mOriginalSize != target.GetProperty(Dali::Actor::Property::SIZE)) + { + // Use Animation not to notify size change and not to change width and height resize policy. + resetAnimation.AnimateTo(Dali::Property(target, Dali::Actor::Property::SIZE), mOriginalSize); + } + resetAnimation.Play(); + + Dali::Toolkit::Control targetControl = GetTargetControl(); + Internal::Control& internalControl = Toolkit::Internal::GetImplementation(targetControl); + Internal::Control::Impl& controlDataImpl = Toolkit::Internal::Control::Impl::Get(internalControl); + controlDataImpl.UpdateVisualProperties(mOriginalVisualProperties); + } + if(IsTransitionWithChild()) { - sourceControl[Dali::Actor::Property::VISIBLE] = true; + waitingControl[Dali::Actor::Property::VISIBLE] = true; } else { - GetImplementation(sourceControl).SetTransparent(false); + GetImplementation(waitingControl).SetTransparent(false); } } +Dali::Toolkit::Control Transition::GetTargetControl() +{ + Dali::Toolkit::Control target = mUseDestinationTarget ? mDestinationControl.GetHandle() : mSourceControl.GetHandle(); + return target; +} + +Dali::Toolkit::Control Transition::GetWaitingControl() +{ + Dali::Toolkit::Control waitingControl = mUseDestinationTarget ? mSourceControl.GetHandle() : mDestinationControl.GetHandle(); + return waitingControl; +} + } // namespace Internal } // namespace Toolkit diff --git a/dali-toolkit/internal/transition/transition-impl.h b/dali-toolkit/internal/transition/transition-impl.h index 6aa1374..7230e2b 100644 --- a/dali-toolkit/internal/transition/transition-impl.h +++ b/dali-toolkit/internal/transition/transition-impl.h @@ -41,10 +41,11 @@ public: * @brief Create a new Transition object. * @param[in] source A source control of this transition. * @param[in] destination A destination control of this transition. + * @param[in] useDestinationTarget True if this transition uses destination control as target. * @param[in] timePeriod The timePeriod of the animation. * @return A smart-pointer to the newly allocated Transition. */ - static TransitionPtr New(Dali::Toolkit::Control source, Dali::Toolkit::Control destination, TimePeriod timePeriod); + static TransitionPtr New(Dali::Toolkit::Control source, Dali::Toolkit::Control destination, bool useDestinationTarget, TimePeriod timePeriod); protected: /** @@ -63,6 +64,7 @@ protected: */ Transition(Dali::Toolkit::Control source, Dali::Toolkit::Control destination, + bool useDestinationTarget, TimePeriod timePeriod); /** @@ -78,8 +80,15 @@ private: Transition& operator=(const Transition& rhs); private: - WeakHandle mSourceControl; - WeakHandle mDestinationControl; + Dali::Toolkit::Control GetTargetControl(); + Dali::Toolkit::Control GetWaitingControl(); + +private: + bool mUseDestinationTarget; + Vector3 mOriginalSize; + std::vector> mOriginalVisualProperties; + WeakHandle mSourceControl; + WeakHandle mDestinationControl; }; } // namespace Internal diff --git a/dali-toolkit/internal/transition/transition-set-impl.cpp b/dali-toolkit/internal/transition/transition-set-impl.cpp index fd019b6..d1b16af 100644 --- a/dali-toolkit/internal/transition/transition-set-impl.cpp +++ b/dali-toolkit/internal/transition/transition-set-impl.cpp @@ -37,6 +37,13 @@ namespace // Signals static constexpr std::string_view SIGNAL_FINISHED = "finished"; +static constexpr float OPACITY_TRANSPARENT = 0.0f; + +float CustomAlphaFunction(float progress) +{ + return (progress >= 1.0f) ? 1.0f : 0.0f; +} + BaseHandle Create() { return Dali::Toolkit::TransitionSet::New(); @@ -117,9 +124,46 @@ void TransitionSet::TransitionPreProcess() void TransitionSet::TransitionStart() { + std::vector> minimumDelays; for(auto&& transition : mTransitions) { transition->Play(); + + // If target Control has appearing transition, the target will not be rendered during delay. + // And if the Control has multiple transitions, the target will not be rendered during minimum delay of the transitions. + // Here we can find minimum delay of each target. + if(!transition->IsPairTransition() && transition->IsAppearingTransition()) + { + bool found = false; + for(uint32_t index = 0; index < minimumDelays.size(); ++index) + { + if(minimumDelays[index].first == transition->GetTarget()) + { + minimumDelays[index].second = std::min(minimumDelays[index].second, transition->GetTimePeriod().delaySeconds); + found = true; + break; + } + } + if(!found) + { + minimumDelays.push_back(std::pair(transition->GetTarget(), transition->GetTimePeriod().delaySeconds)); + } + } + } + + // If the target has delay that is larger than 0, hide the target during minimum delay. + // The custom alpha function make the target hide just during delay. + for(auto&& delay : minimumDelays) + { + if(delay.second > Dali::Math::MACHINE_EPSILON_10) + { + Dali::KeyFrames initialKeyframes = Dali::KeyFrames::New(); + initialKeyframes.Add(0.0f, OPACITY_TRANSPARENT); + initialKeyframes.Add(1.0f, delay.first.GetProperty(Dali::Actor::Property::OPACITY)); + + AlphaFunction alpha(&CustomAlphaFunction); + mAnimation.AnimateBetween(Property(delay.first, Dali::Actor::Property::OPACITY), initialKeyframes, alpha, TimePeriod(delay.second)); + } } mAnimation.FinishedSignal().Connect(this, &TransitionSet::TransitionFinished); diff --git a/dali-toolkit/internal/visuals/animated-image/animated-image-visual.cpp b/dali-toolkit/internal/visuals/animated-image/animated-image-visual.cpp index 9693cc8..d8d61d3 100644 --- a/dali-toolkit/internal/visuals/animated-image/animated-image-visual.cpp +++ b/dali-toolkit/internal/visuals/animated-image/animated-image-visual.cpp @@ -187,9 +187,9 @@ AnimatedImageVisual::AnimatedImageVisual(VisualFactoryCache& factoryCache, Image mUrlIndex(0), mFrameCount(0), mImageSize(), + mActionStatus(DevelAnimatedImageVisual::Action::PLAY), mWrapModeU(WrapMode::DEFAULT), mWrapModeV(WrapMode::DEFAULT), - mActionStatus(DevelAnimatedImageVisual::Action::PLAY), mStopBehavior(DevelImageVisual::StopBehavior::CURRENT_FRAME), mStartFirstFrame(false), mIsJumpTo(false) diff --git a/dali-toolkit/internal/visuals/animated-image/animated-image-visual.h b/dali-toolkit/internal/visuals/animated-image/animated-image-visual.h index 347e9d3..1d21356 100644 --- a/dali-toolkit/internal/visuals/animated-image/animated-image-visual.h +++ b/dali-toolkit/internal/visuals/animated-image/animated-image-visual.h @@ -275,9 +275,10 @@ private: uint32_t mFrameCount; // Number of frames ImageDimensions mImageSize; + DevelAnimatedImageVisual::Action::Type mActionStatus; + Dali::WrapMode::Type mWrapModeU : 3; Dali::WrapMode::Type mWrapModeV : 3; - DevelAnimatedImageVisual::Action::Type mActionStatus : 3; DevelImageVisual::StopBehavior::Type mStopBehavior : 2; bool mStartFirstFrame : 1; bool mIsJumpTo : 1; diff --git a/dali-toolkit/internal/visuals/animated-vector-image/animated-vector-image-visual.cpp b/dali-toolkit/internal/visuals/animated-vector-image/animated-vector-image-visual.cpp index 89d02e8..26495bf 100644 --- a/dali-toolkit/internal/visuals/animated-vector-image/animated-vector-image-visual.cpp +++ b/dali-toolkit/internal/visuals/animated-vector-image/animated-vector-image-visual.cpp @@ -25,6 +25,7 @@ #include // INTERNAL INCLUDES +#include #include #include #include @@ -445,15 +446,6 @@ void AnimatedVectorImageVisual::OnDoAction(const Property::Index actionId, const } break; } - case DevelAnimatedVectorImageVisual::Action::UPDATE_PROPERTY: - { - const Property::Map* map = attributes.GetMap(); - if(map) - { - DoSetProperties(*map); - } - break; - } } TriggerVectorRasterization(); diff --git a/dali-toolkit/internal/visuals/arc/arc-visual.cpp b/dali-toolkit/internal/visuals/arc/arc-visual.cpp index 76328f4..a1c79e9 100644 --- a/dali-toolkit/internal/visuals/arc/arc-visual.cpp +++ b/dali-toolkit/internal/visuals/arc/arc-visual.cpp @@ -22,7 +22,6 @@ #include //INTERNAL INCLUDES -#include #include #include #include @@ -188,23 +187,6 @@ void ArcVisual::OnSetTransform() } } -void ArcVisual::OnDoAction(const Property::Index actionId, const Property::Value& attributes) -{ - // Check if action is valid for this visual type and perform action if possible - switch(actionId) - { - case DevelArcVisual::Action::UPDATE_PROPERTY: - { - const Property::Map* map = attributes.GetMap(); - if(map) - { - DoSetProperties(*map); - } - break; - } - } -} - void ArcVisual::OnInitialize() { Geometry geometry = mFactoryCache.GetGeometry(VisualFactoryCache::QUAD_GEOMETRY); diff --git a/dali-toolkit/internal/visuals/arc/arc-visual.h b/dali-toolkit/internal/visuals/arc/arc-visual.h index 4746351..011b946 100644 --- a/dali-toolkit/internal/visuals/arc/arc-visual.h +++ b/dali-toolkit/internal/visuals/arc/arc-visual.h @@ -107,11 +107,6 @@ protected: */ void OnSetTransform() override; - /** - * @copydoc Visual::Base::OnDoAction - */ - void OnDoAction(const Property::Index actionId, const Property::Value& attributes) override; - private: // Undefined ArcVisual(const ArcVisual& arcVisual) = delete; diff --git a/dali-toolkit/internal/visuals/color/color-visual.cpp b/dali-toolkit/internal/visuals/color/color-visual.cpp index 593eeb6..73b0931 100644 --- a/dali-toolkit/internal/visuals/color/color-visual.cpp +++ b/dali-toolkit/internal/visuals/color/color-visual.cpp @@ -23,7 +23,6 @@ #include //INTERNAL INCLUDES -#include #include #include #include @@ -161,23 +160,6 @@ void ColorVisual::OnSetTransform() } } -void ColorVisual::OnDoAction(const Property::Index actionId, const Property::Value& attributes) -{ - // Check if action is valid for this visual type and perform action if possible - switch(actionId) - { - case DevelColorVisual::Action::UPDATE_PROPERTY: - { - const Property::Map* map = attributes.GetMap(); - if(map) - { - DoSetProperties(*map); - } - break; - } - } -} - void ColorVisual::UpdateShader() { if(mImpl->mRenderer) diff --git a/dali-toolkit/internal/visuals/color/color-visual.h b/dali-toolkit/internal/visuals/color/color-visual.h index 6ced771..5edf2ba 100644 --- a/dali-toolkit/internal/visuals/color/color-visual.h +++ b/dali-toolkit/internal/visuals/color/color-visual.h @@ -104,11 +104,6 @@ protected: void OnSetTransform() override; /** - * @copydoc Visual::Base::OnDoAction - */ - void OnDoAction(const Property::Index actionId, const Property::Value& attributes) override; - - /** * @copydoc Visual::Base::UpdateShader */ void UpdateShader() override; diff --git a/dali-toolkit/internal/visuals/text/text-visual.cpp b/dali-toolkit/internal/visuals/text/text-visual.cpp index 19ecb5c..a4903c5 100644 --- a/dali-toolkit/internal/visuals/text/text-visual.cpp +++ b/dali-toolkit/internal/visuals/text/text-visual.cpp @@ -23,7 +23,6 @@ #include #include #include -#include #include // INTERNAL HEADER @@ -240,6 +239,7 @@ TextVisual::TextVisual(VisualFactoryCache& factoryCache) mController(Text::Controller::New()), mTypesetter(Text::Typesetter::New(mController->GetTextModel())), mAnimatableTextColorPropertyIndex(Property::INVALID_INDEX), + mTextColorAnimatableIndex(Property::INVALID_INDEX), mRendererUpdateNeeded(false) { } @@ -291,23 +291,36 @@ void TextVisual::DoSetOnScene(Actor& actor) // Enable the pre-multiplied alpha to improve the text quality EnablePreMultipliedAlpha(true); - const Vector4& defaultColor = mController->GetTextModel()->GetDefaultColor(); - Dali::Property::Index shaderTextColorIndex = mImpl->mRenderer.RegisterProperty("uTextColorAnimatable", defaultColor); + const Vector4& defaultColor = mController->GetTextModel()->GetDefaultColor(); + if(mTextColorAnimatableIndex == Property::INVALID_INDEX) + { + mTextColorAnimatableIndex = mImpl->mRenderer.RegisterProperty("uTextColorAnimatable", defaultColor); + } + else + { + mImpl->mRenderer.SetProperty(mTextColorAnimatableIndex, defaultColor); + } if(mAnimatableTextColorPropertyIndex != Property::INVALID_INDEX) { // Create constraint for the animatable text's color Property with uTextColorAnimatable in the renderer. - if(shaderTextColorIndex != Property::INVALID_INDEX) + if(mTextColorAnimatableIndex != Property::INVALID_INDEX) { - Constraint colorConstraint = Constraint::New(mImpl->mRenderer, shaderTextColorIndex, TextColorConstraint); - colorConstraint.AddSource(Source(actor, mAnimatableTextColorPropertyIndex)); - colorConstraint.Apply(); - - // Make zero if the alpha value of text color is zero to skip rendering text - Constraint opacityConstraint = Constraint::New(mImpl->mRenderer, Dali::DevelRenderer::Property::OPACITY, OpacityConstraint); - opacityConstraint.AddSource(Source(actor, mAnimatableTextColorPropertyIndex)); - opacityConstraint.Apply(); + if(!mColorConstraint) + { + mColorConstraint = Constraint::New(mImpl->mRenderer, mTextColorAnimatableIndex, TextColorConstraint); + mColorConstraint.AddSource(Source(actor, mAnimatableTextColorPropertyIndex)); + } + mColorConstraint.Apply(); } + + // Make zero if the alpha value of text color is zero to skip rendering text + if(!mOpacityConstraint) + { + mOpacityConstraint = Constraint::New(mImpl->mRenderer, Dali::DevelRenderer::Property::OPACITY, OpacityConstraint); + mOpacityConstraint.AddSource(Source(actor, mAnimatableTextColorPropertyIndex)); + } + mOpacityConstraint.Apply(); } // Renderer needs textures and to be added to control @@ -335,6 +348,15 @@ void TextVisual::RemoveRenderer(Actor& actor) void TextVisual::DoSetOffScene(Actor& actor) { + if(mColorConstraint) + { + mColorConstraint.Remove(); + } + if(mOpacityConstraint) + { + mOpacityConstraint.Remove(); + } + RemoveRenderer(actor); // Resets the control handle. diff --git a/dali-toolkit/internal/visuals/text/text-visual.h b/dali-toolkit/internal/visuals/text/text-visual.h index 7ae5e4e..f9d6c79 100644 --- a/dali-toolkit/internal/visuals/text/text-visual.h +++ b/dali-toolkit/internal/visuals/text/text-visual.h @@ -19,6 +19,7 @@ */ // EXTERNAL INCLUDES +#include #include #include @@ -332,7 +333,10 @@ private: Text::ControllerPtr mController; ///< The text's controller. Text::TypesetterPtr mTypesetter; ///< The text's typesetter. WeakHandle mControl; ///< The control where the renderer is added. + Constraint mColorConstraint{}; ///< Color constraint + Constraint mOpacityConstraint{}; ///< Opacity constraint Property::Index mAnimatableTextColorPropertyIndex; ///< The index of animatable text color property registered by the control. + Property::Index mTextColorAnimatableIndex; ///< The index of uTextColorAnimatable property. bool mRendererUpdateNeeded : 1; ///< The flag to indicate whether the renderer needs to be updated. RendererContainer mRendererList; }; diff --git a/dali-toolkit/internal/visuals/visual-base-impl.cpp b/dali-toolkit/internal/visuals/visual-base-impl.cpp index 443c51c..f0a7af4 100644 --- a/dali-toolkit/internal/visuals/visual-base-impl.cpp +++ b/dali-toolkit/internal/visuals/visual-base-impl.cpp @@ -25,6 +25,7 @@ #include //INTERNAL HEARDER +#include #include #include #include @@ -294,6 +295,11 @@ void Visual::Base::SetProperties(const Property::Map& propertyMap) { mImpl->mBorderlineWidth = width; } + + if(mImpl->mBorderlineWidthIndex != Property::INVALID_INDEX) + { + mImpl->mRenderer.SetProperty(mImpl->mBorderlineWidthIndex, mImpl->mBorderlineWidth); + } break; } case Toolkit::DevelVisual::Property::BORDERLINE_COLOR: @@ -303,6 +309,11 @@ void Visual::Base::SetProperties(const Property::Map& propertyMap) { mImpl->mBorderlineColor = color; } + + if(mImpl->mBorderlineColorIndex != Property::INVALID_INDEX) + { + mImpl->mRenderer.SetProperty(mImpl->mBorderlineColorIndex, mImpl->mBorderlineColor); + } break; } case Toolkit::DevelVisual::Property::BORDERLINE_OFFSET: @@ -312,6 +323,11 @@ void Visual::Base::SetProperties(const Property::Map& propertyMap) { mImpl->mBorderlineOffset = offset; } + + if(mImpl->mBorderlineOffsetIndex != Property::INVALID_INDEX) + { + mImpl->mRenderer.SetProperty(mImpl->mBorderlineOffsetIndex, mImpl->mBorderlineOffset); + } break; } case Toolkit::DevelVisual::Property::CORNER_RADIUS: @@ -337,6 +353,11 @@ void Visual::Base::SetProperties(const Property::Map& propertyMap) mImpl->mCornerRadius = Vector4(radius, radius, radius, radius); } } + + if(mImpl->mCornerRadiusIndex != Property::INVALID_INDEX) + { + mImpl->mRenderer.SetProperty(mImpl->mCornerRadiusIndex, mImpl->mCornerRadius); + } break; } case Toolkit::DevelVisual::Property::CORNER_RADIUS_POLICY: @@ -423,6 +444,20 @@ void Visual::Base::GetNaturalSize(Vector2& naturalSize) void Visual::Base::DoAction(const Property::Index actionId, const Property::Value attributes) { OnDoAction(actionId, attributes); + + // Check if action is valid for this visual type and perform action if possible + switch(actionId) + { + case DevelVisual::Action::UPDATE_PROPERTY: + { + const Property::Map* map = attributes.GetMap(); + if(map) + { + SetProperties(*map); + } + break; + } + } } void Visual::Base::SetDepthIndex(int index) diff --git a/dali-toolkit/public-api/controls/control-impl.cpp b/dali-toolkit/public-api/controls/control-impl.cpp index 17db11b..64745d0 100644 --- a/dali-toolkit/public-api/controls/control-impl.cpp +++ b/dali-toolkit/public-api/controls/control-impl.cpp @@ -37,7 +37,7 @@ #include #include #include -#include +#include #include #include #include @@ -133,7 +133,7 @@ void Control::SetBackgroundColor(const Vector4& color) if(visual && visual.GetType() == Toolkit::Visual::COLOR) { // Update background color only - mImpl->DoAction(Toolkit::Control::Property::BACKGROUND, DevelColorVisual::Action::UPDATE_PROPERTY, map); + mImpl->DoAction(Toolkit::Control::Property::BACKGROUND, DevelVisual::Action::UPDATE_PROPERTY, map); return; } @@ -702,6 +702,102 @@ void Control::SignalDisconnected(SlotObserver* slotObserver, CallbackBase* callb mImpl->SignalDisconnected(slotObserver, callback); } +void Control::MakeVisualTransition(Dali::Property::Map& sourcePropertyMap, Dali::Property::Map& destinationPropertyMap, + Dali::Toolkit::Control source, Dali::Toolkit::Control destination, Dali::Property::Index visualIndex) +{ + sourcePropertyMap.Clear(); + destinationPropertyMap.Clear(); + + Toolkit::Visual::Base sourceVisual = DevelControl::GetVisual(GetImplementation(source), visualIndex); + Toolkit::Visual::Base destinationVisual = DevelControl::GetVisual(GetImplementation(destination), visualIndex); + + // If source or destination doesn't have the visual, do not create transition for the visual. + if(!sourceVisual || !destinationVisual) + { + return; + } + + Property::Map sourceMap; + Property::Map destinationMap; + sourceVisual.CreatePropertyMap(sourceMap); + destinationVisual.CreatePropertyMap(destinationMap); + + static auto findValueVector4 = [](const Property::Map& map, Property::Index index, const Vector4& defaultValue = Vector4()) -> Vector4 + { + Property::Value* propertyValue = map.Find(index); + if(propertyValue) + { + return propertyValue->Get(); + } + return defaultValue; + }; + + static auto findValueFloat = [](const Property::Map& map, Property::Index index, const float& defaultValue = 0.0f) -> float + { + Property::Value* propertyValue = map.Find(index); + if(propertyValue) + { + return propertyValue->Get(); + } + return defaultValue; + }; + + Vector4 defaultMixColor(Color::TRANSPARENT); + Vector4 defaultCornerRadius(0.0f, 0.0f, 0.0f, 0.0f); + float defaultBorderlineWidth(0.0f); + Vector4 defaultBorderlineColor(0.0f, 0.0f, 0.0f, 1.0f); + float defaultBorderlineOffset(0.0f); + + Vector4 sourceMixColor = findValueVector4(sourceMap, Dali::Toolkit::Visual::Property::MIX_COLOR, defaultMixColor); + Vector4 sourceCornerRadius = findValueVector4(sourceMap, Toolkit::DevelVisual::Property::CORNER_RADIUS, defaultCornerRadius); + float sourceBorderlineWidth = findValueFloat(sourceMap, Toolkit::DevelVisual::Property::BORDERLINE_WIDTH, defaultBorderlineWidth); + Vector4 sourceBorderlineColor = findValueVector4(sourceMap, Toolkit::DevelVisual::Property::BORDERLINE_COLOR, defaultBorderlineColor); + float sourceBorderlineOffset = findValueFloat(sourceMap, Toolkit::DevelVisual::Property::BORDERLINE_OFFSET, defaultBorderlineOffset); + + Vector4 destinationMixColor = findValueVector4(destinationMap, Dali::Toolkit::Visual::Property::MIX_COLOR, defaultMixColor); + Vector4 destinationCornerRadius = findValueVector4(destinationMap, Toolkit::DevelVisual::Property::CORNER_RADIUS, defaultCornerRadius); + float destinationBorderlineWidth = findValueFloat(destinationMap, Toolkit::DevelVisual::Property::BORDERLINE_WIDTH, defaultBorderlineWidth); + Vector4 destinationBorderlineColor = findValueVector4(destinationMap, Toolkit::DevelVisual::Property::BORDERLINE_COLOR, defaultBorderlineColor); + float destinationBorderlineOffset = findValueFloat(destinationMap, Toolkit::DevelVisual::Property::BORDERLINE_OFFSET, defaultBorderlineOffset); + + // If the value of the source Control and that of destination Control is different, the property should be transitioned. + if(Vector3(sourceMixColor) != Vector3(destinationMixColor)) + { + sourcePropertyMap.Add(Dali::Toolkit::Visual::Property::MIX_COLOR, Vector3(sourceMixColor)); + destinationPropertyMap.Add(Dali::Toolkit::Visual::Property::MIX_COLOR, Vector3(destinationMixColor)); + } + + if(std::abs(sourceMixColor.a - destinationMixColor.a) > Math::MACHINE_EPSILON_1) + { + sourcePropertyMap.Add(Dali::Toolkit::Visual::Property::OPACITY, sourceMixColor.a); + destinationPropertyMap.Add(Dali::Toolkit::Visual::Property::OPACITY, destinationMixColor.a); + } + + if(sourceCornerRadius != destinationCornerRadius) + { + sourcePropertyMap.Add(Dali::Toolkit::DevelVisual::Property::CORNER_RADIUS, sourceCornerRadius); + destinationPropertyMap.Add(Dali::Toolkit::DevelVisual::Property::CORNER_RADIUS, destinationCornerRadius); + } + + if(sourceBorderlineWidth != destinationBorderlineWidth) + { + sourcePropertyMap.Add(Dali::Toolkit::DevelVisual::Property::BORDERLINE_WIDTH, sourceBorderlineWidth); + destinationPropertyMap.Add(Dali::Toolkit::DevelVisual::Property::BORDERLINE_WIDTH, destinationBorderlineWidth); + } + + if(sourceBorderlineColor != destinationBorderlineColor) + { + sourcePropertyMap.Add(Dali::Toolkit::DevelVisual::Property::BORDERLINE_COLOR, sourceBorderlineColor); + destinationPropertyMap.Add(Dali::Toolkit::DevelVisual::Property::BORDERLINE_COLOR, destinationBorderlineColor); + } + + if(sourceBorderlineOffset != destinationBorderlineOffset) + { + sourcePropertyMap.Add(Dali::Toolkit::DevelVisual::Property::BORDERLINE_OFFSET, sourceBorderlineOffset); + destinationPropertyMap.Add(Dali::Toolkit::DevelVisual::Property::BORDERLINE_OFFSET, destinationBorderlineOffset); + } +} + Control& GetImplementation(Dali::Toolkit::Control& handle) { CustomActorImpl& customInterface = handle.GetImplementation(); diff --git a/dali-toolkit/public-api/controls/control-impl.h b/dali-toolkit/public-api/controls/control-impl.h index 9a68ca1..48c6b9c 100644 --- a/dali-toolkit/public-api/controls/control-impl.h +++ b/dali-toolkit/public-api/controls/control-impl.h @@ -45,6 +45,7 @@ class StyleManager; namespace Internal { + /** * @brief This is the internal base class for all controls. * @@ -617,18 +618,47 @@ public: // API for derived classes to override return NULL; } - // Transition + // Transition APIs + + /** + * @brief Make visual transition from source control to destination control about specific Visual. + * If both of source and destination control have same visual index, than generates information for the transition of this Control. + * + * @param[out] sourcePropertyMap Source property map to be applied on this Control. + * @param[out] destinationPropertyMap Destination property map to be applied on this Control. + * @param[in] source Source control of the animation. + * @param[in] destination Destination control of the animation. + * @param[in] visualIndex Property::Index to make animation. + */ + void MakeVisualTransition(Dali::Property::Map& sourcePropertyMap, Dali::Property::Map& destinationPropertyMap, + Dali::Toolkit::Control source, Dali::Toolkit::Control destination, Dali::Property::Index visualIndex); /** - * @brief Retrieve visual property animations. - * This Control is a destination. + * @brief Retrieves source and destination visual properties for the Transition of this Control. + * The properties of this Control will be transitioned from the propeties of source Control to that of destination control. + * If a property value is different between source and destination Control, + * the property information of each Control will be included in sourceProperties and destinationProperties. + * + * @param[out] sourceProperties Source property list to be applied on this Control. + * @param[out] destinationProperties Destination property list to be applied on this Control. + * @param[in] source Source control of the animation. + * @param[in] destination Destination control of the animation. * - * @param[in] animation generated animation - * @param[in] source source control of the animation. - * @param[in] alphaFunction AlphaFunction of the animation - * @param[in] timePeriod TimePeriod of the animation + * @note This method do not handle Actor properties. + * And the size and order of the sourceProperties and destinationProperties must be synchronized. + */ + virtual void OnCreateTransitions(std::vector>& sourceProperties, + std::vector>& destinationProperties, + Dali::Toolkit::Control source, + Dali::Toolkit::Control destination) + { + } + + /** + * @brief Update visual properties. + * @param[in] properties Property list to be used to update visual properties of this Control. */ - virtual void OnCreateTransitions(Dali::Animation& animation, Dali::Toolkit::Control source, AlphaFunction alphaFunction, TimePeriod timePeriod) + virtual void OnUpdateVisualProperties(const std::vector>& properties) { } diff --git a/dali-toolkit/public-api/controls/gl-view/gl-view.cpp b/dali-toolkit/public-api/controls/gl-view/gl-view.cpp index b5f6a8c..958d031 100644 --- a/dali-toolkit/public-api/controls/gl-view/gl-view.cpp +++ b/dali-toolkit/public-api/controls/gl-view/gl-view.cpp @@ -51,9 +51,9 @@ GlView GlView::DownCast(BaseHandle handle) return Control::DownCast(handle); } -void GlView::RegisterGlCallback(CallbackBase* initCallback, CallbackBase* renderFrameCallback, CallbackBase* terminateCallback) +void GlView::RegisterGlCallbacks(CallbackBase* initCallback, CallbackBase* renderFrameCallback, CallbackBase* terminateCallback) { - Dali::Toolkit::GetImpl(*this).RegisterGlCallback(initCallback, renderFrameCallback, terminateCallback); + Dali::Toolkit::GetImpl(*this).RegisterGlCallbacks(initCallback, renderFrameCallback, terminateCallback); } void GlView::SetResizeCallback(CallbackBase* resizeCallback) diff --git a/dali-toolkit/public-api/controls/gl-view/gl-view.h b/dali-toolkit/public-api/controls/gl-view/gl-view.h index be13db9..57c3201 100644 --- a/dali-toolkit/public-api/controls/gl-view/gl-view.h +++ b/dali-toolkit/public-api/controls/gl-view/gl-view.h @@ -165,7 +165,7 @@ public: * You can't call Dali APIs in your callbacks because it is invoked in GlView's own render thread. * And this must be called before adding GlView to the scene. */ - void RegisterGlCallback(CallbackBase* initCallback, CallbackBase* renderFrameCallback, CallbackBase* terminateCallback); + void RegisterGlCallbacks(CallbackBase* initCallback, CallbackBase* renderFrameCallback, CallbackBase* terminateCallback); /** * @brief Sets the ResizeCallback of the GlView. diff --git a/dali-toolkit/public-api/dali-toolkit-version.cpp b/dali-toolkit/public-api/dali-toolkit-version.cpp index 9935284..5f6856e 100644 --- a/dali-toolkit/public-api/dali-toolkit-version.cpp +++ b/dali-toolkit/public-api/dali-toolkit-version.cpp @@ -29,7 +29,7 @@ namespace Toolkit { const unsigned int TOOLKIT_MAJOR_VERSION = 2; const unsigned int TOOLKIT_MINOR_VERSION = 0; -const unsigned int TOOLKIT_MICRO_VERSION = 48; +const unsigned int TOOLKIT_MICRO_VERSION = 52; const char* const TOOLKIT_BUILD_DATE = __DATE__ " " __TIME__; #ifdef DEBUG_ENABLED diff --git a/dali-toolkit/public-api/transition/transition.cpp b/dali-toolkit/public-api/transition/transition.cpp index 3e2f378..57f7364 100644 --- a/dali-toolkit/public-api/transition/transition.cpp +++ b/dali-toolkit/public-api/transition/transition.cpp @@ -32,9 +32,9 @@ Transition::Transition(Internal::Transition* transition) { } -Transition Transition::New(Dali::Toolkit::Control source, Dali::Toolkit::Control destination, TimePeriod timePeriod) +Transition Transition::New(Dali::Toolkit::Control source, Dali::Toolkit::Control destination, bool useDestinationTarget, TimePeriod timePeriod) { - Internal::TransitionPtr internal = Dali::Toolkit::Internal::Transition::New(source, destination, timePeriod); + Internal::TransitionPtr internal = Dali::Toolkit::Internal::Transition::New(source, destination, useDestinationTarget, timePeriod); return Transition(internal.Get()); } diff --git a/dali-toolkit/public-api/transition/transition.h b/dali-toolkit/public-api/transition/transition.h index 634face..fa27fa6 100644 --- a/dali-toolkit/public-api/transition/transition.h +++ b/dali-toolkit/public-api/transition/transition.h @@ -51,13 +51,14 @@ public: /** * @brief Creates an initialized Transition. * - * @param[in] source Source - * @param[in] destination Destination + * @param[in] source A source control of this transition. + * @param[in] destination A destination control of this transition. + * @param[in] useDestinationTarget True if this transition uses destination control as target. * @param[in] timePeriod The duration in seconds * @return A handle to a newly allocated Dali resource * @note durationSeconds can not be negative. */ - static Transition New(Dali::Toolkit::Control source, Dali::Toolkit::Control destination, TimePeriod timePeriod); + static Transition New(Dali::Toolkit::Control source, Dali::Toolkit::Control destination, bool useDestinationTarget, TimePeriod timePeriod); /** * @brief Downcasts a handle to Transition handle. diff --git a/dali-toolkit/styles/1920x1080_rpi/dali-toolkit-default-theme.json b/dali-toolkit/styles/1920x1080_rpi/dali-toolkit-default-theme.json new file mode 100644 index 0000000..d862b80 --- /dev/null +++ b/dali-toolkit/styles/1920x1080_rpi/dali-toolkit-default-theme.json @@ -0,0 +1,541 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. + * + * This file is part of Dali Toolkit + * + * 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. + */ + + +//****************************************************************************** +// +// Default Reference style theme for a 1920x1080 resolution, The values determined by UX design specification. +// This file can be copied to a new folder within the styles/ directory and amended with new default values. +// Can be overriden if StyleManager applies another style sheet. +// +//****************************************************************************** + +{ + "config": + { + "brokenImageUrl":"{DALI_IMAGE_DIR}broken.png", + "alwaysShowFocus":true, + "clearFocusOnEscape":false + }, + "styles": + { + "Tooltip": + { + "tooltip": + { + "content": + { + "pointSize":24 + }, + "waitTime":0.5, + "background": + { + "visual":"{DALI_IMAGE_DIR}tooltip.9.png", + "border":[1,5,5,1] + }, + "tail": + { + "visibility":false, + "aboveVisual":"{DALI_IMAGE_DIR}tooltip-tail-above.png", + "belowVisual":"{DALI_IMAGE_DIR}tooltip-tail-below.png" + }, + "position":"BELOW", + "hoverPointOffset":[10,10], + "movementThreshold":5, + "disappearOnMovement":false + } + }, + "TextLabel": + { + "pointSize":24, + "enableAutoScroll":false, + "autoScrollLoopCount":2, + "autoScrollGap":50, + "autoScrollSpeed":80, + "ignoreSpacesAfterText":false + }, + + "TextLabelFontSize0": + { + "pointSize":24 + }, + "TextLabelFontSize1": + { + "pointSize":28 + }, + "TextLabelFontSize2": + { + "pointSize":32 + }, + "TextLabelFontSize3": + { + "pointSize":36 + }, + "TextLabelFontSize4": + { + "pointSize":40 + }, + + "TextField": + { + "pointSize":28, + "primaryCursorColor":[0.0,0.72,0.9,1.0], + "secondaryCursorColor":[0.0,0.72,0.9,1.0], + "cursorWidth":6, + "selectionHighlightColor":[0.75,0.96,1.0,1.0], + "grabHandleImage" : "{DALI_STYLE_IMAGE_DIR}cursor_handler_drop_center.png", + "selectionHandleImageLeft" : {"filename":"{DALI_STYLE_IMAGE_DIR}selection_handle_drop_left.png" }, + "selectionHandleImageRight": {"filename":"{DALI_STYLE_IMAGE_DIR}selection_handle_drop_right.png" }, + "enableSelection":false + }, + + "TextFieldFontSize0": + { + "pointSize":24 + }, + "TextFieldFontSize1": + { + "pointSize":28 + }, + "TextFieldFontSize2": + { + "pointSize":32 + }, + "TextFieldFontSize3": + { + "pointSize":36 + }, + "TextFieldFontSize4": + { + "pointSize":40 + }, + "TextSelectionPopup": + { + "popupMaxSize":[1700,100], + "optionDividerSize":[2,0], + "popupDividerColor":[0.23,0.72,0.8,0.11], + "popupIconColor":[1.0,1.0,1.0,1.0], + "popupPressedColor":[0.24,0.72,0.8,0.11], + "background": { + "rendererType": "image", + "url": "{DALI_IMAGE_DIR}selection-popup-background.9.png" + }, + "backgroundBorder": { + "visualType": "IMAGE", + "url": "{DALI_IMAGE_DIR}selection-popup-border.9.png", + "mixColor":[0.24,0.72,0.8,1.0] + }, + "popupFadeInDuration":0.25, + "popupFadeOutDuration":0.25 + }, + "TextSelectionPopupButton": + { + "label": + { + "visualType":"TEXT", + "pointSize":24 + }, + "unselectedBackgroundVisual": + { + "visualType": "IMAGE", + "url": "" + }, + "selectedBackgroundVisual": + { + "visualType": "IMAGE", + "url": "" + } + }, + "TextSelectionToolbar": + { + "enableOvershoot":true, + "enableScrollBar":true, + "scrollView": + { + "overshootAnimationSpeed":360.0, + "overshootSize":[1920.0,130.0] + } + }, + "TextSelectionScrollBar": + { + "indicatorShowDuration":0.25, + "indicatorHideDuration":0.25, + "indicatorTransientDuration":1.0 + }, + "TextSelectionScrollIndicator": + { + "image": + { + "visualType":"IMAGE", + "url":"{DALI_IMAGE_DIR}text_selection_scroll_indicator.9.png" + }, + "color":[0.0,0.72,0.9,0.7] + }, + "ScrollView": + { + "overshootEffectColor":"B018", + "overshootAnimationSpeed":960.0, + "overshootSize":[1920.0,130.0] + }, + "ItemView": + { + "overshootEffectColor":"B018", + "overshootAnimationSpeed":960.0, + "overshootSize":[1920.0,130.0] + }, + "ScrollBar": + { + "indicatorShowDuration":0.25, + "indicatorHideDuration":0.25, + "color":[0.0,0.72,0.9,0.7] + }, + "TextEditor": + { + "pointSize":24, + "primaryCursorColor":[0.0,0.72,0.9,1.0], + "secondaryCursorColor":[0.0,0.72,0.9,1.0], + "cursorWidth":6, + "selectionHighlightColor":[0.75,0.96,1.0,1.0], + "grabHandleImage" : "{DALI_STYLE_IMAGE_DIR}cursor_handler_drop_center.png", + "selectionHandleImageLeft" : {"filename":"{DALI_STYLE_IMAGE_DIR}selection_handle_drop_left.png" }, + "selectionHandleImageRight": {"filename":"{DALI_STYLE_IMAGE_DIR}selection_handle_drop_right.png" }, + "enableScrollBar":true, + "scrollBarShowDuration":0.8, + "scrollBarFadeDuration":0.5, + "enableSelection":false + }, + "ProgressBar": + { + "trackVisual":{ + "visualType":"IMAGE", + "url":"{DALI_IMAGE_DIR}progress-bar-skin-track.9.png" + }, + "progressVisual":{ + "visualType":"IMAGE", + "url":"{DALI_IMAGE_DIR}progress-bar-skin-progress.9.png" + }, + "secondaryProgressVisual":{ + "visualType":"IMAGE", + "url":"{DALI_IMAGE_DIR}progress-bar-skin-secondary-progress.9.png" + }, + "indeterminateVisual":{ + "visualType":"IMAGE", + "pixelArea":[0.0, 0.0, 10.0, 1.0], + "wrapModeU":"REPEAT", + "url":"{DALI_IMAGE_DIR}progress-bar-skin-indeterminate.png" + }, + "indeterminateVisualAnimation": + [ + { + "target":"indeterminateVisual", + "property":"pixelArea", + "initialValue":[0.0, 0.0, 10.0, 1.0], + "targetValue":[-1.0, 0.0, 10.0, 1.0], + "animator": + { + "alphaFunction":"DEFAULT", + "timePeriod": + { + "duration":0.8, + "delay":0 + } + } + } + ], + "labelVisual":{ + "visualType": "TEXT", + "textColor": [ 1.0, 1.0, 1.0, 1.0 ], + "pointSize" : 12.0, // Point size must always be provided to Text Visual + "horizontalAlignment": "CENTER", + "verticalAlignment": "CENTER" + }, + "progressValue": 0.0, + "secondaryProgressValue":0.0, + "indeterminate": false + }, + "CircularProgressBar": + { + "size":[64,64], + "trackVisual":{ + "visualType":"ARC", + "mixColor":[0.0,0.165,0.302,1.0], + "thickness":4.0, + "startAngle":0.0, + "cap":"ROUND" + }, + "progressVisual":{ + "visualType":"ARC", + "mixColor":[0.0,0.549,1.0,1.0], + "thickness":4.0, + "startAngle":0.0, + "cap":"ROUND" + }, + "secondaryProgressVisual":{ + "visualType":"ARC", + "mixColor":[0.0,0.549,1.0,0.3], + "thickness":4.0, + "startAngle":0.0, + "cap":"ROUND" + }, + "indeterminateVisual":{ + "visualType":"ARC", + "mixColor":[0.02,0.71,0.525,1.0], + "thickness":4.0, + "startAngle":267.0, + "sweepAngle":75.0, + "cap":"ROUND" + }, + "indeterminateVisualAnimation": + [ + { + "target":"trackVisual", + "property":"opacity", + "targetValue": 0, + "animator": + { + "alphaFunction":"DEFAULT", + "timePeriod": + { + "duration":0, + "delay":0 + } + } + }, + { + "target":"secondaryProgressVisual", + "property":"opacity", + "targetValue": 0, + "animator": + { + "alphaFunction":"DEFAULT", + "timePeriod": + { + "duration":0, + "delay":0 + } + } + }, + { + "target":"progressVisual", + "property":"sweepAngle", + "initialValue": 75, + "targetValue": 180, + "animator": + { + "alphaFunction":[0.439, 0.0, 0.718, 0.428], + "timePeriod": + { + "duration":1.0, + "delay":0.0 + } + } + }, + { + "target":"progressVisual", + "property":"sweepAngle", + "targetValue": 75, + "animator": + { + "alphaFunction":[0.224, 0.571, 0.53, 1.0], + "timePeriod": + { + "duration":1.0, + "delay":2.0 + } + } + }, + { + "target":"progressVisual", + "property":"startAngle", + "initialValue": 87, + "targetValue": 1887, + "animator": + { + "alphaFunction":[0.33, 0.0, 0.3, 1.0], + "timePeriod": + { + "duration":3.0, + "delay":0.0 + } + } + }, + { + "target":"indeterminateVisual", + "property":"sweepAngle", + "initialValue": 75, + "targetValue": 180, + "animator": + { + "alphaFunction":[0.439, 0.0, 0.718, 0.428], + "timePeriod": + { + "duration":1.0, + "delay":0.0 + } + } + }, + { + "target":"indeterminateVisual", + "property":"sweepAngle", + "targetValue": 75, + "animator": + { + "alphaFunction":[0.224, 0.571, 0.53, 1.0], + "timePeriod": + { + "duration":1.0, + "delay":2.0 + } + } + }, + { + "target":"indeterminateVisual", + "property":"startAngle", + "initialValue": 267, + "targetValue": 2067, + "animator": + { + "alphaFunction":[0.33, 0.0, 0.3, 1.0], + "timePeriod": + { + "duration":3.0, + "delay":0.0 + } + } + } + ], + "labelVisual":{ + "visualType": "TEXT", + "textColor": [ 1.0, 1.0, 1.0, 1.0 ], + "pointSize" : 32.0, // Point size must always be provided to Text Visual + "horizontalAlignment": "CENTER", + "verticalAlignment": "CENTER" + }, + "progressValue": 0.2, + "secondaryProgressValue":0.4, + "indeterminate": false + }, + "Button": + { + "styles":["Tooltip"], + "initialAutoRepeatingDelay":2.0, + "nextAutoRepeatingDelay":0.9 + // Note: Visuals added to Button will be used in all derived buttons unless overridden. + }, + "PushButton": + { + "styles":["Button"], + "autoRepeating":false, + "togglable":false, + "labelPadding":[ 12.0, 12.0, 12.0, 12.0 ], + "label": + { + "visualType": "TEXT", + "horizontalAlignment": "CENTER", + "pointSize" : 24.0, // Point size must always be provided to Text Visual + "verticalAlignment": "CENTER" + }, + "unselectedBackgroundVisual": + { + "visualType": "IMAGE", + "url": "{DALI_IMAGE_DIR}button-up.9.png" + }, + "selectedBackgroundVisual": + { + "visualType": "IMAGE", + "url": "{DALI_IMAGE_DIR}button-down.9.png" + }, + "disabledSelectedBackgroundVisual": + { + "visualType": "IMAGE", + "url": "{DALI_IMAGE_DIR}button-down-disabled.9.png" + }, + "disabledUnselectedBackgroundVisual": + { + "visualType": "IMAGE", + "url": "{DALI_IMAGE_DIR}button-disabled.9.png" + } + }, + "ToggleButton": + { + "styles":["Button"] + }, + "CheckBoxButton": + { + "styles":["Button"], + "labelPadding":[ 12.0, 12.0, 0.0, 0.0 ], + "label": + { + "visualType": "TEXT", + "pointSize" : 24.0, // Point size must always be provided to Text Visual + "verticalAlignment": "CENTER" + }, + "unselectedVisual": + { + "visualType": "IMAGE", + "url": "{DALI_IMAGE_DIR}checkbox-unselected.png" + }, + "selectedVisual": + { + "visualType": "IMAGE", + "url": "{DALI_IMAGE_DIR}checkbox-selected.png" + }, + "disabledUnselectedVisual": + { + "visualType": "IMAGE", + "url": "{DALI_IMAGE_DIR}checkbox-unselected-disabled.png" + }, + "disabledSelectedVisual": + { + "visualType": "IMAGE", + "url": "{DALI_IMAGE_DIR}checkbox-selected-disabled.png" + } + }, + "RadioButton": + { + "styles":["Button"], + "labelPadding":[ 12.0, 12.0, 0.0, 0.0 ], + "label": + { + "visualType": "TEXT", + "pointSize" : 24.0, // Point size must always be provided to Text Visual + "verticalAlignment": "CENTER" + }, + "unselectedVisual": + { + "visualType": "IMAGE", + "url": "{DALI_IMAGE_DIR}radio-button-unselected.png" + }, + "selectedVisual": + { + "visualType": "IMAGE", + "url": "{DALI_IMAGE_DIR}radio-button-selected.png" + }, + "disabledUnselectedVisual": + { + "visualType": "IMAGE", + "url": "{DALI_IMAGE_DIR}radio-button-unselected-disabled.png" + }, + "disabledSelectedVisual": + { + "visualType": "IMAGE", + "url": "{DALI_IMAGE_DIR}radio-button-selected-disabled.png" + } + } + } +} diff --git a/dali-toolkit/styles/1920x1080_rpi/images/cursor_handler_drop_center.png b/dali-toolkit/styles/1920x1080_rpi/images/cursor_handler_drop_center.png new file mode 100644 index 0000000..244096f Binary files /dev/null and b/dali-toolkit/styles/1920x1080_rpi/images/cursor_handler_drop_center.png differ diff --git a/dali-toolkit/styles/1920x1080_rpi/images/selection_handle_drop_left.png b/dali-toolkit/styles/1920x1080_rpi/images/selection_handle_drop_left.png new file mode 100644 index 0000000..244096f Binary files /dev/null and b/dali-toolkit/styles/1920x1080_rpi/images/selection_handle_drop_left.png differ diff --git a/dali-toolkit/styles/1920x1080_rpi/images/selection_handle_drop_right.png b/dali-toolkit/styles/1920x1080_rpi/images/selection_handle_drop_right.png new file mode 100644 index 0000000..244096f Binary files /dev/null and b/dali-toolkit/styles/1920x1080_rpi/images/selection_handle_drop_right.png differ diff --git a/packaging/dali-toolkit.spec b/packaging/dali-toolkit.spec index 1cf7e71..d9a1c86 100644 --- a/packaging/dali-toolkit.spec +++ b/packaging/dali-toolkit.spec @@ -1,6 +1,6 @@ Name: dali2-toolkit Summary: Dali 3D engine Toolkit -Version: 2.0.48 +Version: 2.0.52 Release: 1 Group: System/Libraries License: Apache-2.0 and BSD-3-Clause and MIT @@ -34,6 +34,7 @@ Requires: %{name} = %{version}-%{release} Conflicts: %{name}-resources_480x800 Conflicts: %{name}-resources_720x1280 Conflicts: %{name}-resources_1920x1080 +Conflicts: %{name}-resources_1920x1080_rpi %description resources_360x360 dali-toolkit default resource files for 360x360 Contain po / sounds / common images / style / style images @@ -44,6 +45,7 @@ Requires: %{name} = %{version}-%{release} Conflicts: %{name}-resources_360x360 Conflicts: %{name}-resources_720x1280 Conflicts: %{name}-resources_1920x1080 +Conflicts: %{name}-resources_1920x1080_rpi %description resources_480x800 dali-toolkit default resource files for 480x800 Contain po / sounds / common images / style / style images @@ -54,6 +56,7 @@ Requires: %{name} = %{version}-%{release} Conflicts: %{name}-resources_360x360 Conflicts: %{name}-resources_480x800 Conflicts: %{name}-resources_1920x1080 +Conflicts: %{name}-resources_1920x1080_rpi %description resources_720x1280 dali-toolkit default resource files for 720x1280 Contain po / sounds / common images / style / style images @@ -64,10 +67,23 @@ Requires: %{name} = %{version}-%{release} Conflicts: %{name}-resources_360x360 Conflicts: %{name}-resources_480x800 Conflicts: %{name}-resources_720x1280 +Conflicts: %{name}-resources_1920x1080_rpi %description resources_1920x1080 dali-toolkit default resource files for 1920x1080 Contain po / sounds / common images / style / style images +%package resources_1920x1080_rpi +Summary: default resource files for 1920x1080 on Raspberry Pi 4 +Requires: %{name} = %{version}-%{release} +Conflicts: %{name}-resources_360x360 +Conflicts: %{name}-resources_480x800 +Conflicts: %{name}-resources_720x1280 +Conflicts: %{name}-resources_1920x1080 +%description resources_1920x1080_rpi +dali-toolkit default resource files for 1920x1080 on Raspberry Pi 4 +Contain po / sounds / common images / style / style images + + ############################## # devel ############################## @@ -199,6 +215,8 @@ mkdir -p %{buildroot}%{dali_toolkit_style_files}/720x1280 cp -r dali-toolkit/styles/720x1280/* %{buildroot}%{dali_toolkit_style_files}/720x1280 mkdir -p %{buildroot}%{dali_toolkit_style_files}/1920x1080 cp -r dali-toolkit/styles/1920x1080/* %{buildroot}%{dali_toolkit_style_files}/1920x1080 +mkdir -p %{buildroot}%{dali_toolkit_style_files}/1920x1080_rpi +cp -r dali-toolkit/styles/1920x1080_rpi/* %{buildroot}%{dali_toolkit_style_files}/1920x1080_rpi # Copy default feedback theme cp dali-toolkit/styles/default-feedback-theme.json %{buildroot}%{dali_toolkit_style_files} @@ -244,6 +262,15 @@ case "$1" in ;; esac +%pre resources_1920x1080_rpi +case "$1" in + 2) + pushd %{dali_toolkit_style_files} + rm -rf ./* + popd + ;; +esac + ############################## # Post Install ############################## @@ -271,6 +298,11 @@ pushd %{dali_toolkit_style_files}/1920x1080 for FILE in *; do mv ./"${FILE}" ../"${FILE}"; done popd +%post resources_1920x1080_rpi +pushd %{dali_toolkit_style_files}/1920x1080_rpi +for FILE in *; do mv ./"${FILE}" ../"${FILE}"; done +popd + ############################## # Pre Uninstall ############################## @@ -319,6 +351,17 @@ case "$1" in ;; esac +%preun resources_1920x1080_rpi +case "$1" in + 0) + %preun resources_1920x1080_rpi + pushd %{dali_toolkit_style_files} + mv images ./1920x1080_rpi + mv dali-toolkit-default-theme.json ./1920x1080_rpi + popd + ;; +esac + ############################## # Post Uninstall ############################## @@ -362,6 +405,15 @@ case "$1" in ;; esac +%postun resources_1920x1080_rpi +case "$1" in + 0) + pushd %{dali_toolkit_style_files} + rm -rf * + popd + ;; +esac + ############################## # Files in Binary Packages ############################## @@ -417,6 +469,15 @@ esac %{dali_toolkit_style_files}/default-feedback-theme.json %{_datadir}/locale/*/LC_MESSAGES/* +%files resources_1920x1080_rpi +%manifest dali-toolkit-resources.manifest +%defattr(-,root,root,-) +%{dali_toolkit_image_files}/* +%{dali_toolkit_sound_files}/* +%{dali_toolkit_style_files}/1920x1080_rpi/* +%{dali_toolkit_style_files}/default-feedback-theme.json +%{_datadir}/locale/*/LC_MESSAGES/* + %files -n %{dali2_scene_loader} %if 0%{?enable_dali_smack_rules} %manifest dali-scene-loader.manifest-smack