2 // Copyright (c) 2014 Samsung Electronics Co., Ltd.
4 // Licensed under the Flora License, Version 1.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
8 // http://floralicense.org/license/
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.
18 #include "focus-manager-impl.h"
21 #include <dali-toolkit/public-api/controls/control.h>
22 #include <dali-toolkit/public-api/controls/control-impl.h>
23 #include <dali/integration-api/debug.h>
34 namespace // unnamed namespace
37 #if defined(DEBUG_ENABLED)
38 Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_FOCUS_MANAGER");
41 const char * const ACTOR_FOCUSABLE("focusable");
42 const char * const IS_FOCUS_GROUP("is-focus-group");
44 const char* FOCUS_BORDER_IMAGE_PATH = DALI_IMAGE_DIR "B16-8_TTS_focus.png";
45 const Vector4 FOCUS_BORDER_IMAGE_BORDER = Vector4(7.0f, 7.0f, 7.0f, 7.0f);
47 const char* FOCUS_SOUND_FILE = DALI_SOUND_DIR "Focus.ogg";
48 const char* FOCUS_CHAIN_END_SOUND_FILE = DALI_SOUND_DIR "End_of_List.ogg";
51 * The function to be used in the hit-test algorithm to check whether the actor is hittable.
53 bool IsActorFocusableFunction(Actor actor, Dali::HitTestAlgorithm::TraverseType type)
55 bool hittable = false;
59 case Dali::HitTestAlgorithm::CHECK_ACTOR:
61 // Check whether the actor is visible and not fully transparent.
63 && actor.GetCurrentWorldColor().a > 0.01f) // not FULLY_TRANSPARENT
65 // Check whether the actor is focusable
66 Property::Index propertyActorFocusable = actor.GetPropertyIndex(ACTOR_FOCUSABLE);
67 if(propertyActorFocusable != Property::INVALID_INDEX)
69 hittable = actor.GetProperty<bool>(propertyActorFocusable);
74 case Dali::HitTestAlgorithm::DESCEND_ACTOR_TREE:
76 if( actor.IsVisible() ) // Actor is visible, if not visible then none of its children are visible.
93 FocusManager::FocusManager()
95 mIsFocusWithinGroup(false),
96 mIsEndcapFeedbackEnabled(true),
97 mIsEndcapFeedbackPlayed(false),
98 mCurrentFocusActor(FocusIDPair(0, 0)),
99 mFocusIndicatorActor(Actor()),
100 mRecursiveFocusMoveCounter(0),
101 mIsAccessibilityTtsEnabled(false),
102 mIsFocusIndicatorEnabled(false)
104 CreateDefaultFocusIndicatorActor();
106 AccessibilityManager manager = AccessibilityManager::Get();
107 manager.SetActionHandler(*this);
108 manager.SetGestureHandler(*this);
110 ChangeAccessibilityStatus();
113 FocusManager::~FocusManager()
117 FocusManager::ActorAdditionalInfo FocusManager::GetActorAdditionalInfo(const unsigned int actorID) const
119 ActorAdditionalInfo data;
120 IDAdditionalInfoConstIter iter = mIDAdditionalInfoContainer.find(actorID);
121 if(iter != mIDAdditionalInfoContainer.end())
123 data = (*iter).second;
129 void FocusManager::SynchronizeActorAdditionalInfo(const unsigned int actorID, const unsigned int order)
131 ActorAdditionalInfo actorInfo = GetActorAdditionalInfo(actorID);
132 actorInfo.mFocusOrder = order;
133 mIDAdditionalInfoContainer.erase(actorID);
134 mIDAdditionalInfoContainer.insert(IDAdditionalInfoPair(actorID, actorInfo));
137 void FocusManager::SetAccessibilityAttribute(Actor actor, Toolkit::FocusManager::AccessibilityAttribute type, const std::string& text)
141 unsigned int actorID = actor.GetId();
143 ActorAdditionalInfo info = GetActorAdditionalInfo(actorID);
144 info.mAccessibilityAttributes[type] = text;
146 mIDAdditionalInfoContainer.erase(actorID);
147 mIDAdditionalInfoContainer.insert(IDAdditionalInfoPair(actorID, info));
151 std::string FocusManager::GetAccessibilityAttribute(Actor actor, Toolkit::FocusManager::AccessibilityAttribute type) const
157 ActorAdditionalInfo data = GetActorAdditionalInfo(actor.GetId());
158 text = data.mAccessibilityAttributes[type];
164 void FocusManager::SetFocusOrder(Actor actor, const unsigned int order)
166 // Do nothing if the focus order of the actor is not changed.
167 if(actor && GetFocusOrder(actor) != order)
169 // Firstly delete the actor from the focus chain if it's already there with a different focus order.
170 mFocusIDContainer.erase(GetFocusOrder(actor));
172 // Create actor focusable property if not already created.
173 Property::Index propertyActorFocusable = actor.GetPropertyIndex(ACTOR_FOCUSABLE);
174 if(propertyActorFocusable == Property::INVALID_INDEX)
176 propertyActorFocusable = actor.RegisterProperty(ACTOR_FOCUSABLE, true);
181 // The actor is not focusable without a defined focus order.
182 actor.SetProperty(propertyActorFocusable, false);
184 // If the actor is currently being focused, it should clear the focus
185 if(actor == GetCurrentFocusActor())
190 else // Insert the actor to the focus chain
192 // Check whether there is another actor in the focus chain with the same focus order already.
193 FocusIDIter focusIDIter = mFocusIDContainer.find(order);
194 if(focusIDIter != mFocusIDContainer.end())
196 // We need to increase the focus order of that actor and all the actors followed it
197 // in the focus chain.
198 FocusIDIter lastIter = mFocusIDContainer.end();
199 --lastIter;//We want forward iterator to the last element here
200 mFocusIDContainer.insert(FocusIDPair((*lastIter).first + 1, (*lastIter).second));
202 // Update the actor's focus order in its additional data
203 SynchronizeActorAdditionalInfo((*lastIter).second, (*lastIter).first + 1);
205 for(FocusIDIter iter = lastIter; iter != focusIDIter; iter--)
207 FocusIDIter previousIter = iter;
208 --previousIter;//We want forward iterator to the previous element here
209 unsigned int actorID = (*previousIter).second;
210 (*iter).second = actorID;
212 // Update the actor's focus order in its additional data
213 SynchronizeActorAdditionalInfo(actorID, (*iter).first);
216 mFocusIDContainer.erase(order);
219 // The actor is focusable
220 actor.SetProperty(propertyActorFocusable, true);
222 // Now we insert the actor into the focus chain with the specified focus order
223 mFocusIDContainer.insert(FocusIDPair(order, actor.GetId()));
226 // Update the actor's focus order in its additional data
227 SynchronizeActorAdditionalInfo(actor.GetId(), order);
231 unsigned int FocusManager::GetFocusOrder(Actor actor) const
233 unsigned int focusOrder = 0;
237 ActorAdditionalInfo data = GetActorAdditionalInfo(actor.GetId());
238 focusOrder = data.mFocusOrder;
244 unsigned int FocusManager::GenerateNewFocusOrder() const
246 unsigned int order = 1;
247 FocusIDContainer::const_reverse_iterator iter = mFocusIDContainer.rbegin();
249 if(iter != mFocusIDContainer.rend())
251 order = (*iter).first + 1;
257 Actor FocusManager::GetActorByFocusOrder(const unsigned int order)
259 Actor actor = Actor();
261 FocusIDIter focusIDIter = mFocusIDContainer.find(order);
262 if(focusIDIter != mFocusIDContainer.end())
264 Actor rootActor = Stage::GetCurrent().GetRootLayer();
265 actor = rootActor.FindChildById(mFocusIDContainer[order]);
271 bool FocusManager::SetCurrentFocusActor(Actor actor)
275 return DoSetCurrentFocusActor(actor.GetId());
281 bool FocusManager::DoSetCurrentFocusActor(const unsigned int actorID)
283 Actor rootActor = Stage::GetCurrent().GetRootLayer();
285 // If the group mode is enabled, check which focus group the current focused actor belongs to
287 if(mIsFocusWithinGroup)
289 focusGroup = GetFocusGroup(GetCurrentFocusActor());
294 focusGroup = rootActor;
297 Actor actor = focusGroup.FindChildById(actorID);
299 // Check whether the actor is in the stage
302 // Check whether the actor is focusable
303 bool actorFocusable = false;
304 Property::Index propertyActorFocusable = actor.GetPropertyIndex(ACTOR_FOCUSABLE);
305 if(propertyActorFocusable != Property::INVALID_INDEX)
307 actorFocusable = actor.GetProperty<bool>(propertyActorFocusable);
310 // Go through the actor's hierarchy to check whether the actor is visible
311 bool actorVisible = actor.IsVisible();
312 Actor parent = actor.GetParent();
313 while (actorVisible && parent && parent != rootActor)
315 actorVisible = parent.IsVisible();
316 parent = parent.GetParent();
319 // Check whether the actor is fully transparent
320 bool actorOpaque = actor.GetCurrentWorldColor().a > 0.01f;
322 // Set the focus only when the actor is focusable and visible and not fully transparent
323 if(actorVisible && actorFocusable && actorOpaque)
325 // Draw the focus indicator upon the focused actor
326 if(mIsFocusIndicatorEnabled && mFocusIndicatorActor)
328 actor.Add(mFocusIndicatorActor);
331 // Send notification for the change of focus actor
332 mFocusChangedSignalV2.Emit( GetCurrentFocusActor(), actor );
334 // Save the current focused actor
335 mCurrentFocusActor = FocusIDPair(GetFocusOrder(actor), actorID);
337 if(mIsAccessibilityTtsEnabled)
339 Dali::SoundPlayer soundPlayer = Dali::SoundPlayer::Get();
340 soundPlayer.PlaySound(FOCUS_SOUND_FILE);
342 // Play the accessibility attributes with the TTS player.
343 Dali::TtsPlayer player = Dali::TtsPlayer::Get(Dali::TtsPlayer::SCREEN_READER);
345 // Combine attribute texts to one text
346 std::string informationText;
347 for(int i = 0; i < Toolkit::FocusManager::ACCESSIBILITY_ATTRIBUTE_NUM; i++)
349 if(!GetActorAdditionalInfo(actorID).mAccessibilityAttributes[i].empty())
353 informationText += ", "; // for space time between each information
355 informationText += GetActorAdditionalInfo(actorID).mAccessibilityAttributes[i];
358 player.Play(informationText);
365 DALI_LOG_WARNING("[%s:%d] FAILED\n", __FUNCTION__, __LINE__);
369 Actor FocusManager::GetCurrentFocusActor()
371 Actor rootActor = Stage::GetCurrent().GetRootLayer();
372 return rootActor.FindChildById(mCurrentFocusActor.second);
375 Actor FocusManager::GetCurrentFocusGroup()
377 return GetFocusGroup(GetCurrentFocusActor());
380 unsigned int FocusManager::GetCurrentFocusOrder()
382 return mCurrentFocusActor.first;
385 bool FocusManager::MoveFocusForward()
388 mRecursiveFocusMoveCounter = 0;
390 FocusIDIter focusIDIter = mFocusIDContainer.find(mCurrentFocusActor.first);
391 if(focusIDIter != mFocusIDContainer.end())
393 DALI_LOG_INFO( gLogFilter, Debug::General, "[%s:%d] focus order : %d\n", __FUNCTION__, __LINE__, (*focusIDIter).first);
394 ret = DoMoveFocus(focusIDIter, true, mIsWrapped);
398 // TODO: if there is not focused actor, move first actor
399 if(!mFocusIDContainer.empty())
401 //if there is not focused actor, move 1st actor
402 focusIDIter = mFocusIDContainer.begin(); // TODO: I'm not sure it was sorted.
403 DALI_LOG_INFO( gLogFilter, Debug::General, "[%s:%d] focus order : %d\n", __FUNCTION__, __LINE__, (*focusIDIter).first);
404 ret = DoSetCurrentFocusActor((*focusIDIter).second);
408 DALI_LOG_INFO( gLogFilter, Debug::General, "[%s] %s\n", __FUNCTION__, ret?"SUCCEED!!!":"FAILED!!!");
413 bool FocusManager::MoveFocusBackward()
416 mRecursiveFocusMoveCounter = 0;
418 FocusIDIter focusIDIter = mFocusIDContainer.find(mCurrentFocusActor.first);
419 if(focusIDIter != mFocusIDContainer.end())
421 DALI_LOG_INFO( gLogFilter, Debug::General, "[%s:%d] focus order : %d\n", __FUNCTION__, __LINE__, (*focusIDIter).first);
422 ret = DoMoveFocus(focusIDIter, false, mIsWrapped);
426 // TODO: if there is not focused actor, move last actor
427 if(!mFocusIDContainer.empty())
429 //if there is not focused actor, move last actor
430 focusIDIter = mFocusIDContainer.end();
431 --focusIDIter;//We want forward iterator to the last element here
432 DALI_LOG_INFO( gLogFilter, Debug::General, "[%s:%d] focus order : %d\n", __FUNCTION__, __LINE__, (*focusIDIter).first);
433 ret = DoSetCurrentFocusActor((*focusIDIter).second);
437 DALI_LOG_INFO( gLogFilter, Debug::General, "[%s] %s\n", __FUNCTION__, ret?"SUCCEED!!!":"FAILED!!!");
442 void FocusManager::DoActivate(Actor actor)
446 Dali::Toolkit::Control control = Dali::Toolkit::Control::DownCast(actor);
449 // Notify the control that it is activated
450 control.GetImplementation().OnActivated();
453 // Send notification for the activation of focused actor
454 mFocusedActorActivatedSignalV2.Emit(actor);
458 void FocusManager::ClearFocus()
460 Actor actor = GetCurrentFocusActor();
463 actor.Remove(mFocusIndicatorActor);
466 mCurrentFocusActor = FocusIDPair(0, 0);
468 // Send notification for the change of focus actor
469 mFocusChangedSignalV2.Emit(actor, Actor());
471 if(mIsAccessibilityTtsEnabled)
473 // Stop the TTS playing if any
474 Dali::TtsPlayer player = Dali::TtsPlayer::Get(Dali::TtsPlayer::SCREEN_READER);
479 void FocusManager::Reset()
482 mFocusIDContainer.clear();
483 mIDAdditionalInfoContainer.clear();
486 void FocusManager::SetFocusGroup(Actor actor, bool isFocusGroup)
490 // Create focus group property if not already created.
491 Property::Index propertyIsFocusGroup = actor.GetPropertyIndex(IS_FOCUS_GROUP);
492 if(propertyIsFocusGroup == Property::INVALID_INDEX)
494 propertyIsFocusGroup = actor.RegisterProperty(IS_FOCUS_GROUP, isFocusGroup);
498 actor.SetProperty(propertyIsFocusGroup, isFocusGroup);
503 bool FocusManager::IsFocusGroup(Actor actor) const
505 // Check whether the actor is a focus group
506 bool isFocusGroup = false;
510 Property::Index propertyIsFocusGroup = actor.GetPropertyIndex(IS_FOCUS_GROUP);
511 if(propertyIsFocusGroup != Property::INVALID_INDEX)
513 isFocusGroup = actor.GetProperty<bool>(propertyIsFocusGroup);
520 Actor FocusManager::GetFocusGroup(Actor actor)
522 // Go through the actor's hierarchy to check which focus group the actor belongs to
523 while (actor && !IsFocusGroup(actor))
525 actor = actor.GetParent();
531 void FocusManager::SetGroupMode(bool enabled)
533 mIsFocusWithinGroup = enabled;
536 bool FocusManager::GetGroupMode() const
538 return mIsFocusWithinGroup;
541 void FocusManager::SetWrapMode(bool wrapped)
543 mIsWrapped = wrapped;
546 bool FocusManager::GetWrapMode() const
551 void FocusManager::SetEndCapFeedbackEnabled(bool enabled)
553 mIsEndcapFeedbackEnabled = enabled;
556 bool FocusManager::GetEndCapFeedbackEnabled() const
558 return mIsEndcapFeedbackEnabled;
561 void FocusManager::SetFocusIndicatorActor(Actor indicator)
563 mFocusIndicatorActor = indicator;
566 Actor FocusManager::GetFocusIndicatorActor()
568 return mFocusIndicatorActor;
571 bool FocusManager::DoMoveFocus(FocusIDIter focusIDIter, bool forward, bool wrapped)
573 DALI_LOG_INFO( gLogFilter, Debug::General, "[%s:%d] %d focusable actors\n", __FUNCTION__, __LINE__, mFocusIDContainer.size());
574 DALI_LOG_INFO( gLogFilter, Debug::General, "[%s:%d] focus order : %d\n", __FUNCTION__, __LINE__, (*focusIDIter).first);
576 if( (forward && ++focusIDIter == mFocusIDContainer.end())
577 || (!forward && focusIDIter-- == mFocusIDContainer.begin()) )
581 if(mIsEndcapFeedbackEnabled)
583 if(mIsEndcapFeedbackPlayed == false)
585 // play sound & skip to move once
586 Dali::SoundPlayer soundPlayer = Dali::SoundPlayer::Get();
587 soundPlayer.PlaySound(FOCUS_CHAIN_END_SOUND_FILE);
589 mIsEndcapFeedbackPlayed = true;
592 mIsEndcapFeedbackPlayed = false;
597 focusIDIter = mFocusIDContainer.begin();
601 focusIDIter = mFocusIDContainer.end();
602 --focusIDIter;//We want forward iterator to the last element here
607 if(mIsEndcapFeedbackEnabled)
609 Dali::SoundPlayer soundPlayer = Dali::SoundPlayer::Get();
610 soundPlayer.PlaySound(FOCUS_CHAIN_END_SOUND_FILE);
613 DALI_LOG_INFO( gLogFilter, Debug::General, "[%s:%d] Overshot\n", __FUNCTION__, __LINE__);
614 // Send notification for handling overshooted situation
615 mFocusOvershotSignalV2.Emit(GetCurrentFocusActor(), forward ? Toolkit::FocusManager::OVERSHOT_NEXT : Toolkit::FocusManager::OVERSHOT_PREVIOUS);
617 return false; // Try to move the focus out of the scope
621 if((focusIDIter != mFocusIDContainer.end()) && !DoSetCurrentFocusActor((*focusIDIter).second))
623 mRecursiveFocusMoveCounter++;
624 if(mRecursiveFocusMoveCounter > mFocusIDContainer.size())
626 // We've attempted to focus all the actors in the whole focus chain and no actor
627 // can be focused successfully.
629 DALI_LOG_WARNING("[%s] There is no more focusable actor in %d focus chains\n", __FUNCTION__, mRecursiveFocusMoveCounter);
635 return DoMoveFocus(focusIDIter, forward, wrapped);
642 void FocusManager::SetFocusable(Actor actor, bool focusable)
646 // Create actor focusable property if not already created.
647 Property::Index propertyActorFocusable = actor.GetPropertyIndex(ACTOR_FOCUSABLE);
648 if(propertyActorFocusable == Property::INVALID_INDEX)
650 propertyActorFocusable = actor.RegisterProperty(ACTOR_FOCUSABLE, focusable);
654 actor.SetProperty(propertyActorFocusable, focusable);
659 void FocusManager::CreateDefaultFocusIndicatorActor()
661 // Create a focus indicator actor shared by all the focusable actors
662 Image borderImage = Image::New(FOCUS_BORDER_IMAGE_PATH);
664 ImageActor focusIndicator = ImageActor::New(borderImage);
665 focusIndicator.SetPositionInheritanceMode( Dali::USE_PARENT_POSITION_PLUS_LOCAL_POSITION );
666 focusIndicator.SetStyle( ImageActor::STYLE_NINE_PATCH );
667 focusIndicator.SetNinePatchBorder(FOCUS_BORDER_IMAGE_BORDER);
668 focusIndicator.SetPosition(Vector3(0.0f, 0.0f, 1.0f));
670 // Apply size constraint to the focus indicator
671 Constraint constraint = Constraint::New<Vector3>(Actor::SIZE,
672 ParentSource(Actor::SIZE),
673 EqualToConstraint());
674 focusIndicator.ApplyConstraint(constraint);
676 SetFocusIndicatorActor(focusIndicator);
679 bool FocusManager::ChangeAccessibilityStatus()
681 AccessibilityManager manager = AccessibilityManager::Get();
682 mIsAccessibilityTtsEnabled = manager.IsEnabled();
684 if(mIsAccessibilityTtsEnabled)
686 // Show indicator when tts turned on if there is focused actor.
687 Actor actor = GetCurrentFocusActor();
690 if(mFocusIndicatorActor)
692 actor.Add(mFocusIndicatorActor);
695 mIsFocusIndicatorEnabled = true;
699 // Hide indicator when tts turned off
700 Actor actor = GetCurrentFocusActor();
703 actor.Remove(mFocusIndicatorActor);
705 mIsFocusIndicatorEnabled = false;
711 bool FocusManager::AccessibilityActionNext()
713 if(mIsAccessibilityTtsEnabled)
715 return MoveFocusForward();
723 bool FocusManager::AccessibilityActionPrevious()
725 if(mIsAccessibilityTtsEnabled)
727 return MoveFocusBackward();
735 bool FocusManager::AccessibilityActionActivate()
739 Actor actor = GetCurrentFocusActor();
749 bool FocusManager::AccessibilityActionRead(bool allowReadAgain)
753 if(mIsAccessibilityTtsEnabled)
755 // Find the focusable actor at the read position
756 AccessibilityManager manager = AccessibilityManager::Get();
757 Dali::HitTestAlgorithm::Results results;
758 Dali::HitTestAlgorithm::HitTest( Stage::GetCurrent(), manager.GetReadPosition(), results, IsActorFocusableFunction );
760 FocusIDIter focusIDIter = mFocusIDContainer.find(GetFocusOrder(results.actor));
761 if(focusIDIter != mFocusIDContainer.end())
763 if( allowReadAgain || (results.actor != GetCurrentFocusActor()) )
765 // Move the focus to the actor
766 ret = SetCurrentFocusActor(results.actor);
767 DALI_LOG_INFO( gLogFilter, Debug::General, "[%s:%d] SetCurrentFocusActor returns %s\n", __FUNCTION__, __LINE__, ret?"TRUE":"FALSE");
775 bool FocusManager::AccessibilityActionReadNext()
777 if(mIsAccessibilityTtsEnabled)
779 return MoveFocusForward();
787 bool FocusManager::AccessibilityActionReadPrevious()
789 if(mIsAccessibilityTtsEnabled)
791 return MoveFocusBackward();
799 bool FocusManager::AccessibilityActionUp()
803 if(mIsAccessibilityTtsEnabled)
805 Actor actor = GetCurrentFocusActor();
808 Dali::Toolkit::Control control = Dali::Toolkit::Control::DownCast(actor);
811 // Notify the control that it is activated
812 ret = control.GetImplementation().OnAccessibilityValueChange(true);
820 bool FocusManager::AccessibilityActionDown()
824 if(mIsAccessibilityTtsEnabled)
826 Actor actor = GetCurrentFocusActor();
829 Dali::Toolkit::Control control = Dali::Toolkit::Control::DownCast(actor);
832 // Notify the control that it is activated
833 ret = control.GetImplementation().OnAccessibilityValueChange(false);
841 bool FocusManager::ClearAccessibilityFocus()
843 if(mIsAccessibilityTtsEnabled)
854 bool FocusManager::AccessibilityActionBack()
856 // TODO: Back to previous view
858 return mIsAccessibilityTtsEnabled;
861 bool FocusManager::HandlePanGesture(const Integration::PanGestureEvent& panEvent)
863 bool handled = false;
865 if( panEvent.state == Gesture::Started )
867 // Find the focusable actor at the event position
868 Dali::HitTestAlgorithm::Results results;
869 AccessibilityManager manager = AccessibilityManager::Get();
871 Dali::HitTestAlgorithm::HitTest( Stage::GetCurrent(), panEvent.currentPosition, results, IsActorFocusableFunction );
872 mCurrentGesturedActor = results.actor;
874 if(!mCurrentGesturedActor)
876 DALI_LOG_ERROR("Gesture detected, but no hit actor");
880 // Gesture::Finished (Up) events are delivered with previous (Motion) event position
881 // Use the real previous position; otherwise we may incorrectly get a ZERO velocity
882 if ( Gesture::Finished != panEvent.state )
884 // Store the previous position for next Gesture::Finished iteration.
885 mPreviousPosition = panEvent.previousPosition;
888 Actor rootActor = Stage::GetCurrent().GetRootLayer();
890 Dali::PanGesture pan(panEvent.state);
891 pan.time = panEvent.time;
892 pan.numberOfTouches = panEvent.numberOfTouches;
893 pan.screenPosition = panEvent.currentPosition;
894 pan.screenDisplacement = mPreviousPosition - panEvent.currentPosition;
895 pan.screenVelocity.x = pan.screenDisplacement.x / panEvent.timeDelta;
896 pan.screenVelocity.y = pan.screenDisplacement.y / panEvent.timeDelta;
898 // Only handle the pan gesture when the current focused actor is scrollable or within a scrollable actor
899 while(mCurrentGesturedActor && mCurrentGesturedActor != rootActor && !handled)
901 Dali::Toolkit::Control control = Dali::Toolkit::Control::DownCast(mCurrentGesturedActor);
904 Vector2 localCurrent;
905 control.ScreenToLocal( localCurrent.x, localCurrent.y, panEvent.currentPosition.x, panEvent.currentPosition.y );
906 pan.position = localCurrent;
908 Vector2 localPrevious;
909 control.ScreenToLocal( localPrevious.x, localPrevious.y, mPreviousPosition.x, mPreviousPosition.y );
911 pan.displacement = localCurrent - localPrevious;
912 pan.velocity.x = pan.displacement.x / panEvent.timeDelta;
913 pan.velocity.y = pan.displacement.y / panEvent.timeDelta;
915 handled = control.GetImplementation().OnAccessibilityPan(pan);
918 // If the gesture is not handled by the control, check its parent
921 mCurrentGesturedActor = mCurrentGesturedActor.GetParent();
923 if(!mCurrentGesturedActor)
925 DALI_LOG_ERROR("no more gestured actor");
930 // If handled, then update the pan gesture properties
931 PanGestureDetector::SetPanGestureProperties( pan );
938 Toolkit::FocusManager::FocusChangedSignalV2& FocusManager::FocusChangedSignal()
940 return mFocusChangedSignalV2;
943 Toolkit::FocusManager::FocusOvershotSignalV2& FocusManager::FocusOvershotSignal()
945 return mFocusOvershotSignalV2;
948 Toolkit::FocusManager::FocusedActorActivatedSignalV2& FocusManager::FocusedActorActivatedSignal()
950 return mFocusedActorActivatedSignalV2;
953 bool FocusManager::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
955 Dali::BaseHandle handle( object );
957 bool connected( true );
958 FocusManager* manager = dynamic_cast<FocusManager*>(object);
960 if( Dali::Toolkit::FocusManager::SIGNAL_FOCUS_CHANGED == signalName )
962 manager->FocusChangedSignal().Connect( tracker, functor );
964 else if( Dali::Toolkit::FocusManager::SIGNAL_FOCUS_OVERSHOT == signalName )
966 manager->FocusOvershotSignal().Connect( tracker, functor );
968 else if( Dali::Toolkit::FocusManager::SIGNAL_FOCUSED_ACTOR_ACTIVATED== signalName )
970 manager->FocusedActorActivatedSignal().Connect( tracker, functor );
974 // signalName does not match any signal
981 } // namespace Internal
983 } // namespace Toolkit