(FocusManager) Updated Accessibility features (Part2)
[platform/core/uifw/dali-toolkit.git] / base / dali-toolkit / internal / focus-manager / focus-manager-impl.cpp
1 //
2 // Copyright (c) 2014 Samsung Electronics Co., Ltd.
3 //
4 // Licensed under the Flora License, Version 1.0 (the License);
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //     http://floralicense.org/license/
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an AS IS BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16
17 // CLASS HEADER
18 #include "focus-manager-impl.h"
19
20 // INTERNAL INCLUDES
21 #include <dali-toolkit/public-api/controls/control.h>
22 #include <dali-toolkit/public-api/controls/control-impl.h>
23 #include <dali/integration-api/debug.h>
24
25 namespace Dali
26 {
27
28 namespace Toolkit
29 {
30
31 namespace Internal
32 {
33
34 namespace // unnamed namespace
35 {
36
37 #if defined(DEBUG_ENABLED)
38 Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_FOCUS_MANAGER");
39 #endif
40
41 const char * const ACTOR_FOCUSABLE("focusable");
42 const char * const IS_FOCUS_GROUP("is-focus-group");
43
44 const char* FOCUS_BORDER_IMAGE_PATH = DALI_IMAGE_DIR "B16-8_TTS_focus.png";
45 const Vector4 FOCUS_BORDER_IMAGE_BORDER = Vector4(7.0f, 7.0f, 7.0f, 7.0f);
46
47 const char* FOCUS_SOUND_FILE = DALI_SOUND_DIR "Focus.ogg";
48 const char* FOCUS_CHAIN_END_SOUND_FILE = DALI_SOUND_DIR "End_of_List.ogg";
49
50 /**
51  * The function to be used in the hit-test algorithm to check whether the actor is hittable.
52  */
53 bool IsActorFocusableFunction(Actor actor, Dali::HitTestAlgorithm::TraverseType type)
54 {
55   bool hittable = false;
56
57   switch (type)
58   {
59     case Dali::HitTestAlgorithm::CHECK_ACTOR:
60     {
61       // Check whether the actor is visible and not fully transparent.
62       if( actor.IsVisible()
63        && actor.GetCurrentWorldColor().a > 0.01f) // not FULLY_TRANSPARENT
64       {
65         // Check whether the actor is focusable
66         Property::Index propertyActorFocusable = actor.GetPropertyIndex(ACTOR_FOCUSABLE);
67         if(propertyActorFocusable != Property::INVALID_INDEX)
68         {
69           hittable = actor.GetProperty<bool>(propertyActorFocusable);
70         }
71       }
72       break;
73     }
74     case Dali::HitTestAlgorithm::DESCEND_ACTOR_TREE:
75     {
76       if( actor.IsVisible() ) // Actor is visible, if not visible then none of its children are visible.
77       {
78         hittable = true;
79       }
80       break;
81     }
82     default:
83     {
84       break;
85     }
86   }
87
88   return hittable;
89 };
90
91 }
92
93 FocusManager::FocusManager()
94 : mIsWrapped(false),
95   mIsFocusWithinGroup(false),
96   mIsEndcapFeedbackEnabled(true),
97   mIsEndcapFeedbackPlayed(false),
98   mCurrentFocusActor(FocusIDPair(0, 0)),
99   mFocusIndicatorActor(Actor()),
100   mRecursiveFocusMoveCounter(0),
101   mIsAccessibilityTtsEnabled(false),
102   mIsFocusIndicatorEnabled(false)
103 {
104   CreateDefaultFocusIndicatorActor();
105
106   AccessibilityManager manager = AccessibilityManager::Get();
107   manager.SetActionHandler(*this);
108   manager.SetGestureHandler(*this);
109
110   ChangeAccessibilityStatus();
111 }
112
113 FocusManager::~FocusManager()
114 {
115 }
116
117 FocusManager::ActorAdditionalInfo FocusManager::GetActorAdditionalInfo(const unsigned int actorID) const
118 {
119   ActorAdditionalInfo data;
120   IDAdditionalInfoConstIter iter = mIDAdditionalInfoContainer.find(actorID);
121   if(iter != mIDAdditionalInfoContainer.end())
122   {
123     data = (*iter).second;
124   }
125
126   return data;
127 }
128
129 void FocusManager::SynchronizeActorAdditionalInfo(const unsigned int actorID, const unsigned int order)
130 {
131   ActorAdditionalInfo actorInfo = GetActorAdditionalInfo(actorID);
132   actorInfo.mFocusOrder = order;
133   mIDAdditionalInfoContainer.erase(actorID);
134   mIDAdditionalInfoContainer.insert(IDAdditionalInfoPair(actorID, actorInfo));
135 }
136
137 void FocusManager::SetAccessibilityAttribute(Actor actor, Toolkit::FocusManager::AccessibilityAttribute type, const std::string& text)
138 {
139   if(actor)
140   {
141     unsigned int actorID = actor.GetId();
142
143     ActorAdditionalInfo info = GetActorAdditionalInfo(actorID);
144     info.mAccessibilityAttributes[type] = text;
145
146     mIDAdditionalInfoContainer.erase(actorID);
147     mIDAdditionalInfoContainer.insert(IDAdditionalInfoPair(actorID, info));
148   }
149 }
150
151 std::string FocusManager::GetAccessibilityAttribute(Actor actor, Toolkit::FocusManager::AccessibilityAttribute type) const
152 {
153   std::string text;
154
155   if(actor)
156   {
157     ActorAdditionalInfo data = GetActorAdditionalInfo(actor.GetId());
158     text = data.mAccessibilityAttributes[type];
159   }
160
161   return text;
162 }
163
164 void FocusManager::SetFocusOrder(Actor actor, const unsigned int order)
165 {
166   // Do nothing if the focus order of the actor is not changed.
167   if(actor && GetFocusOrder(actor) != order)
168   {
169     // Firstly delete the actor from the focus chain if it's already there with a different focus order.
170     mFocusIDContainer.erase(GetFocusOrder(actor));
171
172     // Create actor focusable property if not already created.
173     Property::Index propertyActorFocusable = actor.GetPropertyIndex(ACTOR_FOCUSABLE);
174     if(propertyActorFocusable == Property::INVALID_INDEX)
175     {
176       propertyActorFocusable = actor.RegisterProperty(ACTOR_FOCUSABLE, true);
177     }
178
179     if(order == 0)
180     {
181       // The actor is not focusable without a defined focus order.
182       actor.SetProperty(propertyActorFocusable, false);
183
184       // If the actor is currently being focused, it should clear the focus
185       if(actor == GetCurrentFocusActor())
186       {
187         ClearFocus();
188       }
189     }
190     else // Insert the actor to the focus chain
191     {
192       // Check whether there is another actor in the focus chain with the same focus order already.
193       FocusIDIter focusIDIter = mFocusIDContainer.find(order);
194       if(focusIDIter != mFocusIDContainer.end())
195       {
196         // We need to increase the focus order of that actor and all the actors followed it
197         // in the focus chain.
198         FocusIDIter lastIter = mFocusIDContainer.end();
199         --lastIter;//We want forward iterator to the last element here
200         mFocusIDContainer.insert(FocusIDPair((*lastIter).first + 1, (*lastIter).second));
201
202         // Update the actor's focus order in its additional data
203         SynchronizeActorAdditionalInfo((*lastIter).second, (*lastIter).first + 1);
204
205         for(FocusIDIter iter = lastIter; iter != focusIDIter; iter--)
206         {
207           FocusIDIter previousIter = iter;
208           --previousIter;//We want forward iterator to the previous element here
209           unsigned int actorID = (*previousIter).second;
210           (*iter).second = actorID;
211
212           // Update the actor's focus order in its additional data
213           SynchronizeActorAdditionalInfo(actorID, (*iter).first);
214         }
215
216         mFocusIDContainer.erase(order);
217       }
218
219       // The actor is focusable
220       actor.SetProperty(propertyActorFocusable, true);
221
222       // Now we insert the actor into the focus chain with the specified focus order
223       mFocusIDContainer.insert(FocusIDPair(order, actor.GetId()));
224     }
225
226     // Update the actor's focus order in its additional data
227     SynchronizeActorAdditionalInfo(actor.GetId(), order);
228   }
229 }
230
231 unsigned int FocusManager::GetFocusOrder(Actor actor) const
232 {
233   unsigned int focusOrder = 0;
234
235   if(actor)
236   {
237     ActorAdditionalInfo data = GetActorAdditionalInfo(actor.GetId());
238     focusOrder = data.mFocusOrder;
239   }
240
241   return focusOrder;
242 }
243
244 unsigned int FocusManager::GenerateNewFocusOrder() const
245 {
246   unsigned int order = 1;
247   FocusIDContainer::const_reverse_iterator iter = mFocusIDContainer.rbegin();
248
249   if(iter != mFocusIDContainer.rend())
250   {
251     order = (*iter).first + 1;
252   }
253
254   return order;
255 }
256
257 Actor FocusManager::GetActorByFocusOrder(const unsigned int order)
258 {
259   Actor actor = Actor();
260
261   FocusIDIter focusIDIter = mFocusIDContainer.find(order);
262   if(focusIDIter != mFocusIDContainer.end())
263   {
264     Actor rootActor = Stage::GetCurrent().GetRootLayer();
265     actor = rootActor.FindChildById(mFocusIDContainer[order]);
266   }
267
268   return actor;
269 }
270
271 bool FocusManager::SetCurrentFocusActor(Actor actor)
272 {
273   if(actor)
274   {
275     return DoSetCurrentFocusActor(actor.GetId());
276   }
277
278   return false;
279 }
280
281 bool FocusManager::DoSetCurrentFocusActor(const unsigned int actorID)
282 {
283   Actor rootActor = Stage::GetCurrent().GetRootLayer();
284
285   // If the group mode is enabled, check which focus group the current focused actor belongs to
286   Actor focusGroup;
287   if(mIsFocusWithinGroup)
288   {
289     focusGroup = GetFocusGroup(GetCurrentFocusActor());
290   }
291
292   if(!focusGroup)
293   {
294     focusGroup = rootActor;
295   }
296
297   Actor actor = focusGroup.FindChildById(actorID);
298
299   // Check whether the actor is in the stage
300   if(actor)
301   {
302     // Check whether the actor is focusable
303     bool actorFocusable = false;
304     Property::Index propertyActorFocusable = actor.GetPropertyIndex(ACTOR_FOCUSABLE);
305     if(propertyActorFocusable != Property::INVALID_INDEX)
306     {
307       actorFocusable = actor.GetProperty<bool>(propertyActorFocusable);
308     }
309
310     // Go through the actor's hierarchy to check whether the actor is visible
311     bool actorVisible = actor.IsVisible();
312     Actor parent = actor.GetParent();
313     while (actorVisible && parent && parent != rootActor)
314     {
315       actorVisible = parent.IsVisible();
316       parent = parent.GetParent();
317     }
318
319     // Check whether the actor is fully transparent
320     bool actorOpaque = actor.GetCurrentWorldColor().a > 0.01f;
321
322     // Set the focus only when the actor is focusable and visible and not fully transparent
323     if(actorVisible && actorFocusable && actorOpaque)
324     {
325       // Draw the focus indicator upon the focused actor
326       if(mIsFocusIndicatorEnabled && mFocusIndicatorActor)
327       {
328         actor.Add(mFocusIndicatorActor);
329       }
330
331       // Send notification for the change of focus actor
332       mFocusChangedSignalV2.Emit( GetCurrentFocusActor(), actor );
333
334       // Save the current focused actor
335       mCurrentFocusActor = FocusIDPair(GetFocusOrder(actor), actorID);
336
337       if(mIsAccessibilityTtsEnabled)
338       {
339         Dali::SoundPlayer soundPlayer = Dali::SoundPlayer::Get();
340         soundPlayer.PlaySound(FOCUS_SOUND_FILE);
341
342         // Play the accessibility attributes with the TTS player.
343         Dali::TtsPlayer player = Dali::TtsPlayer::Get(Dali::TtsPlayer::SCREEN_READER);
344
345         // Combine attribute texts to one text
346         std::string informationText;
347         for(int i = 0; i < Toolkit::FocusManager::ACCESSIBILITY_ATTRIBUTE_NUM; i++)
348         {
349           if(!GetActorAdditionalInfo(actorID).mAccessibilityAttributes[i].empty())
350           {
351             if( i > 0 )
352             {
353               informationText += ", "; // for space time between each information
354             }
355             informationText += GetActorAdditionalInfo(actorID).mAccessibilityAttributes[i];
356           }
357         }
358         player.Play(informationText);
359       }
360
361       return true;
362     }
363   }
364
365   DALI_LOG_WARNING("[%s:%d] FAILED\n", __FUNCTION__, __LINE__);
366   return false;
367 }
368
369 Actor FocusManager::GetCurrentFocusActor()
370 {
371   Actor rootActor = Stage::GetCurrent().GetRootLayer();
372   return rootActor.FindChildById(mCurrentFocusActor.second);
373 }
374
375 Actor FocusManager::GetCurrentFocusGroup()
376 {
377   return GetFocusGroup(GetCurrentFocusActor());
378 }
379
380 unsigned int FocusManager::GetCurrentFocusOrder()
381 {
382   return mCurrentFocusActor.first;
383 }
384
385 bool FocusManager::MoveFocusForward()
386 {
387   bool ret = false;
388   mRecursiveFocusMoveCounter = 0;
389
390   FocusIDIter focusIDIter = mFocusIDContainer.find(mCurrentFocusActor.first);
391   if(focusIDIter != mFocusIDContainer.end())
392   {
393     DALI_LOG_INFO( gLogFilter, Debug::General, "[%s:%d] focus order : %d\n", __FUNCTION__, __LINE__, (*focusIDIter).first);
394     ret = DoMoveFocus(focusIDIter, true, mIsWrapped);
395   }
396   else
397   {
398     // TODO: if there is not focused actor, move first actor
399     if(!mFocusIDContainer.empty())
400     {
401       //if there is not focused actor, move 1st actor
402       focusIDIter = mFocusIDContainer.begin(); // TODO: I'm not sure it was sorted.
403       DALI_LOG_INFO( gLogFilter, Debug::General, "[%s:%d] focus order : %d\n", __FUNCTION__, __LINE__, (*focusIDIter).first);
404       ret = DoSetCurrentFocusActor((*focusIDIter).second);
405     }
406   }
407
408   DALI_LOG_INFO( gLogFilter, Debug::General, "[%s] %s\n", __FUNCTION__, ret?"SUCCEED!!!":"FAILED!!!");
409
410   return ret;
411 }
412
413 bool FocusManager::MoveFocusBackward()
414 {
415   bool ret = false;
416   mRecursiveFocusMoveCounter = 0;
417
418   FocusIDIter focusIDIter = mFocusIDContainer.find(mCurrentFocusActor.first);
419   if(focusIDIter != mFocusIDContainer.end())
420   {
421     DALI_LOG_INFO( gLogFilter, Debug::General, "[%s:%d] focus order : %d\n", __FUNCTION__, __LINE__, (*focusIDIter).first);
422     ret = DoMoveFocus(focusIDIter, false, mIsWrapped);
423   }
424   else
425   {
426     // TODO: if there is not focused actor, move last actor
427     if(!mFocusIDContainer.empty())
428     {
429       //if there is not focused actor, move last actor
430       focusIDIter = mFocusIDContainer.end();
431       --focusIDIter;//We want forward iterator to the last element here
432       DALI_LOG_INFO( gLogFilter, Debug::General, "[%s:%d] focus order : %d\n", __FUNCTION__, __LINE__, (*focusIDIter).first);
433       ret = DoSetCurrentFocusActor((*focusIDIter).second);
434     }
435   }
436
437   DALI_LOG_INFO( gLogFilter, Debug::General, "[%s] %s\n", __FUNCTION__, ret?"SUCCEED!!!":"FAILED!!!");
438
439   return ret;
440 }
441
442 void FocusManager::DoActivate(Actor actor)
443 {
444   if(actor)
445   {
446     Dali::Toolkit::Control control = Dali::Toolkit::Control::DownCast(actor);
447     if(control)
448     {
449       // Notify the control that it is activated
450       control.GetImplementation().OnActivated();
451     }
452
453     // Send notification for the activation of focused actor
454     mFocusedActorActivatedSignalV2.Emit(actor);
455   }
456 }
457
458 void FocusManager::ClearFocus()
459 {
460   Actor actor = GetCurrentFocusActor();
461   if(actor)
462   {
463     actor.Remove(mFocusIndicatorActor);
464   }
465
466   mCurrentFocusActor = FocusIDPair(0, 0);
467
468   // Send notification for the change of focus actor
469   mFocusChangedSignalV2.Emit(actor, Actor());
470
471   if(mIsAccessibilityTtsEnabled)
472   {
473     // Stop the TTS playing if any
474     Dali::TtsPlayer player = Dali::TtsPlayer::Get(Dali::TtsPlayer::SCREEN_READER);
475     player.Stop();
476   }
477 }
478
479 void FocusManager::Reset()
480 {
481   ClearFocus();
482   mFocusIDContainer.clear();
483   mIDAdditionalInfoContainer.clear();
484 }
485
486 void FocusManager::SetFocusGroup(Actor actor, bool isFocusGroup)
487 {
488   if(actor)
489   {
490     // Create focus group property if not already created.
491     Property::Index propertyIsFocusGroup = actor.GetPropertyIndex(IS_FOCUS_GROUP);
492     if(propertyIsFocusGroup == Property::INVALID_INDEX)
493     {
494       propertyIsFocusGroup = actor.RegisterProperty(IS_FOCUS_GROUP, isFocusGroup);
495     }
496     else
497     {
498       actor.SetProperty(propertyIsFocusGroup, isFocusGroup);
499     }
500   }
501 }
502
503 bool FocusManager::IsFocusGroup(Actor actor) const
504 {
505   // Check whether the actor is a focus group
506   bool isFocusGroup = false;
507
508   if(actor)
509   {
510     Property::Index propertyIsFocusGroup = actor.GetPropertyIndex(IS_FOCUS_GROUP);
511     if(propertyIsFocusGroup != Property::INVALID_INDEX)
512     {
513       isFocusGroup = actor.GetProperty<bool>(propertyIsFocusGroup);
514     }
515   }
516
517   return isFocusGroup;
518 }
519
520 Actor FocusManager::GetFocusGroup(Actor actor)
521 {
522   // Go through the actor's hierarchy to check which focus group the actor belongs to
523   while (actor && !IsFocusGroup(actor))
524   {
525     actor = actor.GetParent();
526   }
527
528   return actor;
529 }
530
531 void FocusManager::SetGroupMode(bool enabled)
532 {
533   mIsFocusWithinGroup = enabled;
534 }
535
536 bool FocusManager::GetGroupMode() const
537 {
538   return mIsFocusWithinGroup;
539 }
540
541 void FocusManager::SetWrapMode(bool wrapped)
542 {
543   mIsWrapped = wrapped;
544 }
545
546 bool FocusManager::GetWrapMode() const
547 {
548   return mIsWrapped;
549 }
550
551 void FocusManager::SetFocusIndicatorActor(Actor indicator)
552 {
553   mFocusIndicatorActor = indicator;
554 }
555
556 Actor FocusManager::GetFocusIndicatorActor()
557 {
558   return mFocusIndicatorActor;
559 }
560
561 bool FocusManager::DoMoveFocus(FocusIDIter focusIDIter, bool forward, bool wrapped)
562 {
563   DALI_LOG_INFO( gLogFilter, Debug::General, "[%s:%d] %d focusable actors\n", __FUNCTION__, __LINE__, mFocusIDContainer.size());
564   DALI_LOG_INFO( gLogFilter, Debug::General, "[%s:%d] focus order : %d\n", __FUNCTION__, __LINE__, (*focusIDIter).first);
565
566   if( (forward && ++focusIDIter == mFocusIDContainer.end())
567     || (!forward && focusIDIter-- == mFocusIDContainer.begin()) )
568   {
569     if(mIsEndcapFeedbackEnabled)
570     {
571       if(mIsEndcapFeedbackPlayed == false)
572       {
573         // play sound & skip moving once
574         Dali::SoundPlayer soundPlayer = Dali::SoundPlayer::Get();
575         soundPlayer.PlaySound(FOCUS_CHAIN_END_SOUND_FILE);
576
577         mIsEndcapFeedbackPlayed = true;
578         return true;
579       }
580       mIsEndcapFeedbackPlayed = false;
581     }
582
583     if(wrapped)
584     {
585       if(forward)
586       {
587         focusIDIter = mFocusIDContainer.begin();
588       }
589       else
590       {
591         focusIDIter = mFocusIDContainer.end();
592         --focusIDIter;//We want forward iterator to the last element here
593       }
594     }
595     else
596     {
597       DALI_LOG_INFO( gLogFilter, Debug::General, "[%s:%d] Overshot\n", __FUNCTION__, __LINE__);
598       // Send notification for handling overshooted situation
599       mFocusOvershotSignalV2.Emit(GetCurrentFocusActor(), forward ? Toolkit::FocusManager::OVERSHOT_NEXT : Toolkit::FocusManager::OVERSHOT_PREVIOUS);
600
601       return false; // Try to move the focus out of the scope
602     }
603   }
604
605   if((focusIDIter != mFocusIDContainer.end()) && !DoSetCurrentFocusActor((*focusIDIter).second))
606   {
607     mRecursiveFocusMoveCounter++;
608     if(mRecursiveFocusMoveCounter > mFocusIDContainer.size())
609     {
610       // We've attempted to focus all the actors in the whole focus chain and no actor
611       // can be focused successfully.
612
613       DALI_LOG_WARNING("[%s] There is no more focusable actor in %d focus chains\n", __FUNCTION__, mRecursiveFocusMoveCounter);
614
615       return false;
616     }
617     else
618     {
619       return DoMoveFocus(focusIDIter, forward, wrapped);
620     }
621   }
622
623   return true;
624 }
625
626 void FocusManager::SetFocusable(Actor actor, bool focusable)
627 {
628   if(actor)
629   {
630     // Create actor focusable property if not already created.
631     Property::Index propertyActorFocusable = actor.GetPropertyIndex(ACTOR_FOCUSABLE);
632     if(propertyActorFocusable == Property::INVALID_INDEX)
633     {
634       propertyActorFocusable = actor.RegisterProperty(ACTOR_FOCUSABLE, focusable);
635     }
636     else
637     {
638       actor.SetProperty(propertyActorFocusable, focusable);
639     }
640   }
641 }
642
643 void FocusManager::CreateDefaultFocusIndicatorActor()
644 {
645   // Create a focus indicator actor shared by all the focusable actors
646   Image borderImage = Image::New(FOCUS_BORDER_IMAGE_PATH);
647
648   ImageActor focusIndicator = ImageActor::New(borderImage);
649   focusIndicator.SetPositionInheritanceMode( Dali::USE_PARENT_POSITION_PLUS_LOCAL_POSITION );
650   focusIndicator.SetStyle( ImageActor::STYLE_NINE_PATCH );
651   focusIndicator.SetNinePatchBorder(FOCUS_BORDER_IMAGE_BORDER);
652   focusIndicator.SetPosition(Vector3(0.0f, 0.0f, 1.0f));
653
654   // Apply size constraint to the focus indicator
655   Constraint constraint = Constraint::New<Vector3>(Actor::SIZE,
656                                                    ParentSource(Actor::SIZE),
657                                                    EqualToConstraint());
658   focusIndicator.ApplyConstraint(constraint);
659
660   SetFocusIndicatorActor(focusIndicator);
661 }
662
663 bool FocusManager::ChangeAccessibilityStatus()
664 {
665   AccessibilityManager manager = AccessibilityManager::Get();
666   mIsAccessibilityTtsEnabled = manager.IsEnabled();
667
668   if(mIsAccessibilityTtsEnabled)
669   {
670     // Show indicator when tts turned on if there is focused actor.
671     Actor actor = GetCurrentFocusActor();
672     if(actor)
673     {
674       if(mFocusIndicatorActor)
675       {
676         actor.Add(mFocusIndicatorActor);
677       }
678     }
679     mIsFocusIndicatorEnabled = true;
680   }
681   else
682   {
683     // Hide indicator when tts turned off
684     Actor actor = GetCurrentFocusActor();
685     if(actor)
686     {
687       actor.Remove(mFocusIndicatorActor);
688     }
689     mIsFocusIndicatorEnabled = false;
690   }
691
692   return true;
693 }
694
695 bool FocusManager::AccessibilityActionNext(bool allowEndFeedback)
696 {
697   if(mIsAccessibilityTtsEnabled)
698   {
699     mIsEndcapFeedbackEnabled = allowEndFeedback;
700     return MoveFocusForward();
701   }
702   else
703   {
704     return false;
705   }
706 }
707
708 bool FocusManager::AccessibilityActionPrevious(bool allowEndFeedback)
709 {
710   if(mIsAccessibilityTtsEnabled)
711   {
712     mIsEndcapFeedbackEnabled = allowEndFeedback;
713     return MoveFocusBackward();
714   }
715   else
716   {
717     return false;
718   }
719 }
720
721 bool FocusManager::AccessibilityActionActivate()
722 {
723   bool ret = false;
724
725   Actor actor = GetCurrentFocusActor();
726   if(actor)
727   {
728     DoActivate(actor);
729     ret = true;
730   }
731
732   return ret;
733 }
734
735 bool FocusManager::AccessibilityActionRead(bool allowReadAgain)
736 {
737   bool ret = false;
738
739   if(mIsAccessibilityTtsEnabled)
740   {
741     // Find the focusable actor at the read position
742     AccessibilityManager manager = AccessibilityManager::Get();
743     Dali::HitTestAlgorithm::Results results;
744     Dali::HitTestAlgorithm::HitTest( Stage::GetCurrent(), manager.GetReadPosition(), results, IsActorFocusableFunction );
745
746     FocusIDIter focusIDIter = mFocusIDContainer.find(GetFocusOrder(results.actor));
747     if(focusIDIter != mFocusIDContainer.end())
748     {
749       if( allowReadAgain || (results.actor != GetCurrentFocusActor()) )
750       {
751         // Move the focus to the actor
752         ret = SetCurrentFocusActor(results.actor);
753         DALI_LOG_INFO( gLogFilter, Debug::General, "[%s:%d] SetCurrentFocusActor returns %s\n", __FUNCTION__, __LINE__, ret?"TRUE":"FALSE");
754       }
755     }
756   }
757
758   return ret;
759 }
760
761 bool FocusManager::AccessibilityActionReadNext(bool allowEndFeedback)
762 {
763   if(mIsAccessibilityTtsEnabled)
764   {
765     return MoveFocusForward();
766   }
767   else
768   {
769     return false;
770   }
771 }
772
773 bool FocusManager::AccessibilityActionReadPrevious(bool allowEndFeedback)
774 {
775   if(mIsAccessibilityTtsEnabled)
776   {
777     return MoveFocusBackward();
778   }
779   else
780   {
781     return false;
782   }
783 }
784
785 bool FocusManager::AccessibilityActionUp()
786 {
787   bool ret = false;
788
789   if(mIsAccessibilityTtsEnabled)
790   {
791     Actor actor = GetCurrentFocusActor();
792     if(actor)
793     {
794       Dali::Toolkit::Control control = Dali::Toolkit::Control::DownCast(actor);
795       if(control)
796       {
797         // Notify the control that it is activated
798         ret = control.GetImplementation().OnAccessibilityValueChange(true);
799       }
800     }
801   }
802
803   return ret;
804 }
805
806 bool FocusManager::AccessibilityActionDown()
807 {
808   bool ret = false;
809
810   if(mIsAccessibilityTtsEnabled)
811   {
812     Actor actor = GetCurrentFocusActor();
813     if(actor)
814     {
815       Dali::Toolkit::Control control = Dali::Toolkit::Control::DownCast(actor);
816       if(control)
817       {
818         // Notify the control that it is activated
819         ret = control.GetImplementation().OnAccessibilityValueChange(false);
820       }
821     }
822   }
823
824   return ret;
825 }
826
827 bool FocusManager::ClearAccessibilityFocus()
828 {
829   if(mIsAccessibilityTtsEnabled)
830   {
831     ClearFocus();
832     return true;
833   }
834   else
835   {
836     return false;
837   }
838 }
839
840 bool FocusManager::AccessibilityActionBack()
841 {
842   // TODO: Back to previous view
843
844   return mIsAccessibilityTtsEnabled;
845 }
846
847 bool FocusManager::AccessibilityActionTouch(const TouchEvent& touchEvent)
848 {
849   bool handled = false;
850
851   // TODO: Need to convert the touchevent for the focused actor?
852
853   Dali::Toolkit::Control control = Dali::Toolkit::Control::DownCast(GetCurrentFocusActor());
854   if(control)
855   {
856     handled = control.GetImplementation().OnAccessibilityTouch(touchEvent);
857   }
858
859   return handled;
860 }
861
862 bool FocusManager::HandlePanGesture(const Integration::PanGestureEvent& panEvent)
863 {
864   bool handled = false;
865
866   if( panEvent.state == Gesture::Started )
867   {
868     // Find the focusable actor at the event position
869     Dali::HitTestAlgorithm::Results results;
870     AccessibilityManager manager = AccessibilityManager::Get();
871
872     Dali::HitTestAlgorithm::HitTest( Stage::GetCurrent(), panEvent.currentPosition, results, IsActorFocusableFunction );
873     mCurrentGesturedActor = results.actor;
874
875     if(!mCurrentGesturedActor)
876     {
877       DALI_LOG_ERROR("Gesture detected, but no hit actor");
878     }
879   }
880
881   // Gesture::Finished (Up) events are delivered with previous (Motion) event position
882   // Use the real previous position; otherwise we may incorrectly get a ZERO velocity
883   if ( Gesture::Finished != panEvent.state )
884   {
885     // Store the previous position for next Gesture::Finished iteration.
886     mPreviousPosition = panEvent.previousPosition;
887   }
888
889   Actor rootActor = Stage::GetCurrent().GetRootLayer();
890
891   Dali::PanGesture pan(panEvent.state);
892   pan.time = panEvent.time;
893   pan.numberOfTouches = panEvent.numberOfTouches;
894   pan.screenPosition = panEvent.currentPosition;
895   pan.screenDisplacement = mPreviousPosition - panEvent.currentPosition;
896   pan.screenVelocity.x = pan.screenDisplacement.x / panEvent.timeDelta;
897   pan.screenVelocity.y = pan.screenDisplacement.y / panEvent.timeDelta;
898
899   // Only handle the pan gesture when the current focused actor is scrollable or within a scrollable actor
900   while(mCurrentGesturedActor && mCurrentGesturedActor != rootActor && !handled)
901   {
902     Dali::Toolkit::Control control = Dali::Toolkit::Control::DownCast(mCurrentGesturedActor);
903     if(control)
904     {
905       Vector2 localCurrent;
906       control.ScreenToLocal( localCurrent.x, localCurrent.y, panEvent.currentPosition.x, panEvent.currentPosition.y );
907       pan.position = localCurrent;
908
909       Vector2 localPrevious;
910       control.ScreenToLocal( localPrevious.x, localPrevious.y, mPreviousPosition.x, mPreviousPosition.y );
911
912       pan.displacement = localCurrent - localPrevious;
913       pan.velocity.x = pan.displacement.x / panEvent.timeDelta;
914       pan.velocity.y = pan.displacement.y / panEvent.timeDelta;
915
916       handled = control.GetImplementation().OnAccessibilityPan(pan);
917     }
918
919     // If the gesture is not handled by the control, check its parent
920     if(!handled)
921     {
922       mCurrentGesturedActor = mCurrentGesturedActor.GetParent();
923
924       if(!mCurrentGesturedActor)
925       {
926         DALI_LOG_ERROR("no more gestured actor");
927       }
928     }
929     else
930     {
931       // If handled, then update the pan gesture properties
932       PanGestureDetector::SetPanGestureProperties( pan );
933     }
934   }
935
936   return handled;
937 }
938
939 Toolkit::FocusManager::FocusChangedSignalV2& FocusManager::FocusChangedSignal()
940 {
941   return mFocusChangedSignalV2;
942 }
943
944 Toolkit::FocusManager::FocusOvershotSignalV2& FocusManager::FocusOvershotSignal()
945 {
946   return mFocusOvershotSignalV2;
947 }
948
949 Toolkit::FocusManager::FocusedActorActivatedSignalV2& FocusManager::FocusedActorActivatedSignal()
950 {
951   return mFocusedActorActivatedSignalV2;
952 }
953
954 bool FocusManager::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
955 {
956   Dali::BaseHandle handle( object );
957
958   bool connected( true );
959   FocusManager* manager = dynamic_cast<FocusManager*>(object);
960
961   if( Dali::Toolkit::FocusManager::SIGNAL_FOCUS_CHANGED == signalName )
962   {
963     manager->FocusChangedSignal().Connect( tracker, functor );
964   }
965   else if( Dali::Toolkit::FocusManager::SIGNAL_FOCUS_OVERSHOT == signalName )
966   {
967     manager->FocusOvershotSignal().Connect( tracker, functor );
968   }
969   else if( Dali::Toolkit::FocusManager::SIGNAL_FOCUSED_ACTOR_ACTIVATED== signalName )
970   {
971     manager->FocusedActorActivatedSignal().Connect( tracker, functor );
972   }
973   else
974   {
975     // signalName does not match any signal
976     connected = false;
977   }
978
979   return connected;
980 }
981
982 } // namespace Internal
983
984 } // namespace Toolkit
985
986 } // namespace Dali