fix keyboard navigation in radio boxes containing hidden or disabled items

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@54930 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin
2008-08-02 19:45:23 +00:00
parent 8758875e0b
commit 05d31b3aca
2 changed files with 90 additions and 79 deletions

View File

@@ -49,7 +49,8 @@ public:
unsigned int GetColumnCount() const { return m_numCols; } unsigned int GetColumnCount() const { return m_numCols; }
unsigned int GetRowCount() const { return m_numRows; } unsigned int GetRowCount() const { return m_numRows; }
// return the item above/below/to the left/right of the given one // return the next active (i.e. shown and not disabled) item above/below/to
// the left/right of the given one
int GetNextItem(int item, wxDirection dir, long style) const; int GetNextItem(int item, wxDirection dir, long style) const;
#if wxUSE_TOOLTIPS #if wxUSE_TOOLTIPS

View File

@@ -64,96 +64,106 @@ void wxRadioBoxBase::SetMajorDim(unsigned int majorDim, long style)
int wxRadioBoxBase::GetNextItem(int item, wxDirection dir, long style) const int wxRadioBoxBase::GetNextItem(int item, wxDirection dir, long style) const
{ {
const int itemStart = item;
int count = GetCount(), int count = GetCount(),
numCols = GetColumnCount(), numCols = GetColumnCount(),
numRows = GetRowCount(); numRows = GetRowCount();
bool horz = (style & wxRA_SPECIFY_COLS) != 0; bool horz = (style & wxRA_SPECIFY_COLS) != 0;
switch ( dir ) do
{ {
case wxUP: switch ( dir )
if ( horz ) {
{ case wxUP:
item -= numCols; if ( horz )
} {
else // vertical layout item -= numCols;
{ }
if ( !item-- ) else // vertical layout
item = count - 1; {
} if ( !item-- )
break; item = count - 1;
}
break;
case wxLEFT: case wxLEFT:
if ( horz ) if ( horz )
{ {
if ( !item-- ) if ( !item-- )
item = count - 1; item = count - 1;
} }
else // vertical layout else // vertical layout
{ {
item -= numRows; item -= numRows;
} }
break; break;
case wxDOWN: case wxDOWN:
if ( horz ) if ( horz )
{ {
item += numCols; item += numCols;
} }
else // vertical layout else // vertical layout
{ {
if ( ++item == count ) if ( ++item == count )
item = 0; item = 0;
} }
break; break;
case wxRIGHT: case wxRIGHT:
if ( horz ) if ( horz )
{ {
if ( ++item == count ) if ( ++item == count )
item = 0; item = 0;
} }
else // vertical layout else // vertical layout
{ {
item += numRows; item += numRows;
} }
break; break;
default: default:
wxFAIL_MSG( _T("unexpected wxDirection value") ); wxFAIL_MSG( _T("unexpected wxDirection value") );
return wxNOT_FOUND; return wxNOT_FOUND;
}
// ensure that the item is in range [0..count)
if ( item < 0 )
{
// first map the item to the one in the same column but in the last
// row
item += count;
// now there are 2 cases: either it is the first item of the last
// row in which case we need to wrap again and get to the last item
// or we can just go to the previous item
if ( item % (horz ? numCols : numRows) )
item--;
else
item = count - 1;
}
else if ( item >= count )
{
// same logic as above
item -= count;
// ... except that we need to check if this is not the last item,
// not the first one
if ( (item + 1) % (horz ? numCols : numRows) )
item++;
else
item = 0;
}
wxASSERT_MSG( item < count && item >= 0,
_T("logic error in wxRadioBox::GetNextItem()") );
} }
// we shouldn't select the non-active items, continue looking for a
// ensure that the item is in range [0..count) // visible and shown one unless we came back to the item we started from in
if ( item < 0 ) // which case bail out to avoid infinite loop
{ while ( !(IsItemShown(item) && IsItemEnabled(item)) && item != itemStart );
// first map the item to the one in the same column but in the last row
item += count;
// now there are 2 cases: either it is the first item of the last row
// in which case we need to wrap again and get to the last item or we
// can just go to the previous item
if ( item % (horz ? numCols : numRows) )
item--;
else
item = count - 1;
}
else if ( item >= count )
{
// same logic as above
item -= count;
// ... except that we need to check if this is not the last item, not
// the first one
if ( (item + 1) % (horz ? numCols : numRows) )
item++;
else
item = 0;
}
wxASSERT_MSG( item < count && item >= 0,
_T("logic error in wxRadioBox::GetNextItem()") );
return item; return item;
} }