From 05d31b3aca84298974766d6021738fb64961a36b Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sat, 2 Aug 2008 19:45:23 +0000 Subject: [PATCH] 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 --- include/wx/radiobox.h | 3 +- src/common/radiocmn.cpp | 172 +++++++++++++++++++++------------------- 2 files changed, 93 insertions(+), 82 deletions(-) diff --git a/include/wx/radiobox.h b/include/wx/radiobox.h index f8d1a6ef48..d5d0582026 100644 --- a/include/wx/radiobox.h +++ b/include/wx/radiobox.h @@ -49,7 +49,8 @@ public: unsigned int GetColumnCount() const { return m_numCols; } 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; #if wxUSE_TOOLTIPS diff --git a/src/common/radiocmn.cpp b/src/common/radiocmn.cpp index 82d9d5bef7..8d954df010 100644 --- a/src/common/radiocmn.cpp +++ b/src/common/radiocmn.cpp @@ -64,96 +64,106 @@ void wxRadioBoxBase::SetMajorDim(unsigned int majorDim, long style) int wxRadioBoxBase::GetNextItem(int item, wxDirection dir, long style) const { + const int itemStart = item; + int count = GetCount(), numCols = GetColumnCount(), numRows = GetRowCount(); bool horz = (style & wxRA_SPECIFY_COLS) != 0; - switch ( dir ) + do { - case wxUP: - if ( horz ) - { - item -= numCols; - } - else // vertical layout - { - if ( !item-- ) - item = count - 1; - } - break; - - case wxLEFT: - if ( horz ) - { - if ( !item-- ) - item = count - 1; - } - else // vertical layout - { - item -= numRows; - } - break; - - case wxDOWN: - if ( horz ) - { - item += numCols; - } - else // vertical layout - { - if ( ++item == count ) - item = 0; - } - break; - - case wxRIGHT: - if ( horz ) - { - if ( ++item == count ) - item = 0; - } - else // vertical layout - { - item += numRows; - } - break; - - default: - wxFAIL_MSG( _T("unexpected wxDirection value") ); - return wxNOT_FOUND; - } + switch ( dir ) + { + case wxUP: + if ( horz ) + { + item -= numCols; + } + else // vertical layout + { + if ( !item-- ) + item = count - 1; + } + break; + + case wxLEFT: + if ( horz ) + { + if ( !item-- ) + item = count - 1; + } + else // vertical layout + { + item -= numRows; + } + break; + + case wxDOWN: + if ( horz ) + { + item += numCols; + } + else // vertical layout + { + if ( ++item == count ) + item = 0; + } + break; + + case wxRIGHT: + if ( horz ) + { + if ( ++item == count ) + item = 0; + } + else // vertical layout + { + item += numRows; + } + break; + + default: + wxFAIL_MSG( _T("unexpected wxDirection value") ); + 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; - } + // 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()") ); + wxASSERT_MSG( item < count && item >= 0, + _T("logic error in wxRadioBox::GetNextItem()") ); + } + // we shouldn't select the non-active items, continue looking for a + // visible and shown one unless we came back to the item we started from in + // which case bail out to avoid infinite loop + while ( !(IsItemShown(item) && IsItemEnabled(item)) && item != itemStart ); return item; } -- 2.45.2