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