+void wxDataViewMainWindow::OnChar( wxKeyEvent &event )
+{
+ wxWindow * const parent = GetParent();
+
+ // propagate the char event upwards
+ wxKeyEvent eventForParent(event);
+ eventForParent.SetEventObject(parent);
+ if ( parent->ProcessWindowEvent(eventForParent) )
+ return;
+
+ if ( parent->HandleAsNavigationKey(event) )
+ return;
+
+ // no item -> nothing to do
+ if (!HasCurrentRow())
+ {
+ event.Skip();
+ return;
+ }
+
+ // don't use m_linesPerPage directly as it might not be computed yet
+ const int pageSize = GetCountPerPage();
+ wxCHECK_RET( pageSize, wxT("should have non zero page size") );
+
+ switch ( event.GetKeyCode() )
+ {
+ case WXK_RETURN:
+ if ( event.HasModifiers() )
+ {
+ event.Skip();
+ break;
+ }
+ else
+ {
+ // Enter activates the item, i.e. sends wxEVT_COMMAND_DATAVIEW_ITEM_ACTIVATED to
+ // it. Only if that event is not handled do we activate column renderer (which
+ // is normally done by Space) or even inline editing.
+
+ const wxDataViewItem item = GetItemByRow(m_currentRow);
+
+ wxDataViewEvent le(wxEVT_COMMAND_DATAVIEW_ITEM_ACTIVATED,
+ parent->GetId());
+ le.SetItem(item);
+ le.SetEventObject(parent);
+ le.SetModel(GetModel());
+
+ if ( parent->ProcessWindowEvent(le) )
+ break;
+ // else: fall through to WXK_SPACE handling
+ }
+
+ case WXK_SPACE:
+ if ( event.HasModifiers() )
+ {
+ event.Skip();
+ break;
+ }
+ else
+ {
+ // Space toggles activatable items or -- if not activatable --
+ // starts inline editing (this is normally done using F2 on
+ // Windows, but Space is common everywhere else, so use it too
+ // for greater cross-platform compatibility).
+
+ const wxDataViewItem item = GetItemByRow(m_currentRow);
+
+ // Activate the current activatable column. If not column is focused (typically
+ // because the user has full row selected), try to find the first activatable
+ // column (this would typically be a checkbox and we don't want to force the user
+ // to set focus on the checkbox column).
+ wxDataViewColumn *activatableCol = FindColumnForEditing(item, wxDATAVIEW_CELL_ACTIVATABLE);
+
+ if ( activatableCol )
+ {
+ const unsigned colIdx = activatableCol->GetModelColumn();
+ const wxRect cell_rect = GetOwner()->GetItemRect(item, activatableCol);
+
+ wxDataViewRenderer *cell = activatableCol->GetRenderer();
+ cell->PrepareForItem(GetModel(), item, colIdx);
+ cell->WXActivateCell(cell_rect, GetModel(), item, colIdx, NULL);
+
+ break;
+ }
+ // else: fall through to WXK_F2 handling
+ }
+
+ case WXK_F2:
+ if ( event.HasModifiers() )
+ {
+ event.Skip();
+ break;
+ }
+ else
+ {
+ if( !m_selection.empty() )
+ {
+ // Mimic Windows 7 behavior: edit the item that has focus
+ // if it is selected and the first selected item if focus
+ // is out of selection.
+ int sel;
+ if ( m_selection.Index(m_currentRow) != wxNOT_FOUND )
+ sel = m_currentRow;
+ else
+ sel = m_selection[0];
+
+
+ const wxDataViewItem item = GetItemByRow(sel);
+
+ // Edit the current column. If no column is focused
+ // (typically because the user has full row selected), try
+ // to find the first editable column.
+ wxDataViewColumn *editableCol = FindColumnForEditing(item, wxDATAVIEW_CELL_EDITABLE);
+
+ if ( editableCol )
+ GetOwner()->EditItem(item, editableCol);
+ }
+ }
+ break;
+
+ case WXK_UP:
+ OnVerticalNavigation( -1, event );
+ break;
+
+ case WXK_DOWN:
+ OnVerticalNavigation( +1, event );
+ break;
+ // Add the process for tree expanding/collapsing
+ case WXK_LEFT:
+ OnLeftKey();
+ break;
+
+ case WXK_RIGHT:
+ OnRightKey();
+ break;
+
+ case WXK_END:
+ OnVerticalNavigation( +(int)GetRowCount(), event );
+ break;
+
+ case WXK_HOME:
+ OnVerticalNavigation( -(int)GetRowCount(), event );
+ break;
+
+ case WXK_PAGEUP:
+ OnVerticalNavigation( -(pageSize - 1), event );
+ break;
+
+ case WXK_PAGEDOWN:
+ OnVerticalNavigation( +(pageSize - 1), event );
+ break;
+
+ default:
+ event.Skip();
+ }
+}
+
+void wxDataViewMainWindow::OnVerticalNavigation(int delta, const wxKeyEvent& event)
+{
+ // if there is no selection, we cannot move it anywhere
+ if (!HasCurrentRow() || IsEmpty())
+ return;
+
+ int newRow = (int)m_currentRow + delta;
+
+ // let's keep the new row inside the allowed range
+ if ( newRow < 0 )
+ newRow = 0;
+
+ const int rowCount = (int)GetRowCount();
+ if ( newRow >= rowCount )
+ newRow = rowCount - 1;
+
+ unsigned int oldCurrent = m_currentRow;
+ unsigned int newCurrent = (unsigned int)newRow;
+
+ // in single selection we just ignore Shift as we can't select several
+ // items anyhow
+ if ( event.ShiftDown() && !IsSingleSel() )
+ {
+ RefreshRow( oldCurrent );
+
+ ChangeCurrentRow( newCurrent );
+
+ // select all the items between the old and the new one
+ if ( oldCurrent > newCurrent )
+ {
+ newCurrent = oldCurrent;
+ oldCurrent = m_currentRow;
+ }
+
+ SelectRows( oldCurrent, newCurrent, true );
+ if (oldCurrent!=newCurrent)
+ SendSelectionChangedEvent(GetItemByRow(m_selection[0]));
+ }
+ else // !shift
+ {
+ RefreshRow( oldCurrent );
+
+ // all previously selected items are unselected unless ctrl is held
+ if ( !event.ControlDown() )
+ SelectAllRows(false);
+
+ ChangeCurrentRow( newCurrent );
+
+ if ( !event.ControlDown() )
+ {
+ SelectRow( m_currentRow, true );
+ SendSelectionChangedEvent(GetItemByRow(m_currentRow));
+ }
+ else
+ RefreshRow( m_currentRow );