Revert "[Tizen] Revert "Changes after touch consumed behaviour change"
[platform/core/uifw/dali-demo.git] / examples / gestures / gesture-example.cpp
index bbae267..fb5b4a7 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ * 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.
 // EXTERNAL INCLUDES
 #include <dali-toolkit/dali-toolkit.h>
 #include <string>
+#include <dali/devel-api/actors/actor-devel.h>
+#include <dali/devel-api/events/rotation-gesture.h>
+#include <dali/devel-api/events/rotation-gesture-detector.h>
 
 using namespace Dali;
 using namespace Dali::Toolkit;
+using namespace std;
 
 namespace
 {
-const Vector4 BACKGROUND_GRADIENT_1 = Vector4( 167.0f, 207.0f, 223.0f, 255.0f ) / 255.0f;
-const Vector4 BACKGROUND_GRADIENT_2 = Vector4(   0.0f,  64.0f, 137.0f, 255.0f ) / 255.0f;
-const Vector2 BACKGROUND_GRADIENT_START_POSITION( 0.0f, -0.5f );
-const Vector2 BACKGROUND_GRADIENT_END_POSITION( 0.0f,  0.5f );
+const Property::Value BACKGROUND
+{
+  { Toolkit::Visual::Property::TYPE, Visual::GRADIENT },
+  { GradientVisual::Property::STOP_COLOR,  Property::Array{ Vector4( 167.0f, 207.0f, 223.0f, 255.0f ) / 255.0f,
+                                                            Vector4(   0.0f,  64.0f, 137.0f, 255.0f ) / 255.0f } },
+  { GradientVisual::Property::START_POSITION, Vector2( 0.0f, -0.5f ) },
+  { GradientVisual::Property::END_POSITION,   Vector2( 0.0f,  0.5f ) }
+};
 
-const Vector4 CONTROL_GRADIENT_1 = Vector4( 234.0f, 185.0f,  45.0f, 255.0f ) / 255.0f;
-const Vector4 CONTROL_GRADIENT_2 = Vector4( 199.0f, 152.0f,  16.0f, 255.0f ) / 255.0f;
-const Vector2 CONTROL_GRADIENT_CENTER( Vector2::ZERO );
-const float CONTROL_GRADIENT_RADIUS( 0.5f );
+const Property::Value CONTROL_BACKGROUND
+{
+  { Toolkit::Visual::Property::TYPE, Visual::GRADIENT },
+  { GradientVisual::Property::STOP_COLOR, Property::Array{ Vector4( 234.0f, 185.0f,  45.0f, 255.0f ) / 255.0f,
+                                                           Vector4( 199.0f, 152.0f,  16.0f, 255.0f ) / 255.0f } },
+  { GradientVisual::Property::CENTER, Vector2::ZERO },
+  { GradientVisual::Property::RADIUS, 0.5f }
+};
 
 const float HELP_ANIMATION_DURATION( 25.0f );
 const float HELP_ANIMATION_SEGMENT_TIME( 5.0f );
@@ -50,51 +62,13 @@ const float PAN_MODE_CHANGE_ANIMATION_DURATION( 0.25f );
 const Vector3 PAN_MODE_START_ANIMATION_SCALE( 1.2f, 1.2f, 1.0f );
 const Vector3 PAN_MODE_END_ANIMATION_SCALE( 0.8f, 0.8f, 1.0f );
 
-const float TAP_ANIMATION_DURATON( 0.5f );
+const float TAP_ANIMATION_DURATION( 0.5f );
 const Vector4 TAP_ANIMATION_COLOR( 0.8f, 0.5, 0.2f, 0.6f );
 
 const Vector3 MINIMUM_SCALE( Vector3::ONE );
 const Vector3 MAXIMUM_SCALE( Vector3::ONE * 2.0f );
 const float SCALE_BACK_ANIMATION_DURATION( 0.25f );
-
-/**
- * @brief Creates a background with a linear gradient which matches parent size & is placed in the center.
- */
-Actor CreateBackground()
-{
-  Actor background = Control::New();
-  background.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS );
-  background.SetParentOrigin( ParentOrigin::CENTER );
-  background.SetProperty(
-      Control::Property::BACKGROUND,
-      Property::Map().Add( Toolkit::Visual::Property::TYPE, Visual::GRADIENT )
-                     .Add( GradientVisual::Property::STOP_COLOR, Property::Array().Add( BACKGROUND_GRADIENT_1 )
-                                                                                  .Add( BACKGROUND_GRADIENT_2 ) )
-                     .Add( GradientVisual::Property::START_POSITION, BACKGROUND_GRADIENT_START_POSITION )
-                     .Add( GradientVisual::Property::END_POSITION,   BACKGROUND_GRADIENT_END_POSITION ) );
-  return background;
-}
-
-/**
- * @brief Create a control with a circular gradient & a specific size & is placed in the center of its parent.
- *
- * @param[in]  size  The size we want the control to be.
- */
-Actor CreateTouchControl( const Vector2& size )
-{
-  Actor touchControl = Control::New();
-  touchControl.SetSize( size );
-  touchControl.SetParentOrigin( ParentOrigin::CENTER );
-  touchControl.SetProperty(
-      Control::Property::BACKGROUND,
-      Property::Map().Add( Toolkit::Visual::Property::TYPE, Visual::GRADIENT )
-                     .Add( GradientVisual::Property::STOP_COLOR, Property::Array().Add( CONTROL_GRADIENT_1 )
-                                                                                  .Add( CONTROL_GRADIENT_2 ) )
-                     .Add( GradientVisual::Property::CENTER, CONTROL_GRADIENT_CENTER )
-                     .Add( GradientVisual::Property::RADIUS, CONTROL_GRADIENT_RADIUS )
-  );
-  return touchControl;
-}
+const float ROTATE_BACK_ANIMATION_DURATION( 0.25f );
 
 /**
  * @brief Shows the given string between the given start and end times.
@@ -107,16 +81,17 @@ Actor CreateTouchControl( const Vector2& size )
  * @param[in]  startTime  When to start the animators
  * @param[in]  endTime    When to end the animators
  */
-void AddHelpInfo( const std::string&& string, Actor parent, Animation animation, float startTime, float endTime )
+void AddHelpInfo( const std::string&& string, const Vector2& windowSize, Actor parent, Animation animation, float startTime, float endTime )
 {
   Actor text = TextLabel::New( std::move( string ) );
-  Vector3 position( Stage::GetCurrent().GetSize() * HELP_TEXT_POSITION_MULTIPLIER );
+  Vector3 position( windowSize * HELP_TEXT_POSITION_MULTIPLIER );
 
-  text.SetAnchorPoint( AnchorPoint::TOP_CENTER );
-  text.SetParentOrigin( ParentOrigin::TOP_CENTER );
-  text.SetPosition( position );
-  text.SetOpacity( 0.0f );
+  text.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_CENTER );
+  text.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_CENTER );
+  text.SetProperty( Actor::Property::POSITION, position );
+  text.SetProperty( Actor::Property::OPACITY, 0.0f );
   text.SetProperty( TextLabel::Property::HORIZONTAL_ALIGNMENT, Text::HorizontalAlignment::CENTER );
+  text.SetProperty( TextLabel::Property::MULTI_LINE, true );
   parent.Add( text );
 
   // Animate IN
@@ -166,30 +141,36 @@ private:
    */
   void Create( Application& application )
   {
-    // Get a handle to the stage & connect to the key event signal
-    Stage stage = Stage::GetCurrent();
-    stage.KeyEventSignal().Connect(this, &GestureExample::OnKeyEvent);
-
-    // Create a background with a gradient
-    Actor background = CreateBackground();
-    stage.Add( background );
-
-    // Create a control that we'll use for the gestures to be a quarter of the size of the stage
-    Actor touchControl = CreateTouchControl( stage.GetSize() * 0.25f );
+    // Get a handle to the window & connect to the key event signal
+    auto window = application.GetWindow();
+    Vector2 windowSize = window.GetSize();
+    window.KeyEventSignal().Connect(this, &GestureExample::OnKeyEvent);
+
+    // Create a background with a linear gradient which matches parent size & is placed in the center.
+    Actor background = Control::New();
+    background.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS );
+    background.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER );
+    background.SetProperty( Control::Property::BACKGROUND, BACKGROUND );
+    window.Add( background );
+
+    // Create a control with a circular gradient that we'll use for the gestures and be a quarter of the size of the window.
+    Actor touchControl = Control::New();
+    touchControl.SetProperty( Actor::Property::SIZE, windowSize * 0.25f );
+    touchControl.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER );
+    touchControl.SetProperty( Control::Property::BACKGROUND, CONTROL_BACKGROUND );
     background.Add( touchControl );
 
     // Connect to the touch signal
     touchControl.TouchSignal().Connect( this, &GestureExample::OnTouch );
-    touchControl.SetLeaveRequired( true );
+    touchControl.SetProperty( Actor::Property::LEAVE_REQUIRED, true );
 
     // Create a long press gesture detector, attach the actor & connect
     mLongPressDetector = LongPressGestureDetector::New();
     mLongPressDetector.Attach( touchControl );
     mLongPressDetector.DetectedSignal().Connect( this, &GestureExample::OnLongPress );
 
-    // Create a pan gesture detector, attach the actor & connect
+    // Create a pan gesture detector & connect, don't attach the actor as we'll attach it when we detect a long-press
     mPanDetector = PanGestureDetector::New();
-    mPanDetector.Attach( touchControl );
     mPanDetector.DetectedSignal().Connect( this, &GestureExample::OnPan );
 
     // Create a tap gesture detector, attach the actor & connect
@@ -202,6 +183,11 @@ private:
     mPinchDetector.Attach( touchControl );
     mPinchDetector.DetectedSignal().Connect( this, &GestureExample::OnPinch );
 
+    // Create a rotation gesture detector, attach the actor & connect
+    mRotationDetector = RotationGestureDetector::New();
+    mRotationDetector.Attach( touchControl );
+    mRotationDetector.DetectedSignal().Connect( this, &GestureExample::OnRotation );
+
     // Create an animation which shakes the actor when in Pan mode
     mShakeAnimation = Animation::New( SHAKY_ANIMATION_DURATION );
     mShakeAnimation.AnimateBy( Property( touchControl, Actor::Property::ORIENTATION ),
@@ -221,9 +207,10 @@ private:
     float startTime( 0.0f );
     float endTime( startTime + HELP_ANIMATION_SEGMENT_TIME );
 
-    AddHelpInfo( "Tap image for animation",         background, helpAnimation, startTime, endTime );
-    AddHelpInfo( "Press & Hold image to drag",      background, helpAnimation, startTime += HELP_ANIMATION_SEGMENT_TIME, endTime += HELP_ANIMATION_SEGMENT_TIME );
-    AddHelpInfo( "Pinch image to resize",           background, helpAnimation, startTime += HELP_ANIMATION_SEGMENT_TIME, endTime += HELP_ANIMATION_SEGMENT_TIME );
+    AddHelpInfo( "Tap image for animation",                              windowSize, background, helpAnimation, startTime, endTime );
+    AddHelpInfo( "Press & Hold image to drag",                           windowSize, background, helpAnimation, startTime += HELP_ANIMATION_SEGMENT_TIME, endTime += HELP_ANIMATION_SEGMENT_TIME );
+    AddHelpInfo( "Pinch image to resize",                                windowSize, background, helpAnimation, startTime += HELP_ANIMATION_SEGMENT_TIME, endTime += HELP_ANIMATION_SEGMENT_TIME );
+    AddHelpInfo( "Move fingers in a circular motion on image to rotate", windowSize, background, helpAnimation, startTime += HELP_ANIMATION_SEGMENT_TIME, endTime += HELP_ANIMATION_SEGMENT_TIME );
     helpAnimation.SetLooping( true );
     helpAnimation.Play();
   }
@@ -234,7 +221,7 @@ private:
    * @param[in]  actor  The touched actor
    * @param[in]  touch  The touch event
    */
-  bool OnTouch( Actor actor, const TouchData& touch )
+  bool OnTouch( Actor actor, const TouchEvent& touch )
   {
     switch( touch.GetState( 0 ) )
     {
@@ -271,7 +258,7 @@ private:
         break;
       }
     }
-    return true;
+    return false;
   }
 
   /**
@@ -282,36 +269,19 @@ private:
    */
   void OnLongPress( Actor actor, const LongPressGesture& longPress )
   {
-    switch( longPress.state )
+    if( longPress.state == Gesture::Started )
     {
-      case Gesture::Started:
-      {
-        // When we first receive a long press, change state to pan mode.
+      // When we first receive a long press, attach the actor to the pan detector.
+      mPanDetector.Attach( actor );
 
-        // Do a small animation to indicate to the user that we are in pan mode.
-        Animation anim = Animation::New( PAN_MODE_CHANGE_ANIMATION_DURATION );
-        anim.AnimateTo( Property( actor, Actor::Property::SCALE ), actor.GetCurrentScale() * PAN_MODE_START_ANIMATION_SCALE, AlphaFunction::BOUNCE );
-        anim.Play();
-        mPanMode = true;
+      // Do a small animation to indicate to the user that we are in pan mode.
+      Animation anim = Animation::New( PAN_MODE_CHANGE_ANIMATION_DURATION );
+      anim.AnimateTo( Property( actor, Actor::Property::SCALE ), actor.GetCurrentProperty< Vector3 >( Actor::Property::SCALE ) * PAN_MODE_START_ANIMATION_SCALE, AlphaFunction::BOUNCE );
+      anim.Play();
 
-        // Start the shake animation so the user knows when they are in pan mode.
-        mShakeAnimation.SetLooping( true );
-        mShakeAnimation.Play();
-        break;
-      }
-
-      case Gesture::Finished:
-      case Gesture::Cancelled:
-      {
-        // We get this state when all touches are released after a long press. We end pan mode...
-        mPanMode = false;
-        break;
-      }
-
-      default:
-      {
-        break;
-      }
+      // Start the shake animation so the user knows when they are in pan mode.
+      mShakeAnimation.SetLooping( true );
+      mShakeAnimation.Play();
     }
   }
 
@@ -323,56 +293,55 @@ private:
    */
   void OnPan( Actor actor, const PanGesture& pan )
   {
-    if( mPanMode || mPanStarted )
-    {
-      // When we are in Pan mode, just move the actor by the displacement.
+    // Just move the actor by the displacement.
 
-      // As the displacement is in local actor coords, we will have to multiply the displacement by the
-      // actor's scale so that it moves the correct amount in the parent's coordinate system.
-      Vector3 scaledDisplacement( pan.displacement );
-      scaledDisplacement *= actor.GetCurrentScale();
+    // As the displacement is in local actor coords, we will have to multiply the displacement by the
+    // actor's scale so that it moves the correct amount in the parent's coordinate system.
+    Vector3 scaledDisplacement( pan.displacement );
+    scaledDisplacement *= actor.GetCurrentProperty< Vector3 >( Actor::Property::SCALE );
 
-      Vector3 currentPosition;
-      actor.GetProperty( Actor::Property::POSITION ).Get( currentPosition );
+    Vector3 currentPosition;
+    actor.GetProperty( Actor::Property::POSITION ).Get( currentPosition );
 
-      Vector3 newPosition = currentPosition + scaledDisplacement;
-      actor.SetPosition( newPosition );
+    Vector3 newPosition = currentPosition + scaledDisplacement;
+    actor.SetProperty( Actor::Property::POSITION, newPosition );
 
-      switch( pan.state )
+    switch( pan.state )
+    {
+      case Gesture::Started:
       {
-        case Gesture::Started:
-        {
-          mPanStarted = true;
-          break;
-        }
-
-        case Gesture::Finished:
-        case Gesture::Cancelled:
-        {
-          // If we cancel or finish the pan, do an animation to indicate this and stop the shake animation.
+        mPanStarted = true;
+        break;
+      }
 
-          Animation anim = Animation::New( PAN_MODE_CHANGE_ANIMATION_DURATION );
-          anim.AnimateTo( Property( actor, Actor::Property::COLOR ), Vector4::ONE );
-          anim.AnimateTo( Property( actor, Actor::Property::SCALE ), actor.GetCurrentScale() * PAN_MODE_END_ANIMATION_SCALE, AlphaFunction::BOUNCE );
-
-          // Move actor back to center if we're out of bounds
-          Vector2 halfStageSize = Stage::GetCurrent().GetSize() * 0.5f;
-          if( ( std::abs( newPosition.x ) > halfStageSize.width  ) ||
-              ( std::abs( newPosition.y ) > halfStageSize.height ) )
-          {
-            anim.AnimateTo( Property( actor, Actor::Property::POSITION ), Vector3::ZERO, AlphaFunction::EASE_IN );
-          }
-          anim.Play();
+      case Gesture::Finished:
+      case Gesture::Cancelled:
+      {
+        // If we cancel or finish the pan, do an animation to indicate this and stop the shake animation.
 
-          mShakeAnimation.SetLooping( false );
-          mPanStarted = false;
-          break;
-        }
+        Animation anim = Animation::New( PAN_MODE_CHANGE_ANIMATION_DURATION );
+        anim.AnimateTo( Property( actor, Actor::Property::COLOR ), Vector4::ONE );
+        anim.AnimateTo( Property( actor, Actor::Property::SCALE ), actor.GetCurrentProperty< Vector3 >( Actor::Property::SCALE ) * PAN_MODE_END_ANIMATION_SCALE, AlphaFunction::BOUNCE );
 
-        default:
+        // Move actor back to center if we're out of bounds
+        Vector2 halfWindowSize = Vector2(mApplication.GetWindow().GetSize()) * 0.5f;
+        if( ( abs( newPosition.x ) > halfWindowSize.width  ) ||
+            ( abs( newPosition.y ) > halfWindowSize.height ) )
         {
-          break;
+          anim.AnimateTo( Property( actor, Actor::Property::POSITION ), Vector3::ZERO, AlphaFunction::EASE_IN );
         }
+        anim.Play();
+
+        // Set end of pan configuration and disconnect the actor from the pan detector
+        mShakeAnimation.SetLooping( false );
+        mPanStarted = false;
+        mPanDetector.Detach( actor );
+        break;
+      }
+
+      default:
+      {
+        break;
       }
     }
   }
@@ -387,10 +356,11 @@ private:
   {
     // Do a short animation to show a tap has happened.
 
-    Animation anim = Animation::New( TAP_ANIMATION_DURATON );
-    anim.AnimateBy( Property( actor, Actor::Property::ORIENTATION ), Quaternion( Degree( 360.0f ), Vector3::ZAXIS ) );
+    Animation anim = Animation::New( TAP_ANIMATION_DURATION );
+    anim.AnimateBy( Property( actor, Actor::Property::ORIENTATION ), Quaternion( ANGLE_360, Vector3::ZAXIS ) );
     anim.AnimateTo( Property( actor, Actor::Property::SCALE ), Vector3::ONE, AlphaFunction::LINEAR );
     anim.AnimateTo( Property( actor, Actor::Property::COLOR ), TAP_ANIMATION_COLOR, AlphaFunction::BOUNCE );
+    anim.AnimateTo( Property( actor, Actor::Property::POSITION ), Vector3::ZERO, AlphaFunction::EASE_OUT_SQUARE );
     anim.Play();
   }
 
@@ -407,14 +377,14 @@ private:
       case Gesture::Started:
       {
         // Starting scale is required so that we know what to multiply the pinch.scale by.
-        mStartingScale = actor.GetCurrentScale();
+        mStartingScale = actor.GetCurrentProperty< Vector3 >( Actor::Property::SCALE );
         break;
       }
 
       case Gesture::Finished:
       case Gesture::Cancelled:
       {
-        Vector3 scale( actor.GetCurrentScale() );
+        Vector3 scale( actor.GetCurrentProperty< Vector3 >( Actor::Property::SCALE ) );
 
         // Ensure the actor sizes itself to be within the limits defined.
         if ( scale.x < MINIMUM_SCALE.x )
@@ -439,7 +409,43 @@ private:
       }
     }
 
-    actor.SetScale( mStartingScale * pinch.scale );
+    actor.SetProperty( Actor::Property::SCALE, mStartingScale * pinch.scale );
+  }
+
+  /**
+   * @brief Called when a rotation gesture is detected on our control.
+   *
+   * @param[in]  actor     The actor that's been pinched
+   * @param[in]  rotation  The rotation gesture information
+   */
+  void OnRotation( Actor actor, const RotationGesture& rotation )
+  {
+    switch( rotation.state )
+    {
+      case Gesture::Started:
+      {
+        // Starting orientation is required so that we know what to multiply the rotation.rotation by.
+        mStartingOrientation = actor.GetCurrentProperty< Quaternion >( Actor::Property::ORIENTATION );
+        break;
+      }
+
+      case Gesture::Finished:
+      case Gesture::Cancelled:
+      {
+        // Do an animation to come back to go back to the original orientation.
+        Animation anim = Animation::New( ROTATE_BACK_ANIMATION_DURATION );
+        anim.AnimateTo( Property( actor, Actor::Property::ORIENTATION ), Quaternion::IDENTITY, AlphaFunction::LINEAR );
+        anim.Play();
+        break;
+      }
+
+      default:
+      {
+        break;
+      }
+    }
+
+    actor.SetProperty( Actor::Property::ORIENTATION, Quaternion( mStartingOrientation * Quaternion( rotation.rotation, Vector3::ZAXIS ) ) );
   }
 
   /**
@@ -466,10 +472,11 @@ private:
   LongPressGestureDetector mLongPressDetector;
   TapGestureDetector mTapDetector;
   PinchGestureDetector mPinchDetector;
+  RotationGestureDetector mRotationDetector;
 
   Vector3 mStartingScale; ///< Set to the scale of the control when pinch starts.
+  Quaternion mStartingOrientation; ///< Set to the orientation of the control when the rotation starts.
   Animation mShakeAnimation; ///< "Shake" animation to show when we are in panning mode.
-  bool mPanMode = false; ///< Set to true when we have long-pressed to put us into panning mode.
   bool mPanStarted = false; ///< Set to true to state that panning has started.
 };