Merge "bug fixed about the rtl markup behavior." into devel/master
authorjoogab yun <joogab.yun@samsung.com>
Fri, 14 Dec 2018 06:09:56 +0000 (06:09 +0000)
committerGerrit Code Review <gerrit@review.ap-northeast-2.compute.internal>
Fri, 14 Dec 2018 06:09:56 +0000 (06:09 +0000)
25 files changed:
automated-tests/src/dali-toolkit-internal/CMakeLists.txt
automated-tests/src/dali-toolkit-internal/utc-Dali-Visuals-internal.cpp
automated-tests/src/dali-toolkit/CMakeLists.txt
automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-vector-animation-renderer.cpp [new file with mode: 0755]
automated-tests/src/dali-toolkit/utc-Dali-AnimatedVectorImageVisual.cpp
automated-tests/src/dali-toolkit/utc-Dali-DragAndDropDetector.cpp [new file with mode: 0755]
build/tizen/dali-toolkit/Makefile.am
dali-toolkit/devel-api/drag-drop-detector/drag-and-drop-detector.cpp [new file with mode: 0755]
dali-toolkit/devel-api/drag-drop-detector/drag-and-drop-detector.h [new file with mode: 0755]
dali-toolkit/devel-api/file.list
dali-toolkit/devel-api/visuals/image-visual-properties-devel.h
dali-toolkit/internal/controls/buttons/button-impl.cpp
dali-toolkit/internal/controls/buttons/button-impl.h
dali-toolkit/internal/controls/control/control-data-impl.cpp
dali-toolkit/internal/drag-drop-detector/drag-and-drop-detector-impl.cpp [new file with mode: 0755]
dali-toolkit/internal/drag-drop-detector/drag-and-drop-detector-impl.h [new file with mode: 0755]
dali-toolkit/internal/file.list
dali-toolkit/internal/visuals/animated-vector-image/animated-vector-image-visual.cpp
dali-toolkit/internal/visuals/animated-vector-image/animated-vector-image-visual.h
dali-toolkit/internal/visuals/animated-vector-image/vector-rasterize-thread.cpp [moved from dali-toolkit/internal/visuals/animated-vector-image/vector-image-rasterize-thread.cpp with 73% similarity]
dali-toolkit/internal/visuals/animated-vector-image/vector-rasterize-thread.h [moved from dali-toolkit/internal/visuals/animated-vector-image/vector-image-rasterize-thread.h with 77% similarity]
dali-toolkit/internal/visuals/visual-string-constants.cpp
dali-toolkit/internal/visuals/visual-string-constants.h
dali-toolkit/public-api/dali-toolkit-version.cpp
packaging/dali-toolkit.spec

index df591a7..7a71661 100755 (executable)
@@ -47,6 +47,7 @@ LIST(APPEND TC_SOURCES
    ../dali-toolkit/dali-toolkit-test-utils/toolkit-singleton-service.cpp
    ../dali-toolkit/dali-toolkit-test-utils/toolkit-timer.cpp
    ../dali-toolkit/dali-toolkit-test-utils/toolkit-tts-player.cpp
+   ../dali-toolkit/dali-toolkit-test-utils/toolkit-vector-animation-renderer.cpp
    ../dali-toolkit/dali-toolkit-test-utils/dali-test-suite-utils.cpp
    ../dali-toolkit/dali-toolkit-test-utils/dummy-control.cpp
    ../dali-toolkit/dali-toolkit-test-utils/mesh-builder.cpp
index 8c31999..4ead28e 100644 (file)
@@ -22,6 +22,7 @@
 #include <dali-toolkit-test-suite-utils.h>
 #include <dali-toolkit/dali-toolkit.h>
 #include <toolkit-text-utils.h>
+#include <toolkit-event-thread-callback.h>
 #include <dali-toolkit/devel-api/visual-factory/visual-factory.h>
 #include <dali-toolkit/internal/visuals/visual-factory-cache.h>
 #include <dali-toolkit/internal/visuals/color/color-visual.h>
@@ -320,3 +321,54 @@ int UtcDaliAnimatedVectorImageVisualCreateInstancePropertyMap(void)
 
   END_TEST;
 }
+
+int UtcDaliAnimatedVectorImageVisualSetProperties(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline( "UtcDaliAnimatedVectorImageVisualSetProperties" );
+
+  Property::Map propertyMap;
+  propertyMap.Add( Toolkit::Visual::Property::TYPE, DevelVisual::ANIMATED_VECTOR_IMAGE )
+             .Add( ImageVisual::Property::URL, TEST_VECTOR_IMAGE_FILE_NAME  )
+             .Add( DevelImageVisual::Property::LOOP_COUNT, 3  )
+             .Add( DevelImageVisual::Property::PLAY_RANGE, Vector2( 0.2f, 0.8f )  );
+
+  Visual::Base visual = VisualFactory::Get().CreateVisual( propertyMap );
+  Toolkit::Internal::Visual::Base& visualImpl = GetImplementation( visual );
+  DALI_TEST_CHECK( visual );
+
+  DummyControl actor = DummyControl::New( true );
+  DummyControlImpl& dummyImpl = static_cast< DummyControlImpl& >( actor.GetImplementation() );
+  dummyImpl.RegisterVisual( DummyControl::Property::TEST_VISUAL, visual );
+  actor.SetSize( 200.0f, 200.0f );
+  Stage::GetCurrent().Add( actor );
+
+  application.SendNotification();
+  application.Render();
+
+  // Wait for resource ready event callback
+  DALI_TEST_EQUALS( Test::WaitForEventThreadTrigger( 1 ), true, TEST_LOCATION );
+
+  // renderer is added to actor
+  DALI_TEST_CHECK( actor.GetRendererCount() == 1u );
+  Renderer renderer = actor.GetRendererAt( 0u );
+  DALI_TEST_CHECK( renderer );
+
+  Property::Map propertyMap1;
+  propertyMap1.Add( DevelImageVisual::Property::LOOP_COUNT, 1  )
+              .Add( DevelImageVisual::Property::PLAY_RANGE, Vector2( 0.4f, 0.6f )  );
+
+  visualImpl.SetProperties( propertyMap1 );
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_CHECK( actor.GetRendererCount() == 1u );
+  renderer = actor.GetRendererAt( 0u );
+  DALI_TEST_CHECK( renderer );
+
+  actor.Unparent( );
+  DALI_TEST_CHECK( actor.GetRendererCount() == 0u );
+
+  END_TEST;
+}
index c8215a5..bd9848f 100755 (executable)
@@ -77,6 +77,7 @@ SET(TC_SOURCES
   utc-Dali-AsyncImageLoader.cpp
   utc-Dali-SyncImageLoader.cpp
   utc-Dali-ControlWrapper.cpp
+  utc-Dali-DragAndDropDetector.cpp
 )
 
 # Append list of test harness files (Won't get parsed for test cases)
@@ -98,6 +99,7 @@ LIST(APPEND TC_SOURCES
   dali-toolkit-test-utils/toolkit-timer.cpp
   dali-toolkit-test-utils/toolkit-tts-player.cpp
   dali-toolkit-test-utils/toolkit-native-image-source.cpp
+  dali-toolkit-test-utils/toolkit-vector-animation-renderer.cpp
   dali-toolkit-test-utils/toolkit-video-player.cpp
   dali-toolkit-test-utils/toolkit-web-engine.cpp
   dali-toolkit-test-utils/toolkit-trigger-event-factory.cpp
diff --git a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-vector-animation-renderer.cpp b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-vector-animation-renderer.cpp
new file mode 100755 (executable)
index 0000000..003b8ea
--- /dev/null
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2018 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/devel-api/adaptor-framework/vector-animation-renderer.h>
+#include <dali/public-api/object/base-object.h>
+#include <toolkit-application.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace Adaptor
+{
+
+class VectorAnimationRenderer: public Dali::BaseObject
+{
+public:
+
+  VectorAnimationRenderer( const std::string& url, Dali::Renderer renderer, uint32_t width, uint32_t height )
+  : mUrl( url ),
+    mRenderer( renderer ),
+    mWidth( width ),
+    mHeight( height )
+  {
+  }
+
+  void SetSize( uint32_t width, uint32_t height )
+  {
+    mWidth = width;
+    mHeight = height;
+  }
+
+  bool StartRender()
+  {
+    return true;
+  }
+
+  void StopRender()
+  {
+  }
+
+  void Render( uint32_t frameNumber )
+  {
+  }
+
+  uint32_t GetTotalFrameNumber()
+  {
+    return 5;
+  }
+
+public:
+
+  std::string mUrl;
+  Dali::Renderer mRenderer;
+  uint32_t mWidth;
+  uint32_t mHeight;
+
+};
+
+inline VectorAnimationRenderer& GetImplementation( Dali::VectorAnimationRenderer& renderer )
+{
+  DALI_ASSERT_ALWAYS( renderer && "VectorAnimationRenderer handle is empty." );
+  BaseObject& handle = renderer.GetBaseObject();
+  return static_cast< Internal::Adaptor::VectorAnimationRenderer& >( handle );
+}
+
+inline const VectorAnimationRenderer& GetImplementation( const Dali::VectorAnimationRenderer& renderer )
+{
+  DALI_ASSERT_ALWAYS( renderer && "VectorAnimationRenderer handle is empty." );
+  const BaseObject& handle = renderer.GetBaseObject();
+  return static_cast< const Internal::Adaptor::VectorAnimationRenderer& >( handle );
+}
+
+} // namespace Adaptor
+
+} // namespace Internal
+
+
+/********************************************************************************/
+/*********************************  PUBLIC CLASS  *******************************/
+/********************************************************************************/
+
+VectorAnimationRenderer VectorAnimationRenderer::New( const std::string& url, Renderer renderer, uint32_t width, uint32_t height )
+{
+  Internal::Adaptor::VectorAnimationRenderer* animationRenderer = new Internal::Adaptor::VectorAnimationRenderer( url, renderer, width, height );
+
+  return VectorAnimationRenderer( animationRenderer );
+}
+
+VectorAnimationRenderer::VectorAnimationRenderer()
+{
+}
+
+VectorAnimationRenderer::~VectorAnimationRenderer()
+{
+}
+
+VectorAnimationRenderer::VectorAnimationRenderer( Internal::Adaptor::VectorAnimationRenderer* internal )
+: BaseHandle( internal )
+{
+}
+
+VectorAnimationRenderer::VectorAnimationRenderer( const VectorAnimationRenderer& handle )
+: BaseHandle( handle )
+{
+}
+
+VectorAnimationRenderer& VectorAnimationRenderer::operator=( const VectorAnimationRenderer& rhs )
+{
+  BaseHandle::operator=( rhs );
+  return *this;
+}
+
+void VectorAnimationRenderer::SetSize( uint32_t width, uint32_t height )
+{
+  Internal::Adaptor::GetImplementation( *this ).SetSize( width, height );
+}
+
+bool VectorAnimationRenderer::StartRender()
+{
+  return Internal::Adaptor::GetImplementation( *this ).StartRender();
+}
+
+void VectorAnimationRenderer::StopRender()
+{
+  Internal::Adaptor::GetImplementation( *this ).StopRender();
+}
+
+void VectorAnimationRenderer::Render( uint32_t frameNumber )
+{
+  Internal::Adaptor::GetImplementation( *this ).Render( frameNumber );
+}
+
+uint32_t VectorAnimationRenderer::GetTotalFrameNumber()
+{
+  return Internal::Adaptor::GetImplementation( *this ).GetTotalFrameNumber();
+}
+
+} // namespace Dali;
+
index 57733dd..c0fee41 100644 (file)
@@ -115,14 +115,92 @@ int UtcDaliVisualFactoryGetAnimatedVectorImageVisual02(void)
   END_TEST;
 }
 
+int UtcDaliVisualFactoryGetAnimatedVectorImageVisual03(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline( "UtcDaliVisualFactoryGetAnimatedVectorImageVisual03: Request animated vector image visual with a Property::Map" );
+
+  Property::Map propertyMap;
+  propertyMap.Add( Toolkit::Visual::Property::TYPE, DevelVisual::ANIMATED_VECTOR_IMAGE )
+             .Add( ImageVisual::Property::URL, TEST_VECTOR_IMAGE_FILE_NAME  )
+             .Add( DevelImageVisual::Property::LOOP_COUNT, 3  )
+             .Add( DevelImageVisual::Property::PLAY_RANGE, Vector2( 0.2f, 0.8f )  );
+
+  Visual::Base visual = VisualFactory::Get().CreateVisual( propertyMap );
+  DALI_TEST_CHECK( visual );
+
+  DummyControl actor = DummyControl::New( true );
+  DummyControlImpl& dummyImpl = static_cast< DummyControlImpl& >( actor.GetImplementation() );
+  dummyImpl.RegisterVisual( DummyControl::Property::TEST_VISUAL, visual );
+  actor.SetSize( 200.0f, 200.0f );
+  Stage::GetCurrent().Add( actor );
+
+  application.SendNotification();
+  application.Render();
+
+  // Wait for resource ready event callback
+  DALI_TEST_EQUALS( Test::WaitForEventThreadTrigger( 1 ), true, TEST_LOCATION );
+
+  // renderer is added to actor
+  DALI_TEST_CHECK( actor.GetRendererCount() == 1u );
+  Renderer renderer = actor.GetRendererAt( 0u );
+  DALI_TEST_CHECK( renderer );
+
+  actor.Unparent( );
+  DALI_TEST_CHECK( actor.GetRendererCount() == 0u );
+
+  END_TEST;
+}
+
+int UtcDaliVisualFactoryGetAnimatedVectorImageVisual04(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline( "UtcDaliVisualFactoryGetAnimatedVectorImageVisual04: Request animated vector image visual with a Property::Map" );
+
+  Property::Map propertyMap;
+  propertyMap.Add( "visualType", DevelVisual::ANIMATED_VECTOR_IMAGE )
+             .Add( "url", TEST_VECTOR_IMAGE_FILE_NAME  )
+             .Add( "loopCount", 3  )
+             .Add( "playRange", Vector2( 0.2f, 0.8f )  );
+
+  Visual::Base visual = VisualFactory::Get().CreateVisual( propertyMap );
+  DALI_TEST_CHECK( visual );
+
+  DummyControl actor = DummyControl::New( true );
+  DummyControlImpl& dummyImpl = static_cast< DummyControlImpl& >( actor.GetImplementation() );
+  dummyImpl.RegisterVisual( DummyControl::Property::TEST_VISUAL, visual );
+  actor.SetSize( 200.0f, 200.0f );
+  Stage::GetCurrent().Add( actor );
+
+  application.SendNotification();
+  application.Render();
+
+  // Wait for resource ready event callback
+  DALI_TEST_EQUALS( Test::WaitForEventThreadTrigger( 1 ), true, TEST_LOCATION );
+
+  // renderer is added to actor
+  DALI_TEST_CHECK( actor.GetRendererCount() == 1u );
+  Renderer renderer = actor.GetRendererAt( 0u );
+  DALI_TEST_CHECK( renderer );
+
+  actor.Unparent( );
+  DALI_TEST_CHECK( actor.GetRendererCount() == 0u );
+
+  END_TEST;
+}
+
 int UtcDaliAnimatedVectorImageVisualGetPropertyMap01(void)
 {
   ToolkitTestApplication application;
   tet_infoline( "UtcDaliAnimatedVectorImageVisualGetPropertyMap01" );
 
+  Vector2 playRange( 0.2f, 0.8f );
+
   Property::Map propertyMap;
   propertyMap.Add( Toolkit::Visual::Property::TYPE,  DevelVisual::ANIMATED_VECTOR_IMAGE )
-             .Add( ImageVisual::Property::URL, TEST_VECTOR_IMAGE_FILE_NAME  );
+             .Add( ImageVisual::Property::URL, TEST_VECTOR_IMAGE_FILE_NAME  )
+             .Add( DevelImageVisual::Property::LOOP_COUNT, 3  )
+             .Add( DevelImageVisual::Property::PLAY_RANGE, playRange  );
 
   // request AnimatedVectorImageVisual with a property map
   VisualFactory factory = VisualFactory::Get();
@@ -140,6 +218,14 @@ int UtcDaliAnimatedVectorImageVisualGetPropertyMap01(void)
   DALI_TEST_CHECK( value );
   DALI_TEST_CHECK( value->Get< std::string >() == TEST_VECTOR_IMAGE_FILE_NAME );
 
+  value = resultMap.Find( DevelImageVisual::Property::LOOP_COUNT, Property::INTEGER );
+  DALI_TEST_CHECK( value );
+  DALI_TEST_CHECK( value->Get< int >() == 3 );
+
+  value = resultMap.Find( DevelImageVisual::Property::PLAY_RANGE, Property::VECTOR2 );
+  DALI_TEST_CHECK( value );
+  DALI_TEST_CHECK( value->Get< Vector2 >() == playRange );
+
   // request AnimatedVectorImageVisual with an URL
   Visual::Base visual2 = factory.CreateVisual( TEST_VECTOR_IMAGE_FILE_NAME, ImageDimensions() );
 
@@ -324,3 +410,81 @@ int UtcDaliAnimatedVectorImageVisualNaturalSize(void)
 
   END_TEST;
 }
+
+int UtcDaliAnimatedVectorImageVisualLoopCount(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline( "UtcDaliAnimatedVectorImageVisualLoopCount" );
+
+  Property::Map propertyMap;
+  propertyMap.Add( Toolkit::Visual::Property::TYPE, DevelVisual::ANIMATED_VECTOR_IMAGE )
+             .Add( ImageVisual::Property::URL, TEST_VECTOR_IMAGE_FILE_NAME  )
+             .Add( DevelImageVisual::Property::LOOP_COUNT, 3  );
+
+  Visual::Base visual = VisualFactory::Get().CreateVisual( propertyMap );
+  DALI_TEST_CHECK( visual );
+
+  DummyControl actor = DummyControl::New( true );
+  DummyControlImpl& dummyImpl = static_cast< DummyControlImpl& >( actor.GetImplementation() );
+  dummyImpl.RegisterVisual( DummyControl::Property::TEST_VISUAL, visual );
+
+  Vector2 controlSize( 20.f, 30.f );
+  actor.SetSize( controlSize );
+
+  Stage::GetCurrent().Add( actor );
+
+  Property::Map attributes;
+  DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedVectorImageVisual::Action::PLAY, attributes );
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( Test::WaitForEventThreadTrigger( 1 ), true, TEST_LOCATION );
+
+  // renderer is added to actor
+  DALI_TEST_CHECK( actor.GetRendererCount() == 1u );
+  Renderer renderer = actor.GetRendererAt( 0u );
+  DALI_TEST_CHECK( renderer );
+
+  END_TEST;
+}
+
+int UtcDaliAnimatedVectorImageVisualPlayRange(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline( "UtcDaliAnimatedVectorImageVisualPlayRange" );
+
+  Vector2 playRange( 0.8f, 0.2f );
+
+  Property::Map propertyMap;
+  propertyMap.Add( Toolkit::Visual::Property::TYPE, DevelVisual::ANIMATED_VECTOR_IMAGE )
+             .Add( ImageVisual::Property::URL, TEST_VECTOR_IMAGE_FILE_NAME  )
+             .Add( DevelImageVisual::Property::PLAY_RANGE, playRange  );
+
+  Visual::Base visual = VisualFactory::Get().CreateVisual( propertyMap );
+  DALI_TEST_CHECK( visual );
+
+  DummyControl actor = DummyControl::New( true );
+  DummyControlImpl& dummyImpl = static_cast< DummyControlImpl& >( actor.GetImplementation() );
+  dummyImpl.RegisterVisual( DummyControl::Property::TEST_VISUAL, visual );
+
+  Vector2 controlSize( 20.f, 30.f );
+  actor.SetSize( controlSize );
+
+  Stage::GetCurrent().Add( actor );
+
+  Property::Map attributes;
+  DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedVectorImageVisual::Action::PLAY, attributes );
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( Test::WaitForEventThreadTrigger( 1 ), true, TEST_LOCATION );
+
+  // renderer is added to actor
+  DALI_TEST_CHECK( actor.GetRendererCount() == 1u );
+  Renderer renderer = actor.GetRendererAt( 0u );
+  DALI_TEST_CHECK( renderer );
+
+  END_TEST;
+}
diff --git a/automated-tests/src/dali-toolkit/utc-Dali-DragAndDropDetector.cpp b/automated-tests/src/dali-toolkit/utc-Dali-DragAndDropDetector.cpp
new file mode 100755 (executable)
index 0000000..3fbbfcd
--- /dev/null
@@ -0,0 +1,602 @@
+/*
+ * Copyright (c) 2018 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 <iostream>
+#include <stdlib.h>
+
+// Need to override adaptor classes for toolkit test harness, so include
+// test harness headers before dali headers.
+#include <dali-toolkit-test-suite-utils.h>
+
+#include <dali-toolkit/devel-api/drag-drop-detector/drag-and-drop-detector.h>
+#include <dali/integration-api/events/touch-event-integ.h>
+#include <dali/integration-api/events/pan-gesture-event.h>
+
+using namespace Dali;
+using namespace Dali::Toolkit;
+
+void utc_dali_toolkit_drag_drop_detector_startup(void)
+{
+  test_return_value = TET_UNDEF;
+}
+
+void utc_dali_toolkit_drag_drop_detector_cleanup(void)
+{
+  test_return_value = TET_PASS;
+}
+
+namespace
+{
+  const int RENDER_FRAME_INTERVAL = 16;
+  struct SignalData
+  {
+    SignalData()
+    :functorCalled(false),
+    control(),
+    detector()
+    {
+    }
+
+    void Reset()
+    {
+      functorCalled = false;
+      control.Reset();
+    }
+
+    bool functorCalled;
+    Control control;
+    Dali::Toolkit::DragAndDropDetector detector;
+  };
+
+  struct DragSignalFunctor
+  {
+    DragSignalFunctor(SignalData& data, bool returnValue = true)
+    :signalData(data),
+    returnValue(returnValue)
+    {
+    }
+
+    bool operator()(Control control, Dali::Toolkit::DragAndDropDetector detector)
+    {
+      signalData.functorCalled = true;
+      signalData.control = control;
+      signalData.detector = detector;
+      return returnValue;
+    }
+
+    SignalData& signalData;
+    bool returnValue;
+    };
+
+  Integration::TouchEvent GenerateSingleTouch(TouchPoint::State state, const Vector2& screenPosition)
+  {
+    Integration::TouchEvent touchEvent;
+    Integration::Point point;
+    point.SetState(static_cast<PointState::Type>(state));
+    point.SetScreenPosition(screenPosition);
+    touchEvent.points.push_back(point);
+    return touchEvent;
+  }
+
+  Integration::PanGestureEvent GeneratePan(
+    Gesture::State state,
+    Vector2 previousPosition,
+    Vector2 currentPosition,
+    unsigned long timeDelta,
+    unsigned int numberOfTouches = 1,
+    unsigned int time = 1u)
+  {
+    Integration::PanGestureEvent pan(state);
+    pan.previousPosition = previousPosition;
+    pan.currentPosition = currentPosition;
+    pan.timeDelta = timeDelta;
+    pan.numberOfTouches = numberOfTouches;
+    pan.time = time;
+
+    return pan;
+  }
+
+}
+
+int UtcDaliDragAndDropDetectorConstructorN(void)
+{
+  ToolkitTestApplication application;
+
+  Dali::Toolkit::DragAndDropDetector detector;
+  DALI_TEST_CHECK(!detector);
+
+  END_TEST;
+}
+
+int UtcDaliDragAndDropDetectorConstructorP(void)
+{
+  ToolkitTestApplication application;
+
+  Dali::Toolkit::DragAndDropDetector detector = Dali::Toolkit::DragAndDropDetector::New();
+  DALI_TEST_CHECK(detector);
+
+  END_TEST;
+}
+
+int UtcDaliDragAndDropDetectorAttachN(void)
+{
+  ToolkitTestApplication application;
+
+  Dali::Toolkit::DragAndDropDetector detector = Dali::Toolkit::DragAndDropDetector::New();
+  Control control;
+  detector.Attach(control);
+
+  DALI_TEST_EQUALS(0, detector.GetAttachedControlCount(), TEST_LOCATION);
+  Control control1 = Control::New();
+  detector.Attach(control1);
+  DALI_TEST_EQUALS(1, detector.GetAttachedControlCount(), TEST_LOCATION);
+  detector.Attach(control1);
+  DALI_TEST_EQUALS(1, detector.GetAttachedControlCount(), TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliDragAndDropDetectorAttachP(void)
+{
+  ToolkitTestApplication application;
+
+  Dali::Toolkit::DragAndDropDetector detector = Dali::Toolkit::DragAndDropDetector::New();
+  Control control = Control::New();
+
+  detector.Attach(control);
+  DALI_TEST_EQUALS(1, detector.GetAttachedControlCount(), TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliDragAndDropDetectorDetachN(void)
+  {
+  ToolkitTestApplication application;
+
+  Dali::Toolkit::DragAndDropDetector detector = Dali::Toolkit::DragAndDropDetector::New();
+  Control control1;
+  Control control2 = Control::New();
+
+  detector.Attach(control1);
+  detector.Attach(control2);
+  DALI_TEST_EQUALS(1, detector.GetAttachedControlCount(), TEST_LOCATION);
+
+  detector.Detach(control2);
+  DALI_TEST_EQUALS(0, detector.GetAttachedControlCount(), TEST_LOCATION);
+
+  detector.Detach(control1);
+  DALI_TEST_EQUALS(0, detector.GetAttachedControlCount(), TEST_LOCATION);
+
+  END_TEST;
+
+}
+
+int UtcDaliDragAndDropDetectorDetachP(void)
+{
+  ToolkitTestApplication application;
+
+  Dali::Toolkit::DragAndDropDetector detector = Dali::Toolkit::DragAndDropDetector::New();
+  Control control1 = Control::New();
+  Control control2 = Control::New();
+  Control control3;
+
+  detector.Attach(control1);
+  detector.Attach(control2);
+  detector.Attach(control3);
+
+  DALI_TEST_EQUALS(2, detector.GetAttachedControlCount(), TEST_LOCATION);
+
+  detector.Detach(control3);
+  DALI_TEST_EQUALS(2, detector.GetAttachedControlCount(), TEST_LOCATION);
+  detector.Detach(control2);
+  DALI_TEST_EQUALS(1, detector.GetAttachedControlCount(), TEST_LOCATION);
+
+  detector.Detach(control1);
+  DALI_TEST_EQUALS(0, detector.GetAttachedControlCount(), TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliDragAndDropDetectorDetachAllN(void)
+{
+  ToolkitTestApplication application;
+
+  Dali::Toolkit::DragAndDropDetector detector = Dali::Toolkit::DragAndDropDetector::New();
+  detector.DetachAll();
+  DALI_TEST_EQUALS(0, detector.GetAttachedControlCount(), TEST_LOCATION);
+
+  END_TEST;
+}
+int UtcDaliDragAndDropDetectorDetachAllP(void)
+{
+  ToolkitTestApplication application;
+
+  Dali::Toolkit::DragAndDropDetector detector = Dali::Toolkit::DragAndDropDetector::New();
+  Control control1 = Control::New();
+  Control control2 = Control::New();
+
+  detector.Attach(control1);
+  detector.Attach(control2);
+  detector.DetachAll();
+  DALI_TEST_EQUALS(0, detector.GetAttachedControlCount(), TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliDragAndDropDetectorGetAttachedControlCountP(void)
+{
+  ToolkitTestApplication application;
+
+  Dali::Toolkit::DragAndDropDetector detector = Dali::Toolkit::DragAndDropDetector::New();
+  Control control1 = Control::New();
+  Control control2 = Control::New();
+
+  detector.Attach(control1);
+  detector.Attach(control2);
+  DALI_TEST_EQUALS(2, detector.GetAttachedControlCount(), TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliDragAndDropDetectorGetAttachedControlN(void)
+{
+  ToolkitTestApplication application;
+
+  Dali::Toolkit::DragAndDropDetector detector = Dali::Toolkit::DragAndDropDetector::New();
+  Control control1 = Control::New();
+  Control control2 = Control::New();
+
+  detector.Attach(control1);
+
+  Control control = detector.GetAttachedControl(1);
+  DALI_TEST_CHECK(!control);
+
+  END_TEST;
+}
+
+int UtcDaliDragAndDropDetectorGetAttachedControlP(void)
+{
+  ToolkitTestApplication application;
+
+  Dali::Toolkit::DragAndDropDetector detector = Dali::Toolkit::DragAndDropDetector::New();
+  Control control1 = Control::New();
+  Control control2 = Control::New();
+
+  detector.Attach(control1);
+  detector.Attach(control2);
+  Control control = detector.GetAttachedControl(1);
+  DALI_TEST_CHECK(control);
+  DALI_TEST_EQUALS(control2, control, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliDragAndDropDetectorStartSignal(void)
+{
+  TestApplication application;
+
+  Dali::Toolkit::DragAndDropDetector detector = Dali::Toolkit::DragAndDropDetector::New();
+  Control control = Control::New();
+  control.SetSize(100.0f, 100.0f);
+  control.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(control);
+  detector.Attach(control);
+
+  application.SendNotification();
+  application.Render(RENDER_FRAME_INTERVAL);
+
+  DALI_TEST_CHECK(detector);
+  DALI_TEST_CHECK(control);
+
+  SignalData data;
+  DragSignalFunctor functor(data);
+  detector.StartedSignal().Connect(&application, functor);
+
+  application.ProcessEvent(GeneratePan(Gesture::Possible, Vector2(10.0f, 10.0f), Vector2(12.0f, 12.0f), 10));
+  application.ProcessEvent(GeneratePan(Gesture::Started, Vector2(10.0f, 10.0f), Vector2(12.0f, 12.0f), 10));
+
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  DALI_TEST_EQUALS(control, data.control, TEST_LOCATION);
+  DALI_TEST_EQUALS(Vector2(12.0f, 12.0f), data.detector.GetCurrentScreenPosition(), TEST_LOCATION);
+  data.Reset();
+
+  END_TEST;
+}
+
+int UtcDaliDragAndDropDetectorEnteredSignal(void)
+{
+  TestApplication application;
+
+  Dali::Toolkit::DragAndDropDetector detector = Dali::Toolkit::DragAndDropDetector::New();
+  Control control1 = Control::New();
+  Control control2 = Control::New();
+  control1.SetSize(100.0f,100.0f);
+  control2.SetSize(100.0f, 100.0f);
+  control1.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  control2.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  control1.SetParentOrigin(ParentOrigin::TOP_LEFT);
+  control2.SetParentOrigin(ParentOrigin::TOP_LEFT);
+  control1.SetPosition(0.0f, 0.0f);
+  control2.SetPosition(0.0f, 100.0f);
+
+  Stage::GetCurrent().Add(control1);
+  Stage::GetCurrent().Add(control2);
+
+  detector.Attach(control1);
+  detector.Attach(control2);
+
+  application.SendNotification();
+  application.Render(RENDER_FRAME_INTERVAL);
+
+  SignalData data;
+  DragSignalFunctor functor(data);
+  detector.EnteredSignal().Connect(&application, functor);
+
+  application.ProcessEvent(GeneratePan(Gesture::Possible, Vector2(10.0f, 10.0f), Vector2(12.0f, 12.0f), 10));
+  application.ProcessEvent(GeneratePan(Gesture::Started, Vector2(10.0f, 10.0f), Vector2(12.0f, 12.0f), 10));
+
+  Vector2 screenCoordinates(10.0f, 110.0f);
+  application.ProcessEvent(GenerateSingleTouch(TouchPoint::Motion, screenCoordinates));
+
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  DALI_TEST_EQUALS(control2, data.control, TEST_LOCATION);
+
+  data.Reset();
+
+  END_TEST;
+
+}
+
+int UtcDaliDragAndDropDetectorMovedSignal(void)
+{
+  TestApplication application;
+
+  Dali::Toolkit::DragAndDropDetector detector = Dali::Toolkit::DragAndDropDetector::New();
+  Control control1 = Control::New();
+  Control control2 = Control::New();
+  control1.SetSize(100.0f,100.0f);
+  control2.SetSize(100.0f, 100.0f);
+  control1.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  control2.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  control1.SetParentOrigin(ParentOrigin::TOP_LEFT);
+  control2.SetParentOrigin(ParentOrigin::TOP_LEFT);
+  control1.SetPosition(0.0f, 0.0f);
+  control2.SetPosition(0.0f, 100.0f);
+
+  Stage::GetCurrent().Add(control1);
+  Stage::GetCurrent().Add(control2);
+
+  detector.Attach(control1);
+  detector.Attach(control2);
+
+  application.SendNotification();
+  application.Render(RENDER_FRAME_INTERVAL);
+
+  SignalData data;
+  DragSignalFunctor functor(data);
+  detector.MovedSignal().Connect(&application, functor);
+
+  application.ProcessEvent(GeneratePan(Gesture::Possible, Vector2(10.0f, 10.0f), Vector2(12.0f, 12.0f), 10));
+  application.ProcessEvent(GeneratePan(Gesture::Started, Vector2(10.0f, 10.0f), Vector2(12.0f, 12.0f), 10));
+
+  Vector2 screenCoordinates(10.0f, 110.0f);
+  application.ProcessEvent(GenerateSingleTouch(TouchPoint::Motion, screenCoordinates));
+
+  screenCoordinates.x = 10.0f;
+  screenCoordinates.y = 120.0f;
+  application.ProcessEvent(GenerateSingleTouch(TouchPoint::Motion, screenCoordinates));
+
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  DALI_TEST_EQUALS(Vector2(10.0f, 120.0f), data.detector.GetCurrentScreenPosition(), TEST_LOCATION);
+  DALI_TEST_EQUALS(control2, data.control, TEST_LOCATION);
+
+  data.Reset();
+
+  END_TEST;
+}
+
+int UtcDaliDragAndDropDetectorExitedSignal(void)
+{
+  TestApplication application;
+
+  Dali::Toolkit::DragAndDropDetector detector = Dali::Toolkit::DragAndDropDetector::New();
+  Control control1 = Control::New();
+  Control control2 = Control::New();
+  control1.SetSize(100.0f,100.0f);
+  control2.SetSize(100.0f, 100.0f);
+  control1.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  control2.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  control1.SetParentOrigin(ParentOrigin::TOP_LEFT);
+  control2.SetParentOrigin(ParentOrigin::TOP_LEFT);
+  control1.SetPosition(0.0f, 0.0f);
+  control2.SetPosition(0.0f, 100.0f);
+
+  control1.SetLeaveRequired(true);
+  control2.SetLeaveRequired(true);
+
+  Stage::GetCurrent().Add(control1);
+  Stage::GetCurrent().Add(control2);
+
+  detector.Attach(control1);
+  detector.Attach(control2);
+
+  application.SendNotification();
+  application.Render(RENDER_FRAME_INTERVAL);
+
+  SignalData data;
+  DragSignalFunctor functor(data);
+  detector.ExitedSignal().Connect(&application, functor);
+
+  application.ProcessEvent(GeneratePan(Gesture::Possible, Vector2(10.0f, 10.0f), Vector2(12.0f, 12.0f), 10));
+  application.ProcessEvent(GeneratePan(Gesture::Started, Vector2(10.0f, 10.0f), Vector2(12.0f, 12.0f), 10));
+
+  Vector2 screenCoordinates(10.0f, 110.0f);
+  application.ProcessEvent(GenerateSingleTouch(TouchPoint::Motion, screenCoordinates));
+
+  screenCoordinates.x = 20.0f;
+  screenCoordinates.y = 20.0f;
+  application.ProcessEvent(GenerateSingleTouch(TouchPoint::Motion, screenCoordinates));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  DALI_TEST_EQUALS(control2, data.control, TEST_LOCATION);
+
+  data.Reset();
+
+  END_TEST;
+}
+
+int UtcDaliDragAndDropDetectorDroppedSignal(void)
+{
+  TestApplication application;
+
+  Dali::Toolkit::DragAndDropDetector detector = Dali::Toolkit::DragAndDropDetector::New();
+  Control control1 = Control::New();
+  Control control2 = Control::New();
+  control1.SetSize(100.0f,100.0f);
+  control2.SetSize(100.0f, 100.0f);
+  control1.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  control2.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  control1.SetParentOrigin(ParentOrigin::TOP_LEFT);
+  control2.SetParentOrigin(ParentOrigin::TOP_LEFT);
+  control1.SetPosition(0.0f, 0.0f);
+  control2.SetPosition(0.0f, 100.0f);
+
+  Stage::GetCurrent().Add(control1);
+  Stage::GetCurrent().Add(control2);
+
+  detector.Attach(control1);
+  detector.Attach(control2);
+
+  application.SendNotification();
+  application.Render(RENDER_FRAME_INTERVAL);
+
+  SignalData data;
+  DragSignalFunctor functor(data);
+  detector.DroppedSignal().Connect(&application, functor);
+
+  application.ProcessEvent(GeneratePan(Gesture::Possible, Vector2(10.0f, 10.0f), Vector2(12.0f, 12.0f), 10));
+  application.ProcessEvent(GeneratePan(Gesture::Started, Vector2(10.0f, 10.0f), Vector2(12.0f, 12.0f), 10));
+
+  Vector2 screenCoordinates(10.0f, 110.0f);
+  application.ProcessEvent(GenerateSingleTouch(TouchPoint::Motion, screenCoordinates));
+
+  screenCoordinates.x = 10.0f;
+  screenCoordinates.y = 112.0f;
+  application.ProcessEvent(GenerateSingleTouch(TouchPoint::Up, screenCoordinates));
+
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  DALI_TEST_EQUALS(control2, data.control, TEST_LOCATION);
+  DALI_TEST_EQUALS(Vector2(10.0f, 112.0f), data.detector.GetCurrentScreenPosition(), TEST_LOCATION);
+  DALI_TEST_EQUALS(true, detector.GetContent().empty(), TEST_LOCATION);
+
+  data.Reset();
+
+  END_TEST;
+}
+
+int UtcDaliDragAndDropDetectorEndedSignal(void)
+{
+  TestApplication application;
+
+  Dali::Toolkit::DragAndDropDetector detector = Dali::Toolkit::DragAndDropDetector::New();
+  Control control1 = Control::New();
+  Control control2 = Control::New();
+  control1.SetSize(100.0f,100.0f);
+  control2.SetSize(100.0f, 100.0f);
+  control1.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  control2.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  control1.SetParentOrigin(ParentOrigin::TOP_LEFT);
+  control2.SetParentOrigin(ParentOrigin::TOP_LEFT);
+  control1.SetPosition(0.0f, 0.0f);
+  control2.SetPosition(0.0f, 100.0f);
+
+  Stage::GetCurrent().Add(control1);
+  Stage::GetCurrent().Add(control2);
+
+  application.SendNotification();
+  application.Render(RENDER_FRAME_INTERVAL);
+
+  detector.Attach(control1);
+  detector.Attach(control2);
+
+  SignalData data;
+  DragSignalFunctor functor(data);
+  detector.EndedSignal().Connect(&application, functor);
+
+  application.ProcessEvent(GeneratePan(Gesture::Possible, Vector2(10.0f, 10.0f), Vector2(12.0f, 12.0f), 10));
+  application.ProcessEvent(GeneratePan(Gesture::Started, Vector2(10.0f, 10.0f), Vector2(12.0f, 12.0f), 10));
+
+  application.ProcessEvent(GenerateSingleTouch(TouchPoint::Down, Vector2(10.0f, 10.0f)));
+
+  application.ProcessEvent(GeneratePan(Gesture::Continuing, Vector2(10.0f, 10.0f), Vector2(120.0f, 12.0f), 10));
+  application.ProcessEvent(GeneratePan(Gesture::Finished, Vector2(120.0f, 12.0f), Vector2(120.0f, 20.0f), 10));
+
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  DALI_TEST_EQUALS(control1, data.control, TEST_LOCATION);
+  data.Reset();
+
+  END_TEST;
+}
+
+int UtcDaliDragAndDropDetectorGetContent(void)
+{
+  TestApplication application;
+
+  Dali::Toolkit::DragAndDropDetector detector = Dali::Toolkit::DragAndDropDetector::New();
+  Control control1 = Control::New();
+  Control control2 = Control::New();
+  control1.SetName("control1");
+  control2.SetName("control2");
+  control1.SetSize(100.0f,100.0f);
+  control2.SetSize(100.0f, 100.0f);
+  control1.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  control2.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  control1.SetParentOrigin(ParentOrigin::TOP_LEFT);
+  control2.SetParentOrigin(ParentOrigin::TOP_LEFT);
+  control1.SetPosition(0.0f, 0.0f);
+  control2.SetPosition(0.0f, 100.0f);
+
+  Stage::GetCurrent().Add(control1);
+  Stage::GetCurrent().Add(control2);
+
+  detector.Attach(control1);
+  detector.Attach(control2);
+
+  application.SendNotification();
+  application.Render(RENDER_FRAME_INTERVAL);
+
+  SignalData data;
+  DragSignalFunctor functor(data);
+  detector.DroppedSignal().Connect(&application, functor);
+
+  application.ProcessEvent(GeneratePan(Gesture::Possible, Vector2(10.0f, 10.0f), Vector2(12.0f, 12.0f), 10));
+  application.ProcessEvent(GeneratePan(Gesture::Started, Vector2(10.0f, 10.0f), Vector2(12.0f, 12.0f), 10));
+
+  Vector2 screenCoordinates(10.0f, 110.0f);
+  application.ProcessEvent(GenerateSingleTouch(TouchPoint::Motion, screenCoordinates));
+
+  screenCoordinates.x = 10.0f;
+  screenCoordinates.y = 112.0f;
+  application.ProcessEvent(GenerateSingleTouch(TouchPoint::Up, screenCoordinates));
+
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  DALI_TEST_EQUALS(control2, data.control, TEST_LOCATION);
+  DALI_TEST_EQUALS(Vector2(10.0f, 112.0f), data.detector.GetCurrentScreenPosition(), TEST_LOCATION);
+  DALI_TEST_EQUALS("control1", detector.GetContent(), TEST_LOCATION);
+
+  data.Reset();
+
+  END_TEST;
+}
index 3d77bb8..53a4788 100644 (file)
@@ -160,6 +160,7 @@ develapitextselectionpopupdir = $(develapicontrolsdir)/text-controls
 develapitextdir =               $(develapidir)/text
 develapivisualfactorydir =      $(develapidir)/visual-factory
 develapivisualsdir =            $(develapidir)/visuals
+develapidragdropdir =           $(develapidir)/drag-drop-detector
 
 # devel headers
 develapi_HEADERS =                  $(devel_api_header_files)
@@ -192,6 +193,7 @@ develapitooltip_HEADERS =           $(devel_api_tooltip_header_files)
 develapitransitioneffects_HEADERS = $(devel_api_transition_effects_header_files)
 develapitextselectionpopup_HEADERS = $(devel_api_text_controls_header_files)
 develapitext_HEADERS =              $(devel_api_text_header_files)
+develapidragdrop_HEADERS =          $(devel_api_drag_and_drop_detector_header_files)
 
 # public api source
 publicapidir =                     $(topleveldir)/public-api
diff --git a/dali-toolkit/devel-api/drag-drop-detector/drag-and-drop-detector.cpp b/dali-toolkit/devel-api/drag-drop-detector/drag-and-drop-detector.cpp
new file mode 100755 (executable)
index 0000000..bbbcf51
--- /dev/null
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2015 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/devel-api/drag-drop-detector/drag-and-drop-detector.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/drag-drop-detector/drag-and-drop-detector-impl.h>
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+DragAndDropDetector::DragAndDropDetector()
+{
+}
+
+DragAndDropDetector::~DragAndDropDetector()
+{
+}
+
+DragAndDropDetector DragAndDropDetector::New()
+{
+  return Internal::DragAndDropDetector::New();
+}
+
+void DragAndDropDetector::Attach(Control control)
+{
+  GetImplementation(*this).Attach(control);
+}
+
+void DragAndDropDetector::Detach(Control control)
+{
+  GetImplementation(*this).Detach(control);
+}
+
+void DragAndDropDetector::DetachAll()
+{
+  GetImplementation(*this).DetachAll();
+}
+
+uint32_t DragAndDropDetector::GetAttachedControlCount() const
+{
+  return GetImplementation(*this).GetAttachedControlCount();
+}
+
+Control DragAndDropDetector::GetAttachedControl(uint32_t index) const
+{
+  return GetImplementation(*this).GetAttachedControl(index);
+}
+
+const std::string& DragAndDropDetector::GetContent() const
+{
+  return GetImplementation(*this).GetContent();
+}
+
+const Vector2& DragAndDropDetector::GetCurrentScreenPosition() const
+{
+  return GetImplementation(*this).GetCurrentScreenPosition();
+}
+
+DragAndDropDetector::DragAndDropSignal& DragAndDropDetector::StartedSignal()
+{
+  return GetImplementation(*this).StartedSignal();
+}
+
+DragAndDropDetector::DragAndDropSignal& DragAndDropDetector::EnteredSignal()
+{
+  return GetImplementation(*this).EnteredSignal();
+}
+
+DragAndDropDetector::DragAndDropSignal& DragAndDropDetector::ExitedSignal()
+{
+  return GetImplementation(*this).ExitedSignal();
+}
+
+DragAndDropDetector::DragAndDropSignal& DragAndDropDetector::MovedSignal()
+{
+  return GetImplementation(*this).MovedSignal();
+}
+
+DragAndDropDetector::DragAndDropSignal& DragAndDropDetector::DroppedSignal()
+{
+  return GetImplementation(*this).DroppedSignal();
+}
+
+DragAndDropDetector::DragAndDropSignal& DragAndDropDetector::EndedSignal()
+{
+  return GetImplementation(*this).EndedSignal();
+}
+
+DragAndDropDetector::DragAndDropDetector( Internal::DragAndDropDetector* detector )
+: BaseHandle( detector )
+{
+}
+
+} //namespace Toolkit
+
+} // namespace Dali
diff --git a/dali-toolkit/devel-api/drag-drop-detector/drag-and-drop-detector.h b/dali-toolkit/devel-api/drag-drop-detector/drag-and-drop-detector.h
new file mode 100755 (executable)
index 0000000..2bd34db
--- /dev/null
@@ -0,0 +1,272 @@
+#ifndef __DALI_DRAG_AND_DROP_DETECTOR_H__
+#define __DALI_DRAG_AND_DROP_DETECTOR_H__
+
+/*
+ * Copyright (c) 2018 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/base-handle.h>
+#include <dali/public-api/signals/dali-signal.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/public-api/dali-toolkit-common.h>
+
+#include <dali-toolkit/public-api/controls/control.h>
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+namespace Internal DALI_INTERNAL
+{
+class DragAndDropDetector;
+}
+
+/**
+ * @brief The DragAndDropDetector%s provides signals when draggable objects are dragged into other object.
+ *
+ * It provides signals for when the draggable object start drag, draggable object enters other object, moves around in other object,
+ * leaves other object, dropped into other object and finally when the drag ended.
+ *
+ * The basic usage is shown below:
+ *
+ * @code
+ *
+ *  void Example()
+ *  {
+ *    DragAndDropDetector detector = DragAndDropDetector::New();
+ *
+ *    // Get notifications when the draggable item start drag
+ *    detector.StartedSignal().Connect( &OnStarted );
+ *
+ *    // Get notifications when the draggable item enters other item
+ *    detector.EnteredSignal().Connect( &OnEntered );
+ *
+ *    // Get notifications when the draggable item leaves other item
+ *    detector.ExitedSignal().Connect( &OnExited );
+ *
+ *    // Get notifications when the draggable item is moved within other item
+ *    detector.MovedSignal().Connect( &OnMoved );
+ *
+ *    // Get notifications when the draggable item is dropped
+ *    detector.DroppedSignal().Connect( &OnDropped );
+ *
+ *    // Get notifications when the draggable object drag ended
+ *    detector.EndedSignal().Connect( &OnEnded );
+ *  }
+ *
+ *  void OnStarted( Control control, DragAndDropDetector detector )
+ *  {
+ *    // Query the new values
+ *    std::cout << "Position = " << detector.GetCurrentScreenPosition() << std::endl;
+ *  }
+ *
+ *  void OnEntered( Control control, DragAndDropDetector detector )
+ *  {
+ *    // Change mode as required
+ *  }
+ *
+ *  void OnExited( Control control, DragAndDropDetector detector )
+ *  {
+ *    // Change mode as required
+ *  }
+ *
+ *  void OnMoved( Control control, DragAndDropDetector detector )
+ *  {
+ *    // Query the new values
+ *    std::cout << "Position = " << detector.GetCurrentScreenPosition() << std::endl;
+ *  }
+ *
+ *  void OnDropped( Control control, DragAndDropDetector detector )
+ *  {
+ *    // Query the new values
+ *    std::cout << "Position = " << detector.GetCurrentScreenPosition() << ", Content = " << detector.GetContent() << std::endl;
+ *  }
+ *
+ *  void OnEnded( Control control, DragAndDropDetector detector )
+ *  {
+ *    // Change mode as required
+ *  }
+ *
+ * @endcode
+ */
+class DALI_TOOLKIT_API DragAndDropDetector : public BaseHandle
+{
+public:
+
+  // Typedefs
+
+  using DragAndDropSignal = Signal< void ( Control, DragAndDropDetector ) >; ///< Drag & Drop signal
+
+  /**
+   * @brief Create an initialized DragAndDropDetector.
+   *
+   * @return A handle to a newly allocated Dali DragAndDropDetector
+   */
+  static DragAndDropDetector New();
+
+  /**
+   * @brief Create an uninitialized handle.
+   *
+   * This can be initialized with DragAndDropDetector::New().
+   */
+  DragAndDropDetector();
+
+  /**
+   * @brief Destructor
+   *
+   * This is non-virtual since derived Handle types must not contain data or virtual methods.
+   */
+  ~DragAndDropDetector();
+
+  /**
+   * @brief Returns the dropped content.
+   *
+   * @return A reference to the string representing the dropped content.
+   */
+  const std::string& GetContent() const;
+
+  /**
+   * @brief Attaches a Control to the detector.
+   *
+   * @note You can attach several controls to a DragAndDropDetector.
+   * DragAndDropDetector will keep a handle to the control and keep it alive as long as
+   * DragAndDropDetector is deleted or Detach is called.
+   */
+  void Attach(Control control);
+
+  /**
+   * @brief Detaches the attached control from the detector.
+   *
+   * @pre The specified control has been attached to the DragAndDropDetector.
+   */
+  void Detach(Control control);
+
+  /**
+   * @brief Detaches all attached control from the detector.
+   *
+   * @pre At least one control has been attached to the DragAndDropDetector.
+   */
+  void DetachAll();
+
+  /**
+   * @brief Returns the number of controls attached to the DragAndDropDetector.
+   *
+   * @pre The DragAndDropDetector has been initialized.
+   */
+  uint32_t GetAttachedControlCount() const;
+
+  /**
+   * @brief Returns a control by index. An empty handle if the index is not valid.
+   *
+   * @pre The DragAndDropDetector has been initialized.
+   */
+  Control GetAttachedControl(uint32_t index) const;
+
+  /**
+   * @brief Returns the current position of the dragged object.
+   *
+   * This is the dropped position when an object is dropped.
+   * @return The current screen position.
+   */
+  const Vector2& GetCurrentScreenPosition() const;
+
+  // Signals
+  /**
+   * @brief This is emitted when a dragged object start drag.
+   *
+   * A callback of the following type may be connected:
+   * @code
+   *   void YourCallback( Control control, DragAndDropDetector detector );
+   * @endcode
+   * @return The signal to connect to.
+   */
+  DragAndDropSignal& StartedSignal();
+
+  /**
+   * @brief This is emitted when a dragged object enters other object.
+   *
+   * A callback of the following type may be connected:
+   * @code
+   *   void YourCallback( Control control, DragAndDropDetector detector );
+   * @endcode
+   * @return The signal to connect to.
+   */
+  DragAndDropSignal& EnteredSignal();
+
+  /**
+   * @brief This is emitted when a dragged object leaves other object.
+   *
+   * A callback of the following type may be connected:
+   * @code
+   *   void YourCallback( Control control, DragAndDropDetector detector );
+   * @endcode
+   * @return The signal to connect to.
+   */
+  DragAndDropSignal& ExitedSignal();
+
+  /**
+   * @brief This is emitted when a dragged object is moved within other object.
+   *
+   * A callback of the following type may be connected:
+   * @code
+   *   void YourCallback( Control control, DragAndDropDetector detector );
+   * @endcode
+   * @return The signal to connect to.
+   */
+  DragAndDropSignal& MovedSignal();
+
+  /**
+   * @brief This is emitted when a dragged object is dropped within other object.
+   *
+   * A callback of the following type may be connected:
+   * @code
+   *   void YourCallback( Control control, DragAndDropDetector detector );
+   * @endcode
+   * @return The signal to connect to.
+   */
+  DragAndDropSignal& DroppedSignal();
+
+  /**
+   * @brief This is emitted when a dragged object drag ended.
+   *
+   * A callback of the following type may be connected:
+   * @code
+   *   void YourCallback( Control control, DragAndDropDetector detector );
+   * @endcode
+   * @return The signal to connect to.
+   */
+  DragAndDropSignal& EndedSignal();
+
+public: // Not intended for application developers
+
+  /**
+   * @brief This constructor is used by DragAndDropDetector::Get().
+   *
+   * @param[in] detector A pointer to the drag and drop detector.
+   */
+  explicit DALI_INTERNAL DragAndDropDetector( Internal::DragAndDropDetector* detector );
+};
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // __DALI_DRAG_AND_DROP_DETECTOR_H__
index 2ddabe9..ebb9631 100755 (executable)
@@ -54,7 +54,8 @@ devel_api_src_files = \
   $(devel_api_src_dir)/visual-factory/transition-data.cpp \
   $(devel_api_src_dir)/visual-factory/visual-factory.cpp \
   $(devel_api_src_dir)/visual-factory/visual-base.cpp \
-  $(devel_api_src_dir)/controls/gaussian-blur-view/gaussian-blur-view.cpp
+  $(devel_api_src_dir)/controls/gaussian-blur-view/gaussian-blur-view.cpp \
+  $(devel_api_src_dir)/drag-drop-detector/drag-and-drop-detector.cpp
 
 # Add devel header files here
 
@@ -198,3 +199,6 @@ devel_api_gaussian_blur_view_header_files = \
 
 devel_api_web_view_header_files = \
   $(devel_api_src_dir)/controls/web-view/web-view.h
+
+devel_api_drag_and_drop_detector_header_files = \
+  $(devel_api_src_dir)/drag-drop-detector/drag-and-drop-detector.h
index b007485..eb39aa6 100644 (file)
@@ -83,6 +83,17 @@ enum Type
    */
   LOOP_COUNT = ORIENTATION_CORRECTION + 3,
 
+  /**
+   * @brief The playing range the AnimatedVectorImageVisual will use.
+   *
+   * Animation will play between the values specified. Both values should be between 0-1,
+   * otherwise they will be ignored. If the range provided is not in proper order ( minimum,maximum ), it will be reordered.
+   *
+   * @details Name "playRange", Type Property::VECTOR2, between 0 and 1
+   * @note Default 0 and 1
+   */
+  PLAY_RANGE = ORIENTATION_CORRECTION + 4
+
 };
 
 } //namespace Property
index 84dd7a1..8c35f25 100644 (file)
@@ -122,7 +122,7 @@ const Scripting::StringEnum ALIGNMENT_STRING_TABLE[] =
 
 const unsigned int ALIGNMENT_STRING_TABLE_COUNT = sizeof( ALIGNMENT_STRING_TABLE ) / sizeof( ALIGNMENT_STRING_TABLE[0] );
 
-const Property::Index GET_VISUAL_INDEX_FOR_STATE[][Button::STATE_COUNT] =
+const Property::Index VISUAL_INDEX_FOR_STATE[][Button::STATE_COUNT] =
 {
   { Toolkit::DevelButton::Property::UNSELECTED_BACKGROUND_VISUAL, Toolkit::DevelButton::Property::UNSELECTED_VISUAL },
   { Toolkit::DevelButton::Property::SELECTED_BACKGROUND_VISUAL, Toolkit::DevelButton::Property::SELECTED_VISUAL  },
@@ -300,19 +300,6 @@ bool Button::ValidateState( State requestedState )
   return transitionTable[mButtonState][requestedState];
 }
 
-void Button::PerformFunctionOnVisualsInState( void(Button::*functionPtr)( Property::Index visualIndex), State state )
-{
-  DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "Button::PerformFunctionOnVisualsInState BACKROUND visual(%d) for state (%d)\n",
-                 GET_VISUAL_INDEX_FOR_STATE[state][BACKGROUND], state );
-  DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "Button::PerformFunctionOnVisualsInState FOREGROUND visuals(%d)  for state (%d)\n",
-                 GET_VISUAL_INDEX_FOR_STATE[state][FOREGROUND], state );
-
-  (this->*functionPtr)( GET_VISUAL_INDEX_FOR_STATE[state][BACKGROUND] );
-  (this->*functionPtr)( GET_VISUAL_INDEX_FOR_STATE[state][FOREGROUND] );
-
-  RelayoutRequest();
-}
-
 void Button::ChangeState( State requestedState )
 {
   DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "Button::ChangeState ReuestedState(%d)\n", requestedState );
@@ -331,10 +318,14 @@ void Button::ChangeState( State requestedState )
   if ( Self().OnStage() )
   {
     OnStateChange( mButtonState ); // Notify derived buttons
-    PerformFunctionOnVisualsInState( &Button::SelectRequiredVisual, mButtonState );
+    SelectRequiredVisual( VISUAL_INDEX_FOR_STATE[ mButtonState ][ BACKGROUND ] );
+    SelectRequiredVisual( VISUAL_INDEX_FOR_STATE[ mButtonState ][ FOREGROUND ] );
     // If animation supported then visual removal should be performed after any transition animation has completed.
     // If Required Visual is not loaded before current visual is removed then a flickering will be evident.
-    PerformFunctionOnVisualsInState( &Button::OnButtonVisualRemoval, mPreviousButtonState ); // Derived button can override OnButtonVisualRemoval
+    // Derived button can override OnButtonVisualRemoval
+    OnButtonVisualRemoval( VISUAL_INDEX_FOR_STATE[ mPreviousButtonState ][ BACKGROUND ] );
+    OnButtonVisualRemoval( VISUAL_INDEX_FOR_STATE[ mPreviousButtonState ][ FOREGROUND ] );
+    RelayoutRequest();
   }
 
   Toolkit::Button handle( GetOwner() );
@@ -421,7 +412,6 @@ Button::Align Button::GetLabelAlignment()
  * 3) Register visual with control with false for enable flag. Button will later enable visual when needed ( Button::SelectRequiredVisual )
  * 4) Unregister visual if empty map was provided. This is the method to remove a visual
  */
-
 void Button::CreateVisualsForComponent( Property::Index index, const Property::Value& value, const int visualDepth )
 {
   DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "CreateVisualsForComponent index(%d)\n", index );
@@ -453,14 +443,17 @@ void Button::CreateVisualsForComponent( Property::Index index, const Property::V
   {
     DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "CreateVisualsForComponent RegisterVisual index(%d) enabled(%s)\n",
                    index, DevelControl::IsVisualEnabled( *this, index )?"true":"false" );
-    DevelControl::RegisterVisual( *this, index, buttonVisual, DevelControl::IsVisualEnabled( *this, index ), visualDepth );
+    // enable the visual if needed for current state
+    const bool enabled = ( ( index == VISUAL_INDEX_FOR_STATE[ mButtonState ][ BACKGROUND ] )||
+                           ( index == VISUAL_INDEX_FOR_STATE[ mButtonState ][ FOREGROUND ] ) );
+    DevelControl::RegisterVisual( *this, index, buttonVisual, enabled, visualDepth );
   }
   else
   {
     DevelControl::UnregisterVisual( *this, index );
     DALI_LOG_INFO( gLogButtonFilter, Debug::General, "CreateVisualsForComponent Visual not created or empty map (clearing visual).(%d)\n", index);
   }
-  PerformFunctionOnVisualsInState( &Button::SelectRequiredVisual, mButtonState );
+  RelayoutRequest();
 }
 
 bool Button::GetPropertyMapForVisual( Property::Index visualIndex, Property::Map& retreivedMap ) const
@@ -770,10 +763,13 @@ void Button::OnStageDisconnection()
 void Button::OnStageConnection( int depth )
 {
   DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "Button::OnStageConnection ptr(%p) \n", this );
-  PerformFunctionOnVisualsInState( &Button::OnButtonVisualRemoval, mPreviousButtonState );
+  OnButtonVisualRemoval( VISUAL_INDEX_FOR_STATE[ mPreviousButtonState ][ BACKGROUND ] );
+  OnButtonVisualRemoval( VISUAL_INDEX_FOR_STATE[ mPreviousButtonState ][ FOREGROUND ] );
   SelectRequiredVisual( Toolkit::Button::Property::LABEL );
-  PerformFunctionOnVisualsInState( &Button::SelectRequiredVisual, mButtonState );
+  SelectRequiredVisual( VISUAL_INDEX_FOR_STATE[ mButtonState ][ BACKGROUND ] );
+  SelectRequiredVisual( VISUAL_INDEX_FOR_STATE[ mButtonState ][ FOREGROUND ] );
   Control::OnStageConnection( depth ); // Enabled visuals will be put on stage
+  RelayoutRequest();
 }
 
 Vector3 Button::GetNaturalSize()
@@ -790,7 +786,7 @@ Vector3 Button::GetNaturalSize()
 
   for ( int state = Button::UNSELECTED_STATE; state < Button::STATE_COUNT; state++ )
   {
-    Toolkit::Visual::Base visual = DevelControl::GetVisual( *this, GET_VISUAL_INDEX_FOR_STATE[state][FOREGROUND] );
+    Toolkit::Visual::Base visual = DevelControl::GetVisual( *this, VISUAL_INDEX_FOR_STATE[state][FOREGROUND] );
     Size visualSize;
     if ( visual )
     {
@@ -805,7 +801,7 @@ Vector3 Button::GetNaturalSize()
   {
     for ( int state = Button::UNSELECTED_STATE; state < Button::STATE_COUNT; state++ )
     {
-      Toolkit::Visual::Base visual = DevelControl::GetVisual( *this, GET_VISUAL_INDEX_FOR_STATE[state][BACKGROUND] );
+      Toolkit::Visual::Base visual = DevelControl::GetVisual( *this, VISUAL_INDEX_FOR_STATE[state][BACKGROUND] );
       Size visualSize;
       if ( visual )
       {
@@ -886,9 +882,8 @@ void Button::OnRelayout( const Vector2& size, RelayoutContainer& container )
 {
   DALI_LOG_INFO( gLogButtonFilter, Debug::General, "OnRelayout targetSize(%f,%f) ptr(%p) state[%d]\n", size.width, size.height, this, mButtonState );
 
-  Toolkit::Visual::Base currentVisual = DevelControl::GetVisual( *this, GET_VISUAL_INDEX_FOR_STATE[mButtonState][FOREGROUND] );
-
-  Toolkit::Visual::Base currentBackGroundVisual = DevelControl::GetVisual( *this, GET_VISUAL_INDEX_FOR_STATE[mButtonState][BACKGROUND] );
+  Toolkit::Visual::Base currentVisual = DevelControl::GetVisual( *this, VISUAL_INDEX_FOR_STATE[mButtonState][FOREGROUND] );
+  Toolkit::Visual::Base currentBackGroundVisual = DevelControl::GetVisual( *this, VISUAL_INDEX_FOR_STATE[mButtonState][BACKGROUND] );
 
   // Sizes and padding set to zero, if not present then values will no effect calculations.
   Vector2 visualPosition = Vector2::ZERO;
@@ -1103,8 +1098,11 @@ void Button::Released()
 void Button::SelectRequiredVisual( Property::Index visualIndex )
 {
   DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "Button::SelectRequiredVisual index(%d) state(%d)\n", visualIndex, mButtonState );
-
-  DevelControl::EnableVisual( *this, visualIndex, true );
+  // only enable visuals that exist
+  if( DevelControl::GetVisual( *this, visualIndex ) )
+  {
+    DevelControl::EnableVisual( *this, visualIndex, true );
+  }
 }
 
 void Button::RemoveVisual( Property::Index visualIndex )
@@ -1256,7 +1254,6 @@ void Button::SetProperty( BaseObject* object, Property::Index index, const Prope
         if( !outTextVisualProperties.Empty() )
         {
           GetImplementation( button ).CreateVisualsForComponent( index, outTextVisualProperties, DepthIndex::CONTENT );
-          GetImplementation( button ).RelayoutRequest();
         }
         break;
       }
@@ -1269,7 +1266,6 @@ void Button::SetProperty( BaseObject* object, Property::Index index, const Prope
                                                     labelAlignment );
 
         GetImplementation( button ).SetLabelAlignment( labelAlignment );
-        GetImplementation( button ).RelayoutRequest();
         break;
       }
 
@@ -1284,7 +1280,6 @@ void Button::SetProperty( BaseObject* object, Property::Index index, const Prope
       {
         Vector4 padding ( value.Get< Vector4 >() );
         GetImplementation( button ).SetForegroundPadding( Padding( padding.x, padding.y, padding.z, padding.w ) );
-        GetImplementation( button ).RelayoutRequest();
         break;
       }
     }
index 8b1417c..7259b98 100644 (file)
@@ -519,13 +519,6 @@ private:
   bool ValidateState( State requestedState );
 
   /**
-   * Perform the given function on the visuals in the given state. Can be used to add and remove visuals.
-   * @param[in] functionPtr pointer to the function to perform an action on a visual
-   * @param[in] state Visuals in this state will be the target
-   */
-  void PerformFunctionOnVisualsInState( void(Button::*functionPtr)( Property::Index visualIndex), State state  );
-
-  /**
    * Changes the button state when an action occurs on it
    * @param[in] requestedState the state to change to
    */
index a8387ee..5e94e8f 100755 (executable)
@@ -477,19 +477,13 @@ void Control::Impl::RegisterVisual( Property::Index index, Toolkit::Visual::Base
   // ( If the control has been type registered )
   if( visual.GetName().empty() )
   {
-    try
+    // returns empty string if index is not found as long as index is not -1
+    std::string visualName = self.GetPropertyName( index );
+    if( !visualName.empty() )
     {
-      std::string visualName = self.GetPropertyName( index );
-      if( !visualName.empty() )
-      {
-        DALI_LOG_INFO( gLogFilter, Debug::Concise, "Setting visual name for property %d to %s\n",
-                       index, visualName.c_str() );
-        visual.SetName( visualName );
-      }
-    }
-    catch( Dali::DaliException e )
-    {
-      DALI_LOG_WARNING( "Attempting to register visual without a registered property, index: %d\n", index );
+      DALI_LOG_INFO( gLogFilter, Debug::Concise, "Setting visual name for property %d to %s\n",
+                     index, visualName.c_str() );
+      visual.SetName( visualName );
     }
   }
 
diff --git a/dali-toolkit/internal/drag-drop-detector/drag-and-drop-detector-impl.cpp b/dali-toolkit/internal/drag-drop-detector/drag-and-drop-detector-impl.cpp
new file mode 100755 (executable)
index 0000000..dcb52fa
--- /dev/null
@@ -0,0 +1,309 @@
+/*
+ * Copyright (c) 2018 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/drag-drop-detector/drag-and-drop-detector-impl.h>
+
+#include <dali/public-api/events/point-state.h>
+#include <dali/public-api/events/touch-data.h>
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+namespace Internal
+{
+
+Dali::Toolkit::DragAndDropDetector DragAndDropDetector::New()
+{
+  Dali::Toolkit::DragAndDropDetector detector = Dali::Toolkit::DragAndDropDetector(new DragAndDropDetector());
+
+  return detector;
+}
+
+void DragAndDropDetector::Attach(Dali::Toolkit::Control& control)
+{
+  if(control)
+  {
+    if(!mControls.empty())
+    {
+      auto match = std::find(mControls.begin(), mControls.end(), control);
+      if(match != mControls.end())
+      {
+        return;
+      }
+    }
+    mControls.push_back(control);
+    control.TouchSignal().Connect(this, &DragAndDropDetector::OnDrag);
+    mFirstEnter.push_back(control.GetId());
+    mPanGestureDetector.Attach(control);
+    mPanGestureDetector.DetectedSignal().Connect(this, &DragAndDropDetector::OnPan);
+  }
+
+}
+
+void DragAndDropDetector::Detach(Dali::Toolkit::Control& control)
+{
+  if(!mControls.empty())
+  {
+    if(!control)
+    {
+      return;
+    }
+
+    auto match = std::find(mControls.begin(), mControls.end(), control);
+
+    if(match != mControls.end())
+    {
+      match->TouchSignal().Disconnect(this, &DragAndDropDetector::OnDrag);
+      mPanGestureDetector.Detach(*match);
+      mFirstEnter.erase(std::find(mFirstEnter.begin(), mFirstEnter.end(), control.GetId()));
+      mControls.erase(match);
+    }
+  }
+}
+
+void DragAndDropDetector::DetachAll()
+{
+  if(!mControls.empty())
+  {
+    auto iter = mControls.begin();
+    for(;iter != mControls.end();)
+    {
+      iter->TouchSignal().Disconnect(this, &DragAndDropDetector::OnDrag);
+      mPanGestureDetector.Detach(*iter);
+      iter = mControls.erase(iter);
+    }
+  }
+
+  if(!mFirstEnter.empty())
+  {
+    auto iter = mFirstEnter.begin();
+    for(;iter != mFirstEnter.end();)
+    {
+      iter = mFirstEnter.erase(iter);
+    }
+  }
+}
+
+uint32_t DragAndDropDetector::GetAttachedControlCount() const
+{
+  return mControls.size();
+}
+
+Dali::Toolkit::Control DragAndDropDetector::GetAttachedControl(uint32_t index) const
+{
+  Dali::Toolkit::Control control;
+
+  if(index < mControls.size())
+  {
+    control = mControls[index];
+  }
+
+  return control;
+}
+
+void DragAndDropDetector::OnPan(Dali::Actor actor, const PanGesture& gesture)
+{
+  Dali::Toolkit::Control control = Dali::Toolkit::Control::DownCast(actor);
+
+  if(gesture.state == Gesture::Started)
+  {
+    mDragLocalPosition = gesture.position;
+    mPointDown = true;
+    mDragControl = control;
+    mFirstEnter.clear();
+    for( auto&& control : mControls)
+    {
+      mFirstEnter.push_back(control.GetId());
+    }
+    float width = control.GetProperty<float>(Dali::Actor::Property::SIZE_WIDTH);
+    float height = control.GetProperty<float>(Dali::Actor::Property::SIZE_HEIGHT);
+    Vector3 actorPos = control.GetProperty<Vector3>(Dali::Actor::Property::POSITION);
+
+    mShadowControl = Dali::Toolkit::Control::New();
+    mShadowControl.SetPosition(actorPos);
+    mShadowControl.SetSize(width, height);
+    mShadowControl.SetBackgroundColor(Vector4(0.3f, 0.3f, 0.3f, 0.7f));
+    mShadowControl.SetParentOrigin(control.GetCurrentParentOrigin());
+    mShadowControl.SetAnchorPoint(control.GetCurrentAnchorPoint());
+    control.GetParent().Add(mShadowControl);
+    SetPosition(gesture.screenPosition);
+    EmitStartedSignal(control);
+  }
+  if(gesture.state == Gesture::Continuing)
+  {
+      Vector2 screenPosition = gesture.screenPosition;
+      control.GetParent().ScreenToLocal(mLocalPosition.x, mLocalPosition.y, screenPosition.x, screenPosition.y);
+      mShadowControl.SetPosition(mLocalPosition.x - mDragLocalPosition.x, mLocalPosition.y - mDragLocalPosition.y);
+  }
+  if(gesture.state == Gesture::Finished)
+  {
+    mDragControl.GetParent().Remove(mShadowControl);
+    EmitEndedSignal(control);
+  }
+}
+
+bool DragAndDropDetector::OnDrag(Dali::Actor actor, const Dali::TouchData& data)
+{
+  Dali::Toolkit::Control control = Dali::Toolkit::Control::DownCast(actor);
+  PointState::Type type = data.GetState(0);
+
+  if(type == PointState::MOTION)
+  {
+    if(mDragControl != control && mPointDown)
+    {
+      auto found = std::find(mFirstEnter.begin(), mFirstEnter.end(), control.GetId());
+      if(mFirstEnter.end() != found)
+      {
+        SetPosition(data.GetScreenPosition(0));
+        mFirstEnter.erase(found);
+        EmitEnteredSignal(control);
+      }
+      else
+      {
+        SetPosition(data.GetScreenPosition(0));
+        EmitMovedSignal(control);
+      }
+    }
+  }
+
+  if(type == PointState::LEAVE)
+  {
+    if(mDragControl != control && mPointDown)
+    {
+      mFirstEnter.push_back(control.GetId());
+      EmitExitedSignal(control);
+    }
+  }
+
+  if(type == PointState::UP)
+  {
+    if(mDragControl != control && mPointDown)
+    {
+      SetPosition(data.GetScreenPosition(0));
+      ClearContent();
+      SetContent(mDragControl.GetName());
+      EmitDroppedSignal(control);
+    }
+
+    if(mShadowControl)
+    {
+    control.GetParent().Remove(mShadowControl);
+    }
+    mPointDown = false;
+  }
+  return true;
+}
+
+const std::string& DragAndDropDetector::GetContent() const
+{
+  return mContent;
+}
+
+const Vector2& DragAndDropDetector::GetCurrentScreenPosition() const
+{
+  return mScreenPosition;
+}
+
+void DragAndDropDetector::SetContent( const std::string& content )
+{
+  mContent = content;
+}
+
+void DragAndDropDetector::ClearContent()
+{
+  mContent.clear();
+}
+
+void DragAndDropDetector::SetPosition( const Vector2& screenPosition )
+{
+  mScreenPosition = screenPosition;
+}
+
+void DragAndDropDetector::EmitStartedSignal(Dali::Toolkit::Control& control)
+{
+  if( !mStartedSignal.Empty() )
+  {
+    Dali::Toolkit::DragAndDropDetector handle( this );
+    mStartedSignal.Emit( control, handle );
+  }
+}
+void DragAndDropDetector::EmitEnteredSignal(Dali::Toolkit::Control& control)
+{
+  if ( !mEnteredSignal.Empty() )
+  {
+    Dali::Toolkit::DragAndDropDetector handle( this );
+    mEnteredSignal.Emit( control, handle );
+  }
+}
+
+void DragAndDropDetector::EmitExitedSignal(Dali::Toolkit::Control& control)
+{
+  if ( !mExitedSignal.Empty() )
+  {
+    Dali::Toolkit::DragAndDropDetector handle( this );
+    mExitedSignal.Emit( control, handle );
+  }
+}
+
+void DragAndDropDetector::EmitMovedSignal(Dali::Toolkit::Control& control)
+{
+  if ( !mMovedSignal.Empty() )
+  {
+    Dali::Toolkit::DragAndDropDetector handle( this );
+    mMovedSignal.Emit( control, handle );
+  }
+}
+
+void DragAndDropDetector::EmitDroppedSignal(Dali::Toolkit::Control& control)
+{
+  if ( !mDroppedSignal.Empty() )
+  {
+    Dali::Toolkit::DragAndDropDetector handle( this );
+    mDroppedSignal.Emit( control, handle );
+  }
+}
+
+void DragAndDropDetector::EmitEndedSignal(Dali::Toolkit::Control& control)
+{
+  if( !mEndedSignal.Empty() )
+  {
+    Dali::Toolkit::DragAndDropDetector handle( this );
+    mEndedSignal.Emit( control, handle );
+  }
+}
+
+DragAndDropDetector::DragAndDropDetector()
+: mContent(),
+  mScreenPosition()
+{
+  mPanGestureDetector = Dali::PanGestureDetector::New();
+  mPointDown = false;
+}
+
+DragAndDropDetector::~DragAndDropDetector()
+{
+}
+
+} // namespace Internal
+
+} //namespace Toolkit
+
+} // namespace Dali
diff --git a/dali-toolkit/internal/drag-drop-detector/drag-and-drop-detector-impl.h b/dali-toolkit/internal/drag-drop-detector/drag-and-drop-detector-impl.h
new file mode 100755 (executable)
index 0000000..e2e1c47
--- /dev/null
@@ -0,0 +1,269 @@
+#ifndef __DALI_INTERNAL_DRAG_AND_DROP_DETECTOR_H__
+#define __DALI_INTERNAL_DRAG_AND_DROP_DETECTOR_H__
+
+/*
+ * Copyright (c) 2018 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 <string>
+#include <vector>
+#include <algorithm>
+
+#include <dali/public-api/object/base-object.h>
+#include <dali/public-api/math/vector2.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/devel-api/drag-drop-detector/drag-and-drop-detector.h>
+#include <dali/public-api/events/pan-gesture-detector.h>
+#include <dali/public-api/events/pan-gesture.h>
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+namespace Internal
+{
+
+using DragAndDropDetectorPtr = IntrusivePtr< DragAndDropDetector >;
+
+/**
+ * This class listens to Drag & Drop events.
+ */
+class DragAndDropDetector : public Dali::BaseObject, public ConnectionTracker
+{
+public:
+
+  using DragAndDropSignal = Dali::Toolkit::DragAndDropDetector::DragAndDropSignal;
+
+  // Creation
+
+  /**
+   * @copydoc Toolkit::DragAndDropDetector::New()
+   */
+  static Dali::Toolkit::DragAndDropDetector New();
+
+  // Public API
+
+  /**
+   * @copydoc Dali::DragAndDropDetector::GetContent() const
+   */
+  const std::string& GetContent() const;
+
+  /**
+   * @copydoc Dali::DragAndDropDetector::GetCurrentScreenPosition() const
+   */
+  const Vector2& GetCurrentScreenPosition() const;
+
+  /**
+   * Attaches control to DragAndDropDetector.
+   * @param[in] control  control that will be attached to DragAndDropDetector.
+   */
+  void Attach(Dali::Toolkit::Control& control);
+
+  /**
+   * Detaches control to DragAndDropDetector.
+   * @param[in] control  control that will be Detached from DragAndDropDetector.
+   */
+  void Detach(Dali::Toolkit::Control& control);
+
+  /**
+   * Detaches all control attached to DragAndDropDetector.
+   */
+  void DetachAll();
+
+  /**
+   * Returns the number of controls attached to the DragAndDropDetector.
+   */
+  uint32_t GetAttachedControlCount() const;
+
+  /**
+   * Returns a control by index. An empty handle if the index is not valid.
+   */
+  Dali::Toolkit::Control GetAttachedControl(uint32_t index) const;
+
+  /**
+   * Sets the dragged content.
+   * @param[in] content  A string that represents the content that has been dropped.
+   */
+  void SetContent( const std::string& content );
+
+  /**
+   * Clears the stored content.
+   */
+  void ClearContent();
+
+  /**
+   * Sets the position the drop occurred.
+   */
+  void SetPosition( const Vector2& screenPosition );
+
+  /**
+   * Called when a draggable object start drag.
+   */
+  void EmitStartedSignal(Dali::Toolkit::Control& control);
+
+  /**
+   * Called when a draggable object enters other object.
+   */
+  void EmitEnteredSignal(Dali::Toolkit::Control& control);
+
+  /**
+   * Called when a draggable object leaves other object.
+   */
+  void EmitExitedSignal(Dali::Toolkit::Control& control);
+
+  /**
+   * Called when a draggable object leaves other object.
+   */
+  void EmitMovedSignal(Dali::Toolkit::Control& control);
+
+  /**
+   * Is called when a drop actually occurs.
+   */
+  void EmitDroppedSignal(Dali::Toolkit::Control& control);
+
+  /**
+   * Called when a draggable object drag ended.
+   */
+  void EmitEndedSignal(Dali::Toolkit::Control& control);
+
+public: // Signals
+
+  /**
+   * @copydoc Dali::Toolkit::DragAndDropDetector::StartedSignal
+   */
+  DragAndDropSignal& StartedSignal()
+  {
+    return mStartedSignal;
+  }
+
+  /**
+   * @copydoc Dali::Toolkit::DragAndDropDetector::EnteredSignal
+   */
+  DragAndDropSignal& EnteredSignal()
+  {
+    return mEnteredSignal;
+  }
+
+  /**
+   * @copydoc Dali::Toolkit::DragAndDropDetector::ExitedSignal
+   */
+  DragAndDropSignal& ExitedSignal()
+  {
+    return mExitedSignal;
+  }
+
+  /**
+   * @copydoc Dali::Toolkit::DragAndDropDetector::MovedSignal
+   */
+  DragAndDropSignal& MovedSignal()
+  {
+    return mMovedSignal;
+  }
+
+  /**
+   * @copydoc Dali::Toolkit::DragAndDropDetector::DroppedSignal
+   */
+  DragAndDropSignal& DroppedSignal()
+  {
+    return mDroppedSignal;
+  }
+
+  /**
+   * @copydoc Dali::Toolkit::DragAndDropDetector::DroppedSignal
+   */
+  DragAndDropSignal& EndedSignal()
+  {
+    return mEndedSignal;
+  }
+
+public:
+  bool OnDrag(Dali::Actor actor, const Dali::TouchData& data);
+  void OnPan(Dali::Actor actor, const PanGesture& gesture);
+
+private:
+
+  // Construction & Destruction
+
+  /**
+   * Constructor.
+   */
+  DragAndDropDetector();
+
+  /**
+   * Destructor.
+   */
+  virtual ~DragAndDropDetector();
+
+  // Undefined
+  DragAndDropDetector( const DragAndDropDetector& ) = delete;
+  DragAndDropDetector& operator=( DragAndDropDetector& );
+
+private:
+
+  std::string mContent;    ///< The current Drag & drop content.
+
+  DragAndDropSignal mStartedSignal;
+  DragAndDropSignal mEnteredSignal;
+  DragAndDropSignal mExitedSignal;
+  DragAndDropSignal mMovedSignal;
+  DragAndDropSignal mDroppedSignal;
+  DragAndDropSignal mEndedSignal;
+
+  std::vector<Dali::Toolkit::Control> mControls;      //controls attached by Attach interface for drag&drop
+  Dali::Toolkit::Control mDragControl;                //the current drag control
+  Dali::Toolkit::Control mShadowControl;              //a shadow control for indicating where the control is, same size as the dragged control
+  std::vector<uint32_t> mFirstEnter;                  //control id indicating if the cursor is enter
+  Dali::PanGestureDetector mPanGestureDetector;       //pangesture for calculating the shadow actor position
+
+  Vector2 mLocalPosition;
+  Vector2 mDragLocalPosition;
+  Vector2 mScreenPosition; ///< The screen position of the drop location.
+
+  bool mPointDown; //bool flag to indicate if PointState::DOWN have been processed
+};
+
+} // namespace Internal
+
+
+// Helpers for public-api forwarding methods
+
+inline Internal::DragAndDropDetector& GetImplementation(Dali::Toolkit::DragAndDropDetector& detector)
+{
+  DALI_ASSERT_ALWAYS( detector && "DragAndDropDetector handle is empty" );
+
+  BaseObject& handle = detector.GetBaseObject();
+
+  return static_cast<Internal::DragAndDropDetector&>(handle);
+}
+
+inline const Internal::DragAndDropDetector& GetImplementation(const Dali::Toolkit::DragAndDropDetector& detector)
+{
+  DALI_ASSERT_ALWAYS( detector && "DragAndDropDetector handle is empty" );
+
+  const BaseObject& handle = detector.GetBaseObject();
+
+  return static_cast<const Internal::DragAndDropDetector&>(handle);
+}
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_DRAG_AND_DROP_DETECTOR_H__
index 44be18c..3a0375e 100755 (executable)
@@ -29,7 +29,7 @@ toolkit_src_files = \
    $(toolkit_src_dir)/visuals/animated-image/rolling-image-cache.cpp \
    $(toolkit_src_dir)/visuals/animated-image/rolling-gif-image-cache.cpp \
    $(toolkit_src_dir)/visuals/animated-vector-image/animated-vector-image-visual.cpp \
-   $(toolkit_src_dir)/visuals/animated-vector-image/vector-image-rasterize-thread.cpp \
+   $(toolkit_src_dir)/visuals/animated-vector-image/vector-rasterize-thread.cpp \
    $(toolkit_src_dir)/visuals/border/border-visual.cpp \
    $(toolkit_src_dir)/visuals/color/color-visual.cpp \
    $(toolkit_src_dir)/visuals/gradient/gradient-visual.cpp \
@@ -175,4 +175,5 @@ toolkit_src_files = \
    $(toolkit_src_dir)/transition-effects/cube-transition-wave-effect-impl.cpp \
    $(toolkit_src_dir)/scripting/script-impl.cpp \
    $(toolkit_src_dir)/scripting/script-plugin-proxy.cpp \
-   $(toolkit_src_dir)/text/xhtml-entities.cpp
+   $(toolkit_src_dir)/text/xhtml-entities.cpp \
+   $(toolkit_src_dir)/drag-drop-detector/drag-and-drop-detector-impl.cpp
index 11f2f24..96c7ddd 100644 (file)
 // INTERNAL INCLUDES
 #include <dali-toolkit/public-api/visuals/image-visual-properties.h>
 #include <dali-toolkit/public-api/visuals/visual-properties.h>
+#include <dali-toolkit/devel-api/visuals/image-visual-properties-devel.h>
 #include <dali-toolkit/internal/visuals/image-visual-shader-factory.h>
 #include <dali-toolkit/internal/visuals/visual-factory-cache.h>
 #include <dali-toolkit/internal/visuals/visual-string-constants.h>
 #include <dali-toolkit/internal/visuals/visual-base-data-impl.h>
-#include <dali-toolkit/internal/visuals/animated-vector-image/vector-image-rasterize-thread.h>
+#include <dali-toolkit/internal/visuals/animated-vector-image/vector-rasterize-thread.h>
 
 namespace Dali
 {
@@ -45,6 +46,7 @@ namespace
 {
 
 const Dali::Vector4 FULL_TEXTURE_RECT( 0.f, 0.f, 1.f, 1.f );
+constexpr auto LOOP_FOREVER = -1;
 
 } // unnamed namespace
 
@@ -68,8 +70,10 @@ AnimatedVectorImageVisual::AnimatedVectorImageVisual( VisualFactoryCache& factor
   mImageVisualShaderFactory( shaderFactory ),
   mUrl( imageUrl ),
   mVisualSize(),
+  mPlayRange( 0.0f, 1.0f ),
   mPlacementActor(),
   mVectorRasterizeThread(),
+  mLoopCount( LOOP_FOREVER ),
   mActionStatus( DevelAnimatedVectorImageVisual::Action::STOP )
 {
   // the rasterized image is with pre-multiplied alpha format
@@ -93,6 +97,8 @@ void AnimatedVectorImageVisual::DoCreatePropertyMap( Property::Map& map ) const
   {
     map.Insert( Toolkit::ImageVisual::Property::URL, mUrl.GetUrl() );
   }
+  map.Insert( Toolkit::DevelImageVisual::Property::LOOP_COUNT, static_cast< int >( mLoopCount ) );
+  map.Insert( Toolkit::DevelImageVisual::Property::PLAY_RANGE, static_cast< Vector2 >( mPlayRange ) );
 }
 
 void AnimatedVectorImageVisual::DoCreateInstancePropertyMap( Property::Map& map ) const
@@ -110,11 +116,63 @@ void AnimatedVectorImageVisual::DoSetProperties( const Property::Map& propertyMa
     {
       DoSetProperty( keyValue.first.indexKey, keyValue.second );
     }
+    else
+    {
+       if( keyValue.first == LOOP_COUNT_NAME )
+       {
+          DoSetProperty( Toolkit::DevelImageVisual::Property::LOOP_COUNT, keyValue.second );
+       }
+       else if( keyValue.first == PLAY_RANGE_NAME )
+       {
+          DoSetProperty( Toolkit::DevelImageVisual::Property::PLAY_RANGE, keyValue.second );
+       }
+    }
   }
 }
 
 void AnimatedVectorImageVisual::DoSetProperty( Property::Index index, const Property::Value& value )
 {
+  switch(index)
+  {
+    case Toolkit::DevelImageVisual::Property::LOOP_COUNT:
+    {
+      int32_t loopCount;
+      if( value.Get( loopCount ) )
+      {
+        mLoopCount = loopCount;
+        if( mVectorRasterizeThread )
+        {
+          mVectorRasterizeThread->SetLoopCount( loopCount );
+        }
+      }
+      break;
+    }
+    case Toolkit::DevelImageVisual::Property::PLAY_RANGE:
+    {
+      Vector2 range;
+      if( value.Get( range ) )
+      {
+        // Make sure the range specified is between 0.0 and 1.0
+        if( range.x >= 0.0f && range.x <= 1.0f && range.y >= 0.0f && range.y <= 1.0f )
+        {
+          Vector2 orderedRange( range );
+          // If the range is not in order swap values
+          if( range.x > range.y )
+          {
+            orderedRange = Vector2( range.y, range.x );
+          }
+
+          mPlayRange = orderedRange;
+
+          if( mVectorRasterizeThread )
+          {
+            mVectorRasterizeThread->SetPlayRange( mPlayRange );
+          }
+        }
+      }
+      break;
+    }
+  }
 }
 
 void AnimatedVectorImageVisual::DoSetOnStage( Actor& actor )
@@ -192,6 +250,9 @@ void AnimatedVectorImageVisual::OnSetTransform()
         mVectorRasterizeThread = std::unique_ptr< VectorRasterizeThread >( new VectorRasterizeThread( mUrl.GetUrl(), mImpl->mRenderer, width, height ) );
 
         mVectorRasterizeThread->SetResourceReadyCallback( new EventThreadCallback( MakeCallback( this, &AnimatedVectorImageVisual::OnResourceReady ) ) );
+        mVectorRasterizeThread->SetLoopCount( mLoopCount );
+        mVectorRasterizeThread->SetPlayRange( mPlayRange );
+
         mVectorRasterizeThread->Start();
 
         if( mActionStatus == DevelAnimatedVectorImageVisual::Action::PLAY )
@@ -207,7 +268,10 @@ void AnimatedVectorImageVisual::OnSetTransform()
       }
       else
       {
-        // TODO: change size
+        uint32_t width = static_cast< uint32_t >( visualSize.width );
+        uint32_t height = static_cast< uint32_t >( visualSize.height );
+
+        mVectorRasterizeThread->SetSize( width, height );
       }
     }
   }
index 33c46b6..268cb06 100644 (file)
@@ -160,8 +160,11 @@ private:
   ImageVisualShaderFactory&                    mImageVisualShaderFactory;
   VisualUrl                                    mUrl;
   Vector2                                      mVisualSize;
+  Vector2                                      mPlayRange;
   WeakHandle< Actor >                          mPlacementActor;
   std::unique_ptr< VectorRasterizeThread >     mVectorRasterizeThread;
+
+  int32_t                                      mLoopCount;
   DevelAnimatedVectorImageVisual::Action::Type mActionStatus;
 };
 
@@ -16,7 +16,7 @@
  */
 
 // CLASS HEADER
-#include <dali-toolkit/internal/visuals/animated-vector-image/vector-image-rasterize-thread.h>
+#include <dali-toolkit/internal/visuals/animated-vector-image/vector-rasterize-thread.h>
 
 // EXTERNAL INCLUDES
 #include <dali/devel-api/adaptor-framework/thread-settings.h>
@@ -37,6 +37,8 @@ namespace Internal
 namespace
 {
 
+constexpr auto LOOP_FOREVER = -1;
+
 #if defined(DEBUG_ENABLED)
 Debug::Filter* gVectorAnimationLogFilter = Debug::Filter::New( Debug::NoLogging, false, "LOG_VECTOR_ANIMATION" );
 #endif
@@ -46,11 +48,18 @@ Debug::Filter* gVectorAnimationLogFilter = Debug::Filter::New( Debug::NoLogging,
 VectorRasterizeThread::VectorRasterizeThread( const std::string& url, Renderer renderer, uint32_t width, uint32_t height )
 : mUrl( url ),
   mVectorRenderer(),
+  mConditionalWait(),
+  mMutex(),
   mResourceReadyTrigger( NULL ),
+  mPlayRange( 0.0f, 1.0f ),
   mCurrentFrame( 0 ),
   mTotalFrame( 0 ),
+  mStartFrame( 0 ),
+  mEndFrame( 0 ),
   mWidth( width ),
   mHeight( height ),
+  mLoopCount( LOOP_FOREVER ),
+  mCurrentLoop( 0 ),
   mNeedRender( false ),
   mPlaying( false ),
   mPaused( false ),
@@ -94,6 +103,14 @@ void VectorRasterizeThread::Run()
   }
 }
 
+void VectorRasterizeThread::SetSize( uint32_t width, uint32_t height )
+{
+  ConditionalWait::ScopedLock lock( mConditionalWait );
+  mVectorRenderer.SetSize( width, height );
+
+  DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::SetSize: width = %d, height = %d\n", width, height );
+}
+
 void VectorRasterizeThread::StartAnimation()
 {
   ConditionalWait::ScopedLock lock( mConditionalWait );
@@ -153,9 +170,34 @@ void VectorRasterizeThread::RenderFrame()
 
 void VectorRasterizeThread::SetResourceReadyCallback( EventThreadCallback* callback )
 {
+  ConditionalWait::ScopedLock lock( mConditionalWait );
   mResourceReadyTrigger = callback;
 }
 
+void VectorRasterizeThread::SetLoopCount( int16_t count )
+{
+  ConditionalWait::ScopedLock lock( mConditionalWait );
+
+  mLoopCount = count;
+
+  // Reset progress
+  mCurrentLoop = 0;
+  mCurrentFrame = mStartFrame;
+}
+
+void VectorRasterizeThread::SetPlayRange( Vector2 range )
+{
+  ConditionalWait::ScopedLock lock( mConditionalWait );
+
+  mPlayRange = range;
+
+  if( mTotalFrame != 0 )
+  {
+    mStartFrame = static_cast< uint32_t >( mPlayRange.x * mTotalFrame + 0.5f );
+    mEndFrame = static_cast< uint32_t >( mPlayRange.y * mTotalFrame + 0.5f );
+  }
+}
+
 bool VectorRasterizeThread::IsThreadReady()
 {
   ConditionalWait::ScopedLock lock( mConditionalWait );
@@ -166,7 +208,8 @@ bool VectorRasterizeThread::IsThreadReady()
 
     if( !mPlaying )
     {
-      mCurrentFrame = 0;
+      mCurrentFrame = mStartFrame;
+      mCurrentLoop = 0;
     }
 
     mConditionalWait.Wait( lock );
@@ -183,7 +226,12 @@ bool VectorRasterizeThread::StartRender()
 
   mTotalFrame = mVectorRenderer.GetTotalFrameNumber();
 
-  DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::StartRender: Renderer is started [%d]\n", mTotalFrame );
+  mStartFrame = static_cast< uint32_t >( mPlayRange.x * mTotalFrame + 0.5f );
+  mEndFrame = static_cast< uint32_t >( mPlayRange.y * mTotalFrame + 0.5f );
+
+  mCurrentFrame = mStartFrame;
+
+  DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::StartRender: Renderer is started [%d (%d, %d)]\n", mTotalFrame, mStartFrame, mEndFrame );
 
   return true;
 }
@@ -197,11 +245,26 @@ void VectorRasterizeThread::Rasterize()
 
   if( mPlaying && !mPaused )
   {
-    mCurrentFrame++;
-
-    if( mCurrentFrame >= mTotalFrame )
+    if( ++mCurrentFrame >= mEndFrame )
     {
-      mCurrentFrame = 0;
+      if( mLoopCount < 0 )
+      {
+        // repeat forever
+        mCurrentFrame = mStartFrame;
+      }
+      else
+      {
+        mCurrentLoop++;
+        if( mCurrentLoop >= mLoopCount )
+        {
+          // Animation is finished
+          mPlaying = false;
+        }
+        else
+        {
+          mCurrentFrame = mStartFrame;
+        }
+      }
     }
   }
 
@@ -58,22 +58,30 @@ public:
   virtual ~VectorRasterizeThread();
 
   /**
-   * @brief Play the vector animation
+   * @brief Sets the target image size.
+   *
+   * @param[in] width The target image width
+   * @param[in] height The target image height
+   */
+  void SetSize( uint32_t width, uint32_t height );
+
+  /**
+   * @brief Play the vector animation.
    */
   void StartAnimation();
 
   /**
-   * @brief Stop the vector animation
+   * @brief Stop the vector animation.
    */
   void StopAnimation();
 
   /**
-   * @brief Pause the vector animation
+   * @brief Pause the vector animation.
    */
   void PauseAnimation();
 
   /**
-   * @brief Resume the vector animation
+   * @brief Resume the vector animation.
    */
   void ResumeAnimation();
 
@@ -84,10 +92,23 @@ public:
 
   /**
    * @brief This callback is called after the first frame is ready.
-   * @param callback The resource ready callback
+   * @param[in] callback The resource ready callback
    */
   void SetResourceReadyCallback( EventThreadCallback* callback );
 
+  /**
+   * @brief Enable looping for 'count' repeats. -1 means to repeat forever.
+   * @param[in] count The number of times to loop
+   */
+  void SetLoopCount( int16_t count );
+
+  /**
+   * @brief Set the playing range.
+   * @param[in] range Two values between [0,1] to specify minimum and maximum progress.
+   * The animation will play between those values.
+   */
+  void SetPlayRange( Vector2 range );
+
 protected:
 
   /**
@@ -127,10 +148,15 @@ private:
   ConditionalWait            mConditionalWait;
   Dali::Mutex                mMutex;
   EventThreadCallback*       mResourceReadyTrigger;
+  Vector2                    mPlayRange;
   uint32_t                   mCurrentFrame;
   uint32_t                   mTotalFrame;
+  uint32_t                   mStartFrame;
+  uint32_t                   mEndFrame;
   uint32_t                   mWidth;
   uint32_t                   mHeight;
+  int16_t                    mLoopCount;
+  int16_t                    mCurrentLoop;
   bool                       mNeedRender;
   bool                       mPlaying;
   bool                       mPaused;
index 9257a74..e0382b3 100644 (file)
@@ -100,6 +100,7 @@ const char * const RELEASE_POLICY_NAME("releasePolicy");
 const char * const ORIENTATION_CORRECTION_NAME("orientationCorrection");
 const char * const AUXILIARY_IMAGE_NAME("auxiliaryImage");
 const char * const AUXILIARY_IMAGE_ALPHA_NAME("auxiliaryImageAlpha");
+const char * const PLAY_RANGE_NAME("playRange");
 
 // Text visual
 const char * const TEXT_PROPERTY( "text" );
index 89b73a7..6ae808b 100644 (file)
@@ -85,6 +85,7 @@ extern const char * const RELEASE_POLICY_NAME;
 extern const char * const ORIENTATION_CORRECTION_NAME;
 extern const char * const AUXILLARY_IMAGE_NAME;
 extern const char * const AUXILLARY_IMAGE_ALPHA_NAME;
+extern const char * const PLAY_RANGE_NAME;
 
 // Text visual
 extern const char * const TEXT_PROPERTY;
index d87b2f7..ff11601 100644 (file)
@@ -31,7 +31,7 @@ namespace Toolkit
 
 const unsigned int TOOLKIT_MAJOR_VERSION = 1;
 const unsigned int TOOLKIT_MINOR_VERSION = 3;
-const unsigned int TOOLKIT_MICRO_VERSION = 52;
+const unsigned int TOOLKIT_MICRO_VERSION = 53;
 const char * const TOOLKIT_BUILD_DATE    = __DATE__ " " __TIME__;
 
 #ifdef DEBUG_ENABLED
index f2d27ea..c41d372 100644 (file)
@@ -1,6 +1,6 @@
 Name:       dali-toolkit
 Summary:    Dali 3D engine Toolkit
-Version:    1.3.52
+Version:    1.3.53
 Release:    1
 Group:      System/Libraries
 License:    Apache-2.0 and BSD-3-Clause and MIT