Conversion to Apache 2.0 license
[platform/core/uifw/dali-toolkit.git] / base / dali-toolkit / internal / focus-manager / focus-manager-impl.cpp
index 193dc29..dbf4146 100644 (file)
@@ -45,6 +45,9 @@ const char * const IS_FOCUS_GROUP("is-focus-group");
 const char* FOCUS_BORDER_IMAGE_PATH = DALI_IMAGE_DIR "B16-8_TTS_focus.png";
 const Vector4 FOCUS_BORDER_IMAGE_BORDER = Vector4(7.0f, 7.0f, 7.0f, 7.0f);
 
+const char* FOCUS_SOUND_FILE = DALI_SOUND_DIR "Focus.ogg";
+const char* FOCUS_CHAIN_END_SOUND_FILE = DALI_SOUND_DIR "End_of_List.ogg";
+
 /**
  * The function to be used in the hit-test algorithm to check whether the actor is hittable.
  */
@@ -91,6 +94,8 @@ bool IsActorFocusableFunction(Actor actor, Dali::HitTestAlgorithm::TraverseType
 FocusManager::FocusManager()
 : mIsWrapped(false),
   mIsFocusWithinGroup(false),
+  mIsEndcapFeedbackEnabled(true),
+  mIsEndcapFeedbackPlayed(false),
   mCurrentFocusActor(FocusIDPair(0, 0)),
   mFocusIndicatorActor(Actor()),
   mRecursiveFocusMoveCounter(0),
@@ -332,6 +337,9 @@ bool FocusManager::DoSetCurrentFocusActor(const unsigned int actorID)
 
       if(mIsAccessibilityTtsEnabled)
       {
+        Dali::SoundPlayer soundPlayer = Dali::SoundPlayer::Get();
+        soundPlayer.PlaySound(FOCUS_SOUND_FILE);
+
         // Play the accessibility attributes with the TTS player.
         Dali::TtsPlayer player = Dali::TtsPlayer::Get(Dali::TtsPlayer::SCREEN_READER);
 
@@ -559,6 +567,20 @@ bool FocusManager::DoMoveFocus(FocusIDIter focusIDIter, bool forward, bool wrapp
   if( (forward && ++focusIDIter == mFocusIDContainer.end())
     || (!forward && focusIDIter-- == mFocusIDContainer.begin()) )
   {
+    if(mIsEndcapFeedbackEnabled)
+    {
+      if(mIsEndcapFeedbackPlayed == false)
+      {
+        // play sound & skip moving once
+        Dali::SoundPlayer soundPlayer = Dali::SoundPlayer::Get();
+        soundPlayer.PlaySound(FOCUS_CHAIN_END_SOUND_FILE);
+
+        mIsEndcapFeedbackPlayed = true;
+        return true;
+      }
+      mIsEndcapFeedbackPlayed = false;
+    }
+
     if(wrapped)
     {
       if(forward)
@@ -671,10 +693,11 @@ bool FocusManager::ChangeAccessibilityStatus()
   return true;
 }
 
-bool FocusManager::AccessibilityActionNext()
+bool FocusManager::AccessibilityActionNext(bool allowEndFeedback)
 {
   if(mIsAccessibilityTtsEnabled)
   {
+    mIsEndcapFeedbackEnabled = allowEndFeedback;
     return MoveFocusForward();
   }
   else
@@ -683,10 +706,11 @@ bool FocusManager::AccessibilityActionNext()
   }
 }
 
-bool FocusManager::AccessibilityActionPrevious()
+bool FocusManager::AccessibilityActionPrevious(bool allowEndFeedback)
 {
   if(mIsAccessibilityTtsEnabled)
   {
+    mIsEndcapFeedbackEnabled = allowEndFeedback;
     return MoveFocusBackward();
   }
   else
@@ -735,7 +759,7 @@ bool FocusManager::AccessibilityActionRead(bool allowReadAgain)
   return ret;
 }
 
-bool FocusManager::AccessibilityActionReadNext()
+bool FocusManager::AccessibilityActionReadNext(bool allowEndFeedback)
 {
   if(mIsAccessibilityTtsEnabled)
   {
@@ -747,7 +771,7 @@ bool FocusManager::AccessibilityActionReadNext()
   }
 }
 
-bool FocusManager::AccessibilityActionReadPrevious()
+bool FocusManager::AccessibilityActionReadPrevious(bool allowEndFeedback)
 {
   if(mIsAccessibilityTtsEnabled)
   {
@@ -821,25 +845,62 @@ bool FocusManager::AccessibilityActionBack()
   return mIsAccessibilityTtsEnabled;
 }
 
+bool FocusManager::AccessibilityActionTouch(const TouchEvent& touchEvent)
+{
+  bool handled = false;
+
+  // TODO: Need to convert the touchevent for the focused actor?
+
+  Dali::Toolkit::Control control = Dali::Toolkit::Control::DownCast(GetCurrentFocusActor());
+  if(control)
+  {
+    handled = control.GetImplementation().OnAccessibilityTouch(touchEvent);
+  }
+
+  return handled;
+}
+
 bool FocusManager::HandlePanGesture(const Integration::PanGestureEvent& panEvent)
 {
   bool handled = false;
 
-  Actor currentGesturedActor = GetCurrentFocusActor();
+  if( panEvent.state == Gesture::Started )
+  {
+    // Find the focusable actor at the event position
+    Dali::HitTestAlgorithm::Results results;
+    AccessibilityManager manager = AccessibilityManager::Get();
+
+    Dali::HitTestAlgorithm::HitTest( Stage::GetCurrent(), panEvent.currentPosition, results, IsActorFocusableFunction );
+    mCurrentGesturedActor = results.actor;
+
+    if(!mCurrentGesturedActor)
+    {
+      DALI_LOG_ERROR("Gesture detected, but no hit actor");
+    }
+  }
+
+  // Gesture::Finished (Up) events are delivered with previous (Motion) event position
+  // Use the real previous position; otherwise we may incorrectly get a ZERO velocity
+  if ( Gesture::Finished != panEvent.state )
+  {
+    // Store the previous position for next Gesture::Finished iteration.
+    mPreviousPosition = panEvent.previousPosition;
+  }
+
   Actor rootActor = Stage::GetCurrent().GetRootLayer();
 
   Dali::PanGesture pan(panEvent.state);
   pan.time = panEvent.time;
   pan.numberOfTouches = panEvent.numberOfTouches;
   pan.screenPosition = panEvent.currentPosition;
-  pan.screenDisplacement = panEvent.previousPosition - panEvent.currentPosition;
+  pan.screenDisplacement = mPreviousPosition - panEvent.currentPosition;
   pan.screenVelocity.x = pan.screenDisplacement.x / panEvent.timeDelta;
   pan.screenVelocity.y = pan.screenDisplacement.y / panEvent.timeDelta;
 
   // Only handle the pan gesture when the current focused actor is scrollable or within a scrollable actor
-  while(currentGesturedActor && currentGesturedActor != rootActor && !handled)
+  while(mCurrentGesturedActor && mCurrentGesturedActor != rootActor && !handled)
   {
-    Dali::Toolkit::Control control = Dali::Toolkit::Control::DownCast(currentGesturedActor);
+    Dali::Toolkit::Control control = Dali::Toolkit::Control::DownCast(mCurrentGesturedActor);
     if(control)
     {
       Vector2 localCurrent;
@@ -847,7 +908,7 @@ bool FocusManager::HandlePanGesture(const Integration::PanGestureEvent& panEvent
       pan.position = localCurrent;
 
       Vector2 localPrevious;
-      control.ScreenToLocal( localPrevious.x, localPrevious.y, panEvent.previousPosition.x, panEvent.previousPosition.y );
+      control.ScreenToLocal( localPrevious.x, localPrevious.y, mPreviousPosition.x, mPreviousPosition.y );
 
       pan.displacement = localCurrent - localPrevious;
       pan.velocity.x = pan.displacement.x / panEvent.timeDelta;
@@ -859,7 +920,12 @@ bool FocusManager::HandlePanGesture(const Integration::PanGestureEvent& panEvent
     // If the gesture is not handled by the control, check its parent
     if(!handled)
     {
-      currentGesturedActor = currentGesturedActor.GetParent();
+      mCurrentGesturedActor = mCurrentGesturedActor.GetParent();
+
+      if(!mCurrentGesturedActor)
+      {
+        DALI_LOG_ERROR("no more gestured actor");
+      }
     }
     else
     {