Support keyboard navigation with Tab in generic wxDataViewCtrl.

Move keyboard focus between columns with Tab and Shift-Tab. Works
similarly to left and right arrows, but wraps around to go to the next
or previous line and doesn't collapse tree nodes.

If focus reaches the last or first cell, the key event is skipped,
allowing normal Tab handling for moving to another control.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@75386 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Václav Slavík
2013-12-16 16:36:05 +00:00
parent 132a0aaacd
commit 15fe4acb3e

View File

@@ -702,9 +702,9 @@ public:
void OnPaint( wxPaintEvent &event ); void OnPaint( wxPaintEvent &event );
void OnCharHook( wxKeyEvent &event ); void OnCharHook( wxKeyEvent &event );
void OnChar( wxKeyEvent &event ); void OnChar( wxKeyEvent &event );
void OnVerticalNavigation(int delta, const wxKeyEvent& event); void OnVerticalNavigation(const wxKeyEvent& event, int delta);
void OnLeftKey(); void OnLeftKey(wxKeyEvent& event);
void OnRightKey(); void OnRightKey(wxKeyEvent& event);
void OnMouse( wxMouseEvent &event ); void OnMouse( wxMouseEvent &event );
void OnSetFocus( wxFocusEvent &event ); void OnSetFocus( wxFocusEvent &event );
void OnKillFocus( wxFocusEvent &event ); void OnKillFocus( wxFocusEvent &event );
@@ -721,7 +721,7 @@ public:
unsigned GetCurrentRow() const { return m_currentRow; } unsigned GetCurrentRow() const { return m_currentRow; }
bool HasCurrentRow() { return m_currentRow != (unsigned int)-1; } bool HasCurrentRow() { return m_currentRow != (unsigned int)-1; }
void ChangeCurrentRow( unsigned int row ); void ChangeCurrentRow( unsigned int row );
bool TryAdvanceCurrentColumn(wxDataViewTreeNode *node, bool forward); bool TryAdvanceCurrentColumn(wxDataViewTreeNode *node, wxKeyEvent& event, bool forward);
wxDataViewColumn *GetCurrentColumn() const { return m_currentCol; } wxDataViewColumn *GetCurrentColumn() const { return m_currentCol; }
void ClearCurrentColumn() { m_currentCol = NULL; } void ClearCurrentColumn() { m_currentCol = NULL; }
@@ -3673,10 +3673,22 @@ void wxDataViewMainWindow::OnCharHook(wxKeyEvent& event)
return; return;
case WXK_RETURN: case WXK_RETURN:
case WXK_TAB:
m_editorRenderer->FinishEditing(); m_editorRenderer->FinishEditing();
return; return;
} }
} }
else if ( m_useCellFocus )
{
if ( event.GetKeyCode() == WXK_TAB )
{
if ( event.ShiftDown() )
OnLeftKey(event);
else
OnRightKey(event);
return;
}
}
event.Skip(); event.Skip();
} }
@@ -3801,35 +3813,35 @@ void wxDataViewMainWindow::OnChar( wxKeyEvent &event )
break; break;
case WXK_UP: case WXK_UP:
OnVerticalNavigation( -1, event ); OnVerticalNavigation(event, -1);
break; break;
case WXK_DOWN: case WXK_DOWN:
OnVerticalNavigation( +1, event ); OnVerticalNavigation(event, +1);
break; break;
// Add the process for tree expanding/collapsing // Add the process for tree expanding/collapsing
case WXK_LEFT: case WXK_LEFT:
OnLeftKey(); OnLeftKey(event);
break; break;
case WXK_RIGHT: case WXK_RIGHT:
OnRightKey(); OnRightKey(event);
break; break;
case WXK_END: case WXK_END:
OnVerticalNavigation( +(int)GetRowCount(), event ); OnVerticalNavigation(event, +(int)GetRowCount());
break; break;
case WXK_HOME: case WXK_HOME:
OnVerticalNavigation( -(int)GetRowCount(), event ); OnVerticalNavigation(event, -(int)GetRowCount());
break; break;
case WXK_PAGEUP: case WXK_PAGEUP:
OnVerticalNavigation( -(pageSize - 1), event ); OnVerticalNavigation(event, -(pageSize - 1));
break; break;
case WXK_PAGEDOWN: case WXK_PAGEDOWN:
OnVerticalNavigation( +(pageSize - 1), event ); OnVerticalNavigation(event, +(pageSize - 1));
break; break;
default: default:
@@ -3837,7 +3849,7 @@ void wxDataViewMainWindow::OnChar( wxKeyEvent &event )
} }
} }
void wxDataViewMainWindow::OnVerticalNavigation(int delta, const wxKeyEvent& event) void wxDataViewMainWindow::OnVerticalNavigation(const wxKeyEvent& event, int delta)
{ {
// if there is no selection, we cannot move it anywhere // if there is no selection, we cannot move it anywhere
if (!HasCurrentRow() || IsEmpty()) if (!HasCurrentRow() || IsEmpty())
@@ -3897,11 +3909,11 @@ void wxDataViewMainWindow::OnVerticalNavigation(int delta, const wxKeyEvent& eve
GetOwner()->EnsureVisible( m_currentRow, -1 ); GetOwner()->EnsureVisible( m_currentRow, -1 );
} }
void wxDataViewMainWindow::OnLeftKey() void wxDataViewMainWindow::OnLeftKey(wxKeyEvent& event)
{ {
if ( IsList() ) if ( IsList() )
{ {
TryAdvanceCurrentColumn(NULL, /*forward=*/false); TryAdvanceCurrentColumn(NULL, event, /*forward=*/false);
} }
else else
{ {
@@ -3909,9 +3921,18 @@ void wxDataViewMainWindow::OnLeftKey()
if ( !node ) if ( !node )
return; return;
if ( TryAdvanceCurrentColumn(node, /*forward=*/false) ) if ( TryAdvanceCurrentColumn(node, event, /*forward=*/false) )
return; return;
const bool dontCollapseNodes = event.GetKeyCode() == WXK_TAB;
if ( dontCollapseNodes )
{
m_currentCol = NULL;
// allow focus change
event.Skip();
return;
}
// Because TryAdvanceCurrentColumn() return false, we are at the first // Because TryAdvanceCurrentColumn() return false, we are at the first
// column or using whole-row selection. In this situation, we can use // column or using whole-row selection. In this situation, we can use
// the standard TreeView handling of the left key. // the standard TreeView handling of the left key.
@@ -3941,11 +3962,11 @@ void wxDataViewMainWindow::OnLeftKey()
} }
} }
void wxDataViewMainWindow::OnRightKey() void wxDataViewMainWindow::OnRightKey(wxKeyEvent& event)
{ {
if ( IsList() ) if ( IsList() )
{ {
TryAdvanceCurrentColumn(NULL, /*forward=*/true); TryAdvanceCurrentColumn(NULL, event, /*forward=*/true);
} }
else else
{ {
@@ -3972,12 +3993,12 @@ void wxDataViewMainWindow::OnRightKey()
} }
else else
{ {
TryAdvanceCurrentColumn(node, /*forward=*/true); TryAdvanceCurrentColumn(node, event, /*forward=*/true);
} }
} }
} }
bool wxDataViewMainWindow::TryAdvanceCurrentColumn(wxDataViewTreeNode *node, bool forward) bool wxDataViewMainWindow::TryAdvanceCurrentColumn(wxDataViewTreeNode *node, wxKeyEvent& event, bool forward)
{ {
if ( GetOwner()->GetColumnCount() == 0 ) if ( GetOwner()->GetColumnCount() == 0 )
return false; return false;
@@ -3985,6 +4006,8 @@ bool wxDataViewMainWindow::TryAdvanceCurrentColumn(wxDataViewTreeNode *node, boo
if ( !m_useCellFocus ) if ( !m_useCellFocus )
return false; return false;
const bool wrapAround = event.GetKeyCode() == WXK_TAB;
if ( node ) if ( node )
{ {
// navigation shouldn't work in branch nodes without other columns: // navigation shouldn't work in branch nodes without other columns:
@@ -4002,13 +4025,48 @@ bool wxDataViewMainWindow::TryAdvanceCurrentColumn(wxDataViewTreeNode *node, boo
return true; return true;
} }
else else
return false; {
if ( !wrapAround )
return false;
}
} }
int idx = GetOwner()->GetColumnIndex(m_currentCol) + (forward ? +1 : -1); int idx = GetOwner()->GetColumnIndex(m_currentCol) + (forward ? +1 : -1);
if ( idx >= (int)GetOwner()->GetColumnCount() ) if ( idx >= (int)GetOwner()->GetColumnCount() )
return false; {
if ( !wrapAround )
return false;
if ( GetCurrentRow() < GetRowCount() - 1 )
{
// go to the first column of the next row:
idx = 0;
OnVerticalNavigation(wxKeyEvent()/*dummy*/, +1);
}
else
{
// allow focus change
event.Skip();
return false;
}
}
if ( idx < 0 && wrapAround )
{
if ( GetCurrentRow() > 0 )
{
// go to the last column of the previous row:
idx = (int)GetOwner()->GetColumnCount() - 1;
OnVerticalNavigation(wxKeyEvent()/*dummy*/, -1);
}
else
{
// allow focus change
event.Skip();
return false;
}
}
GetOwner()->EnsureVisible(m_currentRow, idx); GetOwner()->EnsureVisible(m_currentRow, idx);