WX_DEFINE_OBJARRAY(wxGridCellCoordsArray)
WX_DEFINE_OBJARRAY(wxGridCellWithAttrArray)
+// ----------------------------------------------------------------------------
+// events
+// ----------------------------------------------------------------------------
+
+DEFINE_EVENT_TYPE(wxEVT_GRID_CELL_LEFT_CLICK)
+DEFINE_EVENT_TYPE(wxEVT_GRID_CELL_RIGHT_CLICK)
+DEFINE_EVENT_TYPE(wxEVT_GRID_CELL_LEFT_DCLICK)
+DEFINE_EVENT_TYPE(wxEVT_GRID_CELL_RIGHT_DCLICK)
+DEFINE_EVENT_TYPE(wxEVT_GRID_LABEL_LEFT_CLICK)
+DEFINE_EVENT_TYPE(wxEVT_GRID_LABEL_RIGHT_CLICK)
+DEFINE_EVENT_TYPE(wxEVT_GRID_LABEL_LEFT_DCLICK)
+DEFINE_EVENT_TYPE(wxEVT_GRID_LABEL_RIGHT_DCLICK)
+DEFINE_EVENT_TYPE(wxEVT_GRID_ROW_SIZE)
+DEFINE_EVENT_TYPE(wxEVT_GRID_COL_SIZE)
+DEFINE_EVENT_TYPE(wxEVT_GRID_RANGE_SELECT)
+DEFINE_EVENT_TYPE(wxEVT_GRID_CELL_CHANGE)
+DEFINE_EVENT_TYPE(wxEVT_GRID_SELECT_CELL)
+DEFINE_EVENT_TYPE(wxEVT_GRID_EDITOR_SHOWN)
+DEFINE_EVENT_TYPE(wxEVT_GRID_EDITOR_HIDDEN)
+
// ----------------------------------------------------------------------------
// private classes
// ----------------------------------------------------------------------------
void OnPaint( wxPaintEvent& event );
void OnMouseEvent( wxMouseEvent& event );
+ void OnMouseWheel( wxMouseEvent& event );
void OnKeyDown( wxKeyEvent& event );
void OnKeyUp( wxKeyEvent& );
void OnPaint( wxPaintEvent &event );
void OnMouseEvent( wxMouseEvent& event );
+ void OnMouseWheel( wxMouseEvent& event );
void OnKeyDown( wxKeyEvent& event );
void OnKeyUp( wxKeyEvent& );
wxGrid *m_owner;
void OnMouseEvent( wxMouseEvent& event );
+ void OnMouseWheel( wxMouseEvent& event );
void OnKeyDown( wxKeyEvent& event );
void OnKeyUp( wxKeyEvent& );
void OnPaint( wxPaintEvent& event );
wxGridColLabelWindow *m_colLabelWin;
void OnPaint( wxPaintEvent &event );
+ void OnMouseWheel( wxMouseEvent& event );
void OnMouseEvent( wxMouseEvent& event );
void OnKeyDown( wxKeyEvent& );
void OnKeyUp( wxKeyEvent& );
wxRect wxGridNoCellRect( -1, -1, -1, -1 );
// scroll line size
-// TODO: fixed so far - make configurable later (and also different for x/y)
-static const size_t GRID_SCROLL_LINE = 10;
+// TODO: this doesn't work at all, grid cells have different sizes and approx
+// calculations don't work as because of the size mismatch scrollbars
+// sometimes fail to be shown when they should be or vice versa
+//
+// The scroll bars may be a little flakey once in a while, but that is
+// surely much less horrible than having scroll lines of only 1!!!
+// -- Robin
+static const size_t GRID_SCROLL_LINE = 15; // 1;
+
// the size of hash tables used a bit everywhere (the max number of elements
// in these hash tables is the number of rows/columns)
bool wxGridCellEditor::IsAcceptedKey(wxKeyEvent& event)
{
// accept the simple key presses, not anything with Ctrl/Alt/Meta
- return !event.HasModifiers();
+ return !(event.ControlDown() || event.AltDown());
}
void wxGridCellEditor::StartingKey(wxKeyEvent& event)
m_control = new wxTextCtrl(parent, id, wxEmptyString,
wxDefaultPosition, wxDefaultSize
#if defined(__WXMSW__)
- , wxTE_MULTILINE | wxTE_NO_VSCROLL | wxTE_AUTO_SCROLL
+ , wxTE_PROCESS_TAB | wxTE_MULTILINE |
+ wxTE_NO_VSCROLL | wxTE_AUTO_SCROLL
#endif
);
}
#else // !GTK
int extra_x = ( rect.x > 2 )? 2 : 1;
-
-// MB: treat MSW separately here otherwise the caret doesn't show
-// when the editor is in the first row.
+
+// MB: treat MSW separately here otherwise the caret doesn't show
+// when the editor is in the first row.
#if defined(__WXMSW__)
int extra_y = 2;
#else
if (grid->GetTable()->CanGetValueAs(row, col, wxGRID_VALUE_BOOL))
m_startValue = grid->GetTable()->GetValueAsBool(row, col);
else
- m_startValue = !!grid->GetTable()->GetValue(row, col);
+ {
+ wxString cellval( grid->GetTable()->GetValue(row, col) );
+ m_startValue = !( !cellval || (cellval == "0") );
+ }
CBox()->SetValue(m_startValue);
CBox()->SetFocus();
}
break;
case WXK_TAB:
- event.Skip( m_grid->ProcessEvent( event ) );
+ m_grid->GetEventHandler()->ProcessEvent( event );
break;
case WXK_RETURN:
- if (!m_grid->ProcessEvent(event))
+ case WXK_NUMPAD_ENTER:
+ if (!m_grid->GetEventHandler()->ProcessEvent(event))
m_editor->HandleReturn(event);
break;
case WXK_ESCAPE:
case WXK_TAB:
case WXK_RETURN:
+ case WXK_NUMPAD_ENTER:
break;
default:
if ( grid.GetTable()->CanGetValueAs(row, col, wxGRID_VALUE_BOOL) )
value = grid.GetTable()->GetValueAsBool(row, col);
else
- value = !!grid.GetTable()->GetValue(row, col);
+ {
+ wxString cellval( grid.GetTable()->GetValue(row, col) );
+ value = !( !cellval || (cellval == "0") );
+ }
if ( value )
{
wxGridCellRenderer* wxGridTypeRegistry::GetRenderer(int index)
{
wxGridCellRenderer* renderer = m_typeinfo[index]->m_renderer;
- renderer->IncRef();
+ if (renderer)
+ renderer->IncRef();
return renderer;
}
wxGridCellEditor* wxGridTypeRegistry::GetEditor(int index)
{
wxGridCellEditor* editor = m_typeinfo[index]->m_editor;
- editor->IncRef();
+ if (editor)
+ editor->IncRef();
return editor;
}
BEGIN_EVENT_TABLE( wxGridRowLabelWindow, wxWindow )
EVT_PAINT( wxGridRowLabelWindow::OnPaint )
+ EVT_MOUSEWHEEL( wxGridRowLabelWindow::OnMouseWheel)
EVT_MOUSE_EVENTS( wxGridRowLabelWindow::OnMouseEvent )
EVT_KEY_DOWN( wxGridRowLabelWindow::OnKeyDown )
EVT_KEY_UP( wxGridRowLabelWindow::OnKeyUp )
}
+void wxGridRowLabelWindow::OnMouseWheel( wxMouseEvent& event )
+{
+ m_owner->GetEventHandler()->ProcessEvent(event);
+}
+
+
// This seems to be required for wxMotif otherwise the mouse
// cursor must be in the cell edit control to get key events
//
void wxGridRowLabelWindow::OnKeyDown( wxKeyEvent& event )
{
- if ( !m_owner->ProcessEvent( event ) ) event.Skip();
+ if ( !m_owner->GetEventHandler()->ProcessEvent( event ) ) event.Skip();
}
void wxGridRowLabelWindow::OnKeyUp( wxKeyEvent& event )
{
- if ( !m_owner->ProcessEvent( event ) ) event.Skip();
+ if ( !m_owner->GetEventHandler()->ProcessEvent( event ) ) event.Skip();
}
BEGIN_EVENT_TABLE( wxGridColLabelWindow, wxWindow )
EVT_PAINT( wxGridColLabelWindow::OnPaint )
+ EVT_MOUSEWHEEL( wxGridColLabelWindow::OnMouseWheel)
EVT_MOUSE_EVENTS( wxGridColLabelWindow::OnMouseEvent )
EVT_KEY_DOWN( wxGridColLabelWindow::OnKeyDown )
EVT_KEY_UP( wxGridColLabelWindow::OnKeyUp )
m_owner->ProcessColLabelMouseEvent( event );
}
+void wxGridColLabelWindow::OnMouseWheel( wxMouseEvent& event )
+{
+ m_owner->GetEventHandler()->ProcessEvent(event);
+}
+
// This seems to be required for wxMotif otherwise the mouse
// cursor must be in the cell edit control to get key events
//
void wxGridColLabelWindow::OnKeyDown( wxKeyEvent& event )
{
- if ( !m_owner->ProcessEvent( event ) ) event.Skip();
+ if ( !m_owner->GetEventHandler()->ProcessEvent( event ) ) event.Skip();
}
void wxGridColLabelWindow::OnKeyUp( wxKeyEvent& event )
{
- if ( !m_owner->ProcessEvent( event ) ) event.Skip();
+ if ( !m_owner->GetEventHandler()->ProcessEvent( event ) ) event.Skip();
}
IMPLEMENT_DYNAMIC_CLASS( wxGridCornerLabelWindow, wxWindow )
BEGIN_EVENT_TABLE( wxGridCornerLabelWindow, wxWindow )
+ EVT_MOUSEWHEEL( wxGridCornerLabelWindow::OnMouseWheel)
EVT_MOUSE_EVENTS( wxGridCornerLabelWindow::OnMouseEvent )
EVT_PAINT( wxGridCornerLabelWindow::OnPaint)
EVT_KEY_DOWN( wxGridCornerLabelWindow::OnKeyDown )
}
+void wxGridCornerLabelWindow::OnMouseWheel( wxMouseEvent& event )
+{
+ m_owner->GetEventHandler()->ProcessEvent(event);
+}
+
// This seems to be required for wxMotif otherwise the mouse
// cursor must be in the cell edit control to get key events
//
void wxGridCornerLabelWindow::OnKeyDown( wxKeyEvent& event )
{
- if ( !m_owner->ProcessEvent( event ) ) event.Skip();
+ if ( !m_owner->GetEventHandler()->ProcessEvent( event ) ) event.Skip();
}
void wxGridCornerLabelWindow::OnKeyUp( wxKeyEvent& event )
{
- if ( !m_owner->ProcessEvent( event ) ) event.Skip();
+ if ( !m_owner->GetEventHandler()->ProcessEvent( event ) ) event.Skip();
}
BEGIN_EVENT_TABLE( wxGridWindow, wxPanel )
EVT_PAINT( wxGridWindow::OnPaint )
+ EVT_MOUSEWHEEL( wxGridWindow::OnMouseWheel)
EVT_MOUSE_EVENTS( wxGridWindow::OnMouseEvent )
EVT_KEY_DOWN( wxGridWindow::OnKeyDown )
EVT_KEY_UP( wxGridWindow::OnKeyUp )
m_owner->ProcessGridCellMouseEvent( event );
}
+void wxGridWindow::OnMouseWheel( wxMouseEvent& event )
+{
+ m_owner->GetEventHandler()->ProcessEvent(event);
+}
// This seems to be required for wxMotif/wxGTK otherwise the mouse
// cursor must be in the cell edit control to get key events
//
void wxGridWindow::OnKeyDown( wxKeyEvent& event )
{
- if ( !m_owner->ProcessEvent( event ) ) event.Skip();
+ if ( !m_owner->GetEventHandler()->ProcessEvent( event ) ) event.Skip();
}
void wxGridWindow::OnKeyUp( wxKeyEvent& event )
{
- if ( !m_owner->ProcessEvent( event ) ) event.Skip();
+ if ( !m_owner->GetEventHandler()->ProcessEvent( event ) ) event.Skip();
}
void wxGridWindow::OnEraseBackground( wxEraseEvent& WXUNUSED(event) )
int cw, ch;
GetClientSize( &cw, &ch );
- if ( m_numRows > 0 || m_numCols > 0 )
- {
- int right = m_numCols > 0 ? GetColRight( m_numCols-1 ) + m_extraWidth : 0;
- int bottom = m_numRows > 0 ? GetRowBottom( m_numRows-1 ) + m_extraHeight : 0;
+ if ( m_colLabelWin->IsShown() )
+ cw -= m_rowLabelWidth;
+ if ( m_rowLabelWin->IsShown() )
+ ch -= m_colLabelHeight;
- // TODO: restore the scroll position that we had before sizing
- //
- int x, y;
- GetViewStart( &x, &y );
- SetScrollbars( GRID_SCROLL_LINE, GRID_SCROLL_LINE,
- right/GRID_SCROLL_LINE, bottom/GRID_SCROLL_LINE,
- x, y );
+ // grid total size
+ int w = m_numCols > 0 ? GetColRight(m_numCols - 1) + m_extraWidth + 1 : 0;
+ int h = m_numRows > 0 ? GetRowBottom(m_numRows - 1) + m_extraHeight + 1 : 0;
+
+ // preserve (more or less) the previous position
+ int x, y;
+ GetViewStart( &x, &y );
+ // maybe we don't need scrollbars at all? and if we do, transform w and h
+ // from pixels into logical units
+ if ( w <= cw )
+ {
+ w = 0; x= 0;
+ }
+ else
+ {
+ w = (w + GRID_SCROLL_LINE - 1)/GRID_SCROLL_LINE;
+ if ( x >= w )
+ x = w - 1;
}
+ if ( h <= ch )
+ {
+ h = 0; y = 0;
+ }
+ else
+ {
+ h = (h + GRID_SCROLL_LINE - 1)/GRID_SCROLL_LINE;
+ if ( y >= h )
+ y = h - 1;
+ }
+
+ // do set scrollbar parameters
+ SetScrollbars( GRID_SCROLL_LINE, GRID_SCROLL_LINE,
+ w, h, x, y, (GetBatchCount() != 0));
}
attrProvider->UpdateAttrRows( pos, -((int)numRows) );
// ifdef'd out following patch from Paul Gammans
#if 0
+ // No need to touch column attributes, unless we
// removed _all_ rows, in this case, we remove
// all column attributes.
// I hate to do this here, but the
// needed data is not available inside UpdateAttrRows.
if ( !GetNumberRows() )
attrProvider->UpdateAttrCols( 0, -GetNumberCols() );
-#endif
+#endif
}
if ( !GetBatchCount() )
{
wxGridCellAttrProvider * attrProvider = m_table->GetAttrProvider();
if (attrProvider) {
attrProvider->UpdateAttrCols( pos, -((int)numCols) );
-// ifdef'd out following patch from Paul Gammans
+// ifdef'd out following patch from Paul Gammans
#if 0
// No need to touch row attributes, unless we
// removed _all_ columns, in this case, we remove
// needed data is not available inside UpdateAttrCols.
if ( !GetNumberCols() )
attrProvider->UpdateAttrRows( 0, -GetNumberRows() );
-#endif
+#endif
}
if ( !GetBatchCount() )
{
CalcDimensions();
m_colLabelWin->Refresh();
}
- return TRUE;
}
-#if 0
-// There is no path to this code !!!!!!
- result = TRUE;
+ result = TRUE;
break;
-#endif
}
if (result && !GetBatchCount() )
cursorModes[m_cursorMode], cursorModes[mode]);
#endif // __WXDEBUG__
- if ( mode == m_cursorMode )
+ if ( mode == m_cursorMode &&
+ win == m_winCapture &&
+ captureMouse == (m_winCapture != NULL))
return;
if ( !win )
type,
this,
rowOrCol,
- mouseEv.GetX() + GetColLabelSize(),
- mouseEv.GetY() + GetRowLabelSize(),
+ mouseEv.GetX() + GetRowLabelSize(),
+ mouseEv.GetY() + GetColLabelSize(),
mouseEv.ControlDown(),
mouseEv.ShiftDown(),
mouseEv.AltDown(),
mouseEv.MetaDown() );
-
return GetEventHandler()->ProcessEvent(gridEvt);
}
else if ( type == wxEVT_GRID_RANGE_SELECT )
type,
this,
row, col,
- mouseEv.GetX() + GetColLabelSize(),
- mouseEv.GetY() + GetRowLabelSize(),
+ mouseEv.GetX() + GetRowLabelSize(),
+ mouseEv.GetY() + GetColLabelSize(),
FALSE,
mouseEv.ControlDown(),
mouseEv.ShiftDown(),
mouseEv.AltDown(),
mouseEv.MetaDown() );
-
return GetEventHandler()->ProcessEvent(gridEvt);
}
}
break;
case WXK_RETURN:
+ case WXK_NUMPAD_ENTER:
if ( event.ControlDown() )
{
event.Skip(); // to let the edit control have the return
HideCellEditControl();
DisableCellEditControl();
- if ( IsVisible( m_currentCellCoords, FALSE ) ) // zzz
+ if ( IsVisible( m_currentCellCoords, FALSE ) )
{
wxRect r;
r = BlockToDeviceRect(m_currentCellCoords, m_currentCellCoords);
}
CalcCellsExposed( r );
-
+
// Otherwise refresh redraws the highlight!
m_currentCellCoords = coords;
// (old comment from when this was the body of SelectBlock)
}
-
//
// ------ functions to get/send data (see also public functions)
//
// This is used to redraw all grid lines e.g. when the grid line colour
// has been changed
//
-void wxGrid::DrawAllGridLines( wxDC& dc, const wxRegion & WXUNUSED_GTK(reg) )
+void wxGrid::DrawAllGridLines( wxDC& dc, const wxRegion & WXUNUSED(reg) )
{
if ( !m_gridLinesEnabled ||
!m_numRows ||
{
if ( !IsVisible( m_currentCellCoords ) )
{
- m_cellEditCtrlEnabled = false;
+ m_cellEditCtrlEnabled = FALSE;
return;
}
else
case wxRIGHT: horiz = wxALIGN_RIGHT; break;
case wxCENTRE: horiz = wxALIGN_CENTRE; break;
}
-
+
switch ( vert )
{
case wxTOP: vert = wxALIGN_TOP; break;
case wxBOTTOM: vert = wxALIGN_BOTTOM; break;
case wxCENTRE: vert = wxALIGN_CENTRE; break;
}
-
+
if ( horiz == wxALIGN_LEFT || horiz == wxALIGN_CENTRE || horiz == wxALIGN_RIGHT )
{
m_rowLabelHorizAlign = horiz;
case wxRIGHT: horiz = wxALIGN_RIGHT; break;
case wxCENTRE: horiz = wxALIGN_CENTRE; break;
}
-
+
switch ( vert )
{
case wxTOP: vert = wxALIGN_TOP; break;
case wxBOTTOM: vert = wxALIGN_BOTTOM; break;
case wxCENTRE: vert = wxALIGN_CENTRE; break;
}
-
+
if ( horiz == wxALIGN_LEFT || horiz == wxALIGN_CENTRE || horiz == wxALIGN_RIGHT )
{
m_colLabelHorizAlign = horiz;
if ( rect.height > 0 )
{
CalcScrolledPosition(0, rect.y, &rect.x, &rect.y);
- rect.x = m_left;
+ rect.x = 0;
rect.width = m_rowLabelWidth;
m_rowLabelWin->Refresh( TRUE, &rect );
}
if ( rect.width > 0 )
{
CalcScrolledPosition(rect.x, 0, &rect.x, &rect.y);
- rect.y = m_top;
+ rect.y = 0;
rect.height = m_colLabelHeight;
m_colLabelWin->Refresh( TRUE, &rect );
}
if ( resizeExistingRows )
{
InitRowHeights();
-
- CalcDimensions();
+ if ( !GetBatchCount() )
+ CalcDimensions();
}
}
{
m_rowBottoms[i] += diff;
}
- CalcDimensions();
+ if ( !GetBatchCount() )
+ CalcDimensions();
}
void wxGrid::SetDefaultColSize( int width, bool resizeExistingCols )
if ( resizeExistingCols )
{
InitColWidths();
-
- CalcDimensions();
+ if ( !GetBatchCount() )
+ CalcDimensions();
}
}
{
m_colRights[i] += diff;
}
- CalcDimensions();
+ if ( !GetBatchCount() )
+ CalcDimensions();
}
if ( column )
dc.GetTextExtent( GetColLabelValue(col), &w, &h );
else
- dc.GetTextExtent( GetRowLabelValue(col), &w, &h );
+ dc.GetTextExtent( GetRowLabelValue(row), &w, &h );
extent = column ? w : h;
if ( extent > extentMax )
}
}
- if ( column )
+ if ( column ){
SetColSize(col, extentMax);
- else
+ if ( !GetBatchCount() )
+ {
+ int cw, ch, dummy;
+ m_gridWin->GetClientSize( &cw, &ch );
+ wxRect rect ( CellToRect( 0, col ) );
+ rect.y = 0;
+ CalcScrolledPosition(rect.x, 0, &rect.x, &dummy);
+ rect.width = cw - rect.x;
+ rect.height = m_colLabelHeight;
+ m_colLabelWin->Refresh( TRUE, &rect );
+ }
+ }
+ else{
SetRowSize(row, extentMax);
-
+ if ( !GetBatchCount() )
+ {
+ int cw, ch, dummy;
+ m_gridWin->GetClientSize( &cw, &ch );
+ wxRect rect ( CellToRect( row, 0 ) );
+ rect.x = 0;
+ CalcScrolledPosition(0, rect.y, &dummy, &rect.y);
+ rect.width = m_rowLabelWidth;
+ rect.height = ch - rect.y;
+ m_rowLabelWin->Refresh( TRUE, &rect );
+ }
+ }
if ( setAsMin )
{
if ( column )
{
int width = m_rowLabelWidth;
+ if ( !calcOnly )
+ BeginBatch();
for ( int col = 0; col < m_numCols; col++ )
{
if ( !calcOnly )
width += GetColWidth(col);
}
-
+ if ( !calcOnly )
+ EndBatch();
return width;
}
{
int height = m_colLabelHeight;
+ if ( !calcOnly )
+ BeginBatch();
for ( int row = 0; row < m_numRows; row++ )
{
if ( !calcOnly )
height += GetRowHeight(row);
}
-
+ if ( !calcOnly )
+ EndBatch();
return height;
}
void wxGrid::AutoSize()
{
// set the size too
- SetSize(SetOrCalcColumnSizes(FALSE), SetOrCalcRowSizes(FALSE));
+ SetClientSize(SetOrCalcColumnSizes(FALSE), SetOrCalcRowSizes(FALSE));
}
wxSize wxGrid::DoGetBestSize() const
}
-void wxGrid::SelectBlock( int topRow, int leftCol, int bottomRow, int rightCol,
+void wxGrid::SelectBlock( int topRow, int leftCol, int bottomRow, int rightCol,
bool addToSelected )
{
if ( IsSelection() && !addToSelected )
ClearSelection();
- m_selection->SelectBlock( topRow, leftCol, bottomRow, rightCol,
- FALSE, addToSelected );
+ m_selection->SelectBlock( topRow, leftCol, bottomRow, rightCol,
+ FALSE, addToSelected );
}
void wxGrid::SelectAll()
{
- m_selection->SelectBlock( 0, 0, m_numRows-1, m_numCols-1 );
+ if ( m_numRows > 0 && m_numCols > 0 )
+ m_selection->SelectBlock( 0, 0, m_numRows-1, m_numCols-1 );
+}
+
+//
+// ------ Cell, row and col deselection
+//
+
+void wxGrid::DeselectRow( int row )
+{
+ if ( m_selection->GetSelectionMode() == wxGrid::wxGridSelectRows )
+ {
+ if ( m_selection->IsInSelection(row, 0 ) )
+ m_selection->ToggleCellSelection( row, 0);
+ }
+ else
+ {
+ int nCols = GetNumberCols();
+ for ( int i = 0; i < nCols ; i++ )
+ {
+ if ( m_selection->IsInSelection(row, i ) )
+ m_selection->ToggleCellSelection( row, i);
+ }
+ }
+}
+
+void wxGrid::DeselectCol( int col )
+{
+ if ( m_selection->GetSelectionMode() == wxGrid::wxGridSelectColumns )
+ {
+ if ( m_selection->IsInSelection(0, col ) )
+ m_selection->ToggleCellSelection( 0, col);
+ }
+ else
+ {
+ int nRows = GetNumberRows();
+ for ( int i = 0; i < nRows ; i++ )
+ {
+ if ( m_selection->IsInSelection(i, col ) )
+ m_selection->ToggleCellSelection(i, col);
+ }
+ }
+}
+
+void wxGrid::DeselectCell( int row, int col )
+{
+ if ( m_selection->IsInSelection(row, col) )
+ m_selection->ToggleCellSelection(row, col);
}
bool wxGrid::IsSelection()