(ScrollView) Removed unnecessary scale constraints from scroll-view
[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         soundPlayer.PlaySound(FOCUS_SOUND_FILE);
342
343         // Play the accessibility attributes with the TTS player.
344         Dali::TtsPlayer player = Dali::TtsPlayer::Get(Dali::TtsPlayer::SCREEN_READER);
345
346         // Combine attribute texts to one text
347         std::string informationText;
348         for(int i = 0; i < Toolkit::FocusManager::ACCESSIBILITY_ATTRIBUTE_NUM; i++)
349         {
350           if(!GetActorAdditionalInfo(actorID).mAccessibilityAttributes[i].empty())
351           {
352             if( i > 0 )
353             {
354               informationText += ", "; // for space time between each information
355             }
356             informationText += GetActorAdditionalInfo(actorID).mAccessibilityAttributes[i];
357           }
358         }
359         player.Play(informationText);
360       }
361
362       return true;
363     }
364   }
365
366   DALI_LOG_WARNING("[%s:%d] FAILED\n", __FUNCTION__, __LINE__);
367   return false;
368 }
369
370 Actor FocusManager::GetCurrentFocusActor()
371 {
372   Actor rootActor = Stage::GetCurrent().GetRootLayer();
373   return rootActor.FindChildById(mCurrentFocusActor.second);
374 }
375
376 Actor FocusManager::GetCurrentFocusGroup()
377 {
378   return GetFocusGroup(GetCurrentFocusActor());
379 }
380
381 unsigned int FocusManager::GetCurrentFocusOrder()
382 {
383   return mCurrentFocusActor.first;
384 }
385
386 bool FocusManager::MoveFocusForward()
387 {
388   bool ret = false;
389   mRecursiveFocusMoveCounter = 0;
390
391   FocusIDIter focusIDIter = mFocusIDContainer.find(mCurrentFocusActor.first);
392   if(focusIDIter != mFocusIDContainer.end())
393   {
394     DALI_LOG_INFO( gLogFilter, Debug::General, "[%s:%d] focus order : %d\n", __FUNCTION__, __LINE__, (*focusIDIter).first);
395     ret = DoMoveFocus(focusIDIter, true, mIsWrapped);
396   }
397   else
398   {
399     // TODO: if there is not focused actor, move first actor
400     if(!mFocusIDContainer.empty())
401     {
402       //if there is not focused actor, move 1st actor
403       focusIDIter = mFocusIDContainer.begin(); // TODO: I'm not sure it was sorted.
404       DALI_LOG_INFO( gLogFilter, Debug::General, "[%s:%d] focus order : %d\n", __FUNCTION__, __LINE__, (*focusIDIter).first);
405       ret = DoSetCurrentFocusActor((*focusIDIter).second);
406     }
407   }
408
409   DALI_LOG_INFO( gLogFilter, Debug::General, "[%s] %s\n", __FUNCTION__, ret?"SUCCEED!!!":"FAILED!!!");
410
411   return ret;
412 }
413
414 bool FocusManager::MoveFocusBackward()
415 {
416   bool ret = false;
417   mRecursiveFocusMoveCounter = 0;
418
419   FocusIDIter focusIDIter = mFocusIDContainer.find(mCurrentFocusActor.first);
420   if(focusIDIter != mFocusIDContainer.end())
421   {
422     DALI_LOG_INFO( gLogFilter, Debug::General, "[%s:%d] focus order : %d\n", __FUNCTION__, __LINE__, (*focusIDIter).first);
423     ret = DoMoveFocus(focusIDIter, false, mIsWrapped);
424   }
425   else
426   {
427     // TODO: if there is not focused actor, move last actor
428     if(!mFocusIDContainer.empty())
429     {
430       //if there is not focused actor, move last actor
431       focusIDIter = mFocusIDContainer.end();
432       --focusIDIter;//We want forward iterator to the last element here
433       DALI_LOG_INFO( gLogFilter, Debug::General, "[%s:%d] focus order : %d\n", __FUNCTION__, __LINE__, (*focusIDIter).first);
434       ret = DoSetCurrentFocusActor((*focusIDIter).second);
435     }
436   }
437
438   DALI_LOG_INFO( gLogFilter, Debug::General, "[%s] %s\n", __FUNCTION__, ret?"SUCCEED!!!":"FAILED!!!");
439
440   return ret;
441 }
442
443 void FocusManager::DoActivate(Actor actor)
444 {
445   if(actor)
446   {
447     Dali::Toolkit::Control control = Dali::Toolkit::Control::DownCast(actor);
448     if(control)
449     {
450       // Notify the control that it is activated
451       control.GetImplementation().OnActivated();
452     }
453
454     // Send notification for the activation of focused actor
455     mFocusedActorActivatedSignalV2.Emit(actor);
456   }
457 }
458
459 void FocusManager::ClearFocus()
460 {
461   Actor actor = GetCurrentFocusActor();
462   if(actor)
463   {
464     actor.Remove(mFocusIndicatorActor);
465   }
466
467   mCurrentFocusActor = FocusIDPair(0, 0);
468
469   // Send notification for the change of focus actor
470   mFocusChangedSignalV2.Emit(actor, Actor());
471
472   if(mIsAccessibilityTtsEnabled)
473   {
474     // Stop the TTS playing if any
475     Dali::TtsPlayer player = Dali::TtsPlayer::Get(Dali::TtsPlayer::SCREEN_READER);
476     player.Stop();
477   }
478 }
479
480 void FocusManager::Reset()
481 {
482   ClearFocus();
483   mFocusIDContainer.clear();
484   mIDAdditionalInfoContainer.clear();
485 }
486
487 void FocusManager::SetFocusGroup(Actor actor, bool isFocusGroup)
488 {
489   if(actor)
490   {
491     // Create focus group property if not already created.
492     Property::Index propertyIsFocusGroup = actor.GetPropertyIndex(IS_FOCUS_GROUP);
493     if(propertyIsFocusGroup == Property::INVALID_INDEX)
494     {
495       propertyIsFocusGroup = actor.RegisterProperty(IS_FOCUS_GROUP, isFocusGroup);
496     }
497     else
498     {
499       actor.SetProperty(propertyIsFocusGroup, isFocusGroup);
500     }
501   }
502 }
503
504 bool FocusManager::IsFocusGroup(Actor actor) const
505 {
506   // Check whether the actor is a focus group
507   bool isFocusGroup = false;
508
509   if(actor)
510   {
511     Property::Index propertyIsFocusGroup = actor.GetPropertyIndex(IS_FOCUS_GROUP);
512     if(propertyIsFocusGroup != Property::INVALID_INDEX)
513     {
514       isFocusGroup = actor.GetProperty<bool>(propertyIsFocusGroup);
515     }
516   }
517
518   return isFocusGroup;
519 }
520
521 Actor FocusManager::GetFocusGroup(Actor actor)
522 {
523   // Go through the actor's hierarchy to check which focus group the actor belongs to
524   while (actor && !IsFocusGroup(actor))
525   {
526     actor = actor.GetParent();
527   }
528
529   return actor;
530 }
531
532 void FocusManager::SetGroupMode(bool enabled)
533 {
534   mIsFocusWithinGroup = enabled;
535 }
536
537 bool FocusManager::GetGroupMode() const
538 {
539   return mIsFocusWithinGroup;
540 }
541
542 void FocusManager::SetWrapMode(bool wrapped)
543 {
544   mIsWrapped = wrapped;
545 }
546
547 bool FocusManager::GetWrapMode() const
548 {
549   return mIsWrapped;
550 }
551
552 void FocusManager::SetFocusIndicatorActor(Actor indicator)
553 {
554   mFocusIndicatorActor = indicator;
555 }
556
557 Actor FocusManager::GetFocusIndicatorActor()
558 {
559   return mFocusIndicatorActor;
560 }
561
562 bool FocusManager::DoMoveFocus(FocusIDIter focusIDIter, bool forward, bool wrapped)
563 {
564   DALI_LOG_INFO( gLogFilter, Debug::General, "[%s:%d] %d focusable actors\n", __FUNCTION__, __LINE__, mFocusIDContainer.size());
565   DALI_LOG_INFO( gLogFilter, Debug::General, "[%s:%d] focus order : %d\n", __FUNCTION__, __LINE__, (*focusIDIter).first);
566
567   if( (forward && ++focusIDIter == mFocusIDContainer.end())
568     || (!forward && focusIDIter-- == mFocusIDContainer.begin()) )
569   {
570     if(mIsEndcapFeedbackEnabled)
571     {
572       if(mIsEndcapFeedbackPlayed == false)
573       {
574         // play sound & skip moving once
575         Dali::SoundPlayer soundPlayer = Dali::SoundPlayer::Get();
576         soundPlayer.PlaySound(FOCUS_CHAIN_END_SOUND_FILE);
577
578         mIsEndcapFeedbackPlayed = true;
579         return true;
580       }
581       mIsEndcapFeedbackPlayed = false;
582     }
583
584     if(wrapped)
585     {
586       if(forward)
587       {
588         focusIDIter = mFocusIDContainer.begin();
589       }
590       else
591       {
592         focusIDIter = mFocusIDContainer.end();
593         --focusIDIter;//We want forward iterator to the last element here
594       }
595     }
596     else
597     {
598       DALI_LOG_INFO( gLogFilter, Debug::General, "[%s:%d] Overshot\n", __FUNCTION__, __LINE__);
599       // Send notification for handling overshooted situation
600       mFocusOvershotSignalV2.Emit(GetCurrentFocusActor(), forward ? Toolkit::FocusManager::OVERSHOT_NEXT : Toolkit::FocusManager::OVERSHOT_PREVIOUS);
601
602       return false; // Try to move the focus out of the scope
603     }
604   }
605
606   if((focusIDIter != mFocusIDContainer.end()) && !DoSetCurrentFocusActor((*focusIDIter).second))
607   {
608     mRecursiveFocusMoveCounter++;
609     if(mRecursiveFocusMoveCounter > mFocusIDContainer.size())
610     {
611       // We've attempted to focus all the actors in the whole focus chain and no actor
612       // can be focused successfully.
613
614       DALI_LOG_WARNING("[%s] There is no more focusable actor in %d focus chains\n", __FUNCTION__, mRecursiveFocusMoveCounter);
615
616       return false;
617     }
618     else
619     {
620       return DoMoveFocus(focusIDIter, forward, wrapped);
621     }
622   }
623
624   return true;
625 }
626
627 void FocusManager::SetFocusable(Actor actor, bool focusable)
628 {
629   if(actor)
630   {
631     // Create actor focusable property if not already created.
632     Property::Index propertyActorFocusable = actor.GetPropertyIndex(ACTOR_FOCUSABLE);
633     if(propertyActorFocusable == Property::INVALID_INDEX)
634     {
635       propertyActorFocusable = actor.RegisterProperty(ACTOR_FOCUSABLE, focusable);
636     }
637     else
638     {
639       actor.SetProperty(propertyActorFocusable, focusable);
640     }
641   }
642 }
643
644 void FocusManager::CreateDefaultFocusIndicatorActor()
645 {
646   // Create a focus indicator actor shared by all the focusable actors
647   Image borderImage = Image::New(FOCUS_BORDER_IMAGE_PATH);
648
649   ImageActor focusIndicator = ImageActor::New(borderImage);
650   focusIndicator.SetPositionInheritanceMode( Dali::USE_PARENT_POSITION_PLUS_LOCAL_POSITION );
651   focusIndicator.SetStyle( ImageActor::STYLE_NINE_PATCH );
652   focusIndicator.SetNinePatchBorder(FOCUS_BORDER_IMAGE_BORDER);
653   focusIndicator.SetPosition(Vector3(0.0f, 0.0f, 1.0f));
654
655   // Apply size constraint to the focus indicator
656   Constraint constraint = Constraint::New<Vector3>(Actor::SIZE,
657                                                    ParentSource(Actor::SIZE),
658                                                    EqualToConstraint());
659   focusIndicator.ApplyConstraint(constraint);
660
661   SetFocusIndicatorActor(focusIndicator);
662 }
663
664 bool FocusManager::ChangeAccessibilityStatus()
665 {
666   AccessibilityManager manager = AccessibilityManager::Get();
667   mIsAccessibilityTtsEnabled = manager.IsEnabled();
668
669   if(mIsAccessibilityTtsEnabled)
670   {
671     // Show indicator when tts turned on if there is focused actor.
672     Actor actor = GetCurrentFocusActor();
673     if(actor)
674     {
675       if(mFocusIndicatorActor)
676       {
677         actor.Add(mFocusIndicatorActor);
678       }
679     }
680     mIsFocusIndicatorEnabled = true;
681   }
682   else
683   {
684     // Hide indicator when tts turned off
685     Actor actor = GetCurrentFocusActor();
686     if(actor)
687     {
688       actor.Remove(mFocusIndicatorActor);
689     }
690     mIsFocusIndicatorEnabled = false;
691   }
692
693   return true;
694 }
695
696 bool FocusManager::AccessibilityActionNext(bool allowEndFeedback)
697 {
698   if(mIsAccessibilityTtsEnabled)
699   {
700     mIsEndcapFeedbackEnabled = allowEndFeedback;
701     return MoveFocusForward();
702   }
703   else
704   {
705     return false;
706   }
707 }
708
709 bool FocusManager::AccessibilityActionPrevious(bool allowEndFeedback)
710 {
711   if(mIsAccessibilityTtsEnabled)
712   {
713     mIsEndcapFeedbackEnabled = allowEndFeedback;
714     return MoveFocusBackward();
715   }
716   else
717   {
718     return false;
719   }
720 }
721
722 bool FocusManager::AccessibilityActionActivate()
723 {
724   bool ret = false;
725
726   Actor actor = GetCurrentFocusActor();
727   if(actor)
728   {
729     DoActivate(actor);
730     ret = true;
731   }
732
733   return ret;
734 }
735
736 bool FocusManager::AccessibilityActionRead(bool allowReadAgain)
737 {
738   bool ret = false;
739
740   if(mIsAccessibilityTtsEnabled)
741   {
742     // Find the focusable actor at the read position
743     AccessibilityManager manager = AccessibilityManager::Get();
744     Dali::HitTestAlgorithm::Results results;
745     Dali::HitTestAlgorithm::HitTest( Stage::GetCurrent(), manager.GetReadPosition(), results, IsActorFocusableFunction );
746
747     FocusIDIter focusIDIter = mFocusIDContainer.find(GetFocusOrder(results.actor));
748     if(focusIDIter != mFocusIDContainer.end())
749     {
750       if( allowReadAgain || (results.actor != GetCurrentFocusActor()) )
751       {
752         // Move the focus to the actor
753         ret = SetCurrentFocusActor(results.actor);
754         DALI_LOG_INFO( gLogFilter, Debug::General, "[%s:%d] SetCurrentFocusActor returns %s\n", __FUNCTION__, __LINE__, ret?"TRUE":"FALSE");
755       }
756     }
757   }
758
759   return ret;
760 }
761
762 bool FocusManager::AccessibilityActionReadNext(bool allowEndFeedback)
763 {
764   if(mIsAccessibilityTtsEnabled)
765   {
766     return MoveFocusForward();
767   }
768   else
769   {
770     return false;
771   }
772 }
773
774 bool FocusManager::AccessibilityActionReadPrevious(bool allowEndFeedback)
775 {
776   if(mIsAccessibilityTtsEnabled)
777   {
778     return MoveFocusBackward();
779   }
780   else
781   {
782     return false;
783   }
784 }
785
786 bool FocusManager::AccessibilityActionUp()
787 {
788   bool ret = false;
789
790   if(mIsAccessibilityTtsEnabled)
791   {
792     Actor actor = GetCurrentFocusActor();
793     if(actor)
794     {
795       Dali::Toolkit::Control control = Dali::Toolkit::Control::DownCast(actor);
796       if(control)
797       {
798         // Notify the control that it is activated
799         ret = control.GetImplementation().OnAccessibilityValueChange(true);
800       }
801     }
802   }
803
804   return ret;
805 }
806
807 bool FocusManager::AccessibilityActionDown()
808 {
809   bool ret = false;
810
811   if(mIsAccessibilityTtsEnabled)
812   {
813     Actor actor = GetCurrentFocusActor();
814     if(actor)
815     {
816       Dali::Toolkit::Control control = Dali::Toolkit::Control::DownCast(actor);
817       if(control)
818       {
819         // Notify the control that it is activated
820         ret = control.GetImplementation().OnAccessibilityValueChange(false);
821       }
822     }
823   }
824
825   return ret;
826 }
827
828 bool FocusManager::ClearAccessibilityFocus()
829 {
830   if(mIsAccessibilityTtsEnabled)
831   {
832     ClearFocus();
833     return true;
834   }
835   else
836   {
837     return false;
838   }
839 }
840
841 bool FocusManager::AccessibilityActionBack()
842 {
843   // TODO: Back to previous view
844
845   return mIsAccessibilityTtsEnabled;
846 }
847
848 bool FocusManager::AccessibilityActionTouch(const TouchEvent& touchEvent)
849 {
850   bool handled = false;
851
852   // TODO: Need to convert the touchevent for the focused actor?
853
854   Dali::Toolkit::Control control = Dali::Toolkit::Control::DownCast(GetCurrentFocusActor());
855   if(control)
856   {
857     handled = control.GetImplementation().OnAccessibilityTouch(touchEvent);
858   }
859
860   return handled;
861 }
862
863 bool FocusManager::HandlePanGesture(const Integration::PanGestureEvent& panEvent)
864 {
865   bool handled = false;
866
867   if( panEvent.state == Gesture::Started )
868   {
869     // Find the focusable actor at the event position
870     Dali::HitTestAlgorithm::Results results;
871     AccessibilityManager manager = AccessibilityManager::Get();
872
873     Dali::HitTestAlgorithm::HitTest( Stage::GetCurrent(), panEvent.currentPosition, results, IsActorFocusableFunction );
874     mCurrentGesturedActor = results.actor;
875
876     if(!mCurrentGesturedActor)
877     {
878       DALI_LOG_ERROR("Gesture detected, but no hit actor");
879     }
880   }
881
882   // Gesture::Finished (Up) events are delivered with previous (Motion) event position
883   // Use the real previous position; otherwise we may incorrectly get a ZERO velocity
884   if ( Gesture::Finished != panEvent.state )
885   {
886     // Store the previous position for next Gesture::Finished iteration.
887     mPreviousPosition = panEvent.previousPosition;
888   }
889
890   Actor rootActor = Stage::GetCurrent().GetRootLayer();
891
892   Dali::PanGesture pan(panEvent.state);
893   pan.time = panEvent.time;
894   pan.numberOfTouches = panEvent.numberOfTouches;
895   pan.screenPosition = panEvent.currentPosition;
896   pan.screenDisplacement = mPreviousPosition - panEvent.currentPosition;
897   pan.screenVelocity.x = pan.screenDisplacement.x / panEvent.timeDelta;
898   pan.screenVelocity.y = pan.screenDisplacement.y / panEvent.timeDelta;
899
900   // Only handle the pan gesture when the current focused actor is scrollable or within a scrollable actor
901   while(mCurrentGesturedActor && mCurrentGesturedActor != rootActor && !handled)
902   {
903     Dali::Toolkit::Control control = Dali::Toolkit::Control::DownCast(mCurrentGesturedActor);
904     if(control)
905     {
906       Vector2 localCurrent;
907       control.ScreenToLocal( localCurrent.x, localCurrent.y, panEvent.currentPosition.x, panEvent.currentPosition.y );
908       pan.position = localCurrent;
909
910       Vector2 localPrevious;
911       control.ScreenToLocal( localPrevious.x, localPrevious.y, mPreviousPosition.x, mPreviousPosition.y );
912
913       pan.displacement = localCurrent - localPrevious;
914       pan.velocity.x = pan.displacement.x / panEvent.timeDelta;
915       pan.velocity.y = pan.displacement.y / panEvent.timeDelta;
916
917       handled = control.GetImplementation().OnAccessibilityPan(pan);
918     }
919
920     // If the gesture is not handled by the control, check its parent
921     if(!handled)
922     {
923       mCurrentGesturedActor = mCurrentGesturedActor.GetParent();
924
925       if(!mCurrentGesturedActor)
926       {
927         DALI_LOG_ERROR("no more gestured actor");
928       }
929     }
930     else
931     {
932       // If handled, then update the pan gesture properties
933       PanGestureDetector::SetPanGestureProperties( pan );
934     }
935   }
936
937   return handled;
938 }
939
940 Toolkit::FocusManager::FocusChangedSignalV2& FocusManager::FocusChangedSignal()
941 {
942   return mFocusChangedSignalV2;
943 }
944
945 Toolkit::FocusManager::FocusOvershotSignalV2& FocusManager::FocusOvershotSignal()
946 {
947   return mFocusOvershotSignalV2;
948 }
949
950 Toolkit::FocusManager::FocusedActorActivatedSignalV2& FocusManager::FocusedActorActivatedSignal()
951 {
952   return mFocusedActorActivatedSignalV2;
953 }
954
955 bool FocusManager::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
956 {
957   Dali::BaseHandle handle( object );
958
959   bool connected( true );
960   FocusManager* manager = dynamic_cast<FocusManager*>(object);
961
962   if( Dali::Toolkit::FocusManager::SIGNAL_FOCUS_CHANGED == signalName )
963   {
964     manager->FocusChangedSignal().Connect( tracker, functor );
965   }
966   else if( Dali::Toolkit::FocusManager::SIGNAL_FOCUS_OVERSHOT == signalName )
967   {
968     manager->FocusOvershotSignal().Connect( tracker, functor );
969   }
970   else if( Dali::Toolkit::FocusManager::SIGNAL_FOCUSED_ACTOR_ACTIVATED== signalName )
971   {
972     manager->FocusedActorActivatedSignal().Connect( tracker, functor );
973   }
974   else
975   {
976     // signalName does not match any signal
977     connected = false;
978   }
979
980   return connected;
981 }
982
983 } // namespace Internal
984
985 } // namespace Toolkit
986
987 } // namespace Dali