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