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