Merge "Fix: The last line of the text overlaps with the text-editor's border/edge...
authorBowon Ryu <bowon.ryu@samsung.com>
Tue, 16 Nov 2021 09:27:48 +0000 (09:27 +0000)
committerGerrit Code Review <gerrit@review>
Tue, 16 Nov 2021 09:27:48 +0000 (09:27 +0000)
89 files changed:
automated-tests/src/dali-scene-loader/utc-Dali-StringCallback.cpp
automated-tests/src/dali-toolkit-internal/dali-toolkit-test-utils/accessibility-test-utils.cpp
automated-tests/src/dali-toolkit-internal/dali-toolkit-test-utils/accessibility-test-utils.h
automated-tests/src/dali-toolkit-internal/utc-Dali-Accessibility-Controls-BridgeUp.cpp
automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-application.cpp
automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-application.h
automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-canvas-renderer.cpp
automated-tests/src/dali-toolkit/utc-Dali-AnimatedVectorImageVisual.cpp
automated-tests/src/dali-toolkit/utc-Dali-ArcVisual.cpp
automated-tests/src/dali-toolkit/utc-Dali-CanvasView.cpp
automated-tests/src/dali-toolkit/utc-Dali-GlView.cpp
automated-tests/src/dali-toolkit/utc-Dali-TextLabel.cpp
automated-tests/src/dali-toolkit/utc-Dali-Transition.cpp
dali-toolkit/devel-api/controls/accessible-impl.cpp
dali-toolkit/devel-api/controls/accessible-impl.h
dali-toolkit/devel-api/controls/control-devel.cpp
dali-toolkit/devel-api/controls/control-devel.h
dali-toolkit/devel-api/file.list
dali-toolkit/devel-api/toolkit-action-index-ranges.h [new file with mode: 0644]
dali-toolkit/devel-api/visuals/animated-image-visual-actions-devel.h
dali-toolkit/devel-api/visuals/animated-vector-image-visual-actions-devel.h
dali-toolkit/devel-api/visuals/arc-visual-actions-devel.h [deleted file]
dali-toolkit/devel-api/visuals/image-visual-actions-devel.h
dali-toolkit/devel-api/visuals/visual-actions-devel.h [moved from dali-toolkit/devel-api/visuals/color-visual-actions-devel.h with 60% similarity]
dali-toolkit/internal/controls/canvas-view/canvas-view-impl.cpp
dali-toolkit/internal/controls/canvas-view/canvas-view-impl.h
dali-toolkit/internal/controls/canvas-view/canvas-view-rasterize-thread.cpp
dali-toolkit/internal/controls/canvas-view/canvas-view-rasterize-thread.h
dali-toolkit/internal/controls/control/control-data-impl.cpp
dali-toolkit/internal/controls/control/control-data-impl.h
dali-toolkit/internal/controls/flex-container/flex-container-impl.cpp
dali-toolkit/internal/controls/gl-view/gl-view-impl.cpp
dali-toolkit/internal/controls/gl-view/gl-view-impl.h
dali-toolkit/internal/controls/gl-view/gl-view-render-thread.cpp
dali-toolkit/internal/controls/gl-view/gl-view-render-thread.h
dali-toolkit/internal/controls/image-view/image-view-impl.cpp
dali-toolkit/internal/controls/image-view/image-view-impl.h
dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-impl-constraints.cpp [new file with mode: 0644]
dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-impl-constraints.h [new file with mode: 0644]
dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-impl.cpp
dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-impl.h
dali-toolkit/internal/controls/table-view/table-view-impl.cpp
dali-toolkit/internal/controls/text-controls/common-text-utils.cpp [new file with mode: 0644]
dali-toolkit/internal/controls/text-controls/common-text-utils.h [new file with mode: 0644]
dali-toolkit/internal/controls/text-controls/text-editor-impl.cpp
dali-toolkit/internal/controls/text-controls/text-editor-impl.h
dali-toolkit/internal/controls/text-controls/text-editor-property-handler.cpp [new file with mode: 0644]
dali-toolkit/internal/controls/text-controls/text-editor-property-handler.h [new file with mode: 0644]
dali-toolkit/internal/controls/text-controls/text-field-impl.cpp
dali-toolkit/internal/controls/text-controls/text-field-impl.h
dali-toolkit/internal/controls/text-controls/text-field-property-handler.cpp [new file with mode: 0644]
dali-toolkit/internal/controls/text-controls/text-field-property-handler.h [new file with mode: 0644]
dali-toolkit/internal/file.list
dali-toolkit/internal/graphics/shaders/color-visual-shader.frag
dali-toolkit/internal/text/multi-language-support-impl.cpp
dali-toolkit/internal/text/rendering/view-model.cpp
dali-toolkit/internal/text/text-controller-impl-model-updater.cpp [new file with mode: 0644]
dali-toolkit/internal/text/text-controller-impl-model-updater.h [new file with mode: 0644]
dali-toolkit/internal/text/text-controller-impl.cpp
dali-toolkit/internal/text/text-controller-impl.h
dali-toolkit/internal/text/text-controller.cpp
dali-toolkit/internal/text/text-controller.h
dali-toolkit/internal/transition/transition-base-impl.cpp
dali-toolkit/internal/transition/transition-base-impl.h
dali-toolkit/internal/transition/transition-impl.cpp
dali-toolkit/internal/transition/transition-impl.h
dali-toolkit/internal/transition/transition-set-impl.cpp
dali-toolkit/internal/visuals/animated-image/animated-image-visual.cpp
dali-toolkit/internal/visuals/animated-image/animated-image-visual.h
dali-toolkit/internal/visuals/animated-vector-image/animated-vector-image-visual.cpp
dali-toolkit/internal/visuals/arc/arc-visual.cpp
dali-toolkit/internal/visuals/arc/arc-visual.h
dali-toolkit/internal/visuals/color/color-visual.cpp
dali-toolkit/internal/visuals/color/color-visual.h
dali-toolkit/internal/visuals/text/text-visual.cpp
dali-toolkit/internal/visuals/text/text-visual.h
dali-toolkit/internal/visuals/visual-base-impl.cpp
dali-toolkit/public-api/controls/control-impl.cpp
dali-toolkit/public-api/controls/control-impl.h
dali-toolkit/public-api/controls/gl-view/gl-view.cpp
dali-toolkit/public-api/controls/gl-view/gl-view.h
dali-toolkit/public-api/dali-toolkit-version.cpp
dali-toolkit/public-api/transition/transition.cpp
dali-toolkit/public-api/transition/transition.h
dali-toolkit/styles/1920x1080_rpi/dali-toolkit-default-theme.json [new file with mode: 0644]
dali-toolkit/styles/1920x1080_rpi/images/cursor_handler_drop_center.png [new file with mode: 0644]
dali-toolkit/styles/1920x1080_rpi/images/selection_handle_drop_left.png [new file with mode: 0644]
dali-toolkit/styles/1920x1080_rpi/images/selection_handle_drop_right.png [new file with mode: 0644]
packaging/dali-toolkit.spec

index acd5183..113f40a 100644 (file)
@@ -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;
 }
index a9d9f03..b654d52 100644 (file)
 #include <dali/devel-api/adaptor-framework/accessibility-impl.h>
 #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<TestDBusWrapper*>(DBusWrapper::Installed());
-
-                wr->testMethods[std::tuple<std::string, std::string, std::string, MethodType>{"/org/a11y/bus", "org.a11y.Status", "ScreenReaderEnabled", MethodType::Getter}] = [wr](const MessagePtr &m) -> MessagePtr {
-                    auto reply = wr->newReplyMessage(m);
-                    wr->Encode(reply, std::tuple<TestDBusWrapper::Variant<bool>>{ ScreenReaderEnabled });
-                    return reply;
-                };
-                wr->testMethods[std::tuple<std::string, std::string, std::string, MethodType>{"/org/a11y/bus", "org.a11y.Status", "IsEnabled", MethodType::Getter}] = [wr](const MessagePtr &m) -> MessagePtr {
-                    auto reply = wr->newReplyMessage(m);
-                    wr->Encode(reply, std::tuple<TestDBusWrapper::Variant<bool>>{ IsEnabled });
-                    return reply;
-                };
-                wr->testMethods[std::tuple<std::string, std::string, std::string, MethodType>{"/org/a11y/bus", "org.a11y.Bus", "GetAddress", MethodType::Method}] = [wr](const MessagePtr &m) -> MessagePtr {
-                    auto reply = wr->newReplyMessage(m);
-                    wr->Encode(reply, std::tuple<const char*>{ "bus" });
-                    return reply;
-                };
-                wr->testMethods[std::tuple<std::string, std::string, std::string, MethodType>{"/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<Address>{ {"bus", "root"} });
-                    return reply;
-                };
-                wr->testMethods[std::tuple<std::string, std::string, std::string, MethodType>{"/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<std::string, std::string, std::string, MethodType>{"/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<std::string, std::string, std::string, MethodType>{"/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<std::string, std::string, std::string, MethodType>{"/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<std::string, std::string, std::string, MethodType>{"/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<std::string, std::string, std::string, MethodType>{"/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<std::string, std::string, std::string, MethodType>{"/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<TestDBusWrapper*>(DBusWrapper::Installed());
-            wr->fromTestChangeProperty("/org/a11y/bus", "org.a11y.Status", "ScreenReaderEnabled", b);
-            wr->fromTestChangeProperty("/org/a11y/bus", "org.a11y.Status", "IsEnabled", b);
-        }
-
-        std::vector<Address> TestGetChildren(const Address &adr)
-        {
-            auto wr = static_cast<TestDBusWrapper*>(DBusWrapper::Installed());
-            auto chs = wr->fromTestCall<std::vector<Address>>(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<TestDBusWrapper*>(DBusWrapper::Installed());
-            auto name = wr->fromTestGet<std::string>(adr.GetPath(), "org.a11y.atspi.Accessible", "Name");
-            return name;
-        }
-
-        std::string TestGetDescription(const Address &adr)
-        {
-            auto wr = static_cast<TestDBusWrapper*>(DBusWrapper::Installed());
-            auto description = wr->fromTestGet<std::string>(adr.GetPath(), "org.a11y.atspi.Accessible", "Description");
-            return description;
-        }
-
-        uint32_t TestGetRole(const Address &adr)
-        {
-            auto wr = static_cast<TestDBusWrapper*>(DBusWrapper::Installed());
-            auto chs = wr->fromTestCall<uint32_t>(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<TestDBusWrapper*>(DBusWrapper::Installed());
-            auto chs = wr->fromTestCall<std::string>(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<TestDBusWrapper*>(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<TestDBusWrapper*>(DBusWrapper::Installed());
-            auto chs = wr->fromTestCall<std::string>(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<TestDBusWrapper*>(DBusWrapper::Installed());
-            auto chs = wr->fromTestCall<std::array< uint32_t, 2 >>(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<TestDBusWrapper*>(DBusWrapper::Installed());
-            auto chs = wr->fromTestCall<std::unordered_map< std::string, std::string >>(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<TestDBusWrapper*>(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<TestDBusWrapper*>(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<TestDBusWrapper*>(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<TestDBusWrapper*>(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<TestDBusWrapper*>(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<TestDBusWrapper*>(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<TestDBusWrapper*>(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<TestDBusWrapper*>(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<TestDBusWrapper*>(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<uint32_t>(coordinateType)));
-            return std::move(std::get<0>(chs));
-        }
-
-        int TestGetMdiZOrder(const Address &adr)
-        {
-            auto wr = static_cast<TestDBusWrapper*>(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<TestDBusWrapper*>(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<TestDBusWrapper*>(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<TestDBusWrapper*>(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<TestDBusWrapper*>(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<TestDBusWrapper*>(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<TestDBusWrapper*>(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<TestDBusWrapper*>(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<TestDBusWrapper*>(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<TestDBusWrapper*>(DBusWrapper::Installed());
+
+      wr->testMethods[std::tuple<std::string, std::string, std::string, MethodType>{"/org/a11y/bus", "org.a11y.Status", "ScreenReaderEnabled", MethodType::Getter}] = [wr](const MessagePtr &m) -> MessagePtr {
+          auto reply = wr->newReplyMessage(m);
+          wr->Encode(reply, std::tuple<TestDBusWrapper::Variant<bool>>{ ScreenReaderEnabled });
+          return reply;
+      };
+      wr->testMethods[std::tuple<std::string, std::string, std::string, MethodType>{"/org/a11y/bus", "org.a11y.Status", "IsEnabled", MethodType::Getter}] = [wr](const MessagePtr &m) -> MessagePtr {
+          auto reply = wr->newReplyMessage(m);
+          wr->Encode(reply, std::tuple<TestDBusWrapper::Variant<bool>>{ IsEnabled });
+          return reply;
+      };
+      wr->testMethods[std::tuple<std::string, std::string, std::string, MethodType>{"/org/a11y/bus", "org.a11y.Bus", "GetAddress", MethodType::Method}] = [wr](const MessagePtr &m) -> MessagePtr {
+          auto reply = wr->newReplyMessage(m);
+          wr->Encode(reply, std::tuple<const char*>{ "bus" });
+          return reply;
+      };
+      wr->testMethods[std::tuple<std::string, std::string, std::string, MethodType>{"/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<Address>{ {"bus", "root"} });
+          return reply;
+      };
+      wr->testMethods[std::tuple<std::string, std::string, std::string, MethodType>{"/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<std::string, std::string, std::string, MethodType>{"/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<std::string, std::string, std::string, MethodType>{"/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<std::string, std::string, std::string, MethodType>{"/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<std::string, std::string, std::string, MethodType>{"/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<std::string, std::string, std::string, MethodType>{"/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<std::string, std::string, std::string, MethodType>{"/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<TestDBusWrapper*>(DBusWrapper::Installed());
+    wr->fromTestChangeProperty("/org/a11y/bus", "org.a11y.Status", "ScreenReaderEnabled", b);
+    wr->fromTestChangeProperty("/org/a11y/bus", "org.a11y.Status", "IsEnabled", b);
+  }
+
+  std::vector<Address> TestGetChildren(const Address &adr)
+  {
+    auto wr = static_cast<TestDBusWrapper*>(DBusWrapper::Installed());
+    auto chs = wr->fromTestCall<std::vector<Address>>(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<TestDBusWrapper*>(DBusWrapper::Installed());
+    auto name = wr->fromTestGet<std::string>(adr.GetPath(), "org.a11y.atspi.Accessible", "Name");
+    return name;
+  }
+
+  std::string TestGetDescription(const Address &adr)
+  {
+    auto wr = static_cast<TestDBusWrapper*>(DBusWrapper::Installed());
+    auto description = wr->fromTestGet<std::string>(adr.GetPath(), "org.a11y.atspi.Accessible", "Description");
+    return description;
+  }
+
+  uint32_t TestGetRole(const Address &adr)
+  {
+    auto wr = static_cast<TestDBusWrapper*>(DBusWrapper::Installed());
+    auto chs = wr->fromTestCall<uint32_t>(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<TestDBusWrapper*>(DBusWrapper::Installed());
+    auto chs = wr->fromTestCall<std::string>(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<TestDBusWrapper*>(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<TestDBusWrapper*>(DBusWrapper::Installed());
+    auto chs = wr->fromTestCall<std::string>(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<TestDBusWrapper*>(DBusWrapper::Installed());
+    auto chs = wr->fromTestCall<std::array< uint32_t, 2 >>(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<TestDBusWrapper*>(DBusWrapper::Installed());
+    auto chs = wr->fromTestCall<std::unordered_map< std::string, std::string >>(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<TestDBusWrapper*>(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<TestDBusWrapper*>(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<TestDBusWrapper*>(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<TestDBusWrapper*>(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<TestDBusWrapper*>(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<TestDBusWrapper*>(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<TestDBusWrapper*>(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<TestDBusWrapper*>(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<TestDBusWrapper*>(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<uint32_t>(coordinateType)));
+    return std::move(std::get<0>(chs));
+  }
+
+  int TestGetMdiZOrder(const Address &adr)
+  {
+    auto wr = static_cast<TestDBusWrapper*>(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<TestDBusWrapper*>(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<TestDBusWrapper*>(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<TestDBusWrapper*>(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<TestDBusWrapper*>(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<TestDBusWrapper*>(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<TestDBusWrapper*>(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<TestDBusWrapper*>(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<TestDBusWrapper*>(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
index 6c172fd..92388e2 100644 (file)
@@ -3,42 +3,43 @@
 
 #include <dali/devel-api/adaptor-framework/accessibility.h>
 
-
-namespace Dali {
-    namespace Accessibility {
-        void TestEnableSC(bool b);
-        std::vector<Address> 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<Address> 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__
index 0b1ec0e..047018d 100644 (file)
@@ -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;
index 5e69c95..440270a 100644 (file)
@@ -19,6 +19,8 @@
 
 namespace Dali
 {
+const Rect<int> TestApplication::DEFAULT_SURFACE_RECT = Rect<int>(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<Rect<int>>& damagedRects, Rect<int>& 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*/);
 
index 4f32cd8..02143a7 100644 (file)
@@ -38,6 +38,8 @@ public:
   static const uint32_t DEFAULT_SURFACE_WIDTH  = 480;
   static const uint32_t DEFAULT_SURFACE_HEIGHT = 800;
 
+  static const Rect<int> DEFAULT_SURFACE_RECT;
+
   static constexpr uint32_t DEFAULT_HORIZONTAL_DPI = 220;
   static constexpr uint32_t DEFAULT_VERTICAL_DPI   = 217;
 
index 56c0cd8..43aa8ce 100644 (file)
@@ -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)
index 7f43240..1eb713e 100644 (file)
@@ -27,6 +27,7 @@
 #include <dali-toolkit/devel-api/controls/control-devel.h>
 #include <dali-toolkit/devel-api/visuals/visual-properties-devel.h>
 #include <dali-toolkit/devel-api/visuals/image-visual-properties-devel.h>
+#include <dali-toolkit/devel-api/visuals/visual-actions-devel.h>
 #include <dali-toolkit/devel-api/visuals/animated-vector-image-visual-actions-devel.h>
 #include <dali-toolkit/devel-api/visuals/animated-vector-image-visual-signals-devel.h>
 #include <dali/devel-api/rendering/renderer-devel.h>
@@ -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() );
 
index 583ce16..146a1b5 100644 (file)
@@ -22,7 +22,7 @@
 #include <dali-toolkit/devel-api/controls/control-devel.h>
 #include <dali-toolkit/devel-api/visuals/visual-properties-devel.h>
 #include <dali-toolkit/devel-api/visuals/arc-visual-properties-devel.h>
-#include <dali-toolkit/devel-api/visuals/arc-visual-actions-devel.h>
+#include <dali-toolkit/devel-api/visuals/visual-actions-devel.h>
 #include <dali/devel-api/rendering/renderer-devel.h>
 #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();
index 36cf1df..cee41e0 100644 (file)
@@ -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<Dali::Toolkit::Internal::CanvasRendererRasterizingTask> 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<Dali::Toolkit::Internal::CanvasRendererRasterizingTask> 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<Dali::Toolkit::Internal::CanvasRendererRasterizingTask> task = new Dali::Toolkit::Internal::CanvasRendererRasterizingTask(dummyInternalCanvasView, dummyCanvasRenderer);
+  IntrusivePtr<Dali::Toolkit::Internal::CanvasRendererRasterizingTask> 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();
index 9f74b72..9cefe16 100644 (file)
@@ -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));
index 5495c9d..c9453e1 100644 (file)
@@ -836,6 +836,13 @@ int UtcDaliToolkitTextLabelEmojisP(void)
   application.SendNotification();
   application.Render();
 
+  // EMOJI + ZWJ + EMOJI case for coverage.
+  const std::string emojiWithZWJ = "&#x1f469;&#x200d;&#x1f52c;";
+  label.SetProperty( TextLabel::Property::TEXT, emojiWithZWJ );
+
+  application.SendNotification();
+  application.Render();
+
   END_TEST;
 }
 
index 7e36d2c..0ead710 100755 (executable)
@@ -24,6 +24,8 @@
 #include <dali-toolkit/public-api/transition/transition-set.h>
 #include <dali-toolkit/public-api/transition/transition-base.h>
 #include <dali-toolkit/public-api/transition/transition.h>
+#include <dali-toolkit/public-api/transition/fade-transition.h>
+#include <dali-toolkit/public-api/transition/slide-transition.h>
 
 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<Vector3>(Actor::Property::POSITION), TEST_LOCATION);
+  Property::Map backgroundMap = control2.GetProperty<Property::Map>(Toolkit::Control::Property::BACKGROUND);
+  Vector4 cornerRadius = backgroundMap.Find(Toolkit::DevelVisual::Property::CORNER_RADIUS)->Get<Vector4>();
+  DALI_TEST_EQUALS(destinationRadiusV4, cornerRadius, TEST_LOCATION);
+  float borderlineWidth = backgroundMap.Find(Toolkit::DevelVisual::Property::BORDERLINE_WIDTH)->Get<float>();
+  DALI_TEST_EQUALS(destinationBorderlineWidth, borderlineWidth, TEST_LOCATION);
+  Vector4 borderlineColor = backgroundMap.Find(Toolkit::DevelVisual::Property::BORDERLINE_COLOR)->Get<Vector4>();
+  DALI_TEST_EQUALS(destinationBorderlineColor, borderlineColor, TEST_LOCATION);
+  float borderlineOffset = backgroundMap.Find(Toolkit::DevelVisual::Property::BORDERLINE_OFFSET)->Get<float>();
+  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<Vector3>(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<Vector4>(index);
+  DALI_TEST_NOT_EQUALS(destinationRadiusV4, cornerRadius, 0.00001f, TEST_LOCATION);
+
+  index = renderer.GetPropertyIndex(DevelVisual::Property::BORDERLINE_WIDTH);
+  borderlineWidth = renderer.GetCurrentProperty<float>(index);
+  DALI_TEST_NOT_EQUALS(destinationBorderlineWidth, borderlineWidth, 0.00001f, TEST_LOCATION);
+
+  index = renderer.GetPropertyIndex(DevelVisual::Property::BORDERLINE_COLOR);
+  borderlineColor = renderer.GetCurrentProperty<Vector4>(index);
+  DALI_TEST_NOT_EQUALS(destinationBorderlineColor, borderlineColor, 0.00001f, TEST_LOCATION);
+
+  index = renderer.GetPropertyIndex(DevelVisual::Property::BORDERLINE_OFFSET);
+  borderlineOffset = renderer.GetCurrentProperty<float>(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<Vector3>(Actor::Property::POSITION), TEST_LOCATION);
+  DALI_TEST_EQUALS(destinationSize, control1.GetCurrentProperty<Vector3>(Actor::Property::SIZE), TEST_LOCATION);
+  DALI_TEST_EQUALS(destinationScale, control1.GetCurrentProperty<Vector3>(Actor::Property::SCALE), TEST_LOCATION);
+  DALI_TEST_EQUALS(destinationColor, control1.GetCurrentProperty<Vector4>(Actor::Property::COLOR), TEST_LOCATION);
+  DALI_TEST_EQUALS(destinationOpacity, control1.GetCurrentProperty<float>(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<Vector4>(index);
+  DALI_TEST_EQUALS(destinationRadiusV4, cornerRadius, TEST_LOCATION);
+
+  index = renderer.GetPropertyIndex(DevelVisual::Property::BORDERLINE_WIDTH);
+  borderlineWidth = renderer.GetCurrentProperty<float>(index);
+  DALI_TEST_EQUALS(destinationBorderlineWidth, borderlineWidth, TEST_LOCATION);
+
+  index = renderer.GetPropertyIndex(DevelVisual::Property::BORDERLINE_COLOR);
+  borderlineColor = renderer.GetCurrentProperty<Vector4>(index);
+  DALI_TEST_EQUALS(destinationBorderlineColor, borderlineColor, TEST_LOCATION);
+
+  index = renderer.GetPropertyIndex(DevelVisual::Property::BORDERLINE_OFFSET);
+  borderlineOffset = renderer.GetCurrentProperty<float>(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<Vector3>(Actor::Property::POSITION), TEST_LOCATION);
+  DALI_TEST_EQUALS(sourceSize, control1.GetProperty<Vector3>(Actor::Property::SIZE), TEST_LOCATION);
+  DALI_TEST_EQUALS(sourceScale, control1.GetProperty<Vector3>(Actor::Property::SCALE), TEST_LOCATION);
+  DALI_TEST_EQUALS(sourceColor, control1.GetProperty<Vector4>(Actor::Property::COLOR), TEST_LOCATION);
+  DALI_TEST_EQUALS(sourceOpacity, control1.GetProperty<float>(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<Vector4>(index);
+  DALI_TEST_EQUALS(sourceRadiusV4, cornerRadius, TEST_LOCATION);
+
+  index = renderer.GetPropertyIndex(DevelVisual::Property::BORDERLINE_WIDTH);
+  borderlineWidth = renderer.GetCurrentProperty<float>(index);
+  DALI_TEST_EQUALS(sourceBorderlineWidth, borderlineWidth, TEST_LOCATION);
+
+  index = renderer.GetPropertyIndex(DevelVisual::Property::BORDERLINE_COLOR);
+  borderlineColor = renderer.GetCurrentProperty<Vector4>(index);
+  DALI_TEST_EQUALS(sourceBorderlineColor, borderlineColor, TEST_LOCATION);
+
+  index = renderer.GetPropertyIndex(DevelVisual::Property::BORDERLINE_OFFSET);
+  borderlineOffset = renderer.GetCurrentProperty<float>(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<Vector3>(Actor::Property::WORLD_POSITION);
   Vector3 finishWorldPosition = control2.GetProperty<Vector3>(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<Vector3>(Actor::Property::WORLD_POSITION);
   Vector3 finishWorldPosition = control2.GetProperty<Vector3>(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<float>(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<float>(Actor::Property::OPACITY);
+  DALI_TEST_CHECK(currentOpacity == 0.0f);
+
+  application.SendNotification();
+  application.Render(400);
+
+  currentOpacity = control.GetCurrentProperty<float>(Actor::Property::OPACITY);
+  DALI_TEST_CHECK(currentOpacity == 0.5f);
+
+  application.SendNotification();
+  application.Render(500);
+
+  currentOpacity = control.GetCurrentProperty<float>(Actor::Property::OPACITY);
+  DALI_TEST_CHECK(currentOpacity > 0.5f && currentOpacity < 1.0f);
+
+  application.SendNotification();
+  application.Render(500);
+
+  currentOpacity = control.GetCurrentProperty<float>(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<float>(Actor::Property::OPACITY), TEST_LOCATION);
+
+  END_TEST;
+}
index 9f1c78e..9f6f4f9 100644 (file)
@@ -363,7 +363,6 @@ void AccessibleImpl::ScrollToSelf()
       parent->ScrollToChild(child->Self());
     }
 
-    child = parent;
     parent = dynamic_cast<Toolkit::DevelControl::AccessibleImpl*>(parent->GetParent());
   }
 }
@@ -542,6 +541,11 @@ std::vector<Dali::Accessibility::Relation> AccessibleImpl::GetRelationSet()
   return ret;
 }
 
+Dali::Actor AccessibleImpl::GetInternalActor()
+{
+  return Dali::Actor{};
+}
+
 bool AccessibleImpl::ScrollToChild(Actor child)
 {
   return false;
index aa5084a..8bd0714 100644 (file)
@@ -226,12 +226,17 @@ public:
   std::vector<Dali::Accessibility::Relation> 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);
index 55becb3..dc7a128 100644 (file)
@@ -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);
index 36b83f9..8877646 100644 (file)
@@ -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
  */
index e94f60b..c88b7a0 100755 (executable)
@@ -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 (file)
index 0000000..8e5dbc4
--- /dev/null
@@ -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 <dali/public-api/object/property-index-ranges.h>
+
+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
index dbe9631..94ae63c 100644 (file)
@@ -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 <dali-toolkit/devel-api/toolkit-action-index-ranges.h>
 
 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
index 2955d17..ecb91ae 100644 (file)
@@ -17,6 +17,7 @@
  * limitations under the License.
  *
  */
+#include <dali-toolkit/devel-api/toolkit-action-index-ranges.h>
 
 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 (file)
index 9657084..0000000
+++ /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
index 89ea2d6..66b4715 100644 (file)
@@ -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 <dali-toolkit/devel-api/toolkit-action-index-ranges.h>
 
 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
@@ -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.
  *
  */
 
+// EXTERNAL INCLUDES
+#include <dali-toolkit/devel-api/toolkit-action-index-ranges.h>
+
 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
index 5741a42..e8fefbf 100644 (file)
@@ -23,6 +23,7 @@
 #include <dali/integration-api/adaptor-framework/adaptor.h>
 #include <dali/public-api/object/type-registry-helper.h>
 #include <dali/public-api/object/type-registry.h>
+#include <dali/devel-api/rendering/texture-devel.h>
 
 // INTERNAL INCLUDES
 #include <dali-toolkit/devel-api/controls/control-devel.h>
@@ -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.
index 6b6cf93..4e492eb 100644 (file)
@@ -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;
index 97835c5..ba3daae 100644 (file)
@@ -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();
index 0c16fd9..f89bb91 100644 (file)
@@ -25,7 +25,6 @@
 #include <dali/devel-api/threading/thread.h>
 #include <dali/integration-api/adaptor-framework/log-factory-interface.h>
 #include <dali/public-api/common/intrusive-ptr.h>
-#include <dali/public-api/images/pixel-data.h>
 #include <dali/public-api/object/ref-object.h>
 #include <dali/public-api/rendering/texture-set.h>
 #include <memory>
@@ -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<void(PixelData)>;
+  using RasterizationCompletedSignalType = Signal<void(Texture)>;
 
 public:
   /**
index f9f4376..d9a554e 100644 (file)
@@ -36,6 +36,7 @@
 #include <limits>
 
 // INTERNAL INCLUDES
+#include <dali-toolkit/devel-api/visuals/visual-actions-devel.h>
 #include <dali-toolkit/devel-api/asset-manager/asset-manager.h>
 #include <dali-toolkit/devel-api/controls/control-depth-index-ranges.h>
 #include <dali-toolkit/devel-api/controls/control-devel.h>
@@ -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<std::pair<Dali::Property::Index, Dali::Property::Map>>& sourceProperties,
+                                      std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>>& destinationProperties,
+                                      Dali::Toolkit::Control source, Dali::Toolkit::Control destination)
 {
-  Dali::Toolkit::Control sourceHandle      = Dali::Toolkit::Control::DownCast(source);
-  Property::Map          sourceMap         = sourceHandle.GetProperty<Property::Map>(visualIndex);
-  Dali::Toolkit::Control destinationHandle = Dali::Toolkit::Control::DownCast(mControlImpl.Self());
-  Property::Map          destinationMap    = destinationHandle.GetProperty<Property::Map>(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<Vector4>();
-      }
-      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<float>();
-      }
-      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<Dali::Property>                              properties;
-    std::vector<std::pair<Property::Value, Property::Value>> 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<Dali::Property::Index, Dali::Property::Map>(Toolkit::Control::Property::BACKGROUND, backgroundSourcePropertyMap));
+    destinationProperties.push_back(std::pair<Dali::Property::Index, Dali::Property::Map>(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<Dali::Property::Index, Dali::Property::Map>(Toolkit::DevelControl::Property::SHADOW, shadowSourcePropertyMap));
+    destinationProperties.push_back(std::pair<Dali::Property::Index, Dali::Property::Map>(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<std::pair<Dali::Property::Index, Dali::Property::Map>>& 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()
index 94da0fc..55c49a6 100644 (file)
@@ -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<std::pair<Dali::Property::Index, Dali::Property::Map>>& sourceProperties,
+                         std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>>& 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<std::pair<Dali::Property::Index, Dali::Property::Map>>& properties);
 
   /**
    * @brief Gets the current control's accessible object.
index a3c092d..4a3b065 100644 (file)
@@ -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)
index 64e31d6..b37189a 100644 (file)
@@ -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);
   }
 }
 
index c0114ca..2dcb0b1 100644 (file)
@@ -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()
index db2e98c..3e84cfd 100644 (file)
@@ -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)
   {
index c27c832..753526e 100644 (file)
@@ -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()
index e3701ec..1a653a1 100644 (file)
@@ -24,6 +24,7 @@
 #include <dali/public-api/object/type-registry.h>
 
 // INTERNAL INCLUDES
+#include <dali-toolkit/devel-api/visuals/visual-actions-devel.h>
 #include <dali-toolkit/devel-api/controls/control-devel.h>
 #include <dali-toolkit/devel-api/visual-factory/visual-factory.h>
 #include <dali-toolkit/internal/controls/control/control-data-impl.h>
@@ -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<std::pair<Dali::Property::Index, Dali::Property::Map>>& sourceProperties,
+                                    std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>>& 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<Vector4>();
-    }
-    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<float>();
-    }
-    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<Dali::Property::Index, Dali::Property::Map>(Toolkit::ImageView::Property::IMAGE, imageSourcePropertyMap));
+    destinationProperties.push_back(std::pair<Dali::Property::Index, Dali::Property::Map>(Toolkit::ImageView::Property::IMAGE, imageDestinationPropertyMap));
   }
+}
 
-  std::vector<Dali::Property>                              properties;
-  std::vector<std::pair<Property::Value, Property::Value>> 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<std::pair<Dali::Property::Index, Dali::Property::Map>>& 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);
   }
 }
 
index 023930e..ef48839 100644 (file)
@@ -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<std::pair<Dali::Property::Index, Dali::Property::Map>>& sourceProperties,
+                                   std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>>& destinationProperties,
+                                   Dali::Toolkit::Control                                              source,
+                                   Dali::Toolkit::Control                                              destination) override;
+
+  /**
+   * @copydoc Toolkit::Control::OnUpdateVisualProperties()
+   */
+  virtual void OnUpdateVisualProperties(const std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>>& 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 (file)
index 0000000..24827dd
--- /dev/null
@@ -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 <dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-impl-constraints.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/public-api/controls/scrollable/scroll-view/scroll-view-constraints.h>
+#include <dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-impl.h>
+
+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<Vector2>(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<Vector2>(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<Vector2>(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<Vector2>(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<Vector2>(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<Vector2>(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<Vector2>(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<float>(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<float>(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<Vector3>(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<Vector3>(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 (file)
index 0000000..540a3fd
--- /dev/null
@@ -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 <dali/public-api/animation/constraint.h>
+
+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
index 8ca6855..86cfc56 100644 (file)
@@ -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
 // 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<Vector3>(Actor::Property::POSITION);
-  Vector3 childAnchor   = -actor.GetCurrentProperty<Vector3>(Actor::Property::ANCHOR_POINT) + anchor;
-  Vector3 childSize     = actor.GetCurrentProperty<Vector3>(Actor::Property::SIZE);
+  Dali::Vector3 childPosition = actor.GetCurrentProperty<Dali::Vector3>(Dali::Actor::Property::POSITION);
+  Dali::Vector3 childAnchor   = -actor.GetCurrentProperty<Dali::Vector3>(Dali::Actor::Property::ANCHOR_POINT) + anchor;
+  Dali::Vector3 childSize     = actor.GetCurrentProperty<Dali::Vector3>(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<Vector3>(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<Vector2>(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<Vector3>(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<Vector3>(Actor::Property::SIZE);
-  Vector3 position    = actor.GetCurrentProperty<Vector3>(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<Vector3>(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<Vector3>(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<Vector2>(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<Vector3>(Actor::Property::SIZE);
+  Vector3 position    = actor.GetCurrentProperty<Vector3>(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<Vector3>(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<Vector3>(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<Vector2>(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<Vector2>(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<Vector2>(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<Vector2>(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<Vector2>(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<Vector2>(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<Vector2>(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<float>(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<float>(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<Vector3>(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<Vector3>(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
index aee050e..4d871a7 100644 (file)
@@ -30,6 +30,7 @@
 #include <dali-toolkit/public-api/controls/control-impl.h>
 #include <dali-toolkit/public-api/controls/scrollable/scroll-view/scroll-view-effect.h>
 #include <dali-toolkit/public-api/controls/scrollable/scroll-view/scroll-view.h>
+#include <dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-impl-constraints.h>
 
 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<Toolkit::ScrollBar> 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
index 4b3e019..9aec5ba 100644 (file)
@@ -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 (file)
index 0000000..7331f3e
--- /dev/null
@@ -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 <dali/public-api/actors/layer.h>
+
+#include <dali-toolkit/devel-api/controls/control-depth-index-ranges.h>
+#include <dali-toolkit/internal/controls/text-controls/common-text-utils.h>
+#include <dali-toolkit/internal/text/text-view.h>
+
+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<Actor>&              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<Extents>(Toolkit::Control::Property::PADDING);
+
+      // Support Right-To-Left of padding
+      Dali::LayoutDirection::Type layoutDirection = static_cast<Dali::LayoutDirection::Type>(textActor.GetProperty(Dali::Actor::Property::LAYOUT_DIRECTION).Get<int>());
+      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<Actor>::iterator it    = clippingDecorationActors.begin(),
+                                     endIt = clippingDecorationActors.end();
+        it != endIt;
+        ++it)
+    {
+      self.Add(*it);
+      it->LowerToBottom();
+
+      if(it->GetProperty<std::string>(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 (file)
index 0000000..f2eaba7
--- /dev/null
@@ -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 <dali-toolkit/internal/text/decorator/text-decorator.h>
+#include <dali-toolkit/internal/text/rendering/text-renderer.h>
+#include <dali-toolkit/internal/text/text-controller.h>
+#include <dali-toolkit/public-api/controls/control.h>
+#include <dali-toolkit/public-api/controls/text-controls/text-editor.h>
+#include <dali/public-api/actors/actor.h>
+
+#include <dali/public-api/common/vector-wrapper.h>
+
+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<Actor>&              clippingDecorationActors,
+    Text::Controller::UpdateTextType updateTextType);
+};
+
+} // namespace Dali::Toolkit::Internal
+
+#endif //DALI_TOOLKIT_INTERNAL_TEXT_CONTROLS_COMMON_TEXT_UTILS_H
index 0bdc8c1..0259471 100644 (file)
@@ -24,6 +24,7 @@
 #include <dali/devel-api/object/property-helper-devel.h>
 #include <dali/integration-api/adaptor-framework/adaptor.h>
 #include <dali/integration-api/debug.h>
+#include <dali/public-api/actors/layer.h>
 #include <dali/public-api/adaptor-framework/key.h>
 #include <dali/public-api/common/dali-common.h>
 #include <dali/public-api/object/type-registry-helper.h>
 #include <limits>
 
 // INTERNAL INCLUDES
-#include <dali-toolkit/devel-api/controls/control-depth-index-ranges.h>
 #include <dali-toolkit/devel-api/controls/control-devel.h>
 #include <dali-toolkit/devel-api/focus-manager/keyinput-focus-manager.h>
 #include <dali-toolkit/devel-api/text/rendering-backend.h>
 #include <dali-toolkit/internal/controls/control/control-data-impl.h>
+#include <dali-toolkit/internal/controls/text-controls/common-text-utils.h>
+#include <dali-toolkit/internal/controls/text-controls/text-editor-property-handler.h>
 #include <dali-toolkit/internal/styling/style-manager-impl.h>
 #include <dali-toolkit/internal/text/rendering/text-backend.h>
 #include <dali-toolkit/internal/text/text-effects-style.h>
 
 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<InputStyle::Mask>(inputStyleMask & InputStyle::INPUT_COLOR))
   {
-    const Property::Value* filenameValue = map->Find(IMAGE_MAP_FILENAME_STRING);
-    if(filenameValue)
-    {
-      filenameValue->Get(filename);
-    }
+    editorInputStyleMask = static_cast<Toolkit::TextEditor::InputStyle::Mask>(editorInputStyleMask | Toolkit::TextEditor::InputStyle::COLOR);
+  }
+  if(InputStyle::NONE != static_cast<InputStyle::Mask>(inputStyleMask & InputStyle::INPUT_FONT_FAMILY))
+  {
+    editorInputStyleMask = static_cast<Toolkit::TextEditor::InputStyle::Mask>(editorInputStyleMask | Toolkit::TextEditor::InputStyle::FONT_FAMILY);
+  }
+  if(InputStyle::NONE != static_cast<InputStyle::Mask>(inputStyleMask & InputStyle::INPUT_POINT_SIZE))
+  {
+    editorInputStyleMask = static_cast<Toolkit::TextEditor::InputStyle::Mask>(editorInputStyleMask | Toolkit::TextEditor::InputStyle::POINT_SIZE);
+  }
+  if(InputStyle::NONE != static_cast<InputStyle::Mask>(inputStyleMask & InputStyle::INPUT_FONT_WEIGHT))
+  {
+    editorInputStyleMask = static_cast<Toolkit::TextEditor::InputStyle::Mask>(editorInputStyleMask | Toolkit::TextEditor::InputStyle::FONT_STYLE);
+  }
+  if(InputStyle::NONE != static_cast<InputStyle::Mask>(inputStyleMask & InputStyle::INPUT_FONT_WIDTH))
+  {
+    editorInputStyleMask = static_cast<Toolkit::TextEditor::InputStyle::Mask>(editorInputStyleMask | Toolkit::TextEditor::InputStyle::FONT_STYLE);
+  }
+  if(InputStyle::NONE != static_cast<InputStyle::Mask>(inputStyleMask & InputStyle::INPUT_FONT_SLANT))
+  {
+    editorInputStyleMask = static_cast<Toolkit::TextEditor::InputStyle::Mask>(editorInputStyleMask | Toolkit::TextEditor::InputStyle::FONT_STYLE);
+  }
+  if(InputStyle::NONE != static_cast<InputStyle::Mask>(inputStyleMask & InputStyle::INPUT_LINE_SPACING))
+  {
+    editorInputStyleMask = static_cast<Toolkit::TextEditor::InputStyle::Mask>(editorInputStyleMask | Toolkit::TextEditor::InputStyle::LINE_SPACING);
+  }
+  if(InputStyle::NONE != static_cast<InputStyle::Mask>(inputStyleMask & InputStyle::INPUT_UNDERLINE))
+  {
+    editorInputStyleMask = static_cast<Toolkit::TextEditor::InputStyle::Mask>(editorInputStyleMask | Toolkit::TextEditor::InputStyle::UNDERLINE);
+  }
+  if(InputStyle::NONE != static_cast<InputStyle::Mask>(inputStyleMask & InputStyle::INPUT_SHADOW))
+  {
+    editorInputStyleMask = static_cast<Toolkit::TextEditor::InputStyle::Mask>(editorInputStyleMask | Toolkit::TextEditor::InputStyle::SHADOW);
   }
-  return filename;
+  if(InputStyle::NONE != static_cast<InputStyle::Mask>(inputStyleMask & InputStyle::INPUT_EMBOSS))
+  {
+    editorInputStyleMask = static_cast<Toolkit::TextEditor::InputStyle::Mask>(editorInputStyleMask | Toolkit::TextEditor::InputStyle::EMBOSS);
+  }
+  if(InputStyle::NONE != static_cast<InputStyle::Mask>(inputStyleMask & InputStyle::INPUT_OUTLINE))
+  {
+    editorInputStyleMask = static_cast<Toolkit::TextEditor::InputStyle::Mask>(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<int>();
-        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<std::string>();
-        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<Vector4>();
-        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<std::string>();
-        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<float>();
-        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<Text::HorizontalAlignment::Type>(-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<float>();
-        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<float>();
-        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<Vector4>();
-        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<Vector4>();
-        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<bool>();
-        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<float>();
-        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<float>();
-        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<int>();
-        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<std::string>();
-        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<std::string>();
-        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<Vector4>();
-        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<int>& box = value.Get<Rect<int> >();
-        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<bool>();
-        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<Vector4>();
-        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<std::string>();
-        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<float>();
-        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<float>();
-        impl.mController->SetDefaultLineSpacing(lineSpacing);
-        impl.mRenderer.Reset();
-        break;
-      }
-      case Toolkit::TextEditor::Property::INPUT_LINE_SPACING:
-      {
-        const float lineSpacing = value.Get<float>();
-        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<bool>();
-        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<float>();
-        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<bool>();
-        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<float>();
-        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<float>();
-        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<float>();
-        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<std::string>();
-        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<Vector4>();
-        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<bool>();
-        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<Text::LineWrap::Mode>(-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<bool>();
-        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<bool>();
-        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<bool>() ? DevelText::MatchLayoutDirection::LOCALE : DevelText::MatchLayoutDirection::CONTENTS);
-        break;
-      }
-      case Toolkit::DevelTextEditor::Property::MAX_LENGTH:
-      {
-        const int max = value.Get<int>();
-        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<uint32_t>(value.Get<int>());
-        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<uint32_t>(value.Get<int>());
-        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<bool>();
-        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<float>();
-        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<float>();
-        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<float>();
-        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<uint32_t>(value.Get<int>());
-        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<Vector4>();
-        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<bool>();
-        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<bool>();
-        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<DevelText::EllipsisPosition::Type>(-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<float>();
-        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<int> 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<float>();
-        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<int>(range.first);
-        break;
-      }
-      case Toolkit::DevelTextEditor::Property::SELECTED_TEXT_END:
-      {
-        Uint32Pair range = impl.GetTextSelectionRange();
-        value            = static_cast<int>(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<int>(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<Extents>(Toolkit::Control::Property::PADDING);
-
-      // Support Right-To-Left of padding
-      Dali::LayoutDirection::Type layoutDirection = static_cast<Dali::LayoutDirection::Type>(Self().GetProperty(Dali::Actor::Property::LAYOUT_DIRECTION).Get<int>());
-      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<Actor>::iterator it    = mClippingDecorationActors.begin(),
-                                     endIt = mClippingDecorationActors.end();
-        it != endIt;
-        ++it)
-    {
-      self.Add(*it);
-      it->LowerToBottom();
-
-      if(it->GetProperty<std::string>(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<InputStyle::Mask>(inputStyleMask & InputStyle::INPUT_COLOR))
-  {
-    editorInputStyleMask = static_cast<Toolkit::TextEditor::InputStyle::Mask>(editorInputStyleMask | Toolkit::TextEditor::InputStyle::COLOR);
-  }
-  if(InputStyle::NONE != static_cast<InputStyle::Mask>(inputStyleMask & InputStyle::INPUT_FONT_FAMILY))
-  {
-    editorInputStyleMask = static_cast<Toolkit::TextEditor::InputStyle::Mask>(editorInputStyleMask | Toolkit::TextEditor::InputStyle::FONT_FAMILY);
-  }
-  if(InputStyle::NONE != static_cast<InputStyle::Mask>(inputStyleMask & InputStyle::INPUT_POINT_SIZE))
-  {
-    editorInputStyleMask = static_cast<Toolkit::TextEditor::InputStyle::Mask>(editorInputStyleMask | Toolkit::TextEditor::InputStyle::POINT_SIZE);
-  }
-  if(InputStyle::NONE != static_cast<InputStyle::Mask>(inputStyleMask & InputStyle::INPUT_FONT_WEIGHT))
-  {
-    editorInputStyleMask = static_cast<Toolkit::TextEditor::InputStyle::Mask>(editorInputStyleMask | Toolkit::TextEditor::InputStyle::FONT_STYLE);
-  }
-  if(InputStyle::NONE != static_cast<InputStyle::Mask>(inputStyleMask & InputStyle::INPUT_FONT_WIDTH))
-  {
-    editorInputStyleMask = static_cast<Toolkit::TextEditor::InputStyle::Mask>(editorInputStyleMask | Toolkit::TextEditor::InputStyle::FONT_STYLE);
-  }
-  if(InputStyle::NONE != static_cast<InputStyle::Mask>(inputStyleMask & InputStyle::INPUT_FONT_SLANT))
-  {
-    editorInputStyleMask = static_cast<Toolkit::TextEditor::InputStyle::Mask>(editorInputStyleMask | Toolkit::TextEditor::InputStyle::FONT_STYLE);
-  }
-  if(InputStyle::NONE != static_cast<InputStyle::Mask>(inputStyleMask & InputStyle::INPUT_LINE_SPACING))
-  {
-    editorInputStyleMask = static_cast<Toolkit::TextEditor::InputStyle::Mask>(editorInputStyleMask | Toolkit::TextEditor::InputStyle::LINE_SPACING);
-  }
-  if(InputStyle::NONE != static_cast<InputStyle::Mask>(inputStyleMask & InputStyle::INPUT_UNDERLINE))
-  {
-    editorInputStyleMask = static_cast<Toolkit::TextEditor::InputStyle::Mask>(editorInputStyleMask | Toolkit::TextEditor::InputStyle::UNDERLINE);
-  }
-  if(InputStyle::NONE != static_cast<InputStyle::Mask>(inputStyleMask & InputStyle::INPUT_SHADOW))
-  {
-    editorInputStyleMask = static_cast<Toolkit::TextEditor::InputStyle::Mask>(editorInputStyleMask | Toolkit::TextEditor::InputStyle::SHADOW);
-  }
-  if(InputStyle::NONE != static_cast<InputStyle::Mask>(inputStyleMask & InputStyle::INPUT_EMBOSS))
-  {
-    editorInputStyleMask = static_cast<Toolkit::TextEditor::InputStyle::Mask>(editorInputStyleMask | Toolkit::TextEditor::InputStyle::EMBOSS);
-  }
-  if(InputStyle::NONE != static_cast<InputStyle::Mask>(inputStyleMask & InputStyle::INPUT_OUTLINE))
-  {
-    editorInputStyleMask = static_cast<Toolkit::TextEditor::InputStyle::Mask>(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)
index bc28781..8c5d7be 100644 (file)
@@ -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 (file)
index 0000000..62dfbda
--- /dev/null
@@ -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 <dali-toolkit/internal/controls/text-controls/text-editor-property-handler.h>
+
+#include <dali-toolkit/devel-api/focus-manager/keyinput-focus-manager.h>
+
+#include <dali-toolkit/internal/text/decorator/text-decorator.h>
+#include <dali-toolkit/internal/text/text-controller.h>
+#include <dali-toolkit/internal/text/text-effects-style.h>
+#include <dali-toolkit/internal/text/text-enumerations-impl.h>
+#include <dali-toolkit/internal/text/text-font-style.h>
+#include <dali-toolkit/public-api/text/text-enumerations.h>
+#include <dali/integration-api/debug.h>
+
+#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<int>();
+      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<std::string>();
+      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<Vector4>();
+      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<std::string>();
+      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<float>();
+      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<Text::HorizontalAlignment::Type>(-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<float>();
+      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<float>();
+      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<Vector4>();
+      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<Vector4>();
+      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<bool>();
+      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<float>();
+      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<float>();
+      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<int>();
+      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<std::string>();
+      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<std::string>();
+      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<Vector4>();
+      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<int>& box = value.Get<Rect<int> >();
+      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<bool>();
+      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<Vector4>();
+      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<std::string>();
+      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<float>();
+      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<float>();
+      impl.mController->SetDefaultLineSpacing(lineSpacing);
+      impl.mRenderer.Reset();
+      break;
+    }
+    case Toolkit::TextEditor::Property::INPUT_LINE_SPACING:
+    {
+      const float lineSpacing = value.Get<float>();
+      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<bool>();
+      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<float>();
+      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<bool>();
+      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<float>();
+      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<float>();
+      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<float>();
+      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<std::string>();
+      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<Vector4>();
+      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<bool>();
+      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<Text::LineWrap::Mode>(-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<bool>();
+      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<bool>();
+      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<bool>() ? DevelText::MatchLayoutDirection::LOCALE : DevelText::MatchLayoutDirection::CONTENTS);
+      break;
+    }
+    case Toolkit::DevelTextEditor::Property::MAX_LENGTH:
+    {
+      const int max = value.Get<int>();
+      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<uint32_t>(value.Get<int>());
+      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<uint32_t>(value.Get<int>());
+      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<bool>();
+      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<float>();
+      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<float>();
+      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<float>();
+      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<uint32_t>(value.Get<int>());
+      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<Vector4>();
+      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;