Added nested TableView KeyboardFocus support 43/106743/6
authorUmar <m.umar@partner.samsung.com>
Thu, 22 Dec 2016 18:31:42 +0000 (18:31 +0000)
committerRichard Huang <r.huang@samsung.com>
Fri, 6 Jan 2017 13:11:40 +0000 (13:11 +0000)
Change-Id: I108501a26b13a85efb2b71e7878b1580f0f06ea7

automated-tests/src/dali-toolkit/utc-Dali-TableView.cpp
dali-toolkit/internal/controls/table-view/table-view-impl.cpp
dali-toolkit/internal/controls/table-view/table-view-impl.h

index 7beeb96..590614e 100644 (file)
@@ -915,3 +915,127 @@ int UtcDaliTableViewKeyboardFocus(void)
 
   END_TEST;
 }
 
   END_TEST;
 }
+
+int UtcDaliTableViewKeyboardFocusInNestedTableView(void)
+{
+  ToolkitTestApplication application;
+
+  TableView tableView = TableView::New(3, 3);
+  tableView.SetKeyboardFocusable( true );
+  tableView.SetName( "TableView");
+
+  for ( int row = 0; row < 3; ++row )
+  {
+    for ( int col = 0; col < 3; ++col )
+    {
+      std::ostringstream str;
+      str << row << "-" << col;
+
+      if (row == 1 && col ==1)
+      {
+        // Add a nested 2x2 table view in the middle cell of the parent table view
+        TableView childTableView = TableView::New(2, 2);
+        childTableView.SetName( str.str() );
+
+        for(int childRow = 0; childRow < 2; childRow++)
+        {
+          for(int childCol = 0; childCol < 2; childCol++)
+          {
+            Control control = Control::New();
+            std::ostringstream nameStr;
+            nameStr << row << "-" << col << "-" << childRow << "-" << childCol;
+            control.SetName( nameStr.str() );
+            control.SetKeyboardFocusable( true );
+            childTableView.AddChild( control, TableView::CellPosition( childRow, childCol ) );
+          }
+        }
+        tableView.AddChild( childTableView, TableView::CellPosition( row, col ) );
+      }
+      else
+      {
+        Control control = Control::New();
+        control.SetName( str.str() );
+        control.SetKeyboardFocusable( true );
+        tableView.AddChild( control, TableView::CellPosition( row, col ) );
+      }
+    }
+  }
+
+  Stage::GetCurrent().Add( tableView );
+
+  application.SendNotification();
+  application.Render();
+
+  Actor firstFocusActor = Toolkit::Internal::GetImplementation( tableView ).GetNextKeyboardFocusableActor( Actor(), Control::KeyboardFocus::RIGHT, true );
+  DALI_TEST_CHECK( firstFocusActor );
+  DALI_TEST_CHECK( firstFocusActor.GetName() == "0-0" );
+
+  KeyboardFocusManager manager = KeyboardFocusManager::Get();
+  manager.SetFocusGroupLoop( false );
+  manager.SetCurrentFocusActor( firstFocusActor );
+
+  DALI_TEST_CHECK( manager.GetCurrentFocusActor().GetName() == "0-0" );
+  manager.MoveFocus( Control::KeyboardFocus::RIGHT );
+  DALI_TEST_CHECK( manager.GetCurrentFocusActor().GetName() == "0-1" );
+  manager.MoveFocus( Control::KeyboardFocus::RIGHT );
+  DALI_TEST_CHECK( manager.GetCurrentFocusActor().GetName() == "0-2" );
+  manager.MoveFocus( Control::KeyboardFocus::RIGHT );
+  DALI_TEST_CHECK( manager.GetCurrentFocusActor().GetName() == "1-0" );
+  manager.MoveFocus( Control::KeyboardFocus::RIGHT );
+  DALI_TEST_CHECK( manager.GetCurrentFocusActor().GetName() == "1-1-0-0" );
+  manager.MoveFocus( Control::KeyboardFocus::RIGHT );
+  DALI_TEST_CHECK( manager.GetCurrentFocusActor().GetName() == "1-1-0-1" );
+  manager.MoveFocus( Control::KeyboardFocus::RIGHT );
+  DALI_TEST_CHECK( manager.GetCurrentFocusActor().GetName() == "1-1-1-0" );
+  manager.MoveFocus( Control::KeyboardFocus::RIGHT );
+  DALI_TEST_CHECK( manager.GetCurrentFocusActor().GetName() == "1-1-1-1" );
+  manager.MoveFocus( Control::KeyboardFocus::RIGHT );
+  DALI_TEST_CHECK( manager.GetCurrentFocusActor().GetName() == "1-2" );
+  manager.MoveFocus( Control::KeyboardFocus::RIGHT );
+  DALI_TEST_CHECK( manager.GetCurrentFocusActor().GetName() == "2-0" );
+  manager.MoveFocus( Control::KeyboardFocus::RIGHT );
+  DALI_TEST_CHECK( manager.GetCurrentFocusActor().GetName() == "2-1" );
+  manager.MoveFocus( Control::KeyboardFocus::RIGHT );
+  DALI_TEST_CHECK( manager.GetCurrentFocusActor().GetName() == "2-2" );
+
+  manager.MoveFocus( Control::KeyboardFocus::LEFT );
+  DALI_TEST_CHECK( manager.GetCurrentFocusActor().GetName() == "2-1" );
+  manager.MoveFocus( Control::KeyboardFocus::LEFT );
+  DALI_TEST_CHECK( manager.GetCurrentFocusActor().GetName() == "2-0" );
+  manager.MoveFocus( Control::KeyboardFocus::LEFT );
+  DALI_TEST_CHECK( manager.GetCurrentFocusActor().GetName() == "1-2" );
+  manager.MoveFocus( Control::KeyboardFocus::LEFT );
+  DALI_TEST_CHECK( manager.GetCurrentFocusActor().GetName() == "1-1-1-1" );
+  manager.MoveFocus( Control::KeyboardFocus::LEFT );
+  DALI_TEST_CHECK( manager.GetCurrentFocusActor().GetName() == "1-1-1-0" );
+  manager.MoveFocus( Control::KeyboardFocus::LEFT );
+  DALI_TEST_CHECK( manager.GetCurrentFocusActor().GetName() == "1-1-0-1" );
+  manager.MoveFocus( Control::KeyboardFocus::LEFT );
+  DALI_TEST_CHECK( manager.GetCurrentFocusActor().GetName() == "1-1-0-0" );
+  manager.MoveFocus( Control::KeyboardFocus::LEFT );
+  DALI_TEST_CHECK( manager.GetCurrentFocusActor().GetName() == "1-0" );
+  manager.MoveFocus( Control::KeyboardFocus::LEFT );
+  DALI_TEST_CHECK( manager.GetCurrentFocusActor().GetName() == "0-2" );
+  manager.MoveFocus( Control::KeyboardFocus::LEFT );
+  DALI_TEST_CHECK( manager.GetCurrentFocusActor().GetName() == "0-1" );
+  manager.MoveFocus( Control::KeyboardFocus::LEFT );
+  DALI_TEST_CHECK( manager.GetCurrentFocusActor().GetName() == "0-0" );
+
+  manager.MoveFocus( Control::KeyboardFocus::RIGHT );
+  DALI_TEST_CHECK( manager.GetCurrentFocusActor().GetName() == "0-1" );
+  manager.MoveFocus( Control::KeyboardFocus::DOWN );
+  DALI_TEST_CHECK( manager.GetCurrentFocusActor().GetName() == "1-1-0-0" );
+  manager.MoveFocus( Control::KeyboardFocus::DOWN );
+  DALI_TEST_CHECK( manager.GetCurrentFocusActor().GetName() == "1-1-1-0" );
+  manager.MoveFocus( Control::KeyboardFocus::DOWN );
+  DALI_TEST_CHECK( manager.GetCurrentFocusActor().GetName() == "2-1" );
+
+  manager.MoveFocus( Control::KeyboardFocus::UP );
+  DALI_TEST_CHECK( manager.GetCurrentFocusActor().GetName() == "1-1-1-1" );
+  manager.MoveFocus( Control::KeyboardFocus::UP );
+  DALI_TEST_CHECK( manager.GetCurrentFocusActor().GetName() == "1-1-0-1" );
+  manager.MoveFocus( Control::KeyboardFocus::UP );
+  DALI_TEST_CHECK( manager.GetCurrentFocusActor().GetName() == "0-1" );
+
+  END_TEST;
+}
index dea576c..b616fcf 100644 (file)
@@ -1077,6 +1077,8 @@ TableView::TableView( unsigned int initialRows, unsigned int initialColumns )
   mRowDirty( true ),     // Force recalculation first time
   mColumnDirty( true )
 {
   mRowDirty( true ),     // Force recalculation first time
   mColumnDirty( true )
 {
+  mCurrentColumn = 0;
+  mCurrentRow = 0;
   SetKeyboardNavigationSupport( true );
   ResizeContainers( initialRows, initialColumns );
 }
   SetKeyboardNavigationSupport( true );
   ResizeContainers( initialRows, initialColumns );
 }
@@ -1398,13 +1400,42 @@ Actor TableView::GetNextKeyboardFocusableActor(Actor currentFocusedActor, Toolki
       // Move the focus if we haven't lost it.
       if(!focusLost)
       {
       // Move the focus if we haven't lost it.
       if(!focusLost)
       {
+        // Save the new focus cell positions of TableView.
+        mCurrentColumn = currentColumn;
+        mCurrentRow = currentRow;
+
         nextFocusableActor = GetChildAt(Toolkit::TableView::CellPosition(currentRow, currentColumn));
       }
     }
     else
     {
         nextFocusableActor = GetChildAt(Toolkit::TableView::CellPosition(currentRow, currentColumn));
       }
     }
     else
     {
-      // The current focused actor is not within table view, so the child in the first cell should be focused.
-      nextFocusableActor = GetChildAt(Toolkit::TableView::CellPosition(0, 0));
+      // The current focused actor is not within TableView.
+      // This means that the TableView has gained the Focus again.
+
+      unsigned int numberOfColumns = GetColumns();
+      unsigned int numberOfRows = GetRows();
+
+      if( (mCurrentRow != 0 && mCurrentColumn != 0) && // Last saved cell was not the first cell
+          (mCurrentRow != numberOfRows - 1 && mCurrentColumn != numberOfColumns - 1) ) // Last saved cell was not the last cell
+      {
+        // This condition handles the cases when parent TableView gained the focus again after the child layout
+        // container (i.e. TableView) has no more items (i.e. actors) to be focused on in a given direction.
+
+        // Move the focus to next cell towards the given direction in a TableView if the last saved cell was not the first or last cell.
+        nextFocusableActor = GetNextKeyboardFocusableActor(GetChildAt(Toolkit::TableView::CellPosition(mCurrentRow, mCurrentColumn)), direction, loopEnabled);
+      }
+      else
+      {
+        // Otherwise, move the focus to either the first or the last cell according to the given direction.
+        if(direction == Toolkit::Control::KeyboardFocus::LEFT || direction == Toolkit::Control::KeyboardFocus::UP)
+        {
+          nextFocusableActor = GetChildAt(Toolkit::TableView::CellPosition(numberOfRows - 1, numberOfColumns - 1));
+        }
+        else
+        {
+          nextFocusableActor = GetChildAt(Toolkit::TableView::CellPosition(0, 0));
+        }
+      }
     }
   }
 
     }
   }
 
index d6e62b6..be1f702 100644 (file)
@@ -497,6 +497,8 @@ private: // Data
   Size mFixedTotals;             ///< Accumulated totals for fixed width and height
 
   Size mPadding;                 ///< Padding to apply to each cell
   Size mFixedTotals;             ///< Accumulated totals for fixed width and height
 
   Size mPadding;                 ///< Padding to apply to each cell
+  unsigned int mCurrentRow;      ///< Last / current focused row
+  unsigned int mCurrentColumn;   ///< Last / current focused column
   bool mLayoutingChild;          ///< Can't be a bitfield due to Relayouting lock
   bool mRowDirty : 1;            ///< Flag to indicate the row data is dirty
   bool mColumnDirty : 1;         ///< Flag to indicate the column data is dirty
   bool mLayoutingChild;          ///< Can't be a bitfield due to Relayouting lock
   bool mRowDirty : 1;            ///< Flag to indicate the row data is dirty
   bool mColumnDirty : 1;         ///< Flag to indicate the column data is dirty