X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git;a=blobdiff_plain;f=dali-toolkit%2Finternal%2Ffocus-manager%2Ffocus-manager-impl.cpp;h=1dee2b25407598fbabe2b17710f908c5412765c8;hp=ad3a8e8c75188ff85919f93f73a8062cfab89597;hb=4b347781c8761d2909b235ded2e98d272fa9ac16;hpb=e2eda444afbe82e9591fe198eef339227f90a616 diff --git a/dali-toolkit/internal/focus-manager/focus-manager-impl.cpp b/dali-toolkit/internal/focus-manager/focus-manager-impl.cpp index ad3a8e8..1dee2b2 100644 --- a/dali-toolkit/internal/focus-manager/focus-manager-impl.cpp +++ b/dali-toolkit/internal/focus-manager/focus-manager-impl.cpp @@ -1,26 +1,37 @@ -// -// Copyright (c) 2014 Samsung Electronics Co., Ltd. -// -// Licensed under the Flora License, Version 1.0 (the License); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://floralicense.org/license/ -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an AS IS BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ // CLASS HEADER #include "focus-manager-impl.h" +// EXTERNAL INCLUDES +#include // for strcmp +#include +#include +#include +#include +#include +#include +#include +#include + // INTERNAL INCLUDES #include #include -#include namespace Dali { @@ -34,13 +45,25 @@ namespace Internal namespace // unnamed namespace { +// Signals + +const char* const SIGNAL_FOCUS_CHANGED = "focus-changed"; +const char* const SIGNAL_FOCUS_OVERSHOT = "focus-overshot"; +const char* const SIGNAL_FOCUSED_ACTOR_ACTIVATED = "focused-actor-activated"; + #if defined(DEBUG_ENABLED) Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_FOCUS_MANAGER"); #endif +const char* const ACTOR_FOCUSABLE("focusable"); +const char* const IS_FOCUS_GROUP("is-focus-group"); + const char* FOCUS_BORDER_IMAGE_PATH = DALI_IMAGE_DIR "B16-8_TTS_focus.png"; const Vector4 FOCUS_BORDER_IMAGE_BORDER = Vector4(7.0f, 7.0f, 7.0f, 7.0f); +const char* FOCUS_SOUND_FILE = DALI_SOUND_DIR "Focus.ogg"; +const char* FOCUS_CHAIN_END_SOUND_FILE = DALI_SOUND_DIR "End_of_List.ogg"; + /** * The function to be used in the hit-test algorithm to check whether the actor is hittable. */ @@ -57,7 +80,7 @@ bool IsActorFocusableFunction(Actor actor, Dali::HitTestAlgorithm::TraverseType && actor.GetCurrentWorldColor().a > 0.01f) // not FULLY_TRANSPARENT { // Check whether the actor is focusable - Property::Index propertyActorFocusable = actor.GetPropertyIndex(Toolkit::FocusManager::ACTOR_FOCUSABLE); + Property::Index propertyActorFocusable = actor.GetPropertyIndex(ACTOR_FOCUSABLE); if(propertyActorFocusable != Property::INVALID_INDEX) { hittable = actor.GetProperty(propertyActorFocusable); @@ -87,6 +110,8 @@ bool IsActorFocusableFunction(Actor actor, Dali::HitTestAlgorithm::TraverseType FocusManager::FocusManager() : mIsWrapped(false), mIsFocusWithinGroup(false), + mIsEndcapFeedbackEnabled(false), + mIsEndcapFeedbackPlayed(false), mCurrentFocusActor(FocusIDPair(0, 0)), mFocusIndicatorActor(Actor()), mRecursiveFocusMoveCounter(0), @@ -162,10 +187,10 @@ void FocusManager::SetFocusOrder(Actor actor, const unsigned int order) mFocusIDContainer.erase(GetFocusOrder(actor)); // Create actor focusable property if not already created. - Property::Index propertyActorFocusable = actor.GetPropertyIndex(Toolkit::FocusManager::ACTOR_FOCUSABLE); + Property::Index propertyActorFocusable = actor.GetPropertyIndex(ACTOR_FOCUSABLE); if(propertyActorFocusable == Property::INVALID_INDEX) { - propertyActorFocusable = actor.RegisterProperty(Toolkit::FocusManager::ACTOR_FOCUSABLE, true); + propertyActorFocusable = actor.RegisterProperty(ACTOR_FOCUSABLE, true); } if(order == 0) @@ -293,7 +318,7 @@ bool FocusManager::DoSetCurrentFocusActor(const unsigned int actorID) { // Check whether the actor is focusable bool actorFocusable = false; - Property::Index propertyActorFocusable = actor.GetPropertyIndex(Toolkit::FocusManager::ACTOR_FOCUSABLE); + Property::Index propertyActorFocusable = actor.GetPropertyIndex(ACTOR_FOCUSABLE); if(propertyActorFocusable != Property::INVALID_INDEX) { actorFocusable = actor.GetProperty(propertyActorFocusable); @@ -321,13 +346,19 @@ bool FocusManager::DoSetCurrentFocusActor(const unsigned int actorID) } // Send notification for the change of focus actor - mFocusChangedSignalV2.Emit( GetCurrentFocusActor(), actor ); + mFocusChangedSignal.Emit( GetCurrentFocusActor(), actor ); // Save the current focused actor mCurrentFocusActor = FocusIDPair(GetFocusOrder(actor), actorID); if(mIsAccessibilityTtsEnabled) { + Dali::SoundPlayer soundPlayer = Dali::SoundPlayer::Get(); + if(soundPlayer) + { + soundPlayer.PlaySound(FOCUS_SOUND_FILE); + } + // Play the accessibility attributes with the TTS player. Dali::TtsPlayer player = Dali::TtsPlayer::Get(Dali::TtsPlayer::SCREEN_READER); @@ -436,11 +467,11 @@ void FocusManager::DoActivate(Actor actor) if(control) { // Notify the control that it is activated - control.GetImplementation().OnActivated(); + control.GetImplementation().Activate(); } // Send notification for the activation of focused actor - mFocusedActorActivatedSignalV2.Emit(actor); + mFocusedActorActivatedSignal.Emit(actor); } } @@ -455,7 +486,7 @@ void FocusManager::ClearFocus() mCurrentFocusActor = FocusIDPair(0, 0); // Send notification for the change of focus actor - mFocusChangedSignalV2.Emit(actor, Actor()); + mFocusChangedSignal.Emit(actor, Actor()); if(mIsAccessibilityTtsEnabled) { @@ -477,10 +508,10 @@ void FocusManager::SetFocusGroup(Actor actor, bool isFocusGroup) if(actor) { // Create focus group property if not already created. - Property::Index propertyIsFocusGroup = actor.GetPropertyIndex(Toolkit::FocusManager::IS_FOCUS_GROUP); + Property::Index propertyIsFocusGroup = actor.GetPropertyIndex(IS_FOCUS_GROUP); if(propertyIsFocusGroup == Property::INVALID_INDEX) { - propertyIsFocusGroup = actor.RegisterProperty(Toolkit::FocusManager::IS_FOCUS_GROUP, isFocusGroup); + actor.RegisterProperty(IS_FOCUS_GROUP, isFocusGroup); } else { @@ -496,7 +527,7 @@ bool FocusManager::IsFocusGroup(Actor actor) const if(actor) { - Property::Index propertyIsFocusGroup = actor.GetPropertyIndex(Toolkit::FocusManager::IS_FOCUS_GROUP); + Property::Index propertyIsFocusGroup = actor.GetPropertyIndex(IS_FOCUS_GROUP); if(propertyIsFocusGroup != Property::INVALID_INDEX) { isFocusGroup = actor.GetProperty(propertyIsFocusGroup); @@ -555,6 +586,23 @@ bool FocusManager::DoMoveFocus(FocusIDIter focusIDIter, bool forward, bool wrapp if( (forward && ++focusIDIter == mFocusIDContainer.end()) || (!forward && focusIDIter-- == mFocusIDContainer.begin()) ) { + if(mIsEndcapFeedbackEnabled) + { + if(mIsEndcapFeedbackPlayed == false) + { + // play sound & skip moving once + Dali::SoundPlayer soundPlayer = Dali::SoundPlayer::Get(); + if(soundPlayer) + { + soundPlayer.PlaySound(FOCUS_CHAIN_END_SOUND_FILE); + } + + mIsEndcapFeedbackPlayed = true; + return true; + } + mIsEndcapFeedbackPlayed = false; + } + if(wrapped) { if(forward) @@ -571,7 +619,7 @@ bool FocusManager::DoMoveFocus(FocusIDIter focusIDIter, bool forward, bool wrapp { DALI_LOG_INFO( gLogFilter, Debug::General, "[%s:%d] Overshot\n", __FUNCTION__, __LINE__); // Send notification for handling overshooted situation - mFocusOvershotSignalV2.Emit(GetCurrentFocusActor(), forward ? Toolkit::FocusManager::OVERSHOT_NEXT : Toolkit::FocusManager::OVERSHOT_PREVIOUS); + mFocusOvershotSignal.Emit(GetCurrentFocusActor(), forward ? Toolkit::FocusManager::OVERSHOT_NEXT : Toolkit::FocusManager::OVERSHOT_PREVIOUS); return false; // Try to move the focus out of the scope } @@ -603,10 +651,10 @@ void FocusManager::SetFocusable(Actor actor, bool focusable) if(actor) { // Create actor focusable property if not already created. - Property::Index propertyActorFocusable = actor.GetPropertyIndex(Toolkit::FocusManager::ACTOR_FOCUSABLE); + Property::Index propertyActorFocusable = actor.GetPropertyIndex(ACTOR_FOCUSABLE); if(propertyActorFocusable == Property::INVALID_INDEX) { - propertyActorFocusable = actor.RegisterProperty(Toolkit::FocusManager::ACTOR_FOCUSABLE, focusable); + actor.RegisterProperty(ACTOR_FOCUSABLE, focusable); } else { @@ -618,7 +666,7 @@ void FocusManager::SetFocusable(Actor actor, bool focusable) void FocusManager::CreateDefaultFocusIndicatorActor() { // Create a focus indicator actor shared by all the focusable actors - Image borderImage = Image::New(FOCUS_BORDER_IMAGE_PATH); + Image borderImage = ResourceImage::New(FOCUS_BORDER_IMAGE_PATH); ImageActor focusIndicator = ImageActor::New(borderImage); focusIndicator.SetPositionInheritanceMode( Dali::USE_PARENT_POSITION_PLUS_LOCAL_POSITION ); @@ -627,10 +675,7 @@ void FocusManager::CreateDefaultFocusIndicatorActor() focusIndicator.SetPosition(Vector3(0.0f, 0.0f, 1.0f)); // Apply size constraint to the focus indicator - Constraint constraint = Constraint::New(Actor::SIZE, - ParentSource(Actor::SIZE), - EqualToConstraint()); - focusIndicator.ApplyConstraint(constraint); + focusIndicator.SetResizePolicy( FILL_TO_PARENT, ALL_DIMENSIONS ); SetFocusIndicatorActor(focusIndicator); } @@ -667,10 +712,11 @@ bool FocusManager::ChangeAccessibilityStatus() return true; } -bool FocusManager::AccessibilityActionNext() +bool FocusManager::AccessibilityActionNext(bool allowEndFeedback) { if(mIsAccessibilityTtsEnabled) { + mIsEndcapFeedbackEnabled = allowEndFeedback; return MoveFocusForward(); } else @@ -679,10 +725,11 @@ bool FocusManager::AccessibilityActionNext() } } -bool FocusManager::AccessibilityActionPrevious() +bool FocusManager::AccessibilityActionPrevious(bool allowEndFeedback) { if(mIsAccessibilityTtsEnabled) { + mIsEndcapFeedbackEnabled = allowEndFeedback; return MoveFocusBackward(); } else @@ -731,7 +778,7 @@ bool FocusManager::AccessibilityActionRead(bool allowReadAgain) return ret; } -bool FocusManager::AccessibilityActionReadNext() +bool FocusManager::AccessibilityActionReadNext(bool allowEndFeedback) { if(mIsAccessibilityTtsEnabled) { @@ -743,7 +790,7 @@ bool FocusManager::AccessibilityActionReadNext() } } -bool FocusManager::AccessibilityActionReadPrevious() +bool FocusManager::AccessibilityActionReadPrevious(bool allowEndFeedback) { if(mIsAccessibilityTtsEnabled) { @@ -817,25 +864,62 @@ bool FocusManager::AccessibilityActionBack() return mIsAccessibilityTtsEnabled; } +bool FocusManager::AccessibilityActionTouch(const TouchEvent& touchEvent) +{ + bool handled = false; + + // TODO: Need to convert the touchevent for the focused actor? + + Dali::Toolkit::Control control = Dali::Toolkit::Control::DownCast(GetCurrentFocusActor()); + if(control) + { + handled = control.GetImplementation().OnAccessibilityTouch(touchEvent); + } + + return handled; +} + bool FocusManager::HandlePanGesture(const Integration::PanGestureEvent& panEvent) { bool handled = false; - Actor currentGesturedActor = GetCurrentFocusActor(); + if( panEvent.state == Gesture::Started ) + { + // Find the focusable actor at the event position + Dali::HitTestAlgorithm::Results results; + AccessibilityManager manager = AccessibilityManager::Get(); + + Dali::HitTestAlgorithm::HitTest( Stage::GetCurrent(), panEvent.currentPosition, results, IsActorFocusableFunction ); + mCurrentGesturedActor = results.actor; + + if(!mCurrentGesturedActor) + { + DALI_LOG_ERROR("Gesture detected, but no hit actor"); + } + } + + // Gesture::Finished (Up) events are delivered with previous (Motion) event position + // Use the real previous position; otherwise we may incorrectly get a ZERO velocity + if ( Gesture::Finished != panEvent.state ) + { + // Store the previous position for next Gesture::Finished iteration. + mPreviousPosition = panEvent.previousPosition; + } + Actor rootActor = Stage::GetCurrent().GetRootLayer(); Dali::PanGesture pan(panEvent.state); pan.time = panEvent.time; pan.numberOfTouches = panEvent.numberOfTouches; pan.screenPosition = panEvent.currentPosition; - pan.screenDisplacement = panEvent.previousPosition - panEvent.currentPosition; + pan.screenDisplacement = mPreviousPosition - panEvent.currentPosition; pan.screenVelocity.x = pan.screenDisplacement.x / panEvent.timeDelta; pan.screenVelocity.y = pan.screenDisplacement.y / panEvent.timeDelta; // Only handle the pan gesture when the current focused actor is scrollable or within a scrollable actor - while(currentGesturedActor && currentGesturedActor != rootActor && !handled) + while(mCurrentGesturedActor && mCurrentGesturedActor != rootActor && !handled) { - Dali::Toolkit::Control control = Dali::Toolkit::Control::DownCast(currentGesturedActor); + Dali::Toolkit::Control control = Dali::Toolkit::Control::DownCast(mCurrentGesturedActor); if(control) { Vector2 localCurrent; @@ -843,7 +927,7 @@ bool FocusManager::HandlePanGesture(const Integration::PanGestureEvent& panEvent pan.position = localCurrent; Vector2 localPrevious; - control.ScreenToLocal( localPrevious.x, localPrevious.y, panEvent.previousPosition.x, panEvent.previousPosition.y ); + control.ScreenToLocal( localPrevious.x, localPrevious.y, mPreviousPosition.x, mPreviousPosition.y ); pan.displacement = localCurrent - localPrevious; pan.velocity.x = pan.displacement.x / panEvent.timeDelta; @@ -855,7 +939,12 @@ bool FocusManager::HandlePanGesture(const Integration::PanGestureEvent& panEvent // If the gesture is not handled by the control, check its parent if(!handled) { - currentGesturedActor = currentGesturedActor.GetParent(); + mCurrentGesturedActor = mCurrentGesturedActor.GetParent(); + + if(!mCurrentGesturedActor) + { + DALI_LOG_ERROR("no more gestured actor"); + } } else { @@ -867,19 +956,19 @@ bool FocusManager::HandlePanGesture(const Integration::PanGestureEvent& panEvent return handled; } -Toolkit::FocusManager::FocusChangedSignalV2& FocusManager::FocusChangedSignal() +Toolkit::FocusManager::FocusChangedSignalType& FocusManager::FocusChangedSignal() { - return mFocusChangedSignalV2; + return mFocusChangedSignal; } -Toolkit::FocusManager::FocusOvershotSignalV2& FocusManager::FocusOvershotSignal() +Toolkit::FocusManager::FocusOvershotSignalType& FocusManager::FocusOvershotSignal() { - return mFocusOvershotSignalV2; + return mFocusOvershotSignal; } -Toolkit::FocusManager::FocusedActorActivatedSignalV2& FocusManager::FocusedActorActivatedSignal() +Toolkit::FocusManager::FocusedActorActivatedSignalType& FocusManager::FocusedActorActivatedSignal() { - return mFocusedActorActivatedSignalV2; + return mFocusedActorActivatedSignal; } bool FocusManager::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor ) @@ -887,17 +976,17 @@ bool FocusManager::DoConnectSignal( BaseObject* object, ConnectionTrackerInterfa Dali::BaseHandle handle( object ); bool connected( true ); - FocusManager* manager = dynamic_cast(object); + FocusManager* manager = dynamic_cast( object ); - if( Dali::Toolkit::FocusManager::SIGNAL_FOCUS_CHANGED == signalName ) + if( 0 == strcmp( signalName.c_str(), SIGNAL_FOCUS_CHANGED ) ) { manager->FocusChangedSignal().Connect( tracker, functor ); } - else if( Dali::Toolkit::FocusManager::SIGNAL_FOCUS_OVERSHOT == signalName ) + else if( 0 == strcmp( signalName.c_str(), SIGNAL_FOCUS_OVERSHOT ) ) { manager->FocusOvershotSignal().Connect( tracker, functor ); } - else if( Dali::Toolkit::FocusManager::SIGNAL_FOCUSED_ACTOR_ACTIVATED== signalName ) + else if( 0 == strcmp( signalName.c_str(), SIGNAL_FOCUSED_ACTOR_ACTIVATED ) ) { manager->FocusedActorActivatedSignal().Connect( tracker, functor ); }