From 5a620f526710554807935299e3ef807984ac8558 Mon Sep 17 00:00:00 2001 From: David Steele Date: Tue, 14 Feb 2017 13:10:59 +0000 Subject: [PATCH] Added control focus state change to KeyboardFocusManager Change-Id: Ib58a577df67ce16888b66dd49d4c299d90270181 Signed-off-by: David Steele --- .../dali-toolkit/utc-Dali-KeyboardFocusManager.cpp | 213 ++++++++++++++++++++- dali-toolkit/internal/builder/builder-impl.cpp | 2 +- .../focus-manager/keyboard-focus-manager-impl.cpp | 32 +++- dali-toolkit/public-api/controls/control-impl.cpp | 5 +- 4 files changed, 244 insertions(+), 8 deletions(-) diff --git a/automated-tests/src/dali-toolkit/utc-Dali-KeyboardFocusManager.cpp b/automated-tests/src/dali-toolkit/utc-Dali-KeyboardFocusManager.cpp index 7d40e9e..a480204 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-KeyboardFocusManager.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-KeyboardFocusManager.cpp @@ -24,7 +24,7 @@ #include #include - +#include using namespace Dali; using namespace Dali::Toolkit; @@ -899,3 +899,214 @@ int UtcDaliKeyboardFocusManagerChangeFocusDirectionByKeyEvents(void) } + + + +int UtcDaliKeyboardFocusManagerMoveFocusTestStateChange(void) +{ + ToolkitTestApplication application; + + tet_infoline(" UtcDaliKeyboardFocusManagerMoveFocusTestStateChange"); + + // Register Type + TypeInfo type; + type = TypeRegistry::Get().GetTypeInfo( "KeyboardFocusManager" ); + DALI_TEST_CHECK( type ); + BaseHandle handle = type.CreateInstance(); + DALI_TEST_CHECK( handle ); + + KeyboardFocusManager manager = KeyboardFocusManager::Get(); + DALI_TEST_CHECK(manager); + + bool preFocusChangeSignalVerified = false; + PreFocusChangeCallback preFocusChangeCallback(preFocusChangeSignalVerified); + manager.PreFocusChangeSignal().Connect( &preFocusChangeCallback, &PreFocusChangeCallback::Callback ); + + bool focusChangedSignalVerified = false; + FocusChangedCallback focusChangedCallback(focusChangedSignalVerified); + manager.FocusChangedSignal().Connect( &focusChangedCallback, &FocusChangedCallback::Callback ); + + // Create the first actor and add it to the stage + Control first = Control::New(); + first.SetKeyboardFocusable(true); + Stage::GetCurrent().Add(first); + + // Create the second actor and add it to the stage + Control second = Control::New(); + second.SetKeyboardFocusable(true); + Stage::GetCurrent().Add(second); + + // Move the focus to the right + DALI_TEST_CHECK(manager.MoveFocus(Control::KeyboardFocus::RIGHT) == false); + + // Because no layout control in the stage and no actor is focused, it should emit the PreFocusChange signal + DALI_TEST_CHECK(preFocusChangeCallback.mSignalVerified); + DALI_TEST_CHECK(preFocusChangeCallback.mCurrentFocusedActor == Actor()); + DALI_TEST_CHECK(preFocusChangeCallback.mProposedActorToFocus == Actor()); + DALI_TEST_CHECK(preFocusChangeCallback.mDirection == Control::KeyboardFocus::RIGHT); + preFocusChangeCallback.Reset(); + + // Check that the focus is set on the first actor + DALI_TEST_CHECK(manager.SetCurrentFocusActor(first) == true); + DALI_TEST_CHECK(manager.GetCurrentFocusActor() == first); + DALI_TEST_CHECK(focusChangedCallback.mSignalVerified); + DALI_TEST_CHECK(focusChangedCallback.mOriginalFocusedActor == Actor()); + DALI_TEST_CHECK(focusChangedCallback.mCurrentFocusedActor == first); + DALI_TEST_EQUALS(first.GetProperty(DevelControl::Property::STATE), "FOCUSED", TEST_LOCATION ); + focusChangedCallback.Reset(); + + // Move the focus towards right + DALI_TEST_CHECK(manager.MoveFocus(Control::KeyboardFocus::RIGHT) == false); + + // Because no layout control in the stage and the first actor is focused, it should emit the PreFocusChange signal + DALI_TEST_CHECK(preFocusChangeCallback.mSignalVerified); + DALI_TEST_CHECK(preFocusChangeCallback.mCurrentFocusedActor == first); + DALI_TEST_CHECK(preFocusChangeCallback.mProposedActorToFocus == Actor()); + DALI_TEST_CHECK(preFocusChangeCallback.mDirection == Control::KeyboardFocus::RIGHT); + preFocusChangeCallback.Reset(); + + // Check that the focus is set on the second actor + DALI_TEST_CHECK(manager.SetCurrentFocusActor(second) == true); + DALI_TEST_CHECK(manager.GetCurrentFocusActor() == second); + DALI_TEST_CHECK(focusChangedCallback.mSignalVerified); + DALI_TEST_CHECK(focusChangedCallback.mOriginalFocusedActor == first); + DALI_TEST_CHECK(focusChangedCallback.mCurrentFocusedActor == second); + DALI_TEST_EQUALS(first.GetProperty(DevelControl::Property::STATE), "NORMAL", TEST_LOCATION ); + DALI_TEST_EQUALS(second.GetProperty(DevelControl::Property::STATE), "FOCUSED", TEST_LOCATION ); + focusChangedCallback.Reset(); + + // Move the focus towards up + DALI_TEST_CHECK(manager.MoveFocus(Control::KeyboardFocus::UP) == false); + + // Because no layout control in the stage and no actor is focused, it should emit the PreFocusChange signal + DALI_TEST_CHECK(preFocusChangeCallback.mSignalVerified); + DALI_TEST_CHECK(preFocusChangeCallback.mCurrentFocusedActor == second); + DALI_TEST_CHECK(preFocusChangeCallback.mProposedActorToFocus == Actor()); + DALI_TEST_CHECK(preFocusChangeCallback.mDirection == Control::KeyboardFocus::UP); + preFocusChangeCallback.Reset(); + DALI_TEST_CHECK(!focusChangedCallback.mSignalVerified); + + // Create a 2x2 table view and try to move focus inside it + TableView tableView = TableView::New( 2, 2 ); + Stage::GetCurrent().Add(tableView); + + // Create the third actor + Control third = Control::New(); + third.SetKeyboardFocusable(true); + + // Create the fourth actor + Control fourth = Control::New(); + fourth.SetKeyboardFocusable(true); + + // Add the four children to table view + tableView.AddChild(first, TableView::CellPosition(0, 0)); + tableView.AddChild(second, TableView::CellPosition(0, 1)); + tableView.AddChild(third, TableView::CellPosition(1, 0)); + tableView.AddChild(fourth, TableView::CellPosition(1, 1)); + + // Set the focus to the first actor + DALI_TEST_CHECK(manager.SetCurrentFocusActor(first) == true); + DALI_TEST_CHECK(manager.GetCurrentFocusActor() == first); + DALI_TEST_CHECK(focusChangedCallback.mSignalVerified); + DALI_TEST_CHECK(focusChangedCallback.mOriginalFocusedActor == second); + DALI_TEST_CHECK(focusChangedCallback.mCurrentFocusedActor == first); + + DALI_TEST_EQUALS(first.GetProperty(DevelControl::Property::STATE), "FOCUSED", TEST_LOCATION ); + DALI_TEST_EQUALS(second.GetProperty(DevelControl::Property::STATE), "NORMAL", TEST_LOCATION ); + + focusChangedCallback.Reset(); + + // Move the focus towards right + DALI_TEST_CHECK(manager.MoveFocus(Control::KeyboardFocus::RIGHT) == true); + DALI_TEST_CHECK(manager.GetCurrentFocusActor() == second); + DALI_TEST_CHECK(focusChangedCallback.mSignalVerified); + DALI_TEST_CHECK(focusChangedCallback.mOriginalFocusedActor == first); + DALI_TEST_CHECK(focusChangedCallback.mCurrentFocusedActor == second); + DALI_TEST_EQUALS(first.GetProperty(DevelControl::Property::STATE), "NORMAL", TEST_LOCATION ); + DALI_TEST_EQUALS(second.GetProperty(DevelControl::Property::STATE), "FOCUSED", TEST_LOCATION ); + + focusChangedCallback.Reset(); + + // Move the focus towards down + DALI_TEST_CHECK(manager.MoveFocus(Control::KeyboardFocus::DOWN) == true); + DALI_TEST_CHECK(manager.GetCurrentFocusActor() == fourth); + DALI_TEST_CHECK(focusChangedCallback.mSignalVerified); + DALI_TEST_CHECK(focusChangedCallback.mOriginalFocusedActor == second); + DALI_TEST_CHECK(focusChangedCallback.mCurrentFocusedActor == fourth); + + DALI_TEST_EQUALS(first.GetProperty(DevelControl::Property::STATE), "NORMAL", TEST_LOCATION ); + DALI_TEST_EQUALS(second.GetProperty(DevelControl::Property::STATE), "NORMAL", TEST_LOCATION ); + DALI_TEST_EQUALS(third.GetProperty(DevelControl::Property::STATE), "NORMAL", TEST_LOCATION ); + DALI_TEST_EQUALS(fourth.GetProperty(DevelControl::Property::STATE), "FOCUSED", TEST_LOCATION ); + + focusChangedCallback.Reset(); + + // Move the focus towards left + DALI_TEST_CHECK(manager.MoveFocus(Control::KeyboardFocus::LEFT) == true); + DALI_TEST_CHECK(manager.GetCurrentFocusActor() == third); + DALI_TEST_CHECK(focusChangedCallback.mSignalVerified); + DALI_TEST_CHECK(focusChangedCallback.mOriginalFocusedActor == fourth); + DALI_TEST_CHECK(focusChangedCallback.mCurrentFocusedActor == third); + + DALI_TEST_EQUALS(first.GetProperty(DevelControl::Property::STATE), "NORMAL", TEST_LOCATION ); + DALI_TEST_EQUALS(second.GetProperty(DevelControl::Property::STATE), "NORMAL", TEST_LOCATION ); + DALI_TEST_EQUALS(third.GetProperty(DevelControl::Property::STATE), "FOCUSED", TEST_LOCATION ); + DALI_TEST_EQUALS(fourth.GetProperty(DevelControl::Property::STATE), "NORMAL", TEST_LOCATION ); + + focusChangedCallback.Reset(); + + // Move the focus towards up + DALI_TEST_CHECK(manager.MoveFocus(Control::KeyboardFocus::UP) == true); + DALI_TEST_CHECK(manager.GetCurrentFocusActor() == first); + DALI_TEST_CHECK(focusChangedCallback.mSignalVerified); + DALI_TEST_CHECK(focusChangedCallback.mOriginalFocusedActor == third); + DALI_TEST_CHECK(focusChangedCallback.mCurrentFocusedActor == first); + DALI_TEST_EQUALS(first.GetProperty(DevelControl::Property::STATE), "FOCUSED", TEST_LOCATION ); + DALI_TEST_EQUALS(second.GetProperty(DevelControl::Property::STATE), "NORMAL", TEST_LOCATION ); + DALI_TEST_EQUALS(third.GetProperty(DevelControl::Property::STATE), "NORMAL", TEST_LOCATION ); + DALI_TEST_EQUALS(fourth.GetProperty(DevelControl::Property::STATE), "NORMAL", TEST_LOCATION ); + focusChangedCallback.Reset(); + + // Move the focus towards left. The focus move will fail as no way to move it upwards + DALI_TEST_CHECK(manager.MoveFocus(Control::KeyboardFocus::LEFT) == false); + DALI_TEST_CHECK(manager.GetCurrentFocusActor() == first); + DALI_TEST_CHECK(preFocusChangeCallback.mSignalVerified); + DALI_TEST_CHECK(preFocusChangeCallback.mCurrentFocusedActor == first); + DALI_TEST_CHECK(preFocusChangeCallback.mProposedActorToFocus == Actor()); + DALI_TEST_CHECK(preFocusChangeCallback.mDirection == Control::KeyboardFocus::LEFT); + DALI_TEST_EQUALS(first.GetProperty(DevelControl::Property::STATE), "FOCUSED", TEST_LOCATION ); + DALI_TEST_EQUALS(second.GetProperty(DevelControl::Property::STATE), "NORMAL", TEST_LOCATION ); + DALI_TEST_EQUALS(third.GetProperty(DevelControl::Property::STATE), "NORMAL", TEST_LOCATION ); + DALI_TEST_EQUALS(fourth.GetProperty(DevelControl::Property::STATE), "NORMAL", TEST_LOCATION ); + + preFocusChangeCallback.Reset(); + DALI_TEST_CHECK(!focusChangedCallback.mSignalVerified); + + // Enable the loop + manager.SetFocusGroupLoop(true); + DALI_TEST_CHECK(manager.GetFocusGroupLoop() == true); + + // Move the focus towards left again. The focus should move to the fourth actor. + DALI_TEST_CHECK(manager.MoveFocus(Control::KeyboardFocus::LEFT) == true); + DALI_TEST_CHECK(manager.GetCurrentFocusActor() == fourth); + DALI_TEST_CHECK(focusChangedCallback.mSignalVerified); + DALI_TEST_CHECK(focusChangedCallback.mOriginalFocusedActor == first); + DALI_TEST_CHECK(focusChangedCallback.mCurrentFocusedActor == fourth); + + DALI_TEST_EQUALS(first.GetProperty(DevelControl::Property::STATE), "NORMAL", TEST_LOCATION ); + DALI_TEST_EQUALS(second.GetProperty(DevelControl::Property::STATE), "NORMAL", TEST_LOCATION ); + DALI_TEST_EQUALS(third.GetProperty(DevelControl::Property::STATE), "NORMAL", TEST_LOCATION ); + DALI_TEST_EQUALS(fourth.GetProperty(DevelControl::Property::STATE), "FOCUSED", TEST_LOCATION ); + + focusChangedCallback.Reset(); + + // Clear the focus + manager.ClearFocus(); + DALI_TEST_EQUALS(first.GetProperty(DevelControl::Property::STATE), "NORMAL", TEST_LOCATION ); + DALI_TEST_EQUALS(second.GetProperty(DevelControl::Property::STATE), "NORMAL", TEST_LOCATION ); + DALI_TEST_EQUALS(third.GetProperty(DevelControl::Property::STATE), "NORMAL", TEST_LOCATION ); + DALI_TEST_EQUALS(fourth.GetProperty(DevelControl::Property::STATE), "NORMAL", TEST_LOCATION ); + + + END_TEST; +} diff --git a/dali-toolkit/internal/builder/builder-impl.cpp b/dali-toolkit/internal/builder/builder-impl.cpp index 9b6daa0..ac5ea3e 100644 --- a/dali-toolkit/internal/builder/builder-impl.cpp +++ b/dali-toolkit/internal/builder/builder-impl.cpp @@ -1258,7 +1258,7 @@ void Builder::RecordStyle( StylePtr style, } else { - DALI_LOG_WARNING( "RecordState() Node \"%s\" is not a JSON array or object\n", key.c_str() ); + DALI_LOG_WARNING( "RecordStyle() Node \"%s\" is not a JSON array or object\n", key.c_str() ); } } else if( key == KEYNAME_TYPE || diff --git a/dali-toolkit/internal/focus-manager/keyboard-focus-manager-impl.cpp b/dali-toolkit/internal/focus-manager/keyboard-focus-manager-impl.cpp index 197550f..989997b 100644 --- a/dali-toolkit/internal/focus-manager/keyboard-focus-manager-impl.cpp +++ b/dali-toolkit/internal/focus-manager/keyboard-focus-manager-impl.cpp @@ -38,6 +38,7 @@ #include #include #include +#include namespace Dali { @@ -162,9 +163,18 @@ bool KeyboardFocusManager::DoSetCurrentFocusActor( const unsigned int actorID ) actor.Add( GetFocusIndicatorActor() ); } // Send notification for the change of focus actor + Actor currentFocusedActor = GetCurrentFocusActor(); + if( !mFocusChangedSignal.Empty() ) { - mFocusChangedSignal.Emit(GetCurrentFocusActor(), actor); + mFocusChangedSignal.Emit(currentFocusedActor, actor); + } + + Toolkit::Control currentlyFocusedControl = Toolkit::Control::DownCast(currentFocusedActor); + if( currentlyFocusedControl ) + { + // Do we need it to remember if it was previously DISABLED? + currentlyFocusedControl.SetProperty(DevelControl::Property::STATE, DevelControl::NORMAL ); } DALI_LOG_INFO( gLogFilter, Debug::General, "[%s:%d] Focus Changed\n", __FUNCTION__, __LINE__); @@ -172,6 +182,12 @@ bool KeyboardFocusManager::DoSetCurrentFocusActor( const unsigned int actorID ) // Save the current focused actor mCurrentFocusActor = actorID; + Toolkit::Control newlyFocusedControl = Toolkit::Control::DownCast(actor); + if( newlyFocusedControl ) + { + newlyFocusedControl.SetProperty(DevelControl::Property::STATE, DevelControl::FOCUSED ); + } + // Push Current Focused Actor to FocusHistory mFocusHistory.PushBack( &actor.GetBaseObject() ); @@ -404,17 +420,23 @@ void KeyboardFocusManager::DoKeyboardEnter(Actor actor) void KeyboardFocusManager::ClearFocus() { Actor actor = GetCurrentFocusActor(); - if(actor) + if( actor ) { - if(mFocusIndicatorActor) + if( mFocusIndicatorActor ) { - actor.Remove(mFocusIndicatorActor); + actor.Remove( mFocusIndicatorActor ); } // Send notification for the change of focus actor if( !mFocusChangedSignal.Empty() ) { - mFocusChangedSignal.Emit(actor, Actor()); + mFocusChangedSignal.Emit( actor, Actor() ); + } + + Toolkit::Control currentlyFocusedControl = Toolkit::Control::DownCast( actor ); + if( currentlyFocusedControl ) + { + currentlyFocusedControl.SetProperty( DevelControl::Property::STATE, DevelControl::NORMAL ); } } diff --git a/dali-toolkit/public-api/controls/control-impl.cpp b/dali-toolkit/public-api/controls/control-impl.cpp index 5d3248e..3f58064 100644 --- a/dali-toolkit/public-api/controls/control-impl.cpp +++ b/dali-toolkit/public-api/controls/control-impl.cpp @@ -54,6 +54,7 @@ namespace Dali { +extern bool CaseInsensitiveStringCompare( const std::string& a, const std::string& b ); namespace Toolkit { @@ -322,7 +323,7 @@ public: case Toolkit::DevelControl::Property::STATE: { - Toolkit::DevelControl::State state( DevelControl::NORMAL ); + Toolkit::DevelControl::State state( controlImpl.mImpl->mState ); if( Scripting::GetEnumerationProperty< Toolkit::DevelControl::State >( value, ControlStateTable, ControlStateTableCount, state ) ) { @@ -506,6 +507,8 @@ public: { if( mState != state ) { + // If mState was Disabled, and new state is Focused, should probably + // store that fact, e.g. in another property that FocusManager can access. mState = state; // Trigger state change and transitions -- 2.7.4