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