1 /////////////////////////////////////////////////////////////////////////// 
   2 // Name:        generic/grid.cpp 
   3 // Purpose:     wxGrid and related classes 
   4 // Author:      Michael Bedward (based on code by Julian Smart, Robin Dunn) 
   8 // Copyright:   (c) Michael Bedward (mbedward@ozemail.com.au) 
   9 // Licence:     wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////////// 
  12 // ============================================================================ 
  14 // ============================================================================ 
  16 // ---------------------------------------------------------------------------- 
  18 // ---------------------------------------------------------------------------- 
  21     #pragma implementation "grid.h" 
  24 // For compilers that support precompilatixon, includes "wx/wx.h". 
  25 #include "wx/wxprec.h" 
  35 #if !defined(wxUSE_NEW_GRID) || !(wxUSE_NEW_GRID) 
  37 #else // wxUSE_NEW_GRID 
  41     #include "wx/dcclient.h" 
  42     #include "wx/settings.h" 
  44     #include "wx/textctrl.h" 
  45     #include "wx/checkbox.h" 
  46     #include "wx/combobox.h" 
  47     #include "wx/valtext.h" 
  50 #include "wx/textfile.h" 
  51 #include "wx/spinctrl.h" 
  52 #include "wx/tokenzr.h" 
  55 #include "wx/generic/gridsel.h" 
  57 #if defined(__WXMOTIF__) 
  58     #define WXUNUSED_MOTIF(identifier)  WXUNUSED(identifier) 
  60     #define WXUNUSED_MOTIF(identifier)  identifier 
  63 #if defined(__WXGTK__) 
  64     #define WXUNUSED_GTK(identifier)    WXUNUSED(identifier) 
  66     #define WXUNUSED_GTK(identifier)    identifier 
  69 // Required for wxIs... functions 
  72 // ---------------------------------------------------------------------------- 
  74 // ---------------------------------------------------------------------------- 
  76 WX_DEFINE_EXPORTED_ARRAY(wxGridCellAttr 
*, wxArrayAttrs
); 
  78 struct wxGridCellWithAttr
 
  80     wxGridCellWithAttr(int row
, int col
, wxGridCellAttr 
*attr_
) 
  81         : coords(row
, col
), attr(attr_
) 
  90     wxGridCellCoords coords
; 
  94 WX_DECLARE_EXPORTED_OBJARRAY(wxGridCellWithAttr
, wxGridCellWithAttrArray
); 
  96 #include "wx/arrimpl.cpp" 
  98 WX_DEFINE_OBJARRAY(wxGridCellCoordsArray
) 
  99 WX_DEFINE_OBJARRAY(wxGridCellWithAttrArray
) 
 101 // ---------------------------------------------------------------------------- 
 103 // ---------------------------------------------------------------------------- 
 105 DEFINE_EVENT_TYPE(wxEVT_GRID_CELL_LEFT_CLICK
) 
 106 DEFINE_EVENT_TYPE(wxEVT_GRID_CELL_RIGHT_CLICK
) 
 107 DEFINE_EVENT_TYPE(wxEVT_GRID_CELL_LEFT_DCLICK
) 
 108 DEFINE_EVENT_TYPE(wxEVT_GRID_CELL_RIGHT_DCLICK
) 
 109 DEFINE_EVENT_TYPE(wxEVT_GRID_LABEL_LEFT_CLICK
) 
 110 DEFINE_EVENT_TYPE(wxEVT_GRID_LABEL_RIGHT_CLICK
) 
 111 DEFINE_EVENT_TYPE(wxEVT_GRID_LABEL_LEFT_DCLICK
) 
 112 DEFINE_EVENT_TYPE(wxEVT_GRID_LABEL_RIGHT_DCLICK
) 
 113 DEFINE_EVENT_TYPE(wxEVT_GRID_ROW_SIZE
) 
 114 DEFINE_EVENT_TYPE(wxEVT_GRID_COL_SIZE
) 
 115 DEFINE_EVENT_TYPE(wxEVT_GRID_RANGE_SELECT
) 
 116 DEFINE_EVENT_TYPE(wxEVT_GRID_CELL_CHANGE
) 
 117 DEFINE_EVENT_TYPE(wxEVT_GRID_SELECT_CELL
) 
 118 DEFINE_EVENT_TYPE(wxEVT_GRID_EDITOR_SHOWN
) 
 119 DEFINE_EVENT_TYPE(wxEVT_GRID_EDITOR_HIDDEN
) 
 120 DEFINE_EVENT_TYPE(wxEVT_GRID_EDITOR_CREATED
) 
 122 // ---------------------------------------------------------------------------- 
 124 // ---------------------------------------------------------------------------- 
 126 class WXDLLEXPORT wxGridRowLabelWindow 
: public wxWindow
 
 129     wxGridRowLabelWindow() { m_owner 
= (wxGrid 
*)NULL
; } 
 130     wxGridRowLabelWindow( wxGrid 
*parent
, wxWindowID id
, 
 131                           const wxPoint 
&pos
, const wxSize 
&size 
); 
 136     void OnPaint( wxPaintEvent
& event 
); 
 137     void OnMouseEvent( wxMouseEvent
& event 
); 
 138     void OnMouseWheel( wxMouseEvent
& event 
); 
 139     void OnKeyDown( wxKeyEvent
& event 
); 
 140     void OnKeyUp( wxKeyEvent
& ); 
 142     DECLARE_DYNAMIC_CLASS(wxGridRowLabelWindow
) 
 143     DECLARE_EVENT_TABLE() 
 147 class WXDLLEXPORT wxGridColLabelWindow 
: public wxWindow
 
 150     wxGridColLabelWindow() { m_owner 
= (wxGrid 
*)NULL
; } 
 151     wxGridColLabelWindow( wxGrid 
*parent
, wxWindowID id
, 
 152                           const wxPoint 
&pos
, const wxSize 
&size 
); 
 157     void OnPaint( wxPaintEvent 
&event 
); 
 158     void OnMouseEvent( wxMouseEvent
& event 
); 
 159     void OnMouseWheel( wxMouseEvent
& event 
); 
 160     void OnKeyDown( wxKeyEvent
& event 
); 
 161     void OnKeyUp( wxKeyEvent
& ); 
 163     DECLARE_DYNAMIC_CLASS(wxGridColLabelWindow
) 
 164     DECLARE_EVENT_TABLE() 
 168 class WXDLLEXPORT wxGridCornerLabelWindow 
: public wxWindow
 
 171     wxGridCornerLabelWindow() { m_owner 
= (wxGrid 
*)NULL
; } 
 172     wxGridCornerLabelWindow( wxGrid 
*parent
, wxWindowID id
, 
 173                              const wxPoint 
&pos
, const wxSize 
&size 
); 
 178     void OnMouseEvent( wxMouseEvent
& event 
); 
 179     void OnMouseWheel( wxMouseEvent
& event 
); 
 180     void OnKeyDown( wxKeyEvent
& event 
); 
 181     void OnKeyUp( wxKeyEvent
& ); 
 182     void OnPaint( wxPaintEvent
& event 
); 
 184     DECLARE_DYNAMIC_CLASS(wxGridCornerLabelWindow
) 
 185     DECLARE_EVENT_TABLE() 
 188 class WXDLLEXPORT wxGridWindow 
: public wxPanel
 
 193         m_owner 
= (wxGrid 
*)NULL
; 
 194         m_rowLabelWin 
= (wxGridRowLabelWindow 
*)NULL
; 
 195         m_colLabelWin 
= (wxGridColLabelWindow 
*)NULL
; 
 198     wxGridWindow( wxGrid 
*parent
, 
 199                   wxGridRowLabelWindow 
*rowLblWin
, 
 200                   wxGridColLabelWindow 
*colLblWin
, 
 201                   wxWindowID id
, const wxPoint 
&pos
, const wxSize 
&size 
); 
 204     void ScrollWindow( int dx
, int dy
, const wxRect 
*rect 
); 
 208     wxGridRowLabelWindow     
*m_rowLabelWin
; 
 209     wxGridColLabelWindow     
*m_colLabelWin
; 
 211     void OnPaint( wxPaintEvent 
&event 
); 
 212     void OnMouseWheel( wxMouseEvent
& event 
); 
 213     void OnMouseEvent( wxMouseEvent
& event 
); 
 214     void OnKeyDown( wxKeyEvent
& ); 
 215     void OnKeyUp( wxKeyEvent
& ); 
 216     void OnEraseBackground( wxEraseEvent
& ); 
 219     DECLARE_DYNAMIC_CLASS(wxGridWindow
) 
 220     DECLARE_EVENT_TABLE() 
 225 class wxGridCellEditorEvtHandler 
: public wxEvtHandler
 
 228     wxGridCellEditorEvtHandler() 
 229         : m_grid(0), m_editor(0) 
 231     wxGridCellEditorEvtHandler(wxGrid
* grid
, wxGridCellEditor
* editor
) 
 232         : m_grid(grid
), m_editor(editor
) 
 235     void OnKeyDown(wxKeyEvent
& event
); 
 236     void OnChar(wxKeyEvent
& event
); 
 240     wxGridCellEditor
*   m_editor
; 
 241     DECLARE_DYNAMIC_CLASS(wxGridCellEditorEvtHandler
) 
 242     DECLARE_EVENT_TABLE() 
 246 IMPLEMENT_DYNAMIC_CLASS( wxGridCellEditorEvtHandler
, wxEvtHandler 
) 
 247 BEGIN_EVENT_TABLE( wxGridCellEditorEvtHandler
, wxEvtHandler 
) 
 248     EVT_KEY_DOWN( wxGridCellEditorEvtHandler::OnKeyDown 
) 
 249     EVT_CHAR( wxGridCellEditorEvtHandler::OnChar 
) 
 254 // ---------------------------------------------------------------------------- 
 255 // the internal data representation used by wxGridCellAttrProvider 
 256 // ---------------------------------------------------------------------------- 
 258 // this class stores attributes set for cells 
 259 class WXDLLEXPORT wxGridCellAttrData
 
 262     void SetAttr(wxGridCellAttr 
*attr
, int row
, int col
); 
 263     wxGridCellAttr 
*GetAttr(int row
, int col
) const; 
 264     void UpdateAttrRows( size_t pos
, int numRows 
); 
 265     void UpdateAttrCols( size_t pos
, int numCols 
); 
 268     // searches for the attr for given cell, returns wxNOT_FOUND if not found 
 269     int FindIndex(int row
, int col
) const; 
 271     wxGridCellWithAttrArray m_attrs
; 
 274 // this class stores attributes set for rows or columns 
 275 class WXDLLEXPORT wxGridRowOrColAttrData
 
 278     // empty ctor to suppress warnings 
 279     wxGridRowOrColAttrData() { } 
 280     ~wxGridRowOrColAttrData(); 
 282     void SetAttr(wxGridCellAttr 
*attr
, int rowOrCol
); 
 283     wxGridCellAttr 
*GetAttr(int rowOrCol
) const; 
 284     void UpdateAttrRowsOrCols( size_t pos
, int numRowsOrCols 
); 
 287     wxArrayInt m_rowsOrCols
; 
 288     wxArrayAttrs m_attrs
; 
 291 // NB: this is just a wrapper around 3 objects: one which stores cell 
 292 //     attributes, and 2 others for row/col ones 
 293 class WXDLLEXPORT wxGridCellAttrProviderData
 
 296     wxGridCellAttrData m_cellAttrs
; 
 297     wxGridRowOrColAttrData m_rowAttrs
, 
 302 // ---------------------------------------------------------------------------- 
 303 // data structures used for the data type registry 
 304 // ---------------------------------------------------------------------------- 
 306 struct wxGridDataTypeInfo
 
 308     wxGridDataTypeInfo(const wxString
& typeName
, 
 309                        wxGridCellRenderer
* renderer
, 
 310                        wxGridCellEditor
* editor
) 
 311         : m_typeName(typeName
), m_renderer(renderer
), m_editor(editor
) 
 314     ~wxGridDataTypeInfo() 
 316         wxSafeDecRef(m_renderer
); 
 317         wxSafeDecRef(m_editor
); 
 321     wxGridCellRenderer
* m_renderer
; 
 322     wxGridCellEditor
*   m_editor
; 
 326 WX_DEFINE_EXPORTED_ARRAY(wxGridDataTypeInfo
*, wxGridDataTypeInfoArray
); 
 329 class WXDLLEXPORT wxGridTypeRegistry
 
 332   wxGridTypeRegistry() {} 
 333     ~wxGridTypeRegistry(); 
 335     void RegisterDataType(const wxString
& typeName
, 
 336                      wxGridCellRenderer
* renderer
, 
 337                      wxGridCellEditor
* editor
); 
 339     // find one of already registered data types 
 340     int FindRegisteredDataType(const wxString
& typeName
); 
 342     // try to FindRegisteredDataType(), if this fails and typeName is one of 
 343     // standard typenames, register it and return its index 
 344     int FindDataType(const wxString
& typeName
); 
 346     // try to FindDataType(), if it fails see if it is not one of already 
 347     // registered data types with some params in which case clone the 
 348     // registered data type and set params for it 
 349     int FindOrCloneDataType(const wxString
& typeName
); 
 351     wxGridCellRenderer
* GetRenderer(int index
); 
 352     wxGridCellEditor
*   GetEditor(int index
); 
 355     wxGridDataTypeInfoArray m_typeinfo
; 
 358 // ---------------------------------------------------------------------------- 
 359 // conditional compilation 
 360 // ---------------------------------------------------------------------------- 
 362 #ifndef WXGRID_DRAW_LINES 
 363 #define WXGRID_DRAW_LINES 1 
 366 // ---------------------------------------------------------------------------- 
 368 // ---------------------------------------------------------------------------- 
 370 //#define DEBUG_ATTR_CACHE 
 371 #ifdef DEBUG_ATTR_CACHE 
 372     static size_t gs_nAttrCacheHits 
= 0; 
 373     static size_t gs_nAttrCacheMisses 
= 0; 
 374 #endif // DEBUG_ATTR_CACHE 
 376 // ---------------------------------------------------------------------------- 
 378 // ---------------------------------------------------------------------------- 
 380 wxGridCellCoords 
wxGridNoCellCoords( -1, -1 ); 
 381 wxRect           
wxGridNoCellRect( -1, -1, -1, -1 ); 
 384 // TODO: this doesn't work at all, grid cells have different sizes and approx 
 385 //       calculations don't work as because of the size mismatch scrollbars 
 386 //       sometimes fail to be shown when they should be or vice versa 
 388 //       The scroll bars may be a little flakey once in a while, but that is 
 389 //       surely much less horrible than having scroll lines of only 1!!! 
 391 static const size_t GRID_SCROLL_LINE 
= 15;  // 1; 
 394 // the size of hash tables used a bit everywhere (the max number of elements 
 395 // in these hash tables is the number of rows/columns) 
 396 static const int GRID_HASH_SIZE 
= 100; 
 398 // ============================================================================ 
 400 // ============================================================================ 
 402 // ---------------------------------------------------------------------------- 
 404 // ---------------------------------------------------------------------------- 
 406 wxGridCellEditor::wxGridCellEditor() 
 412 wxGridCellEditor::~wxGridCellEditor() 
 417 void wxGridCellEditor::Create(wxWindow
* WXUNUSED(parent
), 
 418                               wxWindowID 
WXUNUSED(id
), 
 419                               wxEvtHandler
* evtHandler
) 
 422         m_control
->PushEventHandler(evtHandler
); 
 425 void wxGridCellEditor::PaintBackground(const wxRect
& rectCell
, 
 426                                        wxGridCellAttr 
*attr
) 
 428     // erase the background because we might not fill the cell 
 429     wxClientDC 
dc(m_control
->GetParent()); 
 430     dc
.SetPen(*wxTRANSPARENT_PEN
); 
 431     dc
.SetBrush(wxBrush(attr
->GetBackgroundColour(), wxSOLID
)); 
 432     dc
.DrawRectangle(rectCell
); 
 434     // redraw the control we just painted over 
 435     m_control
->Refresh(); 
 438 void wxGridCellEditor::Destroy() 
 442         m_control
->PopEventHandler(TRUE 
/* delete it*/); 
 444         m_control
->Destroy(); 
 449 void wxGridCellEditor::Show(bool show
, wxGridCellAttr 
*attr
) 
 451     wxASSERT_MSG(m_control
, 
 452                  wxT("The wxGridCellEditor must be Created first!")); 
 453     m_control
->Show(show
); 
 457         // set the colours/fonts if we have any 
 460             m_colFgOld 
= m_control
->GetForegroundColour(); 
 461             m_control
->SetForegroundColour(attr
->GetTextColour()); 
 463             m_colBgOld 
= m_control
->GetBackgroundColour(); 
 464             m_control
->SetBackgroundColour(attr
->GetBackgroundColour()); 
 466             m_fontOld 
= m_control
->GetFont(); 
 467             m_control
->SetFont(attr
->GetFont()); 
 469             // can't do anything more in the base class version, the other 
 470             // attributes may only be used by the derived classes 
 475         // restore the standard colours fonts 
 476         if ( m_colFgOld
.Ok() ) 
 478             m_control
->SetForegroundColour(m_colFgOld
); 
 479             m_colFgOld 
= wxNullColour
; 
 482         if ( m_colBgOld
.Ok() ) 
 484             m_control
->SetBackgroundColour(m_colBgOld
); 
 485             m_colBgOld 
= wxNullColour
; 
 488         if ( m_fontOld
.Ok() ) 
 490             m_control
->SetFont(m_fontOld
); 
 491             m_fontOld 
= wxNullFont
; 
 496 void wxGridCellEditor::SetSize(const wxRect
& rect
) 
 498     wxASSERT_MSG(m_control
, 
 499                  wxT("The wxGridCellEditor must be Created first!")); 
 500     m_control
->SetSize(rect
, wxSIZE_ALLOW_MINUS_ONE
); 
 503 void wxGridCellEditor::HandleReturn(wxKeyEvent
& event
) 
 508 bool wxGridCellEditor::IsAcceptedKey(wxKeyEvent
& event
) 
 510     // accept the simple key presses, not anything with Ctrl/Alt/Meta 
 511     return !(event
.ControlDown() || event
.AltDown()); 
 514 void wxGridCellEditor::StartingKey(wxKeyEvent
& event
) 
 519 void wxGridCellEditor::StartingClick() 
 525 // ---------------------------------------------------------------------------- 
 526 // wxGridCellTextEditor 
 527 // ---------------------------------------------------------------------------- 
 529 wxGridCellTextEditor::wxGridCellTextEditor() 
 534 void wxGridCellTextEditor::Create(wxWindow
* parent
, 
 536                                   wxEvtHandler
* evtHandler
) 
 538     m_control 
= new wxTextCtrl(parent
, id
, wxEmptyString
, 
 539                                wxDefaultPosition
, wxDefaultSize
 
 540 #if defined(__WXMSW__) 
 541                                , wxTE_PROCESS_TAB 
| wxTE_MULTILINE 
| 
 542                                  wxTE_NO_VSCROLL 
| wxTE_AUTO_SCROLL
 
 546     // TODO: use m_maxChars 
 548     wxGridCellEditor::Create(parent
, id
, evtHandler
); 
 551 void wxGridCellTextEditor::PaintBackground(const wxRect
& WXUNUSED(rectCell
), 
 552                                            wxGridCellAttr 
* WXUNUSED(attr
)) 
 554     // as we fill the entire client area, don't do anything here to minimize 
 558 void wxGridCellTextEditor::SetSize(const wxRect
& rectOrig
) 
 560     wxRect 
rect(rectOrig
); 
 562     // Make the edit control large enough to allow for internal 
 565     // TODO: remove this if the text ctrl sizing is improved esp. for 
 568 #if defined(__WXGTK__) 
 577     int extra_x 
= ( rect
.x 
> 2 )? 2 : 1; 
 579 // MB: treat MSW separately here otherwise the caret doesn't show 
 580 // when the editor is in the first row. 
 581 #if defined(__WXMSW__) 
 584     int extra_y 
= ( rect
.y 
> 2 )? 2 : 1; 
 587 #if defined(__WXMOTIF__) 
 591     rect
.SetLeft( wxMax(0, rect
.x 
- extra_x
) ); 
 592     rect
.SetTop( wxMax(0, rect
.y 
- extra_y
) ); 
 593     rect
.SetRight( rect
.GetRight() + 2*extra_x 
); 
 594     rect
.SetBottom( rect
.GetBottom() + 2*extra_y 
); 
 597     wxGridCellEditor::SetSize(rect
); 
 600 void wxGridCellTextEditor::BeginEdit(int row
, int col
, wxGrid
* grid
) 
 602     wxASSERT_MSG(m_control
, 
 603                  wxT("The wxGridCellEditor must be Created first!")); 
 605     m_startValue 
= grid
->GetTable()->GetValue(row
, col
); 
 607     DoBeginEdit(m_startValue
); 
 610 void wxGridCellTextEditor::DoBeginEdit(const wxString
& startValue
) 
 612     Text()->SetValue(startValue
); 
 613     Text()->SetInsertionPointEnd(); 
 617 bool wxGridCellTextEditor::EndEdit(int row
, int col
, 
 620     wxASSERT_MSG(m_control
, 
 621                  wxT("The wxGridCellEditor must be Created first!")); 
 623     bool changed 
= FALSE
; 
 624     wxString value 
= Text()->GetValue(); 
 625     if (value 
!= m_startValue
) 
 629         grid
->GetTable()->SetValue(row
, col
, value
); 
 631     m_startValue 
= wxEmptyString
; 
 632     Text()->SetValue(m_startValue
); 
 638 void wxGridCellTextEditor::Reset() 
 640     wxASSERT_MSG(m_control
, 
 641                  wxT("The wxGridCellEditor must be Created first!")); 
 643     DoReset(m_startValue
); 
 646 void wxGridCellTextEditor::DoReset(const wxString
& startValue
) 
 648     Text()->SetValue(startValue
); 
 649     Text()->SetInsertionPointEnd(); 
 652 bool wxGridCellTextEditor::IsAcceptedKey(wxKeyEvent
& event
) 
 654     if ( wxGridCellEditor::IsAcceptedKey(event
) ) 
 656         int keycode 
= event
.GetKeyCode(); 
 670             case WXK_NUMPAD_MULTIPLY
: 
 674             case WXK_NUMPAD_SUBTRACT
: 
 676             case WXK_NUMPAD_DECIMAL
: 
 678             case WXK_NUMPAD_DIVIDE
: 
 682                 // accept 8 bit chars too if isprint() agrees 
 683                 if ( (keycode 
< 255) && (isprint(keycode
)) ) 
 691 void wxGridCellTextEditor::StartingKey(wxKeyEvent
& event
) 
 693     // we don't check for !HasModifiers() because IsAcceptedKey() did it 
 695     // insert the key in the control 
 697     int keycode 
= event
.GetKeyCode(); 
 710             ch 
= _T('0') + keycode 
- WXK_NUMPAD0
; 
 714         case WXK_NUMPAD_MULTIPLY
: 
 724         case WXK_NUMPAD_SUBTRACT
: 
 729         case WXK_NUMPAD_DECIMAL
: 
 734         case WXK_NUMPAD_DIVIDE
: 
 739             if ( keycode 
< 256 && keycode 
>= 0 && isprint(keycode
) ) 
 741                 // FIXME this is not going to work for non letters... 
 742                 if ( !event
.ShiftDown() ) 
 744                     keycode 
= tolower(keycode
); 
 747                 ch 
= (wxChar
)keycode
; 
 757         Text()->AppendText(ch
); 
 765 void wxGridCellTextEditor::HandleReturn( wxKeyEvent
& 
 766                                          WXUNUSED_GTK(WXUNUSED_MOTIF(event
)) ) 
 768 #if defined(__WXMOTIF__) || defined(__WXGTK__) 
 769     // wxMotif needs a little extra help... 
 770     size_t pos 
= (size_t)( Text()->GetInsertionPoint() ); 
 771     wxString 
s( Text()->GetValue() ); 
 772     s 
= s
.Left(pos
) + "\n" + s
.Mid(pos
); 
 774     Text()->SetInsertionPoint( pos 
); 
 776     // the other ports can handle a Return key press 
 782 void wxGridCellTextEditor::SetParameters(const wxString
& params
) 
 792         if ( !params
.ToLong(&tmp
) ) 
 794             wxLogDebug(_T("Invalid wxGridCellTextEditor parameter string '%s' ignored"), params
.c_str()); 
 798             m_maxChars 
= (size_t)tmp
; 
 803 // ---------------------------------------------------------------------------- 
 804 // wxGridCellNumberEditor 
 805 // ---------------------------------------------------------------------------- 
 807 wxGridCellNumberEditor::wxGridCellNumberEditor(int min
, int max
) 
 813 void wxGridCellNumberEditor::Create(wxWindow
* parent
, 
 815                                     wxEvtHandler
* evtHandler
) 
 819         // create a spin ctrl 
 820         m_control 
= new wxSpinCtrl(parent
, -1, wxEmptyString
, 
 821                                    wxDefaultPosition
, wxDefaultSize
, 
 825         wxGridCellEditor::Create(parent
, id
, evtHandler
); 
 829         // just a text control 
 830         wxGridCellTextEditor::Create(parent
, id
, evtHandler
); 
 833         Text()->SetValidator(wxTextValidator(wxFILTER_NUMERIC
)); 
 834 #endif // wxUSE_VALIDATORS 
 838 void wxGridCellNumberEditor::BeginEdit(int row
, int col
, wxGrid
* grid
) 
 840     // first get the value 
 841     wxGridTableBase 
*table 
= grid
->GetTable(); 
 842     if ( table
->CanGetValueAs(row
, col
, wxGRID_VALUE_NUMBER
) ) 
 844         m_valueOld 
= table
->GetValueAsLong(row
, col
); 
 848         wxString sValue 
= table
->GetValue(row
, col
); 
 849         if (! sValue
.ToLong(&m_valueOld
)) 
 851             wxFAIL_MSG( _T("this cell doesn't have numeric value") ); 
 858         Spin()->SetValue((int)m_valueOld
); 
 863         DoBeginEdit(GetString()); 
 867 bool wxGridCellNumberEditor::EndEdit(int row
, int col
, 
 875         value 
= Spin()->GetValue(); 
 876         changed 
= value 
!= m_valueOld
; 
 880         changed 
= Text()->GetValue().ToLong(&value
) && (value 
!= m_valueOld
); 
 885         if (grid
->GetTable()->CanSetValueAs(row
, col
, wxGRID_VALUE_NUMBER
)) 
 886             grid
->GetTable()->SetValueAsLong(row
, col
, value
); 
 888             grid
->GetTable()->SetValue(row
, col
, wxString::Format(wxT("%ld"), value
)); 
 894 void wxGridCellNumberEditor::Reset() 
 898         Spin()->SetValue((int)m_valueOld
); 
 902         DoReset(GetString()); 
 906 bool wxGridCellNumberEditor::IsAcceptedKey(wxKeyEvent
& event
) 
 908     if ( wxGridCellEditor::IsAcceptedKey(event
) ) 
 910         int keycode 
= event
.GetKeyCode(); 
 926             case WXK_NUMPAD_SUBTRACT
: 
 932                 if ( (keycode 
< 128) && isdigit(keycode
) ) 
 940 void wxGridCellNumberEditor::StartingKey(wxKeyEvent
& event
) 
 944         int keycode 
= (int) event
.KeyCode(); 
 945         if ( isdigit(keycode
) || keycode 
== '+' || keycode 
== '-' ) 
 947             wxGridCellTextEditor::StartingKey(event
); 
 957 void wxGridCellNumberEditor::SetParameters(const wxString
& params
) 
 968         if ( params
.BeforeFirst(_T(',')).ToLong(&tmp
) ) 
 972             if ( params
.AfterFirst(_T(',')).ToLong(&tmp
) ) 
 976                 // skip the error message below 
 981         wxLogDebug(_T("Invalid wxGridCellNumberEditor parameter string '%s' ignored"), params
.c_str()); 
 985 // ---------------------------------------------------------------------------- 
 986 // wxGridCellFloatEditor 
 987 // ---------------------------------------------------------------------------- 
 989 wxGridCellFloatEditor::wxGridCellFloatEditor(int width
, int precision
) 
 992     m_precision 
= precision
; 
 995 void wxGridCellFloatEditor::Create(wxWindow
* parent
, 
 997                                    wxEvtHandler
* evtHandler
) 
 999     wxGridCellTextEditor::Create(parent
, id
, evtHandler
); 
1001 #if wxUSE_VALIDATORS 
1002     Text()->SetValidator(wxTextValidator(wxFILTER_NUMERIC
)); 
1003 #endif // wxUSE_VALIDATORS 
1006 void wxGridCellFloatEditor::BeginEdit(int row
, int col
, wxGrid
* grid
) 
1008     // first get the value 
1009     wxGridTableBase 
*table 
= grid
->GetTable(); 
1010     if ( table
->CanGetValueAs(row
, col
, wxGRID_VALUE_FLOAT
) ) 
1012         m_valueOld 
= table
->GetValueAsDouble(row
, col
); 
1016         wxString sValue 
= table
->GetValue(row
, col
); 
1017         if (! sValue
.ToDouble(&m_valueOld
)) 
1019             wxFAIL_MSG( _T("this cell doesn't have float value") ); 
1024     DoBeginEdit(GetString()); 
1027 bool wxGridCellFloatEditor::EndEdit(int row
, int col
, 
1031     if ( Text()->GetValue().ToDouble(&value
) && (value 
!= m_valueOld
) ) 
1033         if (grid
->GetTable()->CanSetValueAs(row
, col
, wxGRID_VALUE_FLOAT
)) 
1034             grid
->GetTable()->SetValueAsDouble(row
, col
, value
); 
1036             grid
->GetTable()->SetValue(row
, col
, wxString::Format(wxT("%f"), value
)); 
1046 void wxGridCellFloatEditor::Reset() 
1048     DoReset(GetString()); 
1051 void wxGridCellFloatEditor::StartingKey(wxKeyEvent
& event
) 
1053     int keycode 
= (int)event
.KeyCode(); 
1054     if ( isdigit(keycode
) || 
1055          keycode 
== '+' || keycode 
== '-' || keycode 
== '.' ) 
1057         wxGridCellTextEditor::StartingKey(event
); 
1059         // skip Skip() below 
1066 void wxGridCellFloatEditor::SetParameters(const wxString
& params
) 
1077         if ( params
.BeforeFirst(_T(',')).ToLong(&tmp
) ) 
1081             if ( params
.AfterFirst(_T(',')).ToLong(&tmp
) ) 
1083                 m_precision 
= (int)tmp
; 
1085                 // skip the error message below 
1090         wxLogDebug(_T("Invalid wxGridCellFloatEditor parameter string '%s' ignored"), params
.c_str()); 
1094 wxString 
wxGridCellFloatEditor::GetString() const 
1097     if ( m_width 
== -1 ) 
1099         // default width/precision 
1102     else if ( m_precision 
== -1 ) 
1104         // default precision 
1105         fmt
.Printf(_T("%%%d.g"), m_width
); 
1109         fmt
.Printf(_T("%%%d.%dg"), m_width
, m_precision
); 
1112     return wxString::Format(fmt
, m_valueOld
); 
1115 bool wxGridCellFloatEditor::IsAcceptedKey(wxKeyEvent
& event
) 
1117     if ( wxGridCellEditor::IsAcceptedKey(event
) ) 
1119         int keycode 
= event
.GetKeyCode(); 
1133             case WXK_NUMPAD_ADD
: 
1135             case WXK_NUMPAD_SUBTRACT
: 
1137             case WXK_NUMPAD_DECIMAL
: 
1141                 // additionally accept 'e' as in '1e+6' 
1142                 if ( (keycode 
< 128) && 
1143                      (isdigit(keycode
) || tolower(keycode
) == 'e') ) 
1151 #endif // wxUSE_TEXTCTRL 
1155 // ---------------------------------------------------------------------------- 
1156 // wxGridCellBoolEditor 
1157 // ---------------------------------------------------------------------------- 
1159 void wxGridCellBoolEditor::Create(wxWindow
* parent
, 
1161                                   wxEvtHandler
* evtHandler
) 
1163     m_control 
= new wxCheckBox(parent
, id
, wxEmptyString
, 
1164                                wxDefaultPosition
, wxDefaultSize
, 
1167     wxGridCellEditor::Create(parent
, id
, evtHandler
); 
1170 void wxGridCellBoolEditor::SetSize(const wxRect
& r
) 
1172     bool resize 
= FALSE
; 
1173     wxSize size 
= m_control
->GetSize(); 
1174     wxCoord minSize 
= wxMin(r
.width
, r
.height
); 
1176     // check if the checkbox is not too big/small for this cell 
1177     wxSize sizeBest 
= m_control
->GetBestSize(); 
1178     if ( !(size 
== sizeBest
) ) 
1180         // reset to default size if it had been made smaller 
1186     if ( size
.x 
>= minSize 
|| size
.y 
>= minSize 
) 
1188         // leave 1 pixel margin 
1189         size
.x 
= size
.y 
= minSize 
- 2; 
1196         m_control
->SetSize(size
); 
1199     // position it in the centre of the rectangle (TODO: support alignment?) 
1201 #if defined(__WXGTK__) || defined (__WXMOTIF__) 
1202     // the checkbox without label still has some space to the right in wxGTK, 
1203     // so shift it to the right 
1205 #elif defined(__WXMSW__) 
1206     // here too, but in other way 
1211     m_control
->Move(r
.x 
+ r
.width
/2 - size
.x
/2, r
.y 
+ r
.height
/2 - size
.y
/2); 
1214 void wxGridCellBoolEditor::Show(bool show
, wxGridCellAttr 
*attr
) 
1216     m_control
->Show(show
); 
1220         wxColour colBg 
= attr 
? attr
->GetBackgroundColour() : *wxLIGHT_GREY
; 
1221         CBox()->SetBackgroundColour(colBg
); 
1225 void wxGridCellBoolEditor::BeginEdit(int row
, int col
, wxGrid
* grid
) 
1227     wxASSERT_MSG(m_control
, 
1228                  wxT("The wxGridCellEditor must be Created first!")); 
1230     if (grid
->GetTable()->CanGetValueAs(row
, col
, wxGRID_VALUE_BOOL
)) 
1231         m_startValue 
= grid
->GetTable()->GetValueAsBool(row
, col
); 
1234         wxString 
cellval( grid
->GetTable()->GetValue(row
, col
) ); 
1235         m_startValue 
= !( !cellval 
|| (cellval 
== "0") ); 
1237     CBox()->SetValue(m_startValue
); 
1241 bool wxGridCellBoolEditor::EndEdit(int row
, int col
, 
1244     wxASSERT_MSG(m_control
, 
1245                  wxT("The wxGridCellEditor must be Created first!")); 
1247     bool changed 
= FALSE
; 
1248     bool value 
= CBox()->GetValue(); 
1249     if ( value 
!= m_startValue 
) 
1254         if (grid
->GetTable()->CanGetValueAs(row
, col
, wxGRID_VALUE_BOOL
)) 
1255             grid
->GetTable()->SetValueAsBool(row
, col
, value
); 
1257             grid
->GetTable()->SetValue(row
, col
, value 
? _T("1") : wxEmptyString
); 
1263 void wxGridCellBoolEditor::Reset() 
1265     wxASSERT_MSG(m_control
, 
1266                  wxT("The wxGridCellEditor must be Created first!")); 
1268     CBox()->SetValue(m_startValue
); 
1271 void wxGridCellBoolEditor::StartingClick() 
1273     CBox()->SetValue(!CBox()->GetValue()); 
1276 bool wxGridCellBoolEditor::IsAcceptedKey(wxKeyEvent
& event
) 
1278     if ( wxGridCellEditor::IsAcceptedKey(event
) ) 
1280         int keycode 
= event
.GetKeyCode(); 
1284             case WXK_NUMPAD_MULTIPLY
: 
1286             case WXK_NUMPAD_ADD
: 
1288             case WXK_NUMPAD_SUBTRACT
: 
1299 #endif // wxUSE_CHECKBOX 
1303 // ---------------------------------------------------------------------------- 
1304 // wxGridCellChoiceEditor 
1305 // ---------------------------------------------------------------------------- 
1307 wxGridCellChoiceEditor::wxGridCellChoiceEditor(size_t count
, 
1308                                                const wxString choices
[], 
1310                       : m_allowOthers(allowOthers
) 
1314         m_choices
.Alloc(count
); 
1315         for ( size_t n 
= 0; n 
< count
; n
++ ) 
1317             m_choices
.Add(choices
[n
]); 
1322 wxGridCellEditor 
*wxGridCellChoiceEditor::Clone() const 
1324     wxGridCellChoiceEditor 
*editor 
= new wxGridCellChoiceEditor
; 
1325     editor
->m_allowOthers 
= m_allowOthers
; 
1326     editor
->m_choices 
= m_choices
; 
1331 void wxGridCellChoiceEditor::Create(wxWindow
* parent
, 
1333                                     wxEvtHandler
* evtHandler
) 
1335     size_t count 
= m_choices
.GetCount(); 
1336     wxString 
*choices 
= new wxString
[count
]; 
1337     for ( size_t n 
= 0; n 
< count
; n
++ ) 
1339         choices
[n
] = m_choices
[n
]; 
1342     m_control 
= new wxComboBox(parent
, id
, wxEmptyString
, 
1343                                wxDefaultPosition
, wxDefaultSize
, 
1345                                m_allowOthers 
? 0 : wxCB_READONLY
); 
1349     wxGridCellEditor::Create(parent
, id
, evtHandler
); 
1352 void wxGridCellChoiceEditor::PaintBackground(const wxRect
& rectCell
, 
1353                                              wxGridCellAttr 
* attr
) 
1355     // as we fill the entire client area, don't do anything here to minimize 
1358     // TODO: It doesn't actually fill the client area since the height of a 
1359     // combo always defaults to the standard...  Until someone has time to 
1360     // figure out the right rectangle to paint, just do it the normal way... 
1361     wxGridCellEditor::PaintBackground(rectCell
, attr
); 
1364 void wxGridCellChoiceEditor::BeginEdit(int row
, int col
, wxGrid
* grid
) 
1366     wxASSERT_MSG(m_control
, 
1367                  wxT("The wxGridCellEditor must be Created first!")); 
1369     m_startValue 
= grid
->GetTable()->GetValue(row
, col
); 
1371     Combo()->SetValue(m_startValue
); 
1372     size_t count 
= m_choices
.GetCount(); 
1373     for (size_t i
=0; i
<count
; i
++) 
1375         if (m_startValue 
== m_choices
[i
]) 
1377             Combo()->SetSelection(i
); 
1381     Combo()->SetInsertionPointEnd(); 
1382     Combo()->SetFocus(); 
1385 bool wxGridCellChoiceEditor::EndEdit(int row
, int col
, 
1388     wxString value 
= Combo()->GetValue(); 
1389     bool changed 
= value 
!= m_startValue
; 
1392         grid
->GetTable()->SetValue(row
, col
, value
); 
1394     m_startValue 
= wxEmptyString
; 
1395     Combo()->SetValue(m_startValue
); 
1400 void wxGridCellChoiceEditor::Reset() 
1402     Combo()->SetValue(m_startValue
); 
1403     Combo()->SetInsertionPointEnd(); 
1406 void wxGridCellChoiceEditor::SetParameters(const wxString
& params
) 
1416     wxStringTokenizer 
tk(params
, _T(',')); 
1417     while ( tk
.HasMoreTokens() ) 
1419         m_choices
.Add(tk
.GetNextToken()); 
1423 #endif // wxUSE_COMBOBOX 
1425 // ---------------------------------------------------------------------------- 
1426 // wxGridCellEditorEvtHandler 
1427 // ---------------------------------------------------------------------------- 
1429 void wxGridCellEditorEvtHandler::OnKeyDown(wxKeyEvent
& event
) 
1431     switch ( event
.KeyCode() ) 
1435             m_grid
->DisableCellEditControl(); 
1439             m_grid
->GetEventHandler()->ProcessEvent( event 
); 
1443         case WXK_NUMPAD_ENTER
: 
1444             if (!m_grid
->GetEventHandler()->ProcessEvent(event
)) 
1445                 m_editor
->HandleReturn(event
); 
1454 void wxGridCellEditorEvtHandler::OnChar(wxKeyEvent
& event
) 
1456     switch ( event
.KeyCode() ) 
1461         case WXK_NUMPAD_ENTER
: 
1469 // ---------------------------------------------------------------------------- 
1470 // wxGridCellWorker is an (almost) empty common base class for 
1471 // wxGridCellRenderer and wxGridCellEditor managing ref counting 
1472 // ---------------------------------------------------------------------------- 
1474 void wxGridCellWorker::SetParameters(const wxString
& WXUNUSED(params
)) 
1479 wxGridCellWorker::~wxGridCellWorker() 
1483 // ============================================================================ 
1485 // ============================================================================ 
1487 // ---------------------------------------------------------------------------- 
1488 // wxGridCellRenderer 
1489 // ---------------------------------------------------------------------------- 
1491 void wxGridCellRenderer::Draw(wxGrid
& grid
, 
1492                               wxGridCellAttr
& attr
, 
1495                               int WXUNUSED(row
), int WXUNUSED(col
), 
1498     dc
.SetBackgroundMode( wxSOLID 
); 
1502         dc
.SetBrush( wxBrush(grid
.GetSelectionBackground(), wxSOLID
) ); 
1506         dc
.SetBrush( wxBrush(attr
.GetBackgroundColour(), wxSOLID
) ); 
1509     dc
.SetPen( *wxTRANSPARENT_PEN 
); 
1510     dc
.DrawRectangle(rect
); 
1513 // ---------------------------------------------------------------------------- 
1514 // wxGridCellStringRenderer 
1515 // ---------------------------------------------------------------------------- 
1517 void wxGridCellStringRenderer::SetTextColoursAndFont(wxGrid
& grid
, 
1518                                                      wxGridCellAttr
& attr
, 
1522     dc
.SetBackgroundMode( wxTRANSPARENT 
); 
1524     // TODO some special colours for attr.IsReadOnly() case? 
1528         dc
.SetTextBackground( grid
.GetSelectionBackground() ); 
1529         dc
.SetTextForeground( grid
.GetSelectionForeground() ); 
1533         dc
.SetTextBackground( attr
.GetBackgroundColour() ); 
1534         dc
.SetTextForeground( attr
.GetTextColour() ); 
1537     dc
.SetFont( attr
.GetFont() ); 
1540 wxSize 
wxGridCellStringRenderer::DoGetBestSize(wxGridCellAttr
& attr
, 
1542                                                const wxString
& text
) 
1544     wxCoord x 
= 0, y 
= 0, max_x 
= 0; 
1545     dc
.SetFont(attr
.GetFont()); 
1546     wxStringTokenizer 
tk(text
, _T('\n')); 
1547     while ( tk
.HasMoreTokens() ) 
1549         dc
.GetTextExtent(tk
.GetNextToken(), &x
, &y
); 
1550         max_x 
= wxMax(max_x
, x
); 
1553     y 
*= 1 + text
.Freq(wxT('\n')); // multiply by the number of lines. 
1555     return wxSize(max_x
, y
); 
1558 wxSize 
wxGridCellStringRenderer::GetBestSize(wxGrid
& grid
, 
1559                                              wxGridCellAttr
& attr
, 
1563     return DoGetBestSize(attr
, dc
, grid
.GetCellValue(row
, col
)); 
1566 void wxGridCellStringRenderer::Draw(wxGrid
& grid
, 
1567                                     wxGridCellAttr
& attr
, 
1569                                     const wxRect
& rectCell
, 
1573     wxGridCellRenderer::Draw(grid
, attr
, dc
, rectCell
, row
, col
, isSelected
); 
1575     // now we only have to draw the text 
1576     SetTextColoursAndFont(grid
, attr
, dc
, isSelected
); 
1579     attr
.GetAlignment(&hAlign
, &vAlign
); 
1581     wxRect rect 
= rectCell
; 
1584     grid
.DrawTextRectangle(dc
, grid
.GetCellValue(row
, col
), 
1585                            rect
, hAlign
, vAlign
); 
1588 // ---------------------------------------------------------------------------- 
1589 // wxGridCellNumberRenderer 
1590 // ---------------------------------------------------------------------------- 
1592 wxString 
wxGridCellNumberRenderer::GetString(wxGrid
& grid
, int row
, int col
) 
1594     wxGridTableBase 
*table 
= grid
.GetTable(); 
1596     if ( table
->CanGetValueAs(row
, col
, wxGRID_VALUE_NUMBER
) ) 
1598         text
.Printf(_T("%ld"), table
->GetValueAsLong(row
, col
)); 
1602         text 
= table
->GetValue(row
, col
); 
1608 void wxGridCellNumberRenderer::Draw(wxGrid
& grid
, 
1609                                     wxGridCellAttr
& attr
, 
1611                                     const wxRect
& rectCell
, 
1615     wxGridCellRenderer::Draw(grid
, attr
, dc
, rectCell
, row
, col
, isSelected
); 
1617     SetTextColoursAndFont(grid
, attr
, dc
, isSelected
); 
1619     // draw the text right aligned by default 
1621     attr
.GetAlignment(&hAlign
, &vAlign
); 
1622     hAlign 
= wxALIGN_RIGHT
; 
1624     wxRect rect 
= rectCell
; 
1627     grid
.DrawTextRectangle(dc
, GetString(grid
, row
, col
), rect
, hAlign
, vAlign
); 
1630 wxSize 
wxGridCellNumberRenderer::GetBestSize(wxGrid
& grid
, 
1631                                              wxGridCellAttr
& attr
, 
1635     return DoGetBestSize(attr
, dc
, GetString(grid
, row
, col
)); 
1638 // ---------------------------------------------------------------------------- 
1639 // wxGridCellFloatRenderer 
1640 // ---------------------------------------------------------------------------- 
1642 wxGridCellFloatRenderer::wxGridCellFloatRenderer(int width
, int precision
) 
1645     SetPrecision(precision
); 
1648 wxGridCellRenderer 
*wxGridCellFloatRenderer::Clone() const 
1650     wxGridCellFloatRenderer 
*renderer 
= new wxGridCellFloatRenderer
; 
1651     renderer
->m_width 
= m_width
; 
1652     renderer
->m_precision 
= m_precision
; 
1653     renderer
->m_format 
= m_format
; 
1658 wxString 
wxGridCellFloatRenderer::GetString(wxGrid
& grid
, int row
, int col
) 
1660     wxGridTableBase 
*table 
= grid
.GetTable(); 
1665     if ( table
->CanGetValueAs(row
, col
, wxGRID_VALUE_FLOAT
) ) 
1667         val 
= table
->GetValueAsDouble(row
, col
); 
1672         text 
= table
->GetValue(row
, col
); 
1673         hasDouble 
= text
.ToDouble(&val
); 
1680             if ( m_width 
== -1 ) 
1682                 if ( m_precision 
== -1 ) 
1684                 // default width/precision 
1685                 m_format 
= _T("%f"); 
1689                     m_format
.Printf(_T("%%.%df"), m_precision
); 
1692             else if ( m_precision 
== -1 ) 
1694                 // default precision 
1695                 m_format
.Printf(_T("%%%d.f"), m_width
); 
1699                 m_format
.Printf(_T("%%%d.%df"), m_width
, m_precision
); 
1703         text
.Printf(m_format
, val
); 
1706     //else: text already contains the string 
1711 void wxGridCellFloatRenderer::Draw(wxGrid
& grid
, 
1712                                    wxGridCellAttr
& attr
, 
1714                                    const wxRect
& rectCell
, 
1718     wxGridCellRenderer::Draw(grid
, attr
, dc
, rectCell
, row
, col
, isSelected
); 
1720     SetTextColoursAndFont(grid
, attr
, dc
, isSelected
); 
1722     // draw the text right aligned by default 
1724     attr
.GetAlignment(&hAlign
, &vAlign
); 
1725     hAlign 
= wxALIGN_RIGHT
; 
1727     wxRect rect 
= rectCell
; 
1730     grid
.DrawTextRectangle(dc
, GetString(grid
, row
, col
), rect
, hAlign
, vAlign
); 
1733 wxSize 
wxGridCellFloatRenderer::GetBestSize(wxGrid
& grid
, 
1734                                             wxGridCellAttr
& attr
, 
1738     return DoGetBestSize(attr
, dc
, GetString(grid
, row
, col
)); 
1741 void wxGridCellFloatRenderer::SetParameters(const wxString
& params
) 
1745         // reset to defaults 
1751         wxString tmp 
= params
.BeforeFirst(_T(',')); 
1755             if ( tmp
.ToLong(&width
) ) 
1757                 SetWidth((int)width
); 
1761                 wxLogDebug(_T("Invalid wxGridCellFloatRenderer width parameter string '%s ignored"), params
.c_str()); 
1765                 tmp 
= params
.AfterFirst(_T(',')); 
1769             if ( tmp
.ToLong(&precision
) ) 
1771                 SetPrecision((int)precision
); 
1775                 wxLogDebug(_T("Invalid wxGridCellFloatRenderer precision parameter string '%s ignored"), params
.c_str()); 
1783 // ---------------------------------------------------------------------------- 
1784 // wxGridCellBoolRenderer 
1785 // ---------------------------------------------------------------------------- 
1787 wxSize 
wxGridCellBoolRenderer::ms_sizeCheckMark
; 
1789 // FIXME these checkbox size calculations are really ugly... 
1791 // between checkmark and box 
1792 static const wxCoord wxGRID_CHECKMARK_MARGIN 
= 2; 
1794 wxSize 
wxGridCellBoolRenderer::GetBestSize(wxGrid
& grid
, 
1795                                            wxGridCellAttr
& WXUNUSED(attr
), 
1800     // compute it only once (no locks for MT safeness in GUI thread...) 
1801     if ( !ms_sizeCheckMark
.x 
) 
1803         // get checkbox size 
1804         wxCoord checkSize 
= 0; 
1805         wxCheckBox 
*checkbox 
= new wxCheckBox(&grid
, -1, wxEmptyString
); 
1806         wxSize size 
= checkbox
->GetBestSize(); 
1807         checkSize 
= size
.y 
+ 2*wxGRID_CHECKMARK_MARGIN
; 
1809         // FIXME wxGTK::wxCheckBox::GetBestSize() gives "wrong" result 
1810 #if defined(__WXGTK__) || defined(__WXMOTIF__) 
1811         checkSize 
-= size
.y 
/ 2; 
1816         ms_sizeCheckMark
.x 
= ms_sizeCheckMark
.y 
= checkSize
; 
1819     return ms_sizeCheckMark
; 
1822 void wxGridCellBoolRenderer::Draw(wxGrid
& grid
, 
1823                                   wxGridCellAttr
& attr
, 
1829     wxGridCellRenderer::Draw(grid
, attr
, dc
, rect
, row
, col
, isSelected
); 
1831     // draw a check mark in the centre (ignoring alignment - TODO) 
1832     wxSize size 
= GetBestSize(grid
, attr
, dc
, row
, col
); 
1834     // don't draw outside the cell 
1835     wxCoord minSize 
= wxMin(rect
.width
, rect
.height
); 
1836     if ( size
.x 
>= minSize 
|| size
.y 
>= minSize 
) 
1838         // and even leave (at least) 1 pixel margin 
1839         size
.x 
= size
.y 
= minSize 
- 2; 
1842     // draw a border around checkmark 
1844     rectBorder
.x 
= rect
.x 
+ rect
.width
/2 - size
.x
/2; 
1845     rectBorder
.y 
= rect
.y 
+ rect
.height
/2 - size
.y
/2; 
1846     rectBorder
.width 
= size
.x
; 
1847     rectBorder
.height 
= size
.y
; 
1850     if ( grid
.GetTable()->CanGetValueAs(row
, col
, wxGRID_VALUE_BOOL
) ) 
1851         value 
= grid
.GetTable()->GetValueAsBool(row
, col
); 
1854         wxString 
cellval( grid
.GetTable()->GetValue(row
, col
) ); 
1855         value 
= !( !cellval 
|| (cellval 
== "0") ); 
1860         wxRect rectMark 
= rectBorder
; 
1862         // MSW DrawCheckMark() is weird (and should probably be changed...) 
1863         rectMark
.Inflate(-wxGRID_CHECKMARK_MARGIN
/2); 
1867         rectMark
.Inflate(-wxGRID_CHECKMARK_MARGIN
); 
1870         dc
.SetTextForeground(attr
.GetTextColour()); 
1871         dc
.DrawCheckMark(rectMark
); 
1874     dc
.SetBrush(*wxTRANSPARENT_BRUSH
); 
1875     dc
.SetPen(wxPen(attr
.GetTextColour(), 1, wxSOLID
)); 
1876     dc
.DrawRectangle(rectBorder
); 
1879 // ---------------------------------------------------------------------------- 
1881 // ---------------------------------------------------------------------------- 
1883 wxGridCellAttr 
*wxGridCellAttr::Clone() const 
1885     wxGridCellAttr 
*attr 
= new wxGridCellAttr
; 
1886     if ( HasTextColour() ) 
1887         attr
->SetTextColour(GetTextColour()); 
1888     if ( HasBackgroundColour() ) 
1889         attr
->SetBackgroundColour(GetBackgroundColour()); 
1891         attr
->SetFont(GetFont()); 
1892     if ( HasAlignment() ) 
1893         attr
->SetAlignment(m_hAlign
, m_vAlign
); 
1897         attr
->SetRenderer(m_renderer
); 
1898         m_renderer
->IncRef(); 
1902         attr
->SetEditor(m_editor
); 
1907         attr
->SetReadOnly(); 
1909     attr
->SetKind( m_attrkind 
); 
1911     attr
->SetDefAttr(m_defGridAttr
); 
1916 void wxGridCellAttr::MergeWith(wxGridCellAttr 
*mergefrom
) 
1918     if ( !HasTextColour() && mergefrom
->HasTextColour() ) 
1919         SetTextColour(mergefrom
->GetTextColour()); 
1920     if ( !HasBackgroundColour() && mergefrom
->HasBackgroundColour() ) 
1921         SetBackgroundColour(mergefrom
->GetBackgroundColour()); 
1922     if ( !HasFont() && mergefrom
->HasFont() ) 
1923         SetFont(mergefrom
->GetFont()); 
1924     if ( !!HasAlignment() && mergefrom
->HasAlignment() ){ 
1926         mergefrom
->GetAlignment( &hAlign
, &vAlign
); 
1927         SetAlignment(hAlign
, vAlign
); 
1930     // Directly access member functions as GetRender/Editor don't just return 
1931     // m_renderer/m_editor 
1933     // Maybe add support for merge of Render and Editor? 
1934     if (!HasRenderer() && mergefrom
->HasRenderer() ) 
1936         m_renderer 
= mergefrom
->m_renderer
; 
1937         m_renderer
->IncRef(); 
1939     if ( !HasEditor() && mergefrom
->HasEditor() ) 
1941         m_editor 
=  mergefrom
->m_editor
; 
1944     if ( !HasReadWriteMode()  && mergefrom
->HasReadWriteMode() ) 
1945         SetReadOnly(mergefrom
->IsReadOnly()); 
1947     SetDefAttr(mergefrom
->m_defGridAttr
); 
1950 const wxColour
& wxGridCellAttr::GetTextColour() const 
1952     if (HasTextColour()) 
1956     else if (m_defGridAttr 
!= this) 
1958         return m_defGridAttr
->GetTextColour(); 
1962         wxFAIL_MSG(wxT("Missing default cell attribute")); 
1963         return wxNullColour
; 
1968 const wxColour
& wxGridCellAttr::GetBackgroundColour() const 
1970     if (HasBackgroundColour()) 
1972     else if (m_defGridAttr 
!= this) 
1973         return m_defGridAttr
->GetBackgroundColour(); 
1976         wxFAIL_MSG(wxT("Missing default cell attribute")); 
1977         return wxNullColour
; 
1982 const wxFont
& wxGridCellAttr::GetFont() const 
1986     else if (m_defGridAttr 
!= this) 
1987         return m_defGridAttr
->GetFont(); 
1990         wxFAIL_MSG(wxT("Missing default cell attribute")); 
1996 void wxGridCellAttr::GetAlignment(int *hAlign
, int *vAlign
) const 
2000         if ( hAlign 
) *hAlign 
= m_hAlign
; 
2001         if ( vAlign 
) *vAlign 
= m_vAlign
; 
2003     else if (m_defGridAttr 
!= this) 
2004         m_defGridAttr
->GetAlignment(hAlign
, vAlign
); 
2007         wxFAIL_MSG(wxT("Missing default cell attribute")); 
2012 // GetRenderer and GetEditor use a slightly different decision path about 
2013 // which attribute to use.  If a non-default attr object has one then it is 
2014 // used, otherwise the default editor or renderer is fetched from the grid and 
2015 // used.  It should be the default for the data type of the cell.  If it is 
2016 // NULL (because the table has a type that the grid does not have in its 
2017 // registry,) then the grid's default editor or renderer is used. 
2019 wxGridCellRenderer
* wxGridCellAttr::GetRenderer(wxGrid
* grid
, int row
, int col
) const 
2021     wxGridCellRenderer
* renderer 
= NULL
; 
2023     if ( m_defGridAttr 
!= this || grid 
== NULL 
) 
2025         renderer 
= m_renderer
;      // use local attribute 
2030     if ( !renderer 
&& grid 
)        // get renderer for the data type 
2032         // GetDefaultRendererForCell() will do IncRef() for us 
2033         renderer 
= grid
->GetDefaultRendererForCell(row
, col
); 
2038         // if we still don't have one then use the grid default 
2039         // (no need for IncRef() here neither) 
2040         renderer 
= m_defGridAttr
->GetRenderer(NULL
,0,0); 
2045         wxFAIL_MSG(wxT("Missing default cell attribute")); 
2051 wxGridCellEditor
* wxGridCellAttr::GetEditor(wxGrid
* grid
, int row
, int col
) const 
2053     wxGridCellEditor
* editor 
= NULL
; 
2055     if ( m_defGridAttr 
!= this || grid 
== NULL 
) 
2057         editor 
= m_editor
;      // use local attribute 
2062     if ( !editor 
&& grid 
)                   // get renderer for the data type 
2063         editor 
= grid
->GetDefaultEditorForCell(row
, col
); 
2066         // if we still don't have one then use the grid default 
2067         editor 
= m_defGridAttr
->GetEditor(NULL
,0,0); 
2071         wxFAIL_MSG(wxT("Missing default cell attribute")); 
2077 // ---------------------------------------------------------------------------- 
2078 // wxGridCellAttrData 
2079 // ---------------------------------------------------------------------------- 
2081 void wxGridCellAttrData::SetAttr(wxGridCellAttr 
*attr
, int row
, int col
) 
2083     int n 
= FindIndex(row
, col
); 
2084     if ( n 
== wxNOT_FOUND 
) 
2086         // add the attribute 
2087         m_attrs
.Add(new wxGridCellWithAttr(row
, col
, attr
)); 
2093             // change the attribute 
2094             m_attrs
[(size_t)n
].attr 
= attr
; 
2098             // remove this attribute 
2099             m_attrs
.RemoveAt((size_t)n
); 
2104 wxGridCellAttr 
*wxGridCellAttrData::GetAttr(int row
, int col
) const 
2106     wxGridCellAttr 
*attr 
= (wxGridCellAttr 
*)NULL
; 
2108     int n 
= FindIndex(row
, col
); 
2109     if ( n 
!= wxNOT_FOUND 
) 
2111         attr 
= m_attrs
[(size_t)n
].attr
; 
2118 void wxGridCellAttrData::UpdateAttrRows( size_t pos
, int numRows 
) 
2120     size_t count 
= m_attrs
.GetCount(); 
2121     for ( size_t n 
= 0; n 
< count
; n
++ ) 
2123         wxGridCellCoords
& coords 
= m_attrs
[n
].coords
; 
2124         wxCoord row 
= coords
.GetRow(); 
2125         if ((size_t)row 
>= pos
) 
2129                 // If rows inserted, include row counter where necessary 
2130                 coords
.SetRow(row 
+ numRows
); 
2132             else if (numRows 
< 0) 
2134                 // If rows deleted ... 
2135                 if ((size_t)row 
>= pos 
- numRows
) 
2137                     // ...either decrement row counter (if row still exists)... 
2138                     coords
.SetRow(row 
+ numRows
); 
2142                     // ...or remove the attribute 
2143                     m_attrs
.RemoveAt((size_t)n
); 
2151 void wxGridCellAttrData::UpdateAttrCols( size_t pos
, int numCols 
) 
2153     size_t count 
= m_attrs
.GetCount(); 
2154     for ( size_t n 
= 0; n 
< count
; n
++ ) 
2156         wxGridCellCoords
& coords 
= m_attrs
[n
].coords
; 
2157         wxCoord col 
= coords
.GetCol(); 
2158         if ( (size_t)col 
>= pos 
) 
2162                 // If rows inserted, include row counter where necessary 
2163                 coords
.SetCol(col 
+ numCols
); 
2165             else if (numCols 
< 0) 
2167                 // If rows deleted ... 
2168                 if ((size_t)col 
>= pos 
- numCols
) 
2170                     // ...either decrement row counter (if row still exists)... 
2171                     coords
.SetCol(col 
+ numCols
); 
2175                     // ...or remove the attribute 
2176                     m_attrs
.RemoveAt((size_t)n
); 
2184 int wxGridCellAttrData::FindIndex(int row
, int col
) const 
2186     size_t count 
= m_attrs
.GetCount(); 
2187     for ( size_t n 
= 0; n 
< count
; n
++ ) 
2189         const wxGridCellCoords
& coords 
= m_attrs
[n
].coords
; 
2190         if ( (coords
.GetRow() == row
) && (coords
.GetCol() == col
) ) 
2199 // ---------------------------------------------------------------------------- 
2200 // wxGridRowOrColAttrData 
2201 // ---------------------------------------------------------------------------- 
2203 wxGridRowOrColAttrData::~wxGridRowOrColAttrData() 
2205     size_t count 
= m_attrs
.Count(); 
2206     for ( size_t n 
= 0; n 
< count
; n
++ ) 
2208         m_attrs
[n
]->DecRef(); 
2212 wxGridCellAttr 
*wxGridRowOrColAttrData::GetAttr(int rowOrCol
) const 
2214     wxGridCellAttr 
*attr 
= (wxGridCellAttr 
*)NULL
; 
2216     int n 
= m_rowsOrCols
.Index(rowOrCol
); 
2217     if ( n 
!= wxNOT_FOUND 
) 
2219         attr 
= m_attrs
[(size_t)n
]; 
2226 void wxGridRowOrColAttrData::SetAttr(wxGridCellAttr 
*attr
, int rowOrCol
) 
2228     int i 
= m_rowsOrCols
.Index(rowOrCol
); 
2229     if ( i 
== wxNOT_FOUND 
) 
2231         // add the attribute 
2232         m_rowsOrCols
.Add(rowOrCol
); 
2237         size_t n 
= (size_t)i
; 
2240             // change the attribute 
2241             m_attrs
[n
]->DecRef(); 
2246             // remove this attribute 
2247             m_attrs
[n
]->DecRef(); 
2248             m_rowsOrCols
.RemoveAt(n
); 
2249             m_attrs
.RemoveAt(n
); 
2254 void wxGridRowOrColAttrData::UpdateAttrRowsOrCols( size_t pos
, int numRowsOrCols 
) 
2256     size_t count 
= m_attrs
.GetCount(); 
2257     for ( size_t n 
= 0; n 
< count
; n
++ ) 
2259         int & rowOrCol 
= m_rowsOrCols
[n
]; 
2260         if ( (size_t)rowOrCol 
>= pos 
) 
2262             if ( numRowsOrCols 
> 0 ) 
2264                 // If rows inserted, include row counter where necessary 
2265                 rowOrCol 
+= numRowsOrCols
; 
2267             else if ( numRowsOrCols 
< 0) 
2269                 // If rows deleted, either decrement row counter (if row still exists) 
2270                 if ((size_t)rowOrCol 
>= pos 
- numRowsOrCols
) 
2271                     rowOrCol 
+= numRowsOrCols
; 
2274                     m_rowsOrCols
.RemoveAt((size_t)n
); 
2275                     m_attrs
.RemoveAt((size_t)n
); 
2283 // ---------------------------------------------------------------------------- 
2284 // wxGridCellAttrProvider 
2285 // ---------------------------------------------------------------------------- 
2287 wxGridCellAttrProvider::wxGridCellAttrProvider() 
2289     m_data 
= (wxGridCellAttrProviderData 
*)NULL
; 
2292 wxGridCellAttrProvider::~wxGridCellAttrProvider() 
2297 void wxGridCellAttrProvider::InitData() 
2299     m_data 
= new wxGridCellAttrProviderData
; 
2302 wxGridCellAttr 
*wxGridCellAttrProvider::GetAttr(int row
, int col
, 
2303                                                 wxGridCellAttr::wxAttrKind  kind 
) const 
2305     wxGridCellAttr 
*attr 
= (wxGridCellAttr 
*)NULL
; 
2310             case (wxGridCellAttr::Any
): 
2311                 //Get cached merge attributes. 
2312                 // Currenlty not used as no cache implemented as not mutiable 
2313                 // attr = m_data->m_mergeAttr.GetAttr(row, col); 
2316                     //Basicaly implement old version. 
2317                     //Also check merge cache, so we don't have to re-merge every time.. 
2318                     wxGridCellAttr 
*attrcell 
= (wxGridCellAttr 
*)NULL
, 
2319                                    *attrrow 
= (wxGridCellAttr 
*)NULL
, 
2320                                    *attrcol 
= (wxGridCellAttr 
*)NULL
; 
2322                     attrcell 
= m_data
->m_cellAttrs
.GetAttr(row
, col
); 
2323                     attrcol 
= m_data
->m_colAttrs
.GetAttr(col
); 
2324                     attrrow 
= m_data
->m_rowAttrs
.GetAttr(row
); 
2326                     if((attrcell 
!= attrrow
) && (attrrow 
!=attrcol
) && (attrcell 
!= attrcol
)){ 
2327                         // Two or move are non NULL 
2328                         attr 
= new wxGridCellAttr
; 
2329                         attr
->SetKind(wxGridCellAttr::Merged
); 
2333                             attr
->MergeWith(attrcell
); 
2337                             attr
->MergeWith(attrcol
); 
2341                             attr
->MergeWith(attrrow
); 
2344                         //store merge attr if cache implemented 
2346                         //m_data->m_mergeAttr.SetAttr(attr, row, col); 
2350                         // one or none is non null return it or null. 
2351                         if(attrrow
) attr 
= attrrow
; 
2352                         if(attrcol
) attr 
= attrcol
; 
2353                         if(attrcell
) attr 
= attrcell
; 
2357             case (wxGridCellAttr::Cell
): 
2358                 attr 
= m_data
->m_cellAttrs
.GetAttr(row
, col
); 
2360             case (wxGridCellAttr::Col
): 
2361                  attr 
= m_data
->m_colAttrs
.GetAttr(col
); 
2363             case (wxGridCellAttr::Row
): 
2364             attr 
= m_data
->m_rowAttrs
.GetAttr(row
); 
2368                 // (wxGridCellAttr::Default): 
2369                 // (wxGridCellAttr::Merged): 
2376 void wxGridCellAttrProvider::SetAttr(wxGridCellAttr 
*attr
, 
2382     m_data
->m_cellAttrs
.SetAttr(attr
, row
, col
); 
2385 void wxGridCellAttrProvider::SetRowAttr(wxGridCellAttr 
*attr
, int row
) 
2390     m_data
->m_rowAttrs
.SetAttr(attr
, row
); 
2393 void wxGridCellAttrProvider::SetColAttr(wxGridCellAttr 
*attr
, int col
) 
2398     m_data
->m_colAttrs
.SetAttr(attr
, col
); 
2401 void wxGridCellAttrProvider::UpdateAttrRows( size_t pos
, int numRows 
) 
2405         m_data
->m_cellAttrs
.UpdateAttrRows( pos
, numRows 
); 
2407         m_data
->m_rowAttrs
.UpdateAttrRowsOrCols( pos
, numRows 
); 
2411 void wxGridCellAttrProvider::UpdateAttrCols( size_t pos
, int numCols 
) 
2415         m_data
->m_cellAttrs
.UpdateAttrCols( pos
, numCols 
); 
2417         m_data
->m_colAttrs
.UpdateAttrRowsOrCols( pos
, numCols 
); 
2421 // ---------------------------------------------------------------------------- 
2422 // wxGridTypeRegistry 
2423 // ---------------------------------------------------------------------------- 
2425 wxGridTypeRegistry::~wxGridTypeRegistry() 
2427     size_t count 
= m_typeinfo
.Count(); 
2428     for ( size_t i 
= 0; i 
< count
; i
++ ) 
2429         delete m_typeinfo
[i
]; 
2433 void wxGridTypeRegistry::RegisterDataType(const wxString
& typeName
, 
2434                                           wxGridCellRenderer
* renderer
, 
2435                                           wxGridCellEditor
* editor
) 
2437     wxGridDataTypeInfo
* info 
= new wxGridDataTypeInfo(typeName
, renderer
, editor
); 
2439     // is it already registered? 
2440     int loc 
= FindRegisteredDataType(typeName
); 
2441     if ( loc 
!= wxNOT_FOUND 
) 
2443         delete m_typeinfo
[loc
]; 
2444         m_typeinfo
[loc
] = info
; 
2448         m_typeinfo
.Add(info
); 
2452 int wxGridTypeRegistry::FindRegisteredDataType(const wxString
& typeName
) 
2454     size_t count 
= m_typeinfo
.GetCount(); 
2455     for ( size_t i 
= 0; i 
< count
; i
++ ) 
2457         if ( typeName 
== m_typeinfo
[i
]->m_typeName 
) 
2466 int wxGridTypeRegistry::FindDataType(const wxString
& typeName
) 
2468     int index 
= FindRegisteredDataType(typeName
); 
2469     if ( index 
== wxNOT_FOUND 
) 
2471         // check whether this is one of the standard ones, in which case 
2472         // register it "on the fly" 
2474         if ( typeName 
== wxGRID_VALUE_STRING 
) 
2476             RegisterDataType(wxGRID_VALUE_STRING
, 
2477                              new wxGridCellStringRenderer
, 
2478                              new wxGridCellTextEditor
); 
2480 #endif // wxUSE_TEXTCTRL 
2482         if ( typeName 
== wxGRID_VALUE_BOOL 
) 
2484             RegisterDataType(wxGRID_VALUE_BOOL
, 
2485                              new wxGridCellBoolRenderer
, 
2486                              new wxGridCellBoolEditor
); 
2488 #endif // wxUSE_CHECKBOX 
2490         if ( typeName 
== wxGRID_VALUE_NUMBER 
) 
2492             RegisterDataType(wxGRID_VALUE_NUMBER
, 
2493                              new wxGridCellNumberRenderer
, 
2494                              new wxGridCellNumberEditor
); 
2496         else if ( typeName 
== wxGRID_VALUE_FLOAT 
) 
2498             RegisterDataType(wxGRID_VALUE_FLOAT
, 
2499                              new wxGridCellFloatRenderer
, 
2500                              new wxGridCellFloatEditor
); 
2502 #endif // wxUSE_TEXTCTRL 
2504         if ( typeName 
== wxGRID_VALUE_CHOICE 
) 
2506             RegisterDataType(wxGRID_VALUE_CHOICE
, 
2507                              new wxGridCellStringRenderer
, 
2508                              new wxGridCellChoiceEditor
); 
2510 #endif // wxUSE_COMBOBOX 
2515         // we get here only if just added the entry for this type, so return 
2517         index 
= m_typeinfo
.GetCount() - 1; 
2523 int wxGridTypeRegistry::FindOrCloneDataType(const wxString
& typeName
) 
2525     int index 
= FindDataType(typeName
); 
2526     if ( index 
== wxNOT_FOUND 
) 
2528         // the first part of the typename is the "real" type, anything after ':' 
2529         // are the parameters for the renderer 
2530         index 
= FindDataType(typeName
.BeforeFirst(_T(':'))); 
2531         if ( index 
== wxNOT_FOUND 
) 
2536         wxGridCellRenderer 
*renderer 
= GetRenderer(index
); 
2537         wxGridCellRenderer 
*rendererOld 
= renderer
; 
2538         renderer 
= renderer
->Clone(); 
2539         rendererOld
->DecRef(); 
2541         wxGridCellEditor 
*editor 
= GetEditor(index
); 
2542         wxGridCellEditor 
*editorOld 
= editor
; 
2543         editor 
= editor
->Clone(); 
2544         editorOld
->DecRef(); 
2546         // do it even if there are no parameters to reset them to defaults 
2547         wxString params 
= typeName
.AfterFirst(_T(':')); 
2548         renderer
->SetParameters(params
); 
2549         editor
->SetParameters(params
); 
2551         // register the new typename 
2552         RegisterDataType(typeName
, renderer
, editor
); 
2554         // we just registered it, it's the last one 
2555         index 
= m_typeinfo
.GetCount() - 1; 
2561 wxGridCellRenderer
* wxGridTypeRegistry::GetRenderer(int index
) 
2563     wxGridCellRenderer
* renderer 
= m_typeinfo
[index
]->m_renderer
; 
2569 wxGridCellEditor
* wxGridTypeRegistry::GetEditor(int index
) 
2571     wxGridCellEditor
* editor 
= m_typeinfo
[index
]->m_editor
; 
2577 // ---------------------------------------------------------------------------- 
2579 // ---------------------------------------------------------------------------- 
2581 IMPLEMENT_ABSTRACT_CLASS( wxGridTableBase
, wxObject 
) 
2584 wxGridTableBase::wxGridTableBase() 
2586     m_view 
= (wxGrid 
*) NULL
; 
2587     m_attrProvider 
= (wxGridCellAttrProvider 
*) NULL
; 
2590 wxGridTableBase::~wxGridTableBase() 
2592     delete m_attrProvider
; 
2595 void wxGridTableBase::SetAttrProvider(wxGridCellAttrProvider 
*attrProvider
) 
2597     delete m_attrProvider
; 
2598     m_attrProvider 
= attrProvider
; 
2601 bool wxGridTableBase::CanHaveAttributes() 
2603     if ( ! GetAttrProvider() ) 
2605         // use the default attr provider by default 
2606         SetAttrProvider(new wxGridCellAttrProvider
); 
2611 wxGridCellAttr 
*wxGridTableBase::GetAttr(int row
, int col
, wxGridCellAttr::wxAttrKind  kind
) 
2613     if ( m_attrProvider 
) 
2614         return m_attrProvider
->GetAttr(row
, col
, kind
); 
2616         return (wxGridCellAttr 
*)NULL
; 
2619 void wxGridTableBase::SetAttr(wxGridCellAttr
* attr
, int row
, int col
) 
2621     if ( m_attrProvider 
) 
2623         attr
->SetKind(wxGridCellAttr::Cell
); 
2624         m_attrProvider
->SetAttr(attr
, row
, col
); 
2628         // as we take ownership of the pointer and don't store it, we must 
2634 void wxGridTableBase::SetRowAttr(wxGridCellAttr 
*attr
, int row
) 
2636     if ( m_attrProvider 
) 
2638         attr
->SetKind(wxGridCellAttr::Row
); 
2639         m_attrProvider
->SetRowAttr(attr
, row
); 
2643         // as we take ownership of the pointer and don't store it, we must 
2649 void wxGridTableBase::SetColAttr(wxGridCellAttr 
*attr
, int col
) 
2651     if ( m_attrProvider 
) 
2653         attr
->SetKind(wxGridCellAttr::Col
); 
2654         m_attrProvider
->SetColAttr(attr
, col
); 
2658         // as we take ownership of the pointer and don't store it, we must 
2664 bool wxGridTableBase::InsertRows( size_t WXUNUSED(pos
), 
2665                                   size_t WXUNUSED(numRows
) ) 
2667     wxFAIL_MSG( wxT("Called grid table class function InsertRows\nbut your derived table class does not override this function") ); 
2672 bool wxGridTableBase::AppendRows( size_t WXUNUSED(numRows
) ) 
2674     wxFAIL_MSG( wxT("Called grid table class function AppendRows\nbut your derived table class does not override this function")); 
2679 bool wxGridTableBase::DeleteRows( size_t WXUNUSED(pos
), 
2680                                   size_t WXUNUSED(numRows
) ) 
2682     wxFAIL_MSG( wxT("Called grid table class function DeleteRows\nbut your derived table class does not override this function")); 
2687 bool wxGridTableBase::InsertCols( size_t WXUNUSED(pos
), 
2688                                   size_t WXUNUSED(numCols
) ) 
2690     wxFAIL_MSG( wxT("Called grid table class function InsertCols\nbut your derived table class does not override this function")); 
2695 bool wxGridTableBase::AppendCols( size_t WXUNUSED(numCols
) ) 
2697     wxFAIL_MSG(wxT("Called grid table class function AppendCols\nbut your derived table class does not override this function")); 
2702 bool wxGridTableBase::DeleteCols( size_t WXUNUSED(pos
), 
2703                                   size_t WXUNUSED(numCols
) ) 
2705     wxFAIL_MSG( wxT("Called grid table class function DeleteCols\nbut your derived table class does not override this function")); 
2711 wxString 
wxGridTableBase::GetRowLabelValue( int row 
) 
2714     s 
<< row 
+ 1; // RD: Starting the rows at zero confuses users, no matter 
2715                   //     how much it makes sense to us geeks. 
2719 wxString 
wxGridTableBase::GetColLabelValue( int col 
) 
2721     // default col labels are: 
2722     //   cols 0 to 25   : A-Z 
2723     //   cols 26 to 675 : AA-ZZ 
2728     for ( n 
= 1; ; n
++ ) 
2730         s 
+= (_T('A') + (wxChar
)( col%26 
)); 
2732         if ( col 
< 0 ) break; 
2735     // reverse the string... 
2737     for ( i 
= 0;  i 
< n
;  i
++ ) 
2746 wxString 
wxGridTableBase::GetTypeName( int WXUNUSED(row
), int WXUNUSED(col
) ) 
2748     return wxGRID_VALUE_STRING
; 
2751 bool wxGridTableBase::CanGetValueAs( int WXUNUSED(row
), int WXUNUSED(col
), 
2752                                      const wxString
& typeName 
) 
2754     return typeName 
== wxGRID_VALUE_STRING
; 
2757 bool wxGridTableBase::CanSetValueAs( int row
, int col
, const wxString
& typeName 
) 
2759     return CanGetValueAs(row
, col
, typeName
); 
2762 long wxGridTableBase::GetValueAsLong( int WXUNUSED(row
), int WXUNUSED(col
) ) 
2767 double wxGridTableBase::GetValueAsDouble( int WXUNUSED(row
), int WXUNUSED(col
) ) 
2772 bool wxGridTableBase::GetValueAsBool( int WXUNUSED(row
), int WXUNUSED(col
) ) 
2777 void wxGridTableBase::SetValueAsLong( int WXUNUSED(row
), int WXUNUSED(col
), 
2778                                       long WXUNUSED(value
) ) 
2782 void wxGridTableBase::SetValueAsDouble( int WXUNUSED(row
), int WXUNUSED(col
), 
2783                                         double WXUNUSED(value
) ) 
2787 void wxGridTableBase::SetValueAsBool( int WXUNUSED(row
), int WXUNUSED(col
), 
2788                                       bool WXUNUSED(value
) ) 
2793 void* wxGridTableBase::GetValueAsCustom( int WXUNUSED(row
), int WXUNUSED(col
), 
2794                                          const wxString
& WXUNUSED(typeName
) ) 
2799 void  wxGridTableBase::SetValueAsCustom( int WXUNUSED(row
), int WXUNUSED(col
), 
2800                                          const wxString
& WXUNUSED(typeName
), 
2801                                          void* WXUNUSED(value
) ) 
2805 ////////////////////////////////////////////////////////////////////// 
2807 // Message class for the grid table to send requests and notifications 
2811 wxGridTableMessage::wxGridTableMessage() 
2813     m_table 
= (wxGridTableBase 
*) NULL
; 
2819 wxGridTableMessage::wxGridTableMessage( wxGridTableBase 
*table
, int id
, 
2820                                         int commandInt1
, int commandInt2 
) 
2824     m_comInt1 
= commandInt1
; 
2825     m_comInt2 
= commandInt2
; 
2830 ////////////////////////////////////////////////////////////////////// 
2832 // A basic grid table for string data. An object of this class will 
2833 // created by wxGrid if you don't specify an alternative table class. 
2836 WX_DEFINE_OBJARRAY(wxGridStringArray
) 
2838 IMPLEMENT_DYNAMIC_CLASS( wxGridStringTable
, wxGridTableBase 
) 
2840 wxGridStringTable::wxGridStringTable() 
2845 wxGridStringTable::wxGridStringTable( int numRows
, int numCols 
) 
2850     m_data
.Alloc( numRows 
); 
2853     sa
.Alloc( numCols 
); 
2854     for ( col 
= 0;  col 
< numCols
;  col
++ ) 
2856         sa
.Add( wxEmptyString 
); 
2859     for ( row 
= 0;  row 
< numRows
;  row
++ ) 
2865 wxGridStringTable::~wxGridStringTable() 
2869 int wxGridStringTable::GetNumberRows() 
2871     return m_data
.GetCount(); 
2874 int wxGridStringTable::GetNumberCols() 
2876     if ( m_data
.GetCount() > 0 ) 
2877         return m_data
[0].GetCount(); 
2882 wxString 
wxGridStringTable::GetValue( int row
, int col 
) 
2884     wxASSERT_MSG( (row 
< GetNumberRows()) && (col 
< GetNumberCols()), 
2885                   _T("invalid row or column index in wxGridStringTable") ); 
2887     return m_data
[row
][col
]; 
2890 void wxGridStringTable::SetValue( int row
, int col
, const wxString
& value 
) 
2892     wxASSERT_MSG( (row 
< GetNumberRows()) && (col 
< GetNumberCols()), 
2893                   _T("invalid row or column index in wxGridStringTable") ); 
2895     m_data
[row
][col
] = value
; 
2898 bool wxGridStringTable::IsEmptyCell( int row
, int col 
) 
2900     wxASSERT_MSG( (row 
< GetNumberRows()) && (col 
< GetNumberCols()), 
2901                   _T("invalid row or column index in wxGridStringTable") ); 
2903     return (m_data
[row
][col
] == wxEmptyString
); 
2906 void wxGridStringTable::Clear() 
2909     int numRows
, numCols
; 
2911     numRows 
= m_data
.GetCount(); 
2914         numCols 
= m_data
[0].GetCount(); 
2916         for ( row 
= 0;  row 
< numRows
;  row
++ ) 
2918             for ( col 
= 0;  col 
< numCols
;  col
++ ) 
2920                 m_data
[row
][col
] = wxEmptyString
; 
2927 bool wxGridStringTable::InsertRows( size_t pos
, size_t numRows 
) 
2931     size_t curNumRows 
= m_data
.GetCount(); 
2932     size_t curNumCols 
= ( curNumRows 
> 0 ? m_data
[0].GetCount() : 
2933                           ( GetView() ? GetView()->GetNumberCols() : 0 ) ); 
2935     if ( pos 
>= curNumRows 
) 
2937         return AppendRows( numRows 
); 
2941     sa
.Alloc( curNumCols 
); 
2942     for ( col 
= 0;  col 
< curNumCols
;  col
++ ) 
2944         sa
.Add( wxEmptyString 
); 
2947     for ( row 
= pos
;  row 
< pos 
+ numRows
;  row
++ ) 
2949         m_data
.Insert( sa
, row 
); 
2953         wxGridTableMessage 
msg( this, 
2954                                 wxGRIDTABLE_NOTIFY_ROWS_INSERTED
, 
2958         GetView()->ProcessTableMessage( msg 
); 
2964 bool wxGridStringTable::AppendRows( size_t numRows 
) 
2968     size_t curNumRows 
= m_data
.GetCount(); 
2969     size_t curNumCols 
= ( curNumRows 
> 0 ? m_data
[0].GetCount() : 
2970                           ( GetView() ? GetView()->GetNumberCols() : 0 ) ); 
2973     if ( curNumCols 
> 0 ) 
2975         sa
.Alloc( curNumCols 
); 
2976         for ( col 
= 0;  col 
< curNumCols
;  col
++ ) 
2978             sa
.Add( wxEmptyString 
); 
2982     for ( row 
= 0;  row 
< numRows
;  row
++ ) 
2989         wxGridTableMessage 
msg( this, 
2990                                 wxGRIDTABLE_NOTIFY_ROWS_APPENDED
, 
2993         GetView()->ProcessTableMessage( msg 
); 
2999 bool wxGridStringTable::DeleteRows( size_t pos
, size_t numRows 
) 
3003     size_t curNumRows 
= m_data
.GetCount(); 
3005     if ( pos 
>= curNumRows 
) 
3008         errmsg
.Printf(wxT("Called wxGridStringTable::DeleteRows(pos=%d, N=%d)\nPos value is invalid for present table with %d rows"), 
3009                       pos
, numRows
, curNumRows 
); 
3010         wxFAIL_MSG( errmsg 
); 
3014     if ( numRows 
> curNumRows 
- pos 
) 
3016         numRows 
= curNumRows 
- pos
; 
3019     if ( numRows 
>= curNumRows 
) 
3021         m_data
.Empty();  // don't release memory just yet 
3025         for ( n 
= 0;  n 
< numRows
;  n
++ ) 
3027             m_data
.RemoveAt( pos 
); 
3032         wxGridTableMessage 
msg( this, 
3033                                 wxGRIDTABLE_NOTIFY_ROWS_DELETED
, 
3037         GetView()->ProcessTableMessage( msg 
); 
3043 bool wxGridStringTable::InsertCols( size_t pos
, size_t numCols 
) 
3047     size_t curNumRows 
= m_data
.GetCount(); 
3048     size_t curNumCols 
= ( curNumRows 
> 0 ? m_data
[0].GetCount() : 
3049                           ( GetView() ? GetView()->GetNumberCols() : 0 ) ); 
3051     if ( pos 
>= curNumCols 
) 
3053         return AppendCols( numCols 
); 
3056     for ( row 
= 0;  row 
< curNumRows
;  row
++ ) 
3058         for ( col 
= pos
;  col 
< pos 
+ numCols
;  col
++ ) 
3060             m_data
[row
].Insert( wxEmptyString
, col 
); 
3065         wxGridTableMessage 
msg( this, 
3066                                 wxGRIDTABLE_NOTIFY_COLS_INSERTED
, 
3070         GetView()->ProcessTableMessage( msg 
); 
3076 bool wxGridStringTable::AppendCols( size_t numCols 
) 
3080     size_t curNumRows 
= m_data
.GetCount(); 
3084         // TODO: something better than this ? 
3086         wxFAIL_MSG( wxT("Unable to append cols to a grid table with no rows.\nCall AppendRows() first") ); 
3091     for ( row 
= 0;  row 
< curNumRows
;  row
++ ) 
3093         for ( n 
= 0;  n 
< numCols
;  n
++ ) 
3095             m_data
[row
].Add( wxEmptyString 
); 
3101         wxGridTableMessage 
msg( this, 
3102                                 wxGRIDTABLE_NOTIFY_COLS_APPENDED
, 
3105         GetView()->ProcessTableMessage( msg 
); 
3111 bool wxGridStringTable::DeleteCols( size_t pos
, size_t numCols 
) 
3115     size_t curNumRows 
= m_data
.GetCount(); 
3116     size_t curNumCols 
= ( curNumRows 
> 0 ? m_data
[0].GetCount() : 
3117                           ( GetView() ? GetView()->GetNumberCols() : 0 ) ); 
3119     if ( pos 
>= curNumCols 
) 
3122         errmsg
.Printf( wxT("Called wxGridStringTable::DeleteCols(pos=%d, N=%d)...\nPos value is invalid for present table with %d cols"), 
3123                         pos
, numCols
, curNumCols 
); 
3124         wxFAIL_MSG( errmsg 
); 
3128     if ( numCols 
> curNumCols 
- pos 
) 
3130         numCols 
= curNumCols 
- pos
; 
3133     for ( row 
= 0;  row 
< curNumRows
;  row
++ ) 
3135         if ( numCols 
>= curNumCols 
) 
3137             m_data
[row
].Clear(); 
3141             for ( n 
= 0;  n 
< numCols
;  n
++ ) 
3143                 m_data
[row
].RemoveAt( pos 
); 
3149         wxGridTableMessage 
msg( this, 
3150                                 wxGRIDTABLE_NOTIFY_COLS_DELETED
, 
3154         GetView()->ProcessTableMessage( msg 
); 
3160 wxString 
wxGridStringTable::GetRowLabelValue( int row 
) 
3162     if ( row 
> (int)(m_rowLabels
.GetCount()) - 1 ) 
3164         // using default label 
3166         return wxGridTableBase::GetRowLabelValue( row 
); 
3170         return m_rowLabels
[ row 
]; 
3174 wxString 
wxGridStringTable::GetColLabelValue( int col 
) 
3176     if ( col 
> (int)(m_colLabels
.GetCount()) - 1 ) 
3178         // using default label 
3180         return wxGridTableBase::GetColLabelValue( col 
); 
3184         return m_colLabels
[ col 
]; 
3188 void wxGridStringTable::SetRowLabelValue( int row
, const wxString
& value 
) 
3190     if ( row 
> (int)(m_rowLabels
.GetCount()) - 1 ) 
3192         int n 
= m_rowLabels
.GetCount(); 
3194         for ( i 
= n
;  i 
<= row
;  i
++ ) 
3196             m_rowLabels
.Add( wxGridTableBase::GetRowLabelValue(i
) ); 
3200     m_rowLabels
[row
] = value
; 
3203 void wxGridStringTable::SetColLabelValue( int col
, const wxString
& value 
) 
3205     if ( col 
> (int)(m_colLabels
.GetCount()) - 1 ) 
3207         int n 
= m_colLabels
.GetCount(); 
3209         for ( i 
= n
;  i 
<= col
;  i
++ ) 
3211             m_colLabels
.Add( wxGridTableBase::GetColLabelValue(i
) ); 
3215     m_colLabels
[col
] = value
; 
3220 ////////////////////////////////////////////////////////////////////// 
3221 ////////////////////////////////////////////////////////////////////// 
3223 IMPLEMENT_DYNAMIC_CLASS( wxGridRowLabelWindow
, wxWindow 
) 
3225 BEGIN_EVENT_TABLE( wxGridRowLabelWindow
, wxWindow 
) 
3226     EVT_PAINT( wxGridRowLabelWindow::OnPaint 
) 
3227     EVT_MOUSEWHEEL( wxGridRowLabelWindow::OnMouseWheel
) 
3228     EVT_MOUSE_EVENTS( wxGridRowLabelWindow::OnMouseEvent 
) 
3229     EVT_KEY_DOWN( wxGridRowLabelWindow::OnKeyDown 
) 
3230     EVT_KEY_UP( wxGridRowLabelWindow::OnKeyUp 
) 
3233 wxGridRowLabelWindow::wxGridRowLabelWindow( wxGrid 
*parent
, 
3235                                             const wxPoint 
&pos
, const wxSize 
&size 
) 
3236   : wxWindow( parent
, id
, pos
, size
, wxWANTS_CHARS 
) 
3241 void wxGridRowLabelWindow::OnPaint( wxPaintEvent
& WXUNUSED(event
) ) 
3245     // NO - don't do this because it will set both the x and y origin 
3246     // coords to match the parent scrolled window and we just want to 
3247     // set the y coord  - MB 
3249     // m_owner->PrepareDC( dc ); 
3252     m_owner
->CalcUnscrolledPosition( 0, 0, &x
, &y 
); 
3253     dc
.SetDeviceOrigin( 0, -y 
); 
3255     wxArrayInt rows 
= m_owner
->CalcRowLabelsExposed( GetUpdateRegion() ); 
3256     m_owner
->DrawRowLabels( dc 
, rows 
); 
3260 void wxGridRowLabelWindow::OnMouseEvent( wxMouseEvent
& event 
) 
3262     m_owner
->ProcessRowLabelMouseEvent( event 
); 
3266 void wxGridRowLabelWindow::OnMouseWheel( wxMouseEvent
& event 
) 
3268     m_owner
->GetEventHandler()->ProcessEvent(event
); 
3272 // This seems to be required for wxMotif otherwise the mouse 
3273 // cursor must be in the cell edit control to get key events 
3275 void wxGridRowLabelWindow::OnKeyDown( wxKeyEvent
& event 
) 
3277     if ( !m_owner
->GetEventHandler()->ProcessEvent( event 
) ) event
.Skip(); 
3280 void wxGridRowLabelWindow::OnKeyUp( wxKeyEvent
& event 
) 
3282     if ( !m_owner
->GetEventHandler()->ProcessEvent( event 
) ) event
.Skip(); 
3287 ////////////////////////////////////////////////////////////////////// 
3289 IMPLEMENT_DYNAMIC_CLASS( wxGridColLabelWindow
, wxWindow 
) 
3291 BEGIN_EVENT_TABLE( wxGridColLabelWindow
, wxWindow 
) 
3292     EVT_PAINT( wxGridColLabelWindow::OnPaint 
) 
3293     EVT_MOUSEWHEEL( wxGridColLabelWindow::OnMouseWheel
) 
3294     EVT_MOUSE_EVENTS( wxGridColLabelWindow::OnMouseEvent 
) 
3295     EVT_KEY_DOWN( wxGridColLabelWindow::OnKeyDown 
) 
3296     EVT_KEY_UP( wxGridColLabelWindow::OnKeyUp 
) 
3299 wxGridColLabelWindow::wxGridColLabelWindow( wxGrid 
*parent
, 
3301                                             const wxPoint 
&pos
, const wxSize 
&size 
) 
3302   : wxWindow( parent
, id
, pos
, size
, wxWANTS_CHARS 
) 
3307 void wxGridColLabelWindow::OnPaint( wxPaintEvent
& WXUNUSED(event
) ) 
3311     // NO - don't do this because it will set both the x and y origin 
3312     // coords to match the parent scrolled window and we just want to 
3313     // set the x coord  - MB 
3315     // m_owner->PrepareDC( dc ); 
3318     m_owner
->CalcUnscrolledPosition( 0, 0, &x
, &y 
); 
3319     dc
.SetDeviceOrigin( -x
, 0 ); 
3321     wxArrayInt cols 
= m_owner
->CalcColLabelsExposed( GetUpdateRegion() ); 
3322     m_owner
->DrawColLabels( dc 
, cols 
); 
3326 void wxGridColLabelWindow::OnMouseEvent( wxMouseEvent
& event 
) 
3328     m_owner
->ProcessColLabelMouseEvent( event 
); 
3331 void wxGridColLabelWindow::OnMouseWheel( wxMouseEvent
& event 
) 
3333     m_owner
->GetEventHandler()->ProcessEvent(event
); 
3337 // This seems to be required for wxMotif otherwise the mouse 
3338 // cursor must be in the cell edit control to get key events 
3340 void wxGridColLabelWindow::OnKeyDown( wxKeyEvent
& event 
) 
3342     if ( !m_owner
->GetEventHandler()->ProcessEvent( event 
) ) event
.Skip(); 
3345 void wxGridColLabelWindow::OnKeyUp( wxKeyEvent
& event 
) 
3347     if ( !m_owner
->GetEventHandler()->ProcessEvent( event 
) ) event
.Skip(); 
3352 ////////////////////////////////////////////////////////////////////// 
3354 IMPLEMENT_DYNAMIC_CLASS( wxGridCornerLabelWindow
, wxWindow 
) 
3356 BEGIN_EVENT_TABLE( wxGridCornerLabelWindow
, wxWindow 
) 
3357     EVT_MOUSEWHEEL( wxGridCornerLabelWindow::OnMouseWheel
) 
3358     EVT_MOUSE_EVENTS( wxGridCornerLabelWindow::OnMouseEvent 
) 
3359     EVT_PAINT( wxGridCornerLabelWindow::OnPaint
) 
3360     EVT_KEY_DOWN( wxGridCornerLabelWindow::OnKeyDown 
) 
3361     EVT_KEY_UP( wxGridCornerLabelWindow::OnKeyUp 
) 
3364 wxGridCornerLabelWindow::wxGridCornerLabelWindow( wxGrid 
*parent
, 
3366                                                   const wxPoint 
&pos
, const wxSize 
&size 
) 
3367   : wxWindow( parent
, id
, pos
, size
, wxWANTS_CHARS 
) 
3372 void wxGridCornerLabelWindow::OnPaint( wxPaintEvent
& WXUNUSED(event
) ) 
3376     int client_height 
= 0; 
3377     int client_width 
= 0; 
3378     GetClientSize( &client_width
, &client_height 
); 
3380     dc
.SetPen( *wxBLACK_PEN 
); 
3381     dc
.DrawLine( client_width
-1, client_height
-1, client_width
-1, 0 ); 
3382     dc
.DrawLine( client_width
-1, client_height
-1, 0, client_height
-1 ); 
3384     dc
.SetPen( *wxWHITE_PEN 
); 
3385     dc
.DrawLine( 0, 0, client_width
, 0 ); 
3386     dc
.DrawLine( 0, 0, 0, client_height 
); 
3390 void wxGridCornerLabelWindow::OnMouseEvent( wxMouseEvent
& event 
) 
3392     m_owner
->ProcessCornerLabelMouseEvent( event 
); 
3396 void wxGridCornerLabelWindow::OnMouseWheel( wxMouseEvent
& event 
) 
3398     m_owner
->GetEventHandler()->ProcessEvent(event
); 
3401 // This seems to be required for wxMotif otherwise the mouse 
3402 // cursor must be in the cell edit control to get key events 
3404 void wxGridCornerLabelWindow::OnKeyDown( wxKeyEvent
& event 
) 
3406     if ( !m_owner
->GetEventHandler()->ProcessEvent( event 
) ) event
.Skip(); 
3409 void wxGridCornerLabelWindow::OnKeyUp( wxKeyEvent
& event 
) 
3411     if ( !m_owner
->GetEventHandler()->ProcessEvent( event 
) ) event
.Skip(); 
3416 ////////////////////////////////////////////////////////////////////// 
3418 IMPLEMENT_DYNAMIC_CLASS( wxGridWindow
, wxPanel 
) 
3420 BEGIN_EVENT_TABLE( wxGridWindow
, wxPanel 
) 
3421     EVT_PAINT( wxGridWindow::OnPaint 
) 
3422     EVT_MOUSEWHEEL( wxGridWindow::OnMouseWheel
) 
3423     EVT_MOUSE_EVENTS( wxGridWindow::OnMouseEvent 
) 
3424     EVT_KEY_DOWN( wxGridWindow::OnKeyDown 
) 
3425     EVT_KEY_UP( wxGridWindow::OnKeyUp 
) 
3426     EVT_ERASE_BACKGROUND( wxGridWindow::OnEraseBackground 
) 
3429 wxGridWindow::wxGridWindow( wxGrid 
*parent
, 
3430                             wxGridRowLabelWindow 
*rowLblWin
, 
3431                             wxGridColLabelWindow 
*colLblWin
, 
3432                             wxWindowID id
, const wxPoint 
&pos
, const wxSize 
&size 
) 
3433         : wxPanel( parent
, id
, pos
, size
, wxWANTS_CHARS
, "grid window" ) 
3436     m_rowLabelWin 
= rowLblWin
; 
3437     m_colLabelWin 
= colLblWin
; 
3438     SetBackgroundColour(_T("WHITE")); 
3442 wxGridWindow::~wxGridWindow() 
3447 void wxGridWindow::OnPaint( wxPaintEvent 
&WXUNUSED(event
) ) 
3449     wxPaintDC 
dc( this ); 
3450     m_owner
->PrepareDC( dc 
); 
3451     wxRegion reg 
= GetUpdateRegion(); 
3452     wxGridCellCoordsArray DirtyCells 
= m_owner
->CalcCellsExposed( reg 
); 
3453     m_owner
->DrawGridCellArea( dc 
, DirtyCells
); 
3454 #if WXGRID_DRAW_LINES 
3455     m_owner
->DrawAllGridLines( dc
, reg 
); 
3457     m_owner
->DrawGridSpace( dc 
); 
3458     m_owner
->DrawHighlight( dc 
, DirtyCells 
); 
3462 void wxGridWindow::ScrollWindow( int dx
, int dy
, const wxRect 
*rect 
) 
3464     wxPanel::ScrollWindow( dx
, dy
, rect 
); 
3465     m_rowLabelWin
->ScrollWindow( 0, dy
, rect 
); 
3466     m_colLabelWin
->ScrollWindow( dx
, 0, rect 
); 
3470 void wxGridWindow::OnMouseEvent( wxMouseEvent
& event 
) 
3472     m_owner
->ProcessGridCellMouseEvent( event 
); 
3475 void wxGridWindow::OnMouseWheel( wxMouseEvent
& event 
) 
3477     m_owner
->GetEventHandler()->ProcessEvent(event
); 
3480 // This seems to be required for wxMotif/wxGTK otherwise the mouse 
3481 // cursor must be in the cell edit control to get key events 
3483 void wxGridWindow::OnKeyDown( wxKeyEvent
& event 
) 
3485     if ( !m_owner
->GetEventHandler()->ProcessEvent( event 
) ) event
.Skip(); 
3488 void wxGridWindow::OnKeyUp( wxKeyEvent
& event 
) 
3490     if ( !m_owner
->GetEventHandler()->ProcessEvent( event 
) ) event
.Skip(); 
3493 void wxGridWindow::OnEraseBackground( wxEraseEvent
& WXUNUSED(event
) ) 
3498 ////////////////////////////////////////////////////////////////////// 
3501 IMPLEMENT_DYNAMIC_CLASS( wxGrid
, wxScrolledWindow 
) 
3503 BEGIN_EVENT_TABLE( wxGrid
, wxScrolledWindow 
) 
3504     EVT_PAINT( wxGrid::OnPaint 
) 
3505     EVT_SIZE( wxGrid::OnSize 
) 
3506     EVT_KEY_DOWN( wxGrid::OnKeyDown 
) 
3507     EVT_KEY_UP( wxGrid::OnKeyUp 
) 
3508     EVT_ERASE_BACKGROUND( wxGrid::OnEraseBackground 
) 
3511 wxGrid::wxGrid( wxWindow 
*parent
, 
3516                  const wxString
& name 
) 
3517   : wxScrolledWindow( parent
, id
, pos
, size
, (style 
| wxWANTS_CHARS
), name 
), 
3518     m_colMinWidths(GRID_HASH_SIZE
), 
3519     m_rowMinHeights(GRID_HASH_SIZE
) 
3527     // Must do this or ~wxScrollHelper will pop the wrong event handler 
3528     SetTargetWindow(this); 
3530     wxSafeDecRef(m_defaultCellAttr
); 
3532 #ifdef DEBUG_ATTR_CACHE 
3533     size_t total 
= gs_nAttrCacheHits 
+ gs_nAttrCacheMisses
; 
3534     wxPrintf(_T("wxGrid attribute cache statistics: " 
3535                 "total: %u, hits: %u (%u%%)\n"), 
3536              total
, gs_nAttrCacheHits
, 
3537              total 
? (gs_nAttrCacheHits
*100) / total 
: 0); 
3543     delete m_typeRegistry
; 
3549 // ----- internal init and update functions 
3552 void wxGrid::Create() 
3554     m_created 
= FALSE
;    // set to TRUE by CreateGrid 
3556     m_table        
= (wxGridTableBase 
*) NULL
; 
3559     m_cellEditCtrlEnabled 
= FALSE
; 
3561     m_defaultCellAttr 
= new wxGridCellAttr
; 
3562     m_defaultCellAttr
->SetDefAttr(m_defaultCellAttr
); 
3564     // Set default cell attributes 
3565     m_defaultCellAttr
->SetKind(wxGridCellAttr::Default
); 
3566     m_defaultCellAttr
->SetFont(GetFont()); 
3567     m_defaultCellAttr
->SetAlignment(wxALIGN_LEFT
, wxALIGN_TOP
); 
3568     m_defaultCellAttr
->SetTextColour( 
3569         wxSystemSettings::GetSystemColour(wxSYS_COLOUR_WINDOWTEXT
)); 
3570     m_defaultCellAttr
->SetBackgroundColour( 
3571         wxSystemSettings::GetSystemColour(wxSYS_COLOUR_WINDOW
)); 
3572     m_defaultCellAttr
->SetRenderer(new wxGridCellStringRenderer
); 
3573     m_defaultCellAttr
->SetEditor(new wxGridCellTextEditor
); 
3578     m_currentCellCoords 
= wxGridNoCellCoords
; 
3580     m_rowLabelWidth 
= WXGRID_DEFAULT_ROW_LABEL_WIDTH
; 
3581     m_colLabelHeight 
= WXGRID_DEFAULT_COL_LABEL_HEIGHT
; 
3583     // create the type registry 
3584     m_typeRegistry 
= new wxGridTypeRegistry
; 
3586     // subwindow components that make up the wxGrid 
3587     m_cornerLabelWin 
= new wxGridCornerLabelWindow( this, 
3592     m_rowLabelWin 
= new wxGridRowLabelWindow( this, 
3597     m_colLabelWin 
= new wxGridColLabelWindow( this, 
3602     m_gridWin 
= new wxGridWindow( this, 
3609     SetTargetWindow( m_gridWin 
); 
3613 bool wxGrid::CreateGrid( int numRows
, int numCols
, 
3614                          wxGrid::wxGridSelectionModes selmode 
) 
3616     wxCHECK_MSG( !m_created
, 
3618                  wxT("wxGrid::CreateGrid or wxGrid::SetTable called more than once") ); 
3620     m_numRows 
= numRows
; 
3621     m_numCols 
= numCols
; 
3623     m_table 
= new wxGridStringTable( m_numRows
, m_numCols 
); 
3624     m_table
->SetView( this ); 
3626     m_selection 
= new wxGridSelection( this, selmode 
); 
3633 void wxGrid::SetSelectionMode(wxGrid::wxGridSelectionModes selmode
) 
3637         wxFAIL_MSG( wxT("Called wxGrid::SetSelectionMode() before calling CreateGrid()") ); 
3640         m_selection
->SetSelectionMode( selmode 
); 
3643 bool wxGrid::SetTable( wxGridTableBase 
*table
, bool takeOwnership
, 
3644                        wxGrid::wxGridSelectionModes selmode 
) 
3648         // RD: Actually, this should probably be allowed.  I think it would be 
3649         // nice to be able to switch multiple Tables in and out of a single 
3650         // View at runtime.  Is there anything in the implmentation that would 
3653         // At least, you now have to cope with m_selection 
3654         wxFAIL_MSG( wxT("wxGrid::CreateGrid or wxGrid::SetTable called more than once") ); 
3659         m_numRows 
= table
->GetNumberRows(); 
3660         m_numCols 
= table
->GetNumberCols(); 
3663         m_table
->SetView( this ); 
3666         m_selection 
= new wxGridSelection( this, selmode 
); 
3677     m_rowLabelWidth  
= WXGRID_DEFAULT_ROW_LABEL_WIDTH
; 
3678     m_colLabelHeight 
= WXGRID_DEFAULT_COL_LABEL_HEIGHT
; 
3680     if ( m_rowLabelWin 
) 
3682         m_labelBackgroundColour 
= m_rowLabelWin
->GetBackgroundColour(); 
3686         m_labelBackgroundColour 
= wxColour( _T("WHITE") ); 
3689     m_labelTextColour 
= wxColour( _T("BLACK") ); 
3692     m_attrCache
.row 
= -1; 
3694     // TODO: something better than this ? 
3696     m_labelFont 
= this->GetFont(); 
3697     m_labelFont
.SetWeight( m_labelFont
.GetWeight() + 2 ); 
3699     m_rowLabelHorizAlign 
= wxALIGN_LEFT
; 
3700     m_rowLabelVertAlign  
= wxALIGN_CENTRE
; 
3702     m_colLabelHorizAlign 
= wxALIGN_CENTRE
; 
3703     m_colLabelVertAlign  
= wxALIGN_TOP
; 
3705     m_defaultColWidth  
= WXGRID_DEFAULT_COL_WIDTH
; 
3706     m_defaultRowHeight 
= m_gridWin
->GetCharHeight(); 
3708 #if defined(__WXMOTIF__) || defined(__WXGTK__)  // see also text ctrl sizing in ShowCellEditControl() 
3709     m_defaultRowHeight 
+= 8; 
3711     m_defaultRowHeight 
+= 4; 
3714     m_gridLineColour 
= wxColour( 128, 128, 255 ); 
3715     m_gridLinesEnabled 
= TRUE
; 
3716     m_cellHighlightColour 
= m_gridLineColour
; 
3717     m_cellHighlightPenWidth 
= 2; 
3718     m_cellHighlightROPenWidth 
= 1; 
3720     m_cursorMode  
= WXGRID_CURSOR_SELECT_CELL
; 
3721     m_winCapture 
= (wxWindow 
*)NULL
; 
3722     m_canDragRowSize 
= TRUE
; 
3723     m_canDragColSize 
= TRUE
; 
3724     m_canDragGridSize 
= TRUE
; 
3726     m_dragRowOrCol 
= -1; 
3727     m_isDragging 
= FALSE
; 
3728     m_startDragPos 
= wxDefaultPosition
; 
3730     m_waitForSlowClick 
= FALSE
; 
3732     m_rowResizeCursor 
= wxCursor( wxCURSOR_SIZENS 
); 
3733     m_colResizeCursor 
= wxCursor( wxCURSOR_SIZEWE 
); 
3735     m_currentCellCoords 
= wxGridNoCellCoords
; 
3737     m_selectingTopLeft 
= wxGridNoCellCoords
; 
3738     m_selectingBottomRight 
= wxGridNoCellCoords
; 
3739     m_selectionBackground 
= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_HIGHLIGHT
); 
3740     m_selectionForeground 
= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_HIGHLIGHTTEXT
); 
3742     m_editable 
= TRUE
;  // default for whole grid 
3744     m_inOnKeyDown 
= FALSE
; 
3753 // ---------------------------------------------------------------------------- 
3754 // the idea is to call these functions only when necessary because they create 
3755 // quite big arrays which eat memory mostly unnecessary - in particular, if 
3756 // default widths/heights are used for all rows/columns, we may not use these 
3759 // with some extra code, it should be possible to only store the 
3760 // widths/heights different from default ones but this will be done later... 
3761 // ---------------------------------------------------------------------------- 
3763 void wxGrid::InitRowHeights() 
3765     m_rowHeights
.Empty(); 
3766     m_rowBottoms
.Empty(); 
3768     m_rowHeights
.Alloc( m_numRows 
); 
3769     m_rowBottoms
.Alloc( m_numRows 
); 
3772     for ( int i 
= 0;  i 
< m_numRows
;  i
++ ) 
3774         m_rowHeights
.Add( m_defaultRowHeight 
); 
3775         rowBottom 
+= m_defaultRowHeight
; 
3776         m_rowBottoms
.Add( rowBottom 
); 
3780 void wxGrid::InitColWidths() 
3782     m_colWidths
.Empty(); 
3783     m_colRights
.Empty(); 
3785     m_colWidths
.Alloc( m_numCols 
); 
3786     m_colRights
.Alloc( m_numCols 
); 
3788     for ( int i 
= 0;  i 
< m_numCols
;  i
++ ) 
3790         m_colWidths
.Add( m_defaultColWidth 
); 
3791         colRight 
+= m_defaultColWidth
; 
3792         m_colRights
.Add( colRight 
); 
3796 int wxGrid::GetColWidth(int col
) const 
3798     return m_colWidths
.IsEmpty() ? m_defaultColWidth 
: m_colWidths
[col
]; 
3801 int wxGrid::GetColLeft(int col
) const 
3803     return m_colRights
.IsEmpty() ? col 
* m_defaultColWidth
 
3804                                  : m_colRights
[col
] - m_colWidths
[col
]; 
3807 int wxGrid::GetColRight(int col
) const 
3809     return m_colRights
.IsEmpty() ? (col 
+ 1) * m_defaultColWidth
 
3813 int wxGrid::GetRowHeight(int row
) const 
3815     return m_rowHeights
.IsEmpty() ? m_defaultRowHeight 
: m_rowHeights
[row
]; 
3818 int wxGrid::GetRowTop(int row
) const 
3820     return m_rowBottoms
.IsEmpty() ? row 
* m_defaultRowHeight
 
3821                                   : m_rowBottoms
[row
] - m_rowHeights
[row
]; 
3824 int wxGrid::GetRowBottom(int row
) const 
3826     return m_rowBottoms
.IsEmpty() ? (row 
+ 1) * m_defaultRowHeight
 
3827                                   : m_rowBottoms
[row
]; 
3830 void wxGrid::CalcDimensions() 
3833     GetClientSize( &cw
, &ch 
); 
3835     if ( m_colLabelWin
->IsShown() ) 
3836         cw 
-= m_rowLabelWidth
; 
3837     if ( m_rowLabelWin
->IsShown() ) 
3838         ch 
-= m_colLabelHeight
; 
3841     int w 
= m_numCols 
> 0 ? GetColRight(m_numCols 
- 1) + m_extraWidth 
+ 1 : 0; 
3842     int h 
= m_numRows 
> 0 ? GetRowBottom(m_numRows 
- 1) + m_extraHeight 
+ 1 : 0; 
3844     // preserve (more or less) the previous position 
3846     GetViewStart( &x
, &y 
); 
3847     // maybe we don't need scrollbars at all? and if we do, transform w and h 
3848     // from pixels into logical units 
3855         w 
= (w 
+ GRID_SCROLL_LINE 
- 1)/GRID_SCROLL_LINE
; 
3865         h 
= (h 
+ GRID_SCROLL_LINE 
- 1)/GRID_SCROLL_LINE
; 
3870     // do set scrollbar parameters 
3871     SetScrollbars( GRID_SCROLL_LINE
, GRID_SCROLL_LINE
, 
3872                    w
, h
, x
, y
, (GetBatchCount() != 0)); 
3876 void wxGrid::CalcWindowSizes() 
3879     GetClientSize( &cw
, &ch 
); 
3881     if ( m_cornerLabelWin
->IsShown() ) 
3882         m_cornerLabelWin
->SetSize( 0, 0, m_rowLabelWidth
, m_colLabelHeight 
); 
3884     if ( m_colLabelWin
->IsShown() ) 
3885         m_colLabelWin
->SetSize( m_rowLabelWidth
, 0, cw
-m_rowLabelWidth
, m_colLabelHeight
); 
3887     if ( m_rowLabelWin
->IsShown() ) 
3888         m_rowLabelWin
->SetSize( 0, m_colLabelHeight
, m_rowLabelWidth
, ch
-m_colLabelHeight
); 
3890     if ( m_gridWin
->IsShown() ) 
3891         m_gridWin
->SetSize( m_rowLabelWidth
, m_colLabelHeight
, cw
-m_rowLabelWidth
, ch
-m_colLabelHeight
); 
3895 // this is called when the grid table sends a message to say that it 
3896 // has been redimensioned 
3898 bool wxGrid::Redimension( wxGridTableMessage
& msg 
) 
3901     bool result 
= FALSE
; 
3904     // if we were using the default widths/heights so far, we must change them 
3906     if ( m_colWidths
.IsEmpty() ) 
3911     if ( m_rowHeights
.IsEmpty() ) 
3917     switch ( msg
.GetId() ) 
3919         case wxGRIDTABLE_NOTIFY_ROWS_INSERTED
: 
3921             size_t pos 
= msg
.GetCommandInt(); 
3922             int numRows 
= msg
.GetCommandInt2(); 
3924             m_numRows 
+= numRows
; 
3926             if ( !m_rowHeights
.IsEmpty() ) 
3928                 for ( i 
= 0;  i 
< numRows
;  i
++ ) 
3930                     m_rowHeights
.Insert( m_defaultRowHeight
, pos 
); 
3931                     m_rowBottoms
.Insert( 0, pos 
); 
3935                 if ( pos 
> 0 ) bottom 
= m_rowBottoms
[pos
-1]; 
3937                 for ( i 
= pos
;  i 
< m_numRows
;  i
++ ) 
3939                     bottom 
+= m_rowHeights
[i
]; 
3940                     m_rowBottoms
[i
] = bottom
; 
3943             if ( m_currentCellCoords 
== wxGridNoCellCoords 
) 
3945                 // if we have just inserted cols into an empty grid the current 
3946                 // cell will be undefined... 
3948                 SetCurrentCell( 0, 0 ); 
3950             m_selection
->UpdateRows( pos
, numRows 
); 
3951             wxGridCellAttrProvider 
* attrProvider 
= m_table
->GetAttrProvider(); 
3953                 attrProvider
->UpdateAttrRows( pos
, numRows 
); 
3955             if ( !GetBatchCount() ) 
3958                 m_rowLabelWin
->Refresh(); 
3964         case wxGRIDTABLE_NOTIFY_ROWS_APPENDED
: 
3966             int numRows 
= msg
.GetCommandInt(); 
3967             int oldNumRows 
= m_numRows
; 
3968             m_numRows 
+= numRows
; 
3970             if ( !m_rowHeights
.IsEmpty() ) 
3972                 for ( i 
= 0;  i 
< numRows
;  i
++ ) 
3974                     m_rowHeights
.Add( m_defaultRowHeight 
); 
3975                     m_rowBottoms
.Add( 0 ); 
3979                 if ( oldNumRows 
> 0 ) bottom 
= m_rowBottoms
[oldNumRows
-1]; 
3981                 for ( i 
= oldNumRows
;  i 
< m_numRows
;  i
++ ) 
3983                     bottom 
+= m_rowHeights
[i
]; 
3984                     m_rowBottoms
[i
] = bottom
; 
3987             if ( m_currentCellCoords 
== wxGridNoCellCoords 
) 
3989                 // if we have just inserted cols into an empty grid the current 
3990                 // cell will be undefined... 
3992                 SetCurrentCell( 0, 0 ); 
3994             if ( !GetBatchCount() ) 
3997                 m_rowLabelWin
->Refresh(); 
4003         case wxGRIDTABLE_NOTIFY_ROWS_DELETED
: 
4005             size_t pos 
= msg
.GetCommandInt(); 
4006             int numRows 
= msg
.GetCommandInt2(); 
4007             m_numRows 
-= numRows
; 
4009             if ( !m_rowHeights
.IsEmpty() ) 
4011                 for ( i 
= 0;  i 
< numRows
;  i
++ ) 
4013                     m_rowHeights
.RemoveAt( pos 
); 
4014                     m_rowBottoms
.RemoveAt( pos 
); 
4018                 for ( i 
= 0;  i 
< m_numRows
;  i
++ ) 
4020                     h 
+= m_rowHeights
[i
]; 
4021                     m_rowBottoms
[i
] = h
; 
4026                 m_currentCellCoords 
= wxGridNoCellCoords
; 
4030                 if ( m_currentCellCoords
.GetRow() >= m_numRows 
) 
4031                     m_currentCellCoords
.Set( 0, 0 ); 
4033             m_selection
->UpdateRows( pos
, -((int)numRows
) ); 
4034             wxGridCellAttrProvider 
* attrProvider 
= m_table
->GetAttrProvider(); 
4036                 attrProvider
->UpdateAttrRows( pos
, -((int)numRows
) ); 
4037 // ifdef'd out following patch from Paul Gammans 
4039                 // No need to touch column attributes, unless we 
4040                 // removed _all_ rows, in this case, we remove 
4041                 // all column attributes. 
4042                 // I hate to do this here, but the 
4043                 // needed data is not available inside UpdateAttrRows. 
4044                 if ( !GetNumberRows() ) 
4045                     attrProvider
->UpdateAttrCols( 0, -GetNumberCols() ); 
4048             if ( !GetBatchCount() ) 
4051                 m_rowLabelWin
->Refresh(); 
4057         case wxGRIDTABLE_NOTIFY_COLS_INSERTED
: 
4059             size_t pos 
= msg
.GetCommandInt(); 
4060             int numCols 
= msg
.GetCommandInt2(); 
4061             m_numCols 
+= numCols
; 
4063             if ( !m_colWidths
.IsEmpty() ) 
4065                 for ( i 
= 0;  i 
< numCols
;  i
++ ) 
4067                     m_colWidths
.Insert( m_defaultColWidth
, pos 
); 
4068                     m_colRights
.Insert( 0, pos 
); 
4072                 if ( pos 
> 0 ) right 
= m_colRights
[pos
-1]; 
4074                 for ( i 
= pos
;  i 
< m_numCols
;  i
++ ) 
4076                     right 
+= m_colWidths
[i
]; 
4077                     m_colRights
[i
] = right
; 
4080             if ( m_currentCellCoords 
== wxGridNoCellCoords 
) 
4082                 // if we have just inserted cols into an empty grid the current 
4083                 // cell will be undefined... 
4085                 SetCurrentCell( 0, 0 ); 
4087             m_selection
->UpdateCols( pos
, numCols 
); 
4088             wxGridCellAttrProvider 
* attrProvider 
= m_table
->GetAttrProvider(); 
4090                 attrProvider
->UpdateAttrCols( pos
, numCols 
); 
4091             if ( !GetBatchCount() ) 
4094                 m_colLabelWin
->Refresh(); 
4101         case wxGRIDTABLE_NOTIFY_COLS_APPENDED
: 
4103             int numCols 
= msg
.GetCommandInt(); 
4104             int oldNumCols 
= m_numCols
; 
4105             m_numCols 
+= numCols
; 
4106             if ( !m_colWidths
.IsEmpty() ) 
4108                 for ( i 
= 0;  i 
< numCols
;  i
++ ) 
4110                     m_colWidths
.Add( m_defaultColWidth 
); 
4111                     m_colRights
.Add( 0 ); 
4115                 if ( oldNumCols 
> 0 ) right 
= m_colRights
[oldNumCols
-1]; 
4117                 for ( i 
= oldNumCols
;  i 
< m_numCols
;  i
++ ) 
4119                     right 
+= m_colWidths
[i
]; 
4120                     m_colRights
[i
] = right
; 
4123             if ( m_currentCellCoords 
== wxGridNoCellCoords 
) 
4125                 // if we have just inserted cols into an empty grid the current 
4126                 // cell will be undefined... 
4128                 SetCurrentCell( 0, 0 ); 
4130             if ( !GetBatchCount() ) 
4133                 m_colLabelWin
->Refresh(); 
4139         case wxGRIDTABLE_NOTIFY_COLS_DELETED
: 
4141             size_t pos 
= msg
.GetCommandInt(); 
4142             int numCols 
= msg
.GetCommandInt2(); 
4143             m_numCols 
-= numCols
; 
4145             if ( !m_colWidths
.IsEmpty() ) 
4147                 for ( i 
= 0;  i 
< numCols
;  i
++ ) 
4149                     m_colWidths
.RemoveAt( pos 
); 
4150                     m_colRights
.RemoveAt( pos 
); 
4154                 for ( i 
= 0;  i 
< m_numCols
;  i
++ ) 
4156                     w 
+= m_colWidths
[i
]; 
4162                 m_currentCellCoords 
= wxGridNoCellCoords
; 
4166                 if ( m_currentCellCoords
.GetCol() >= m_numCols 
) 
4167                   m_currentCellCoords
.Set( 0, 0 ); 
4169             m_selection
->UpdateCols( pos
, -((int)numCols
) ); 
4170             wxGridCellAttrProvider 
* attrProvider 
= m_table
->GetAttrProvider(); 
4172                 attrProvider
->UpdateAttrCols( pos
, -((int)numCols
) ); 
4173 // ifdef'd out following patch from Paul Gammans 
4175                 // No need to touch row attributes, unless we 
4176                 // removed _all_ columns, in this case, we remove 
4177                 // all row attributes. 
4178                 // I hate to do this here, but the 
4179                 // needed data is not available inside UpdateAttrCols. 
4180                 if ( !GetNumberCols() ) 
4181                     attrProvider
->UpdateAttrRows( 0, -GetNumberRows() ); 
4184             if ( !GetBatchCount() ) 
4187                 m_colLabelWin
->Refresh(); 
4194     if (result 
&& !GetBatchCount() ) 
4195         m_gridWin
->Refresh(); 
4200 wxArrayInt 
wxGrid::CalcRowLabelsExposed( const wxRegion
& reg 
) 
4202     wxRegionIterator 
iter( reg 
); 
4205     wxArrayInt  rowlabels
;            
4212         // TODO: remove this when we can... 
4213         // There is a bug in wxMotif that gives garbage update 
4214         // rectangles if you jump-scroll a long way by clicking the 
4215         // scrollbar with middle button.  This is a work-around 
4217 #if defined(__WXMOTIF__) 
4219         m_gridWin
->GetClientSize( &cw
, &ch 
); 
4220         if ( r
.GetTop() > ch 
) r
.SetTop( 0 ); 
4221         r
.SetBottom( wxMin( r
.GetBottom(), ch 
) ); 
4224         // logical bounds of update region 
4227         CalcUnscrolledPosition( 0, r
.GetTop(), &dummy
, &top 
); 
4228         CalcUnscrolledPosition( 0, r
.GetBottom(), &dummy
, &bottom 
); 
4230         // find the row labels within these bounds 
4233         for ( row 
= 0;  row 
< m_numRows
;  row
++ ) 
4235             if ( GetRowBottom(row
) < top 
) 
4238             if ( GetRowTop(row
) > bottom 
) 
4241             rowlabels
.Add( row 
); 
4251 wxArrayInt 
wxGrid::CalcColLabelsExposed( const wxRegion
& reg 
) 
4253     wxRegionIterator 
iter( reg 
); 
4256     wxArrayInt colLabels
; 
4263         // TODO: remove this when we can... 
4264         // There is a bug in wxMotif that gives garbage update 
4265         // rectangles if you jump-scroll a long way by clicking the 
4266         // scrollbar with middle button.  This is a work-around 
4268 #if defined(__WXMOTIF__) 
4270         m_gridWin
->GetClientSize( &cw
, &ch 
); 
4271         if ( r
.GetLeft() > cw 
) r
.SetLeft( 0 ); 
4272         r
.SetRight( wxMin( r
.GetRight(), cw 
) ); 
4275         // logical bounds of update region 
4278         CalcUnscrolledPosition( r
.GetLeft(), 0, &left
, &dummy 
); 
4279         CalcUnscrolledPosition( r
.GetRight(), 0, &right
, &dummy 
); 
4281         // find the cells within these bounds 
4284         for ( col 
= 0;  col 
< m_numCols
;  col
++ ) 
4286             if ( GetColRight(col
) < left 
) 
4289             if ( GetColLeft(col
) > right 
) 
4292             colLabels
.Add( col 
); 
4301 wxGridCellCoordsArray 
wxGrid::CalcCellsExposed( const wxRegion
& reg 
) 
4303     wxRegionIterator 
iter( reg 
); 
4306     wxGridCellCoordsArray  cellsExposed
; 
4308     int left
, top
, right
, bottom
; 
4313         // TODO: remove this when we can... 
4314         // There is a bug in wxMotif that gives garbage update 
4315         // rectangles if you jump-scroll a long way by clicking the 
4316         // scrollbar with middle button.  This is a work-around 
4318 #if defined(__WXMOTIF__) 
4320         m_gridWin
->GetClientSize( &cw
, &ch 
); 
4321         if ( r
.GetTop() > ch 
) r
.SetTop( 0 ); 
4322         if ( r
.GetLeft() > cw 
) r
.SetLeft( 0 ); 
4323         r
.SetRight( wxMin( r
.GetRight(), cw 
) ); 
4324         r
.SetBottom( wxMin( r
.GetBottom(), ch 
) ); 
4327         // logical bounds of update region 
4329         CalcUnscrolledPosition( r
.GetLeft(), r
.GetTop(), &left
, &top 
); 
4330         CalcUnscrolledPosition( r
.GetRight(), r
.GetBottom(), &right
, &bottom 
); 
4332         // find the cells within these bounds 
4335         for ( row 
= 0;  row 
< m_numRows
;  row
++ ) 
4337             if ( GetRowBottom(row
) <= top 
) 
4340             if ( GetRowTop(row
) > bottom 
) 
4344             for ( col 
= 0;  col 
< m_numCols
;  col
++ ) 
4346                 if ( GetColRight(col
) <= left 
) 
4349                 if ( GetColLeft(col
) > right 
) 
4352                 cellsExposed
.Add( wxGridCellCoords( row
, col 
) ); 
4359     return cellsExposed
; 
4363 void wxGrid::ProcessRowLabelMouseEvent( wxMouseEvent
& event 
) 
4366     wxPoint 
pos( event
.GetPosition() ); 
4367     CalcUnscrolledPosition( pos
.x
, pos
.y
, &x
, &y 
); 
4369     if ( event
.Dragging() ) 
4371         m_isDragging 
= TRUE
; 
4373         if ( event
.LeftIsDown() ) 
4375             switch( m_cursorMode 
) 
4377                 case WXGRID_CURSOR_RESIZE_ROW
: 
4379                     int cw
, ch
, left
, dummy
; 
4380                     m_gridWin
->GetClientSize( &cw
, &ch 
); 
4381                     CalcUnscrolledPosition( 0, 0, &left
, &dummy 
); 
4383                     wxClientDC 
dc( m_gridWin 
); 
4386                                GetRowTop(m_dragRowOrCol
) + 
4387                                GetRowMinimalHeight(m_dragRowOrCol
) ); 
4388                     dc
.SetLogicalFunction(wxINVERT
); 
4389                     if ( m_dragLastPos 
>= 0 ) 
4391                         dc
.DrawLine( left
, m_dragLastPos
, left
+cw
, m_dragLastPos 
); 
4393                     dc
.DrawLine( left
, y
, left
+cw
, y 
); 
4398                 case WXGRID_CURSOR_SELECT_ROW
: 
4399                     if ( (row 
= YToRow( y 
)) >= 0 ) 
4401                         m_selection
->SelectRow( row
, 
4402                                                 event
.ControlDown(), 
4408                 // default label to suppress warnings about "enumeration value 
4409                 // 'xxx' not handled in switch 
4417     m_isDragging 
= FALSE
; 
4420     // ------------ Entering or leaving the window 
4422     if ( event
.Entering() || event
.Leaving() ) 
4424         ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
, m_rowLabelWin
); 
4428     // ------------ Left button pressed 
4430     else if ( event
.LeftDown() ) 
4432         // don't send a label click event for a hit on the 
4433         // edge of the row label - this is probably the user 
4434         // wanting to resize the row 
4436         if ( YToEdgeOfRow(y
) < 0 ) 
4440                  !SendEvent( wxEVT_GRID_LABEL_LEFT_CLICK
, row
, -1, event 
) ) 
4442                 if ( !event
.ShiftDown() && !event
.ControlDown() ) 
4444                 if ( event
.ShiftDown() ) 
4445                     m_selection
->SelectBlock( m_currentCellCoords
.GetRow(), 
4448                                               GetNumberCols() - 1, 
4449                                               event
.ControlDown(), 
4454                     m_selection
->SelectRow( row
, 
4455                                             event
.ControlDown(), 
4459                 ChangeCursorMode(WXGRID_CURSOR_SELECT_ROW
, m_rowLabelWin
); 
4464             // starting to drag-resize a row 
4466             if ( CanDragRowSize() ) 
4467                 ChangeCursorMode(WXGRID_CURSOR_RESIZE_ROW
, m_rowLabelWin
); 
4472     // ------------ Left double click 
4474     else if (event
.LeftDClick() ) 
4476         if ( YToEdgeOfRow(y
) < 0 ) 
4479             SendEvent( wxEVT_GRID_LABEL_LEFT_DCLICK
, row
, -1, event 
); 
4484     // ------------ Left button released 
4486     else if ( event
.LeftUp() ) 
4488         if ( m_cursorMode 
== WXGRID_CURSOR_RESIZE_ROW 
) 
4490             DoEndDragResizeRow(); 
4492             // Note: we are ending the event *after* doing 
4493             // default processing in this case 
4495             SendEvent( wxEVT_GRID_ROW_SIZE
, m_dragRowOrCol
, -1, event 
); 
4498         ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
, m_rowLabelWin
); 
4503     // ------------ Right button down 
4505     else if ( event
.RightDown() ) 
4508         if ( !SendEvent( wxEVT_GRID_LABEL_RIGHT_CLICK
, row
, -1, event 
) ) 
4510             // no default action at the moment 
4515     // ------------ Right double click 
4517     else if ( event
.RightDClick() ) 
4520         if ( !SendEvent( wxEVT_GRID_LABEL_RIGHT_DCLICK
, row
, -1, event 
) ) 
4522             // no default action at the moment 
4527     // ------------ No buttons down and mouse moving 
4529     else if ( event
.Moving() ) 
4531         m_dragRowOrCol 
= YToEdgeOfRow( y 
); 
4532         if ( m_dragRowOrCol 
>= 0 ) 
4534             if ( m_cursorMode 
== WXGRID_CURSOR_SELECT_CELL 
) 
4536                 // don't capture the mouse yet 
4537                 if ( CanDragRowSize() ) 
4538                     ChangeCursorMode(WXGRID_CURSOR_RESIZE_ROW
, m_rowLabelWin
, FALSE
); 
4541         else if ( m_cursorMode 
!= WXGRID_CURSOR_SELECT_CELL 
) 
4543             ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
, m_rowLabelWin
, FALSE
); 
4549 void wxGrid::ProcessColLabelMouseEvent( wxMouseEvent
& event 
) 
4552     wxPoint 
pos( event
.GetPosition() ); 
4553     CalcUnscrolledPosition( pos
.x
, pos
.y
, &x
, &y 
); 
4555     if ( event
.Dragging() ) 
4557         m_isDragging 
= TRUE
; 
4559         if ( event
.LeftIsDown() ) 
4561             switch( m_cursorMode 
) 
4563                 case WXGRID_CURSOR_RESIZE_COL
: 
4565                     int cw
, ch
, dummy
, top
; 
4566                     m_gridWin
->GetClientSize( &cw
, &ch 
); 
4567                     CalcUnscrolledPosition( 0, 0, &dummy
, &top 
); 
4569                     wxClientDC 
dc( m_gridWin 
); 
4572                     x 
= wxMax( x
, GetColLeft(m_dragRowOrCol
) + 
4573                                   GetColMinimalWidth(m_dragRowOrCol
)); 
4574                     dc
.SetLogicalFunction(wxINVERT
); 
4575                     if ( m_dragLastPos 
>= 0 ) 
4577                         dc
.DrawLine( m_dragLastPos
, top
, m_dragLastPos
, top
+ch 
); 
4579                     dc
.DrawLine( x
, top
, x
, top
+ch 
); 
4584                 case WXGRID_CURSOR_SELECT_COL
: 
4585                     if ( (col 
= XToCol( x 
)) >= 0 ) 
4587                         m_selection
->SelectCol( col
, 
4588                                                 event
.ControlDown(), 
4594                 // default label to suppress warnings about "enumeration value 
4595                 // 'xxx' not handled in switch 
4603     m_isDragging 
= FALSE
; 
4606     // ------------ Entering or leaving the window 
4608     if ( event
.Entering() || event
.Leaving() ) 
4610         ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
, m_colLabelWin
); 
4614     // ------------ Left button pressed 
4616     else if ( event
.LeftDown() ) 
4618         // don't send a label click event for a hit on the 
4619         // edge of the col label - this is probably the user 
4620         // wanting to resize the col 
4622         if ( XToEdgeOfCol(x
) < 0 ) 
4626                  !SendEvent( wxEVT_GRID_LABEL_LEFT_CLICK
, -1, col
, event 
) ) 
4628                 if ( !event
.ShiftDown() && !event
.ControlDown() ) 
4630                 if ( event
.ShiftDown() ) 
4631                     m_selection
->SelectBlock( 0, 
4632                                               m_currentCellCoords
.GetCol(), 
4633                                               GetNumberRows() - 1, col
, 
4634                                               event
.ControlDown(), 
4639                     m_selection
->SelectCol( col
, 
4640                                             event
.ControlDown(), 
4644                 ChangeCursorMode(WXGRID_CURSOR_SELECT_COL
, m_colLabelWin
); 
4649             // starting to drag-resize a col 
4651             if ( CanDragColSize() ) 
4652                 ChangeCursorMode(WXGRID_CURSOR_RESIZE_COL
, m_colLabelWin
); 
4657     // ------------ Left double click 
4659     if ( event
.LeftDClick() ) 
4661         if ( XToEdgeOfCol(x
) < 0 ) 
4664             SendEvent( wxEVT_GRID_LABEL_LEFT_DCLICK
, -1, col
, event 
); 
4669     // ------------ Left button released 
4671     else if ( event
.LeftUp() ) 
4673         if ( m_cursorMode 
== WXGRID_CURSOR_RESIZE_COL 
) 
4675             DoEndDragResizeCol(); 
4677             // Note: we are ending the event *after* doing 
4678             // default processing in this case 
4680             SendEvent( wxEVT_GRID_COL_SIZE
, -1, m_dragRowOrCol
, event 
); 
4683         ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
, m_colLabelWin
); 
4688     // ------------ Right button down 
4690     else if ( event
.RightDown() ) 
4693         if ( !SendEvent( wxEVT_GRID_LABEL_RIGHT_CLICK
, -1, col
, event 
) ) 
4695             // no default action at the moment 
4700     // ------------ Right double click 
4702     else if ( event
.RightDClick() ) 
4705         if ( !SendEvent( wxEVT_GRID_LABEL_RIGHT_DCLICK
, -1, col
, event 
) ) 
4707             // no default action at the moment 
4712     // ------------ No buttons down and mouse moving 
4714     else if ( event
.Moving() ) 
4716         m_dragRowOrCol 
= XToEdgeOfCol( x 
); 
4717         if ( m_dragRowOrCol 
>= 0 ) 
4719             if ( m_cursorMode 
== WXGRID_CURSOR_SELECT_CELL 
) 
4721                 // don't capture the cursor yet 
4722                 if ( CanDragColSize() ) 
4723                     ChangeCursorMode(WXGRID_CURSOR_RESIZE_COL
, m_colLabelWin
, FALSE
); 
4726         else if ( m_cursorMode 
!= WXGRID_CURSOR_SELECT_CELL 
) 
4728             ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
, m_colLabelWin
, FALSE
); 
4734 void wxGrid::ProcessCornerLabelMouseEvent( wxMouseEvent
& event 
) 
4736     if ( event
.LeftDown() ) 
4738         // indicate corner label by having both row and 
4741         if ( !SendEvent( wxEVT_GRID_LABEL_LEFT_CLICK
, -1, -1, event 
) ) 
4747     else if ( event
.LeftDClick() ) 
4749         SendEvent( wxEVT_GRID_LABEL_LEFT_DCLICK
, -1, -1, event 
); 
4752     else if ( event
.RightDown() ) 
4754         if ( !SendEvent( wxEVT_GRID_LABEL_RIGHT_CLICK
, -1, -1, event 
) ) 
4756             // no default action at the moment 
4760     else if ( event
.RightDClick() ) 
4762         if ( !SendEvent( wxEVT_GRID_LABEL_RIGHT_DCLICK
, -1, -1, event 
) ) 
4764             // no default action at the moment 
4769 void wxGrid::ChangeCursorMode(CursorMode mode
, 
4774     static const wxChar 
*cursorModes
[] = 
4783     wxLogTrace(_T("grid"), 
4784                _T("wxGrid cursor mode (mouse capture for %s): %s -> %s"), 
4785                win 
== m_colLabelWin 
? _T("colLabelWin") 
4786                                     : win 
? _T("rowLabelWin") 
4788                cursorModes
[m_cursorMode
], cursorModes
[mode
]); 
4789 #endif // __WXDEBUG__ 
4791     if ( mode 
== m_cursorMode 
&& 
4792          win 
== m_winCapture 
&& 
4793          captureMouse 
== (m_winCapture 
!= NULL
)) 
4798         // by default use the grid itself 
4804         m_winCapture
->ReleaseMouse(); 
4805         m_winCapture 
= (wxWindow 
*)NULL
; 
4808     m_cursorMode 
= mode
; 
4810     switch ( m_cursorMode 
) 
4812         case WXGRID_CURSOR_RESIZE_ROW
: 
4813             win
->SetCursor( m_rowResizeCursor 
); 
4816         case WXGRID_CURSOR_RESIZE_COL
: 
4817             win
->SetCursor( m_colResizeCursor 
); 
4821             win
->SetCursor( *wxSTANDARD_CURSOR 
); 
4824     // we need to capture mouse when resizing 
4825     bool resize 
= m_cursorMode 
== WXGRID_CURSOR_RESIZE_ROW 
|| 
4826                   m_cursorMode 
== WXGRID_CURSOR_RESIZE_COL
; 
4828     if ( captureMouse 
&& resize 
) 
4830         win
->CaptureMouse(); 
4835 void wxGrid::ProcessGridCellMouseEvent( wxMouseEvent
& event 
) 
4838     wxPoint 
pos( event
.GetPosition() ); 
4839     CalcUnscrolledPosition( pos
.x
, pos
.y
, &x
, &y 
); 
4841     wxGridCellCoords coords
; 
4842     XYToCell( x
, y
, coords 
); 
4844     if ( event
.Dragging() ) 
4846         //wxLogDebug("pos(%d, %d) coords(%d, %d)", pos.x, pos.y, coords.GetRow(), coords.GetCol()); 
4848         // Don't start doing anything until the mouse has been drug at 
4849         // least 3 pixels in any direction... 
4852             if (m_startDragPos 
== wxDefaultPosition
) 
4854                 m_startDragPos 
= pos
; 
4857             if (abs(m_startDragPos
.x 
- pos
.x
) < 4 && abs(m_startDragPos
.y 
- pos
.y
) < 4) 
4861         m_isDragging 
= TRUE
; 
4862         if ( m_cursorMode 
== WXGRID_CURSOR_SELECT_CELL 
) 
4864             // Hide the edit control, so it 
4865             // won't interfer with drag-shrinking. 
4866             if ( IsCellEditControlShown() ) 
4868                 HideCellEditControl(); 
4869                 SaveEditControlValue(); 
4872             // Have we captured the mouse yet? 
4875                 m_winCapture 
= m_gridWin
; 
4876                 m_winCapture
->CaptureMouse(); 
4879             if ( coords 
!= wxGridNoCellCoords 
) 
4881                 if ( event
.ControlDown() ) 
4883                     if ( m_selectingKeyboard 
== wxGridNoCellCoords
) 
4884                         m_selectingKeyboard 
= coords
; 
4885                     HighlightBlock ( m_selectingKeyboard
, coords 
); 
4889                     if ( !IsSelection() ) 
4891                         HighlightBlock( coords
, coords 
); 
4895                         HighlightBlock( m_currentCellCoords
, coords 
); 
4899                 if (! IsVisible(coords
)) 
4901                     MakeCellVisible(coords
); 
4902                     // TODO: need to introduce a delay or something here.  The 
4903                     // scrolling is way to fast, at least on MSW - also on GTK. 
4907         else if ( m_cursorMode 
== WXGRID_CURSOR_RESIZE_ROW 
) 
4909             int cw
, ch
, left
, dummy
; 
4910             m_gridWin
->GetClientSize( &cw
, &ch 
); 
4911             CalcUnscrolledPosition( 0, 0, &left
, &dummy 
); 
4913             wxClientDC 
dc( m_gridWin 
); 
4915             y 
= wxMax( y
, GetRowTop(m_dragRowOrCol
) + 
4916                           GetRowMinimalHeight(m_dragRowOrCol
) ); 
4917             dc
.SetLogicalFunction(wxINVERT
); 
4918             if ( m_dragLastPos 
>= 0 ) 
4920                 dc
.DrawLine( left
, m_dragLastPos
, left
+cw
, m_dragLastPos 
); 
4922             dc
.DrawLine( left
, y
, left
+cw
, y 
); 
4925         else if ( m_cursorMode 
== WXGRID_CURSOR_RESIZE_COL 
) 
4927             int cw
, ch
, dummy
, top
; 
4928             m_gridWin
->GetClientSize( &cw
, &ch 
); 
4929             CalcUnscrolledPosition( 0, 0, &dummy
, &top 
); 
4931             wxClientDC 
dc( m_gridWin 
); 
4933             x 
= wxMax( x
, GetColLeft(m_dragRowOrCol
) + 
4934                           GetColMinimalWidth(m_dragRowOrCol
) ); 
4935             dc
.SetLogicalFunction(wxINVERT
); 
4936             if ( m_dragLastPos 
>= 0 ) 
4938                 dc
.DrawLine( m_dragLastPos
, top
, m_dragLastPos
, top
+ch 
); 
4940             dc
.DrawLine( x
, top
, x
, top
+ch 
); 
4947     m_isDragging 
= FALSE
; 
4948     m_startDragPos 
= wxDefaultPosition
; 
4950     // VZ: if we do this, the mode is reset to WXGRID_CURSOR_SELECT_CELL 
4951     //     immediately after it becomes WXGRID_CURSOR_RESIZE_ROW/COL under 
4954     if ( event
.Entering() || event
.Leaving() ) 
4956         ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
); 
4957         m_gridWin
->SetCursor( *wxSTANDARD_CURSOR 
); 
4962     // ------------ Left button pressed 
4964     if ( event
.LeftDown() && coords 
!= wxGridNoCellCoords 
) 
4966         if ( !SendEvent( wxEVT_GRID_CELL_LEFT_CLICK
, 
4971             if ( !event
.ControlDown() ) 
4973             if ( event
.ShiftDown() ) 
4975                 m_selection
->SelectBlock( m_currentCellCoords
.GetRow(), 
4976                                           m_currentCellCoords
.GetCol(), 
4979                                           event
.ControlDown(), 
4984             else if ( XToEdgeOfCol(x
) < 0  && 
4985                       YToEdgeOfRow(y
) < 0 ) 
4987                 DisableCellEditControl(); 
4988                 MakeCellVisible( coords 
); 
4990                 // if this is the second click on this cell then start 
4992                 if ( m_waitForSlowClick 
&& 
4993                      (coords 
== m_currentCellCoords
) && 
4994                      CanEnableCellControl()) 
4996                     EnableCellEditControl(); 
4998                     wxGridCellAttr
* attr 
= GetCellAttr(m_currentCellCoords
); 
4999                     wxGridCellEditor 
*editor 
= attr
->GetEditor(this, 
5002                     editor
->StartingClick(); 
5006                     m_waitForSlowClick 
= FALSE
; 
5010                     if ( event
.ControlDown() ) 
5012                         m_selection
->ToggleCellSelection( coords
.GetRow(), 
5014                                                           event
.ControlDown(), 
5018                         m_selectingTopLeft 
= wxGridNoCellCoords
; 
5019                         m_selectingBottomRight 
= wxGridNoCellCoords
; 
5020                         m_selectingKeyboard 
= coords
; 
5024                         SetCurrentCell( coords 
); 
5025                         if ( m_selection
->GetSelectionMode() 
5026                              != wxGrid::wxGridSelectCells
) 
5027                             HighlightBlock( coords
, coords 
); 
5029                     m_waitForSlowClick 
= TRUE
; 
5036     // ------------ Left double click 
5038     else if ( event
.LeftDClick() && coords 
!= wxGridNoCellCoords 
) 
5040         DisableCellEditControl(); 
5042         if ( XToEdgeOfCol(x
) < 0  &&  YToEdgeOfRow(y
) < 0 ) 
5044             SendEvent( wxEVT_GRID_CELL_LEFT_DCLICK
, 
5052     // ------------ Left button released 
5054     else if ( event
.LeftUp() ) 
5056         if ( m_cursorMode 
== WXGRID_CURSOR_SELECT_CELL 
) 
5058             if ( m_selectingTopLeft 
!= wxGridNoCellCoords 
&& 
5059                  m_selectingBottomRight 
!= wxGridNoCellCoords 
) 
5063                     m_winCapture
->ReleaseMouse(); 
5064                     m_winCapture 
= NULL
; 
5066                 m_selection
->SelectBlock( m_selectingTopLeft
.GetRow(), 
5067                                           m_selectingTopLeft
.GetCol(), 
5068                                           m_selectingBottomRight
.GetRow(), 
5069                                           m_selectingBottomRight
.GetCol(), 
5070                                           event
.ControlDown(), 
5074                 m_selectingTopLeft 
= wxGridNoCellCoords
; 
5075                 m_selectingBottomRight 
= wxGridNoCellCoords
; 
5078             // Show the edit control, if it has been hidden for 
5080             ShowCellEditControl(); 
5082         else if ( m_cursorMode 
== WXGRID_CURSOR_RESIZE_ROW 
) 
5084             ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
); 
5085             DoEndDragResizeRow(); 
5087             // Note: we are ending the event *after* doing 
5088             // default processing in this case 
5090             SendEvent( wxEVT_GRID_ROW_SIZE
, m_dragRowOrCol
, -1, event 
); 
5092         else if ( m_cursorMode 
== WXGRID_CURSOR_RESIZE_COL 
) 
5094             ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
); 
5095             DoEndDragResizeCol(); 
5097             // Note: we are ending the event *after* doing 
5098             // default processing in this case 
5100             SendEvent( wxEVT_GRID_COL_SIZE
, -1, m_dragRowOrCol
, event 
); 
5107     // ------------ Right button down 
5109     else if ( event
.RightDown() && coords 
!= wxGridNoCellCoords 
) 
5111         DisableCellEditControl(); 
5112         if ( !SendEvent( wxEVT_GRID_CELL_RIGHT_CLICK
, 
5117             // no default action at the moment 
5122     // ------------ Right double click 
5124     else if ( event
.RightDClick() && coords 
!= wxGridNoCellCoords 
) 
5126         DisableCellEditControl(); 
5127         if ( !SendEvent( wxEVT_GRID_CELL_RIGHT_DCLICK
, 
5132             // no default action at the moment 
5136     // ------------ Moving and no button action 
5138     else if ( event
.Moving() && !event
.IsButton() ) 
5140         int dragRow 
= YToEdgeOfRow( y 
); 
5141         int dragCol 
= XToEdgeOfCol( x 
); 
5143         // Dragging on the corner of a cell to resize in both 
5144         // directions is not implemented yet... 
5146         if ( dragRow 
>= 0  &&  dragCol 
>= 0 ) 
5148             ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
); 
5154             m_dragRowOrCol 
= dragRow
; 
5156             if ( m_cursorMode 
== WXGRID_CURSOR_SELECT_CELL 
) 
5158                 if ( CanDragRowSize() && CanDragGridSize() ) 
5159                     ChangeCursorMode(WXGRID_CURSOR_RESIZE_ROW
); 
5164                 m_dragRowOrCol 
= dragCol
; 
5172             m_dragRowOrCol 
= dragCol
; 
5174             if ( m_cursorMode 
== WXGRID_CURSOR_SELECT_CELL 
) 
5176                 if ( CanDragColSize() && CanDragGridSize() ) 
5177                     ChangeCursorMode(WXGRID_CURSOR_RESIZE_COL
); 
5183         // Neither on a row or col edge 
5185         if ( m_cursorMode 
!= WXGRID_CURSOR_SELECT_CELL 
) 
5187             ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
); 
5193 void wxGrid::DoEndDragResizeRow() 
5195     if ( m_dragLastPos 
>= 0 ) 
5197         // erase the last line and resize the row 
5199         int cw
, ch
, left
, dummy
; 
5200         m_gridWin
->GetClientSize( &cw
, &ch 
); 
5201         CalcUnscrolledPosition( 0, 0, &left
, &dummy 
); 
5203         wxClientDC 
dc( m_gridWin 
); 
5205         dc
.SetLogicalFunction( wxINVERT 
); 
5206         dc
.DrawLine( left
, m_dragLastPos
, left
+cw
, m_dragLastPos 
); 
5207         HideCellEditControl(); 
5208         SaveEditControlValue(); 
5210         int rowTop 
= GetRowTop(m_dragRowOrCol
); 
5211         SetRowSize( m_dragRowOrCol
, 
5212                     wxMax( m_dragLastPos 
- rowTop
, WXGRID_MIN_ROW_HEIGHT 
) ); 
5214         if ( !GetBatchCount() ) 
5216             // Only needed to get the correct rect.y: 
5217             wxRect 
rect ( CellToRect( m_dragRowOrCol
, 0 ) ); 
5219             CalcScrolledPosition(0, rect
.y
, &dummy
, &rect
.y
); 
5220             rect
.width 
= m_rowLabelWidth
; 
5221             rect
.height 
= ch 
- rect
.y
; 
5222             m_rowLabelWin
->Refresh( TRUE
, &rect 
); 
5224             m_gridWin
->Refresh( FALSE
, &rect 
); 
5227         ShowCellEditControl(); 
5232 void wxGrid::DoEndDragResizeCol() 
5234     if ( m_dragLastPos 
>= 0 ) 
5236         // erase the last line and resize the col 
5238         int cw
, ch
, dummy
, top
; 
5239         m_gridWin
->GetClientSize( &cw
, &ch 
); 
5240         CalcUnscrolledPosition( 0, 0, &dummy
, &top 
); 
5242         wxClientDC 
dc( m_gridWin 
); 
5244         dc
.SetLogicalFunction( wxINVERT 
); 
5245         dc
.DrawLine( m_dragLastPos
, top
, m_dragLastPos
, top
+ch 
); 
5246         HideCellEditControl(); 
5247         SaveEditControlValue(); 
5249         int colLeft 
= GetColLeft(m_dragRowOrCol
); 
5250         SetColSize( m_dragRowOrCol
, 
5251                     wxMax( m_dragLastPos 
- colLeft
, 
5252                            GetColMinimalWidth(m_dragRowOrCol
) ) ); 
5254         if ( !GetBatchCount() ) 
5256             // Only needed to get the correct rect.x: 
5257             wxRect 
rect ( CellToRect( 0, m_dragRowOrCol 
) ); 
5259             CalcScrolledPosition(rect
.x
, 0, &rect
.x
, &dummy
); 
5260             rect
.width 
= cw 
- rect
.x
; 
5261             rect
.height 
= m_colLabelHeight
; 
5262             m_colLabelWin
->Refresh( TRUE
, &rect 
); 
5264             m_gridWin
->Refresh( FALSE
, &rect 
); 
5267         ShowCellEditControl(); 
5274 // ------ interaction with data model 
5276 bool wxGrid::ProcessTableMessage( wxGridTableMessage
& msg 
) 
5278     switch ( msg
.GetId() ) 
5280         case wxGRIDTABLE_REQUEST_VIEW_GET_VALUES
: 
5281             return GetModelValues(); 
5283         case wxGRIDTABLE_REQUEST_VIEW_SEND_VALUES
: 
5284             return SetModelValues(); 
5286         case wxGRIDTABLE_NOTIFY_ROWS_INSERTED
: 
5287         case wxGRIDTABLE_NOTIFY_ROWS_APPENDED
: 
5288         case wxGRIDTABLE_NOTIFY_ROWS_DELETED
: 
5289         case wxGRIDTABLE_NOTIFY_COLS_INSERTED
: 
5290         case wxGRIDTABLE_NOTIFY_COLS_APPENDED
: 
5291         case wxGRIDTABLE_NOTIFY_COLS_DELETED
: 
5292             return Redimension( msg 
); 
5301 // The behaviour of this function depends on the grid table class 
5302 // Clear() function.  For the default wxGridStringTable class the 
5303 // behavious is to replace all cell contents with wxEmptyString but 
5304 // not to change the number of rows or cols. 
5306 void wxGrid::ClearGrid() 
5310         if (IsCellEditControlEnabled()) 
5311             DisableCellEditControl(); 
5314         if ( !GetBatchCount() ) m_gridWin
->Refresh(); 
5319 bool wxGrid::InsertRows( int pos
, int numRows
, bool WXUNUSED(updateLabels
) ) 
5321     // TODO: something with updateLabels flag 
5325         wxFAIL_MSG( wxT("Called wxGrid::InsertRows() before calling CreateGrid()") ); 
5331         if (IsCellEditControlEnabled()) 
5332             DisableCellEditControl(); 
5334         return m_table
->InsertRows( pos
, numRows 
); 
5336         // the table will have sent the results of the insert row 
5337         // operation to this view object as a grid table message 
5343 bool wxGrid::AppendRows( int numRows
, bool WXUNUSED(updateLabels
) ) 
5345     // TODO: something with updateLabels flag 
5349         wxFAIL_MSG( wxT("Called wxGrid::AppendRows() before calling CreateGrid()") ); 
5353     return ( m_table 
&& m_table
->AppendRows( numRows 
) ); 
5354     // the table will have sent the results of the append row 
5355     // operation to this view object as a grid table message 
5359 bool wxGrid::DeleteRows( int pos
, int numRows
, bool WXUNUSED(updateLabels
) ) 
5361     // TODO: something with updateLabels flag 
5365         wxFAIL_MSG( wxT("Called wxGrid::DeleteRows() before calling CreateGrid()") ); 
5371         if (IsCellEditControlEnabled()) 
5372             DisableCellEditControl(); 
5374         return (m_table
->DeleteRows( pos
, numRows 
)); 
5375         // the table will have sent the results of the delete row 
5376         // operation to this view object as a grid table message 
5382 bool wxGrid::InsertCols( int pos
, int numCols
, bool WXUNUSED(updateLabels
) ) 
5384     // TODO: something with updateLabels flag 
5388         wxFAIL_MSG( wxT("Called wxGrid::InsertCols() before calling CreateGrid()") ); 
5394         if (IsCellEditControlEnabled()) 
5395             DisableCellEditControl(); 
5397         return m_table
->InsertCols( pos
, numCols 
); 
5398         // the table will have sent the results of the insert col 
5399         // operation to this view object as a grid table message 
5405 bool wxGrid::AppendCols( int numCols
, bool WXUNUSED(updateLabels
) ) 
5407     // TODO: something with updateLabels flag 
5411         wxFAIL_MSG( wxT("Called wxGrid::AppendCols() before calling CreateGrid()") ); 
5415     return ( m_table 
&& m_table
->AppendCols( numCols 
) ); 
5416     // the table will have sent the results of the append col 
5417     // operation to this view object as a grid table message 
5421 bool wxGrid::DeleteCols( int pos
, int numCols
, bool WXUNUSED(updateLabels
) ) 
5423     // TODO: something with updateLabels flag 
5427         wxFAIL_MSG( wxT("Called wxGrid::DeleteCols() before calling CreateGrid()") ); 
5433         if (IsCellEditControlEnabled()) 
5434             DisableCellEditControl(); 
5436         return ( m_table
->DeleteCols( pos
, numCols 
) ); 
5437         // the table will have sent the results of the delete col 
5438         // operation to this view object as a grid table message 
5446 // ----- event handlers 
5449 // Generate a grid event based on a mouse event and 
5450 // return the result of ProcessEvent() 
5452 bool wxGrid::SendEvent( const wxEventType type
, 
5454                         wxMouseEvent
& mouseEv 
) 
5456     if ( type 
== wxEVT_GRID_ROW_SIZE 
|| type 
== wxEVT_GRID_COL_SIZE 
) 
5458         int rowOrCol 
= (row 
== -1 ? col 
: row
); 
5460         wxGridSizeEvent 
gridEvt( GetId(), 
5464                                  mouseEv
.GetX() + GetRowLabelSize(), 
5465                                  mouseEv
.GetY() + GetColLabelSize(), 
5466                                  mouseEv
.ControlDown(), 
5467                                  mouseEv
.ShiftDown(), 
5469                                  mouseEv
.MetaDown() ); 
5470         return GetEventHandler()->ProcessEvent(gridEvt
); 
5472     else if ( type 
== wxEVT_GRID_RANGE_SELECT 
) 
5474         // Right now, it should _never_ end up here! 
5475         wxGridRangeSelectEvent 
gridEvt( GetId(), 
5479                                         m_selectingBottomRight
, 
5481                                         mouseEv
.ControlDown(), 
5482                                         mouseEv
.ShiftDown(), 
5484                                         mouseEv
.MetaDown() ); 
5486         return GetEventHandler()->ProcessEvent(gridEvt
); 
5490         wxGridEvent 
gridEvt( GetId(), 
5494                              mouseEv
.GetX() + GetRowLabelSize(), 
5495                              mouseEv
.GetY() + GetColLabelSize(), 
5497                              mouseEv
.ControlDown(), 
5498                              mouseEv
.ShiftDown(), 
5500                              mouseEv
.MetaDown() ); 
5501         return GetEventHandler()->ProcessEvent(gridEvt
); 
5506 // Generate a grid event of specified type and return the result 
5507 // of ProcessEvent(). 
5509 bool wxGrid::SendEvent( const wxEventType type
, 
5512     if ( type 
== wxEVT_GRID_ROW_SIZE 
|| type 
== wxEVT_GRID_COL_SIZE 
) 
5514         int rowOrCol 
= (row 
== -1 ? col 
: row
); 
5516         wxGridSizeEvent 
gridEvt( GetId(), 
5521         return GetEventHandler()->ProcessEvent(gridEvt
); 
5525         wxGridEvent 
gridEvt( GetId(), 
5530         return GetEventHandler()->ProcessEvent(gridEvt
); 
5535 void wxGrid::OnPaint( wxPaintEvent
& WXUNUSED(event
) ) 
5537     wxPaintDC 
dc(this);  // needed to prevent zillions of paint events on MSW 
5541 // This is just here to make sure that CalcDimensions gets called when 
5542 // the grid view is resized... then the size event is skipped to allow 
5543 // the box sizers to handle everything 
5545 void wxGrid::OnSize( wxSizeEvent
& WXUNUSED(event
) ) 
5552 void wxGrid::OnKeyDown( wxKeyEvent
& event 
) 
5554     if ( m_inOnKeyDown 
) 
5556         // shouldn't be here - we are going round in circles... 
5558         wxFAIL_MSG( wxT("wxGrid::OnKeyDown called while already active") ); 
5561     m_inOnKeyDown 
= TRUE
; 
5563     // propagate the event up and see if it gets processed 
5565     wxWindow 
*parent 
= GetParent(); 
5566     wxKeyEvent 
keyEvt( event 
); 
5567     keyEvt
.SetEventObject( parent 
); 
5569     if ( !parent
->GetEventHandler()->ProcessEvent( keyEvt 
) ) 
5572         // try local handlers 
5574         switch ( event
.KeyCode() ) 
5577                 if ( event
.ControlDown() ) 
5579                     MoveCursorUpBlock( event
.ShiftDown() ); 
5583                     MoveCursorUp( event
.ShiftDown() ); 
5588                 if ( event
.ControlDown() ) 
5590                     MoveCursorDownBlock( event
.ShiftDown() ); 
5594                     MoveCursorDown( event
.ShiftDown() ); 
5599                 if ( event
.ControlDown() ) 
5601                     MoveCursorLeftBlock( event
.ShiftDown() ); 
5605                     MoveCursorLeft( event
.ShiftDown() ); 
5610                 if ( event
.ControlDown() ) 
5612                     MoveCursorRightBlock( event
.ShiftDown() ); 
5616                     MoveCursorRight( event
.ShiftDown() ); 
5621             case WXK_NUMPAD_ENTER
: 
5622                 if ( event
.ControlDown() ) 
5624                     event
.Skip();  // to let the edit control have the return 
5628                     if ( GetGridCursorRow() < GetNumberRows()-1 ) 
5630                         MoveCursorDown( event
.ShiftDown() ); 
5634                         // at the bottom of a column 
5635                         HideCellEditControl(); 
5636                         SaveEditControlValue(); 
5646                 if (event
.ShiftDown()) 
5648                     if ( GetGridCursorCol() > 0 ) 
5650                         MoveCursorLeft( FALSE 
); 
5655                         HideCellEditControl(); 
5656                         SaveEditControlValue(); 
5661                     if ( GetGridCursorCol() < GetNumberCols()-1 ) 
5663                         MoveCursorRight( FALSE 
); 
5668                         HideCellEditControl(); 
5669                         SaveEditControlValue(); 
5675                 if ( event
.ControlDown() ) 
5677                     MakeCellVisible( 0, 0 ); 
5678                     SetCurrentCell( 0, 0 ); 
5687                 if ( event
.ControlDown() ) 
5689                     MakeCellVisible( m_numRows
-1, m_numCols
-1 ); 
5690                     SetCurrentCell( m_numRows
-1, m_numCols
-1 ); 
5707                 if ( event
.ControlDown() ) 
5709                     m_selection
->ToggleCellSelection( m_currentCellCoords
.GetRow(), 
5710                                                       m_currentCellCoords
.GetCol(), 
5711                                                       event
.ControlDown(), 
5717                 if ( !IsEditable() ) 
5719                     MoveCursorRight( FALSE 
); 
5722                 // Otherwise fall through to default 
5725                 // is it possible to edit the current cell at all? 
5726                 if ( !IsCellEditControlEnabled() && CanEnableCellControl() ) 
5728                     // yes, now check whether the cells editor accepts the key 
5729                     int row 
= m_currentCellCoords
.GetRow(); 
5730                     int col 
= m_currentCellCoords
.GetCol(); 
5731                     wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
5732                     wxGridCellEditor 
*editor 
= attr
->GetEditor(this, row
, col
); 
5734                     // <F2> is special and will always start editing, for 
5735                     // other keys - ask the editor itself 
5736                     if ( (event
.KeyCode() == WXK_F2 
&& !event
.HasModifiers()) 
5737                          || editor
->IsAcceptedKey(event
) ) 
5739                         EnableCellEditControl(); 
5740                         editor
->StartingKey(event
); 
5752                     // let others process char events with modifiers or all 
5753                     // char events for readonly cells 
5760     m_inOnKeyDown 
= FALSE
; 
5763 void wxGrid::OnKeyUp( wxKeyEvent
& event 
) 
5765     // try local handlers 
5767     if ( event
.KeyCode() == WXK_SHIFT 
) 
5769         if ( m_selectingTopLeft 
!= wxGridNoCellCoords 
&& 
5770              m_selectingBottomRight 
!= wxGridNoCellCoords 
) 
5771             m_selection
->SelectBlock( m_selectingTopLeft
.GetRow(), 
5772                                       m_selectingTopLeft
.GetCol(), 
5773                                       m_selectingBottomRight
.GetRow(), 
5774                                       m_selectingBottomRight
.GetCol(), 
5775                                       event
.ControlDown(), 
5779         m_selectingTopLeft 
= wxGridNoCellCoords
; 
5780         m_selectingBottomRight 
= wxGridNoCellCoords
; 
5781         m_selectingKeyboard 
= wxGridNoCellCoords
; 
5785 void wxGrid::OnEraseBackground(wxEraseEvent
&) 
5789 void wxGrid::SetCurrentCell( const wxGridCellCoords
& coords 
) 
5791     if ( SendEvent( wxEVT_GRID_SELECT_CELL
, coords
.GetRow(), coords
.GetCol() ) ) 
5793         // the event has been intercepted - do nothing 
5797     wxClientDC 
dc(m_gridWin
); 
5800     if ( m_currentCellCoords 
!= wxGridNoCellCoords 
) 
5802         HideCellEditControl(); 
5803         DisableCellEditControl(); 
5805         if ( IsVisible( m_currentCellCoords
, FALSE 
) ) 
5808             r 
= BlockToDeviceRect(m_currentCellCoords
, coords
); 
5809             if ( !m_gridLinesEnabled 
) 
5817              wxGridCellCoordsArray cells 
= CalcCellsExposed( r 
); 
5819             // Otherwise refresh redraws the highlight! 
5820             m_currentCellCoords 
= coords
; 
5822             DrawGridCellArea(dc
,cells
); 
5823             DrawAllGridLines( dc
, r 
); 
5827     m_currentCellCoords 
= coords
; 
5829     wxGridCellAttr
* attr 
= GetCellAttr(coords
); 
5830     DrawCellHighlight(dc
, attr
); 
5835 void wxGrid::HighlightBlock( int topRow
, int leftCol
, int bottomRow
, int rightCol 
) 
5838     wxGridCellCoords updateTopLeft
, updateBottomRight
; 
5840     if ( m_selection
->GetSelectionMode() == wxGrid::wxGridSelectRows 
) 
5843         rightCol 
= GetNumberCols() - 1; 
5845     else if ( m_selection
->GetSelectionMode() == wxGrid::wxGridSelectColumns 
) 
5848         bottomRow 
= GetNumberRows() - 1; 
5850     if ( topRow 
> bottomRow 
) 
5857     if ( leftCol 
> rightCol 
) 
5864     updateTopLeft 
= wxGridCellCoords( topRow
, leftCol 
); 
5865     updateBottomRight 
= wxGridCellCoords( bottomRow
, rightCol 
); 
5867     if ( m_selectingTopLeft 
!= updateTopLeft 
|| 
5868          m_selectingBottomRight 
!= updateBottomRight 
) 
5870         // Compute two optimal update rectangles: 
5871         // Either one rectangle is a real subset of the 
5872         // other, or they are (almost) disjoint! 
5874         bool    need_refresh
[4]; 
5878         need_refresh
[3] = FALSE
; 
5881         // Store intermediate values 
5882         wxCoord oldLeft   
= m_selectingTopLeft
.GetCol(); 
5883         wxCoord oldTop    
= m_selectingTopLeft
.GetRow(); 
5884         wxCoord oldRight  
= m_selectingBottomRight
.GetCol(); 
5885         wxCoord oldBottom 
= m_selectingBottomRight
.GetRow(); 
5887         // Determine the outer/inner coordinates. 
5888         if (oldLeft 
> leftCol
) 
5894         if (oldTop 
> topRow 
) 
5900         if (oldRight 
< rightCol 
) 
5903             oldRight 
= rightCol
; 
5906         if (oldBottom 
< bottomRow
) 
5909             oldBottom 
= bottomRow
; 
5913         // Now, either the stuff marked old is the outer 
5914         // rectangle or we don't have a situation where one 
5915         // is contained in the other. 
5917         if ( oldLeft 
< leftCol 
) 
5919             need_refresh
[0] = TRUE
; 
5920             rect
[0] = BlockToDeviceRect( wxGridCellCoords ( oldTop
, 
5922                                          wxGridCellCoords ( oldBottom
, 
5926         if ( oldTop  
< topRow 
) 
5928             need_refresh
[1] = TRUE
; 
5929             rect
[1] = BlockToDeviceRect( wxGridCellCoords ( oldTop
, 
5931                                          wxGridCellCoords ( topRow 
- 1, 
5935         if ( oldRight 
> rightCol 
) 
5937             need_refresh
[2] = TRUE
; 
5938             rect
[2] = BlockToDeviceRect( wxGridCellCoords ( oldTop
, 
5940                                          wxGridCellCoords ( oldBottom
, 
5944         if ( oldBottom 
> bottomRow 
) 
5946             need_refresh
[3] = TRUE
; 
5947             rect
[3] = BlockToDeviceRect( wxGridCellCoords ( bottomRow 
+ 1, 
5949                                          wxGridCellCoords ( oldBottom
, 
5955         m_selectingTopLeft 
= updateTopLeft
; 
5956         m_selectingBottomRight 
= updateBottomRight
; 
5958         // various Refresh() calls 
5959         for (i 
= 0; i 
< 4; i
++ ) 
5960             if ( need_refresh
[i
] && rect
[i
] != wxGridNoCellRect 
) 
5961                 m_gridWin
->Refresh( FALSE
, &(rect
[i
]) ); 
5964     // never generate an event as it will be generated from 
5965     // wxGridSelection::SelectBlock! 
5966     // (old comment from when this was the body of SelectBlock) 
5970 // ------ functions to get/send data (see also public functions) 
5973 bool wxGrid::GetModelValues() 
5977         // all we need to do is repaint the grid 
5979         m_gridWin
->Refresh(); 
5987 bool wxGrid::SetModelValues() 
5993         for ( row 
= 0;  row 
< m_numRows
;  row
++ ) 
5995             for ( col 
= 0;  col 
< m_numCols
;  col
++ ) 
5997                 m_table
->SetValue( row
, col
, GetCellValue(row
, col
) ); 
6009 // Note - this function only draws cells that are in the list of 
6010 // exposed cells (usually set from the update region by 
6011 // CalcExposedCells) 
6013 void wxGrid::DrawGridCellArea( wxDC
& dc
, const wxGridCellCoordsArray
& cells 
) 
6015     if ( !m_numRows 
|| !m_numCols 
) return; 
6018     size_t numCells 
= cells
.GetCount(); 
6020     for ( i 
= 0;  i 
< numCells
;  i
++ ) 
6022         DrawCell( dc
, cells
[i
] ); 
6027 void wxGrid::DrawGridSpace( wxDC
& dc 
) 
6030   m_gridWin
->GetClientSize( &cw
, &ch 
); 
6033   CalcUnscrolledPosition( cw
, ch
, &right
, &bottom 
); 
6035   int rightCol 
= m_numCols 
> 0 ? GetColRight(m_numCols 
- 1) : 0; 
6036   int bottomRow 
= m_numRows 
> 0 ? GetRowBottom(m_numRows 
- 1) : 0 ; 
6038   if ( right 
> rightCol 
|| bottom 
> bottomRow 
) 
6041       CalcUnscrolledPosition( 0, 0, &left
, &top 
); 
6043       dc
.SetBrush( wxBrush(GetDefaultCellBackgroundColour(), wxSOLID
) ); 
6044       dc
.SetPen( *wxTRANSPARENT_PEN 
); 
6046       if ( right 
> rightCol 
) 
6048           dc
.DrawRectangle( rightCol
, top
, right 
- rightCol
, ch
); 
6051       if ( bottom 
> bottomRow 
) 
6053           dc
.DrawRectangle( left
, bottomRow
, cw
, bottom 
- bottomRow
); 
6059 void wxGrid::DrawCell( wxDC
& dc
, const wxGridCellCoords
& coords 
) 
6061     int row 
= coords
.GetRow(); 
6062     int col 
= coords
.GetCol(); 
6064     if ( GetColWidth(col
) <= 0 || GetRowHeight(row
) <= 0 ) 
6067     // we draw the cell border ourselves 
6068 #if !WXGRID_DRAW_LINES 
6069     if ( m_gridLinesEnabled 
) 
6070         DrawCellBorder( dc
, coords 
); 
6073     wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
6075     bool isCurrent 
= coords 
== m_currentCellCoords
; 
6077     wxRect rect 
= CellToRect( row
, col 
); 
6079     // if the editor is shown, we should use it and not the renderer 
6080     // Note: However, only if it is really _shown_, i.e. not hidden! 
6081     if ( isCurrent 
&& IsCellEditControlShown() ) 
6083         wxGridCellEditor 
*editor 
= attr
->GetEditor(this, row
, col
); 
6084         editor
->PaintBackground(rect
, attr
); 
6089         // but all the rest is drawn by the cell renderer and hence may be 
6091         wxGridCellRenderer 
*renderer 
= attr
->GetRenderer(this, row
, col
); 
6092         renderer
->Draw(*this, *attr
, dc
, rect
, row
, col
, IsInSelection(coords
)); 
6099 void wxGrid::DrawCellHighlight( wxDC
& dc
, const wxGridCellAttr 
*attr 
) 
6101     int row 
= m_currentCellCoords
.GetRow(); 
6102     int col 
= m_currentCellCoords
.GetCol(); 
6104     if ( GetColWidth(col
) <= 0 || GetRowHeight(row
) <= 0 ) 
6107     wxRect rect 
= CellToRect(row
, col
); 
6109     // hmmm... what could we do here to show that the cell is disabled? 
6110     // for now, I just draw a thinner border than for the other ones, but 
6111     // it doesn't look really good 
6113     int penWidth 
= attr
->IsReadOnly() ? m_cellHighlightROPenWidth 
: m_cellHighlightPenWidth
; 
6117         // The center of th drawn line is where the position/width/height of 
6118         // the rectangle is actually at, (on wxMSW atr least,) so we will 
6119         // reduce the size of the rectangle to compensate for the thickness of 
6120         // the line.  If this is too strange on non wxMSW platforms then 
6121         // please #ifdef this appropriately. 
6122         rect
.x 
+= penWidth
/2; 
6123         rect
.y 
+= penWidth
/2; 
6124         rect
.width 
-= penWidth
-1; 
6125         rect
.height 
-= penWidth
-1; 
6128         // Now draw the rectangle 
6129         dc
.SetPen(wxPen(m_cellHighlightColour
, penWidth
, wxSOLID
)); 
6130         dc
.SetBrush(*wxTRANSPARENT_BRUSH
); 
6131         dc
.DrawRectangle(rect
); 
6135         // VZ: my experiments with 3d borders... 
6137         // how to properly set colours for arbitrary bg? 
6138         wxCoord x1 
= rect
.x
, 
6140                 x2 
= rect
.x 
+ rect
.width 
-1, 
6141                 y2 
= rect
.y 
+ rect
.height 
-1; 
6143         dc
.SetPen(*wxWHITE_PEN
); 
6144         dc
.DrawLine(x1
, y1
, x2
, y1
); 
6145         dc
.DrawLine(x1
, y1
, x1
, y2
); 
6147         dc
.DrawLine(x1 
+ 1, y2 
- 1, x2 
- 1, y2 
- 1); 
6148         dc
.DrawLine(x2 
- 1, y1 
+ 1, x2 
- 1, y2 
); 
6150         dc
.SetPen(*wxBLACK_PEN
); 
6151         dc
.DrawLine(x1
, y2
, x2
, y2
); 
6152         dc
.DrawLine(x2
, y1
, x2
, y2
+1); 
6157 void wxGrid::DrawCellBorder( wxDC
& dc
, const wxGridCellCoords
& coords 
) 
6159     int row 
= coords
.GetRow(); 
6160     int col 
= coords
.GetCol(); 
6161     if ( GetColWidth(col
) <= 0 || GetRowHeight(row
) <= 0 ) 
6164     dc
.SetPen( wxPen(GetGridLineColour(), 1, wxSOLID
) ); 
6166     // right hand border 
6168     dc
.DrawLine( GetColRight(col
), GetRowTop(row
), 
6169                  GetColRight(col
), GetRowBottom(row
) ); 
6173     dc
.DrawLine( GetColLeft(col
), GetRowBottom(row
), 
6174                  GetColRight(col
), GetRowBottom(row
) ); 
6177 void wxGrid::DrawHighlight(wxDC
& dc
,const  wxGridCellCoordsArray
& cells
) 
6179     // This if block was previously in wxGrid::OnPaint but that doesn't 
6180     // seem to get called under wxGTK - MB 
6182     if ( m_currentCellCoords 
== wxGridNoCellCoords  
&& 
6183          m_numRows 
&& m_numCols 
) 
6185         m_currentCellCoords
.Set(0, 0); 
6188     if ( IsCellEditControlShown() ) 
6190         // don't show highlight when the edit control is shown 
6194     // if the active cell was repainted, repaint its highlight too because it 
6195     // might have been damaged by the grid lines 
6196     size_t count 
= cells
.GetCount(); 
6197     for ( size_t n 
= 0; n 
< count
; n
++ ) 
6199         if ( cells
[n
] == m_currentCellCoords 
) 
6201             wxGridCellAttr
* attr 
= GetCellAttr(m_currentCellCoords
); 
6202             DrawCellHighlight(dc
, attr
); 
6210 // TODO: remove this ??? 
6211 // This is used to redraw all grid lines e.g. when the grid line colour 
6214 void wxGrid::DrawAllGridLines( wxDC
& dc
, const wxRegion 
& WXUNUSED(reg
) ) 
6216     if ( !m_gridLinesEnabled 
|| 
6218          !m_numCols 
) return; 
6220     int top
, bottom
, left
, right
; 
6222 #if 0  //#ifndef __WXGTK__ 
6226       m_gridWin
->GetClientSize(&cw
, &ch
); 
6228       // virtual coords of visible area 
6230       CalcUnscrolledPosition( 0, 0, &left
, &top 
); 
6231       CalcUnscrolledPosition( cw
, ch
, &right
, &bottom 
); 
6236       reg
.GetBox(x
, y
, w
, h
); 
6237       CalcUnscrolledPosition( x
, y
, &left
, &top 
); 
6238       CalcUnscrolledPosition( x 
+ w
, y 
+ h
, &right
, &bottom 
); 
6242       m_gridWin
->GetClientSize(&cw
, &ch
); 
6243       CalcUnscrolledPosition( 0, 0, &left
, &top 
); 
6244       CalcUnscrolledPosition( cw
, ch
, &right
, &bottom 
); 
6247     // avoid drawing grid lines past the last row and col 
6249     right 
= wxMin( right
, GetColRight(m_numCols 
- 1) ); 
6250     bottom 
= wxMin( bottom
, GetRowBottom(m_numRows 
- 1) ); 
6252     dc
.SetPen( wxPen(GetGridLineColour(), 1, wxSOLID
) ); 
6254     // horizontal grid lines 
6257     for ( i 
= 0; i 
< m_numRows
; i
++ ) 
6259         int bot 
= GetRowBottom(i
) - 1; 
6268             dc
.DrawLine( left
, bot
, right
, bot 
); 
6273     // vertical grid lines 
6275     for ( i 
= 0; i 
< m_numCols
; i
++ ) 
6277         int colRight 
= GetColRight(i
) - 1; 
6278         if ( colRight 
> right 
) 
6283         if ( colRight 
>= left 
) 
6285             dc
.DrawLine( colRight
, top
, colRight
, bottom 
); 
6291 void wxGrid::DrawRowLabels( wxDC
& dc 
,const wxArrayInt
& rows
) 
6293     if ( !m_numRows 
) return; 
6296     size_t numLabels 
= rows
.GetCount(); 
6298     for ( i 
= 0;  i 
< numLabels
;  i
++ ) 
6300         DrawRowLabel( dc
, rows
[i
] ); 
6305 void wxGrid::DrawRowLabel( wxDC
& dc
, int row 
) 
6307     if ( GetRowHeight(row
) <= 0 ) 
6310     int rowTop 
= GetRowTop(row
), 
6311         rowBottom 
= GetRowBottom(row
) - 1; 
6313     dc
.SetPen( *wxBLACK_PEN 
); 
6314     dc
.DrawLine( m_rowLabelWidth
-1, rowTop
, 
6315                  m_rowLabelWidth
-1, rowBottom 
); 
6317     dc
.DrawLine( 0, rowBottom
, m_rowLabelWidth
-1, rowBottom 
); 
6319     dc
.SetPen( *wxWHITE_PEN 
); 
6320     dc
.DrawLine( 0, rowTop
, 0, rowBottom 
); 
6321     dc
.DrawLine( 0, rowTop
, m_rowLabelWidth
-1, rowTop 
); 
6323     dc
.SetBackgroundMode( wxTRANSPARENT 
); 
6324     dc
.SetTextForeground( GetLabelTextColour() ); 
6325     dc
.SetFont( GetLabelFont() ); 
6328     GetRowLabelAlignment( &hAlign
, &vAlign 
); 
6332     rect
.SetY( GetRowTop(row
) + 2 ); 
6333     rect
.SetWidth( m_rowLabelWidth 
- 4 ); 
6334     rect
.SetHeight( GetRowHeight(row
) - 4 ); 
6335     DrawTextRectangle( dc
, GetRowLabelValue( row 
), rect
, hAlign
, vAlign 
); 
6339 void wxGrid::DrawColLabels( wxDC
& dc
,const wxArrayInt
& cols 
) 
6341     if ( !m_numCols 
) return; 
6344     size_t numLabels 
= cols
.GetCount(); 
6346     for ( i 
= 0;  i 
< numLabels
;  i
++ ) 
6348         DrawColLabel( dc
, cols
[i
] ); 
6353 void wxGrid::DrawColLabel( wxDC
& dc
, int col 
) 
6355     if ( GetColWidth(col
) <= 0 ) 
6358     int colLeft 
= GetColLeft(col
), 
6359         colRight 
= GetColRight(col
) - 1; 
6361     dc
.SetPen( *wxBLACK_PEN 
); 
6362     dc
.DrawLine( colRight
, 0, 
6363                  colRight
, m_colLabelHeight
-1 ); 
6365     dc
.DrawLine( colLeft
, m_colLabelHeight
-1, 
6366                  colRight
, m_colLabelHeight
-1 ); 
6368     dc
.SetPen( *wxWHITE_PEN 
); 
6369     dc
.DrawLine( colLeft
, 0, colLeft
, m_colLabelHeight
-1 ); 
6370     dc
.DrawLine( colLeft
, 0, colRight
, 0 ); 
6372     dc
.SetBackgroundMode( wxTRANSPARENT 
); 
6373     dc
.SetTextForeground( GetLabelTextColour() ); 
6374     dc
.SetFont( GetLabelFont() ); 
6376     dc
.SetBackgroundMode( wxTRANSPARENT 
); 
6377     dc
.SetTextForeground( GetLabelTextColour() ); 
6378     dc
.SetFont( GetLabelFont() ); 
6381     GetColLabelAlignment( &hAlign
, &vAlign 
); 
6384     rect
.SetX( colLeft 
+ 2 ); 
6386     rect
.SetWidth( GetColWidth(col
) - 4 ); 
6387     rect
.SetHeight( m_colLabelHeight 
- 4 ); 
6388     DrawTextRectangle( dc
, GetColLabelValue( col 
), rect
, hAlign
, vAlign 
); 
6391 void wxGrid::DrawTextRectangle( wxDC
& dc
, 
6392                                 const wxString
& value
, 
6397     wxArrayString lines
; 
6399     dc
.SetClippingRegion( rect 
); 
6400     StringToLines( value
, lines 
); 
6403     //Forward to new API. 
6404     DrawTextRectangle(  dc
, 
6412 void wxGrid::DrawTextRectangle( wxDC
& dc
, 
6413                                 const wxArrayString
& lines
, 
6418     long textWidth
, textHeight
; 
6419     long lineWidth
, lineHeight
; 
6421     if ( lines
.GetCount() ) 
6423         GetTextBoxSize( dc
, lines
, &textWidth
, &textHeight 
); 
6424         dc
.GetTextExtent( lines
[0], &lineWidth
, &lineHeight 
); 
6427         switch ( horizAlign 
) 
6430                 x 
= rect
.x 
+ (rect
.width 
- textWidth 
- 1); 
6433             case wxALIGN_CENTRE
: 
6434                 x 
= rect
.x 
+ ((rect
.width 
- textWidth
)/2); 
6443         switch ( vertAlign 
) 
6445             case wxALIGN_BOTTOM
: 
6446                 y 
= rect
.y 
+ (rect
.height 
- textHeight 
- 1); 
6449             case wxALIGN_CENTRE
: 
6450                 y 
= rect
.y 
+ ((rect
.height 
- textHeight
)/2); 
6459         for ( size_t i 
= 0;  i 
< lines
.GetCount();  i
++ ) 
6461             dc
.DrawText( lines
[i
], (int)x
, (int)y 
); 
6466     dc
.DestroyClippingRegion(); 
6470 // Split multi line text up into an array of strings.  Any existing 
6471 // contents of the string array are preserved. 
6473 void wxGrid::StringToLines( const wxString
& value
, wxArrayString
& lines 
) 
6477     wxString eol 
= wxTextFile::GetEOL( wxTextFileType_Unix 
); 
6478     wxString tVal 
= wxTextFile::Translate( value
, wxTextFileType_Unix 
); 
6480     while ( startPos 
< (int)tVal
.Length() ) 
6482         pos 
= tVal
.Mid(startPos
).Find( eol 
); 
6487         else if ( pos 
== 0 ) 
6489             lines
.Add( wxEmptyString 
); 
6493             lines
.Add( value
.Mid(startPos
, pos
) ); 
6497     if ( startPos 
< (int)value
.Length() ) 
6499         lines
.Add( value
.Mid( startPos 
) ); 
6504 void wxGrid::GetTextBoxSize( wxDC
& dc
, 
6505                              const wxArrayString
& lines
, 
6506                              long *width
, long *height 
) 
6513     for ( i 
= 0;  i 
< lines
.GetCount();  i
++ ) 
6515         dc
.GetTextExtent( lines
[i
], &lineW
, &lineH 
); 
6516         w 
= wxMax( w
, lineW 
); 
6525 // ------ Batch processing. 
6527 void wxGrid::EndBatch() 
6529     if ( m_batchCount 
> 0 ) 
6532         if ( !m_batchCount 
) 
6535             m_rowLabelWin
->Refresh(); 
6536             m_colLabelWin
->Refresh(); 
6537             m_cornerLabelWin
->Refresh(); 
6538             m_gridWin
->Refresh(); 
6543 // Use this, rather than wxWindow::Refresh(), to force an immediate 
6544 // repainting of the grid. Has no effect if you are already inside a 
6545 // BeginBatch / EndBatch block. 
6547 void wxGrid::ForceRefresh() 
6555 // ------ Edit control functions 
6559 void wxGrid::EnableEditing( bool edit 
) 
6561     // TODO: improve this ? 
6563     if ( edit 
!= m_editable 
) 
6565         if(!edit
) EnableCellEditControl(edit
); 
6571 void wxGrid::EnableCellEditControl( bool enable 
) 
6576     if ( m_currentCellCoords 
== wxGridNoCellCoords 
) 
6577         SetCurrentCell( 0, 0 ); 
6579     if ( enable 
!= m_cellEditCtrlEnabled 
) 
6581         // TODO allow the app to Veto() this event? 
6582         SendEvent(enable 
? wxEVT_GRID_EDITOR_SHOWN 
: wxEVT_GRID_EDITOR_HIDDEN
); 
6586             // this should be checked by the caller! 
6587             wxASSERT_MSG( CanEnableCellControl(), 
6588                           _T("can't enable editing for this cell!") ); 
6590             // do it before ShowCellEditControl() 
6591             m_cellEditCtrlEnabled 
= enable
; 
6593             ShowCellEditControl(); 
6597             HideCellEditControl(); 
6598             SaveEditControlValue(); 
6600             // do it after HideCellEditControl() 
6601             m_cellEditCtrlEnabled 
= enable
; 
6606 bool wxGrid::IsCurrentCellReadOnly() const 
6609     wxGridCellAttr
* attr 
= ((wxGrid 
*)this)->GetCellAttr(m_currentCellCoords
); 
6610     bool readonly 
= attr
->IsReadOnly(); 
6616 bool wxGrid::CanEnableCellControl() const 
6618     return m_editable 
&& !IsCurrentCellReadOnly(); 
6621 bool wxGrid::IsCellEditControlEnabled() const 
6623     // the cell edit control might be disable for all cells or just for the 
6624     // current one if it's read only 
6625     return m_cellEditCtrlEnabled 
? !IsCurrentCellReadOnly() : FALSE
; 
6628 bool wxGrid::IsCellEditControlShown() const 
6630     bool isShown 
= FALSE
; 
6632     if ( m_cellEditCtrlEnabled 
) 
6634         int row 
= m_currentCellCoords
.GetRow(); 
6635         int col 
= m_currentCellCoords
.GetCol(); 
6636         wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
6637         wxGridCellEditor
* editor 
= attr
->GetEditor((wxGrid
*) this, row
, col
); 
6642             if ( editor
->IsCreated() ) 
6644                 isShown 
= editor
->GetControl()->IsShown(); 
6654 void wxGrid::ShowCellEditControl() 
6656     if ( IsCellEditControlEnabled() ) 
6658         if ( !IsVisible( m_currentCellCoords 
) ) 
6660             m_cellEditCtrlEnabled 
= FALSE
; 
6665             wxRect rect 
= CellToRect( m_currentCellCoords 
); 
6666             int row 
= m_currentCellCoords
.GetRow(); 
6667             int col 
= m_currentCellCoords
.GetCol(); 
6669             // convert to scrolled coords 
6671             CalcScrolledPosition( rect
.x
, rect
.y
, &rect
.x
, &rect
.y 
); 
6673             // done in PaintBackground() 
6675             // erase the highlight and the cell contents because the editor 
6676             // might not cover the entire cell 
6677             wxClientDC 
dc( m_gridWin 
); 
6679             dc
.SetBrush(*wxLIGHT_GREY_BRUSH
); //wxBrush(attr->GetBackgroundColour(), wxSOLID)); 
6680             dc
.SetPen(*wxTRANSPARENT_PEN
); 
6681             dc
.DrawRectangle(rect
); 
6684             // cell is shifted by one pixel 
6688             wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
6689             wxGridCellEditor
* editor 
= attr
->GetEditor(this, row
, col
); 
6690             if ( !editor
->IsCreated() ) 
6692                 editor
->Create(m_gridWin
, -1, 
6693                                new wxGridCellEditorEvtHandler(this, editor
)); 
6695                 wxGridEditorCreatedEvent 
evt(GetId(), 
6696                                              wxEVT_GRID_EDITOR_CREATED
, 
6700                                              editor
->GetControl()); 
6701                 GetEventHandler()->ProcessEvent(evt
); 
6704             editor
->Show( TRUE
, attr 
); 
6706             editor
->SetSize( rect 
); 
6708             editor
->BeginEdit(row
, col
, this); 
6717 void wxGrid::HideCellEditControl() 
6719     if ( IsCellEditControlEnabled() ) 
6721         int row 
= m_currentCellCoords
.GetRow(); 
6722         int col 
= m_currentCellCoords
.GetCol(); 
6724         wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
6725         wxGridCellEditor 
*editor 
= attr
->GetEditor(this, row
, col
); 
6726         editor
->Show( FALSE 
); 
6729         m_gridWin
->SetFocus(); 
6730         wxRect 
rect( CellToRect( row
, col 
) ); 
6731         m_gridWin
->Refresh( FALSE
, &rect 
); 
6736 void wxGrid::SaveEditControlValue() 
6738     if ( IsCellEditControlEnabled() ) 
6740         int row 
= m_currentCellCoords
.GetRow(); 
6741         int col 
= m_currentCellCoords
.GetCol(); 
6743         wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
6744         wxGridCellEditor
* editor 
= attr
->GetEditor(this, row
, col
); 
6745         bool changed 
= editor
->EndEdit(row
, col
, this); 
6752             SendEvent( wxEVT_GRID_CELL_CHANGE
, 
6753                        m_currentCellCoords
.GetRow(), 
6754                        m_currentCellCoords
.GetCol() ); 
6761 // ------ Grid location functions 
6762 //  Note that all of these functions work with the logical coordinates of 
6763 //  grid cells and labels so you will need to convert from device 
6764 //  coordinates for mouse events etc. 
6767 void wxGrid::XYToCell( int x
, int y
, wxGridCellCoords
& coords 
) 
6769     int row 
= YToRow(y
); 
6770     int col 
= XToCol(x
); 
6772     if ( row 
== -1  ||  col 
== -1 ) 
6774         coords 
= wxGridNoCellCoords
; 
6778         coords
.Set( row
, col 
); 
6783 int wxGrid::YToRow( int y 
) 
6787     for ( i 
= 0;  i 
< m_numRows
;  i
++ ) 
6789         if ( y 
< GetRowBottom(i
) ) 
6797 int wxGrid::XToCol( int x 
) 
6801     for ( i 
= 0;  i 
< m_numCols
;  i
++ ) 
6803         if ( x 
< GetColRight(i
) ) 
6811 // return the row number that that the y coord is near the edge of, or 
6812 // -1 if not near an edge 
6814 int wxGrid::YToEdgeOfRow( int y 
) 
6818     for ( i 
= 0;  i 
< m_numRows
;  i
++ ) 
6820         if ( GetRowHeight(i
) > WXGRID_LABEL_EDGE_ZONE 
) 
6822             d 
= abs( y 
- GetRowBottom(i
) ); 
6823             if ( d 
< WXGRID_LABEL_EDGE_ZONE 
) 
6832 // return the col number that that the x coord is near the edge of, or 
6833 // -1 if not near an edge 
6835 int wxGrid::XToEdgeOfCol( int x 
) 
6839     for ( i 
= 0;  i 
< m_numCols
;  i
++ ) 
6841         if ( GetColWidth(i
) > WXGRID_LABEL_EDGE_ZONE 
) 
6843             d 
= abs( x 
- GetColRight(i
) ); 
6844             if ( d 
< WXGRID_LABEL_EDGE_ZONE 
) 
6853 wxRect 
wxGrid::CellToRect( int row
, int col 
) 
6855     wxRect 
rect( -1, -1, -1, -1 ); 
6857     if ( row 
>= 0  &&  row 
< m_numRows  
&& 
6858          col 
>= 0  &&  col 
< m_numCols 
) 
6860         rect
.x 
= GetColLeft(col
); 
6861         rect
.y 
= GetRowTop(row
); 
6862         rect
.width 
= GetColWidth(col
); 
6863         rect
.height 
= GetRowHeight(row
); 
6866     // if grid lines are enabled, then the area of the cell is a bit smaller 
6867     if (m_gridLinesEnabled
) { 
6875 bool wxGrid::IsVisible( int row
, int col
, bool wholeCellVisible 
) 
6877     // get the cell rectangle in logical coords 
6879     wxRect 
r( CellToRect( row
, col 
) ); 
6881     // convert to device coords 
6883     int left
, top
, right
, bottom
; 
6884     CalcScrolledPosition( r
.GetLeft(), r
.GetTop(), &left
, &top 
); 
6885     CalcScrolledPosition( r
.GetRight(), r
.GetBottom(), &right
, &bottom 
); 
6887     // check against the client area of the grid window 
6890     m_gridWin
->GetClientSize( &cw
, &ch 
); 
6892     if ( wholeCellVisible 
) 
6894         // is the cell wholly visible ? 
6896         return ( left 
>= 0  &&  right 
<= cw  
&& 
6897                  top 
>= 0  &&  bottom 
<= ch 
); 
6901         // is the cell partly visible ? 
6903         return ( ((left 
>=0 && left 
< cw
) || (right 
> 0 && right 
<= cw
))  && 
6904                  ((top 
>=0 && top 
< ch
) || (bottom 
> 0 && bottom 
<= ch
)) ); 
6909 // make the specified cell location visible by doing a minimal amount 
6912 void wxGrid::MakeCellVisible( int row
, int col 
) 
6915     int xpos 
= -1, ypos 
= -1; 
6917     if ( row 
>= 0  &&  row 
< m_numRows  
&& 
6918          col 
>= 0  &&  col 
< m_numCols 
) 
6920         // get the cell rectangle in logical coords 
6922         wxRect 
r( CellToRect( row
, col 
) ); 
6924         // convert to device coords 
6926         int left
, top
, right
, bottom
; 
6927         CalcScrolledPosition( r
.GetLeft(), r
.GetTop(), &left
, &top 
); 
6928         CalcScrolledPosition( r
.GetRight(), r
.GetBottom(), &right
, &bottom 
); 
6931         m_gridWin
->GetClientSize( &cw
, &ch 
); 
6937         else if ( bottom 
> ch 
) 
6939             int h 
= r
.GetHeight(); 
6941             for ( i 
= row
-1;  i 
>= 0;  i
-- ) 
6943                 int rowHeight 
= GetRowHeight(i
); 
6944                 if ( h 
+ rowHeight 
> ch 
) 
6951             // we divide it later by GRID_SCROLL_LINE, make sure that we don't 
6952             // have rounding errors (this is important, because if we do, we 
6953             // might not scroll at all and some cells won't be redrawn) 
6954             ypos 
+= GRID_SCROLL_LINE 
/ 2; 
6961         else if ( right 
> cw 
) 
6963             int w 
= r
.GetWidth(); 
6965             for ( i 
= col
-1;  i 
>= 0;  i
-- ) 
6967                 int colWidth 
= GetColWidth(i
); 
6968                 if ( w 
+ colWidth 
> cw 
) 
6975             // see comment for ypos above 
6976             xpos 
+= GRID_SCROLL_LINE 
/ 2; 
6979         if ( xpos 
!= -1  ||  ypos 
!= -1 ) 
6981             if ( xpos 
!= -1 ) xpos 
/= GRID_SCROLL_LINE
; 
6982             if ( ypos 
!= -1 ) ypos 
/= GRID_SCROLL_LINE
; 
6983             Scroll( xpos
, ypos 
); 
6991 // ------ Grid cursor movement functions 
6994 bool wxGrid::MoveCursorUp( bool expandSelection 
) 
6996     if ( m_currentCellCoords 
!= wxGridNoCellCoords  
&& 
6997          m_currentCellCoords
.GetRow() >= 0 ) 
6999         if ( expandSelection
) 
7001             if ( m_selectingKeyboard 
== wxGridNoCellCoords 
) 
7002                 m_selectingKeyboard 
= m_currentCellCoords
; 
7003             if ( m_selectingKeyboard
.GetRow() > 0 ) 
7005                 m_selectingKeyboard
.SetRow( m_selectingKeyboard
.GetRow() - 1 ); 
7006                 MakeCellVisible( m_selectingKeyboard
.GetRow(), 
7007                                  m_selectingKeyboard
.GetCol() ); 
7008                 HighlightBlock( m_currentCellCoords
, m_selectingKeyboard 
); 
7011         else if ( m_currentCellCoords
.GetRow() > 0 ) 
7014             MakeCellVisible( m_currentCellCoords
.GetRow() - 1, 
7015                              m_currentCellCoords
.GetCol() ); 
7016             SetCurrentCell( m_currentCellCoords
.GetRow() - 1, 
7017                             m_currentCellCoords
.GetCol() ); 
7028 bool wxGrid::MoveCursorDown( bool expandSelection 
) 
7030     if ( m_currentCellCoords 
!= wxGridNoCellCoords  
&& 
7031          m_currentCellCoords
.GetRow() < m_numRows 
) 
7033         if ( expandSelection 
) 
7035             if ( m_selectingKeyboard 
== wxGridNoCellCoords 
) 
7036                 m_selectingKeyboard 
= m_currentCellCoords
; 
7037             if ( m_selectingKeyboard
.GetRow() < m_numRows
-1 ) 
7039                 m_selectingKeyboard
.SetRow( m_selectingKeyboard
.GetRow() + 1 ); 
7040                 MakeCellVisible( m_selectingKeyboard
.GetRow(), 
7041                         m_selectingKeyboard
.GetCol() ); 
7042                 HighlightBlock( m_currentCellCoords
, m_selectingKeyboard 
); 
7045         else if ( m_currentCellCoords
.GetRow() < m_numRows 
- 1 ) 
7048             MakeCellVisible( m_currentCellCoords
.GetRow() + 1, 
7049                              m_currentCellCoords
.GetCol() ); 
7050             SetCurrentCell( m_currentCellCoords
.GetRow() + 1, 
7051                             m_currentCellCoords
.GetCol() ); 
7062 bool wxGrid::MoveCursorLeft( bool expandSelection 
) 
7064     if ( m_currentCellCoords 
!= wxGridNoCellCoords  
&& 
7065          m_currentCellCoords
.GetCol() >= 0 ) 
7067         if ( expandSelection 
) 
7069             if ( m_selectingKeyboard 
== wxGridNoCellCoords 
) 
7070                 m_selectingKeyboard 
= m_currentCellCoords
; 
7071             if ( m_selectingKeyboard
.GetCol() > 0 ) 
7073                 m_selectingKeyboard
.SetCol( m_selectingKeyboard
.GetCol() - 1 ); 
7074                 MakeCellVisible( m_selectingKeyboard
.GetRow(), 
7075                         m_selectingKeyboard
.GetCol() ); 
7076                 HighlightBlock( m_currentCellCoords
, m_selectingKeyboard 
); 
7079         else if ( m_currentCellCoords
.GetCol() > 0 ) 
7082             MakeCellVisible( m_currentCellCoords
.GetRow(), 
7083                              m_currentCellCoords
.GetCol() - 1 ); 
7084             SetCurrentCell( m_currentCellCoords
.GetRow(), 
7085                             m_currentCellCoords
.GetCol() - 1 ); 
7096 bool wxGrid::MoveCursorRight( bool expandSelection 
) 
7098     if ( m_currentCellCoords 
!= wxGridNoCellCoords  
&& 
7099          m_currentCellCoords
.GetCol() < m_numCols 
) 
7101         if ( expandSelection 
) 
7103             if ( m_selectingKeyboard 
== wxGridNoCellCoords 
) 
7104                 m_selectingKeyboard 
= m_currentCellCoords
; 
7105             if ( m_selectingKeyboard
.GetCol() < m_numCols 
- 1 ) 
7107                 m_selectingKeyboard
.SetCol( m_selectingKeyboard
.GetCol() + 1 ); 
7108                 MakeCellVisible( m_selectingKeyboard
.GetRow(), 
7109                         m_selectingKeyboard
.GetCol() ); 
7110                 HighlightBlock( m_currentCellCoords
, m_selectingKeyboard 
); 
7113         else if ( m_currentCellCoords
.GetCol() < m_numCols 
- 1 ) 
7116             MakeCellVisible( m_currentCellCoords
.GetRow(), 
7117                              m_currentCellCoords
.GetCol() + 1 ); 
7118             SetCurrentCell( m_currentCellCoords
.GetRow(), 
7119                             m_currentCellCoords
.GetCol() + 1 ); 
7130 bool wxGrid::MovePageUp() 
7132     if ( m_currentCellCoords 
== wxGridNoCellCoords 
) return FALSE
; 
7134     int row 
= m_currentCellCoords
.GetRow(); 
7138         m_gridWin
->GetClientSize( &cw
, &ch 
); 
7140         int y 
= GetRowTop(row
); 
7141         int newRow 
= YToRow( y 
- ch 
+ 1 ); 
7146         else if ( newRow 
== row 
) 
7151         MakeCellVisible( newRow
, m_currentCellCoords
.GetCol() ); 
7152         SetCurrentCell( newRow
, m_currentCellCoords
.GetCol() ); 
7160 bool wxGrid::MovePageDown() 
7162     if ( m_currentCellCoords 
== wxGridNoCellCoords 
) return FALSE
; 
7164     int row 
= m_currentCellCoords
.GetRow(); 
7165     if ( row 
< m_numRows 
) 
7168         m_gridWin
->GetClientSize( &cw
, &ch 
); 
7170         int y 
= GetRowTop(row
); 
7171         int newRow 
= YToRow( y 
+ ch 
); 
7174             newRow 
= m_numRows 
- 1; 
7176         else if ( newRow 
== row 
) 
7181         MakeCellVisible( newRow
, m_currentCellCoords
.GetCol() ); 
7182         SetCurrentCell( newRow
, m_currentCellCoords
.GetCol() ); 
7190 bool wxGrid::MoveCursorUpBlock( bool expandSelection 
) 
7193          m_currentCellCoords 
!= wxGridNoCellCoords  
&& 
7194          m_currentCellCoords
.GetRow() > 0 ) 
7196         int row 
= m_currentCellCoords
.GetRow(); 
7197         int col 
= m_currentCellCoords
.GetCol(); 
7199         if ( m_table
->IsEmptyCell(row
, col
) ) 
7201             // starting in an empty cell: find the next block of 
7207                 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break; 
7210         else if ( m_table
->IsEmptyCell(row
-1, col
) ) 
7212             // starting at the top of a block: find the next block 
7218                 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break; 
7223             // starting within a block: find the top of the block 
7228                 if ( m_table
->IsEmptyCell(row
, col
) ) 
7236         MakeCellVisible( row
, col 
); 
7237         if ( expandSelection 
) 
7239             m_selectingKeyboard 
= wxGridCellCoords( row
, col 
); 
7240             HighlightBlock( m_currentCellCoords
, m_selectingKeyboard 
); 
7245             SetCurrentCell( row
, col 
); 
7253 bool wxGrid::MoveCursorDownBlock( bool expandSelection 
) 
7256          m_currentCellCoords 
!= wxGridNoCellCoords  
&& 
7257          m_currentCellCoords
.GetRow() < m_numRows
-1 ) 
7259         int row 
= m_currentCellCoords
.GetRow(); 
7260         int col 
= m_currentCellCoords
.GetCol(); 
7262         if ( m_table
->IsEmptyCell(row
, col
) ) 
7264             // starting in an empty cell: find the next block of 
7267             while ( row 
< m_numRows
-1 ) 
7270                 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break; 
7273         else if ( m_table
->IsEmptyCell(row
+1, col
) ) 
7275             // starting at the bottom of a block: find the next block 
7278             while ( row 
< m_numRows
-1 ) 
7281                 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break; 
7286             // starting within a block: find the bottom of the block 
7288             while ( row 
< m_numRows
-1 ) 
7291                 if ( m_table
->IsEmptyCell(row
, col
) ) 
7299         MakeCellVisible( row
, col 
); 
7300         if ( expandSelection 
) 
7302             m_selectingKeyboard 
= wxGridCellCoords( row
, col 
); 
7303             HighlightBlock( m_currentCellCoords
, m_selectingKeyboard 
); 
7308             SetCurrentCell( row
, col 
); 
7317 bool wxGrid::MoveCursorLeftBlock( bool expandSelection 
) 
7320          m_currentCellCoords 
!= wxGridNoCellCoords  
&& 
7321          m_currentCellCoords
.GetCol() > 0 ) 
7323         int row 
= m_currentCellCoords
.GetRow(); 
7324         int col 
= m_currentCellCoords
.GetCol(); 
7326         if ( m_table
->IsEmptyCell(row
, col
) ) 
7328             // starting in an empty cell: find the next block of 
7334                 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break; 
7337         else if ( m_table
->IsEmptyCell(row
, col
-1) ) 
7339             // starting at the left of a block: find the next block 
7345                 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break; 
7350             // starting within a block: find the left of the block 
7355                 if ( m_table
->IsEmptyCell(row
, col
) ) 
7363         MakeCellVisible( row
, col 
); 
7364         if ( expandSelection 
) 
7366             m_selectingKeyboard 
= wxGridCellCoords( row
, col 
); 
7367             HighlightBlock( m_currentCellCoords
, m_selectingKeyboard 
); 
7372             SetCurrentCell( row
, col 
); 
7381 bool wxGrid::MoveCursorRightBlock( bool expandSelection 
) 
7384          m_currentCellCoords 
!= wxGridNoCellCoords  
&& 
7385          m_currentCellCoords
.GetCol() < m_numCols
-1 ) 
7387         int row 
= m_currentCellCoords
.GetRow(); 
7388         int col 
= m_currentCellCoords
.GetCol(); 
7390         if ( m_table
->IsEmptyCell(row
, col
) ) 
7392             // starting in an empty cell: find the next block of 
7395             while ( col 
< m_numCols
-1 ) 
7398                 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break; 
7401         else if ( m_table
->IsEmptyCell(row
, col
+1) ) 
7403             // starting at the right of a block: find the next block 
7406             while ( col 
< m_numCols
-1 ) 
7409                 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break; 
7414             // starting within a block: find the right of the block 
7416             while ( col 
< m_numCols
-1 ) 
7419                 if ( m_table
->IsEmptyCell(row
, col
) ) 
7427         MakeCellVisible( row
, col 
); 
7428         if ( expandSelection 
) 
7430             m_selectingKeyboard 
= wxGridCellCoords( row
, col 
); 
7431             HighlightBlock( m_currentCellCoords
, m_selectingKeyboard 
); 
7436             SetCurrentCell( row
, col 
); 
7448 // ------ Label values and formatting 
7451 void wxGrid::GetRowLabelAlignment( int *horiz
, int *vert 
) 
7453     *horiz 
= m_rowLabelHorizAlign
; 
7454     *vert  
= m_rowLabelVertAlign
; 
7457 void wxGrid::GetColLabelAlignment( int *horiz
, int *vert 
) 
7459     *horiz 
= m_colLabelHorizAlign
; 
7460     *vert  
= m_colLabelVertAlign
; 
7463 wxString 
wxGrid::GetRowLabelValue( int row 
) 
7467         return m_table
->GetRowLabelValue( row 
); 
7477 wxString 
wxGrid::GetColLabelValue( int col 
) 
7481         return m_table
->GetColLabelValue( col 
); 
7492 void wxGrid::SetRowLabelSize( int width 
) 
7494     width 
= wxMax( width
, 0 ); 
7495     if ( width 
!= m_rowLabelWidth 
) 
7499             m_rowLabelWin
->Show( FALSE 
); 
7500             m_cornerLabelWin
->Show( FALSE 
); 
7502         else if ( m_rowLabelWidth 
== 0 ) 
7504             m_rowLabelWin
->Show( TRUE 
); 
7505             if ( m_colLabelHeight 
> 0 ) m_cornerLabelWin
->Show( TRUE 
); 
7508         m_rowLabelWidth 
= width
; 
7515 void wxGrid::SetColLabelSize( int height 
) 
7517     height 
= wxMax( height
, 0 ); 
7518     if ( height 
!= m_colLabelHeight 
) 
7522             m_colLabelWin
->Show( FALSE 
); 
7523             m_cornerLabelWin
->Show( FALSE 
); 
7525         else if ( m_colLabelHeight 
== 0 ) 
7527             m_colLabelWin
->Show( TRUE 
); 
7528             if ( m_rowLabelWidth 
> 0 ) m_cornerLabelWin
->Show( TRUE 
); 
7531         m_colLabelHeight 
= height
; 
7538 void wxGrid::SetLabelBackgroundColour( const wxColour
& colour 
) 
7540     if ( m_labelBackgroundColour 
!= colour 
) 
7542         m_labelBackgroundColour 
= colour
; 
7543         m_rowLabelWin
->SetBackgroundColour( colour 
); 
7544         m_colLabelWin
->SetBackgroundColour( colour 
); 
7545         m_cornerLabelWin
->SetBackgroundColour( colour 
); 
7547         if ( !GetBatchCount() ) 
7549             m_rowLabelWin
->Refresh(); 
7550             m_colLabelWin
->Refresh(); 
7551             m_cornerLabelWin
->Refresh(); 
7556 void wxGrid::SetLabelTextColour( const wxColour
& colour 
) 
7558     if ( m_labelTextColour 
!= colour 
) 
7560         m_labelTextColour 
= colour
; 
7561         if ( !GetBatchCount() ) 
7563             m_rowLabelWin
->Refresh(); 
7564             m_colLabelWin
->Refresh(); 
7569 void wxGrid::SetLabelFont( const wxFont
& font 
) 
7572     if ( !GetBatchCount() ) 
7574         m_rowLabelWin
->Refresh(); 
7575         m_colLabelWin
->Refresh(); 
7579 void wxGrid::SetRowLabelAlignment( int horiz
, int vert 
) 
7581     // allow old (incorrect) defs to be used 
7584         case wxLEFT
:   horiz 
= wxALIGN_LEFT
; break; 
7585         case wxRIGHT
:  horiz 
= wxALIGN_RIGHT
; break; 
7586         case wxCENTRE
: horiz 
= wxALIGN_CENTRE
; break; 
7591         case wxTOP
:    vert 
= wxALIGN_TOP
;    break; 
7592         case wxBOTTOM
: vert 
= wxALIGN_BOTTOM
; break; 
7593         case wxCENTRE
: vert 
= wxALIGN_CENTRE
; break; 
7596     if ( horiz 
== wxALIGN_LEFT 
|| horiz 
== wxALIGN_CENTRE 
|| horiz 
== wxALIGN_RIGHT 
) 
7598         m_rowLabelHorizAlign 
= horiz
; 
7601     if ( vert 
== wxALIGN_TOP 
|| vert 
== wxALIGN_CENTRE 
|| vert 
== wxALIGN_BOTTOM 
) 
7603         m_rowLabelVertAlign 
= vert
; 
7606     if ( !GetBatchCount() ) 
7608         m_rowLabelWin
->Refresh(); 
7612 void wxGrid::SetColLabelAlignment( int horiz
, int vert 
) 
7614     // allow old (incorrect) defs to be used 
7617         case wxLEFT
:   horiz 
= wxALIGN_LEFT
; break; 
7618         case wxRIGHT
:  horiz 
= wxALIGN_RIGHT
; break; 
7619         case wxCENTRE
: horiz 
= wxALIGN_CENTRE
; break; 
7624         case wxTOP
:    vert 
= wxALIGN_TOP
;    break; 
7625         case wxBOTTOM
: vert 
= wxALIGN_BOTTOM
; break; 
7626         case wxCENTRE
: vert 
= wxALIGN_CENTRE
; break; 
7629     if ( horiz 
== wxALIGN_LEFT 
|| horiz 
== wxALIGN_CENTRE 
|| horiz 
== wxALIGN_RIGHT 
) 
7631         m_colLabelHorizAlign 
= horiz
; 
7634     if ( vert 
== wxALIGN_TOP 
|| vert 
== wxALIGN_CENTRE 
|| vert 
== wxALIGN_BOTTOM 
) 
7636         m_colLabelVertAlign 
= vert
; 
7639     if ( !GetBatchCount() ) 
7641         m_colLabelWin
->Refresh(); 
7645 void wxGrid::SetRowLabelValue( int row
, const wxString
& s 
) 
7649         m_table
->SetRowLabelValue( row
, s 
); 
7650         if ( !GetBatchCount() ) 
7652             wxRect rect 
= CellToRect( row
, 0); 
7653             if ( rect
.height 
> 0 ) 
7655                 CalcScrolledPosition(0, rect
.y
, &rect
.x
, &rect
.y
); 
7657                 rect
.width 
= m_rowLabelWidth
; 
7658                 m_rowLabelWin
->Refresh( TRUE
, &rect 
); 
7664 void wxGrid::SetColLabelValue( int col
, const wxString
& s 
) 
7668         m_table
->SetColLabelValue( col
, s 
); 
7669         if ( !GetBatchCount() ) 
7671             wxRect rect 
= CellToRect( 0, col 
); 
7672             if ( rect
.width 
> 0 ) 
7674                 CalcScrolledPosition(rect
.x
, 0, &rect
.x
, &rect
.y
); 
7676                 rect
.height 
= m_colLabelHeight
; 
7677                 m_colLabelWin
->Refresh( TRUE
, &rect 
); 
7683 void wxGrid::SetGridLineColour( const wxColour
& colour 
) 
7685     if ( m_gridLineColour 
!= colour 
) 
7687         m_gridLineColour 
= colour
; 
7689         wxClientDC 
dc( m_gridWin 
); 
7691         DrawAllGridLines( dc
, wxRegion() ); 
7696 void wxGrid::SetCellHighlightColour( const wxColour
& colour 
) 
7698     if ( m_cellHighlightColour 
!= colour 
) 
7700         m_cellHighlightColour 
= colour
; 
7702         wxClientDC 
dc( m_gridWin 
); 
7704         wxGridCellAttr
* attr 
= GetCellAttr(m_currentCellCoords
); 
7705         DrawCellHighlight(dc
, attr
); 
7710 void wxGrid::SetCellHighlightPenWidth(int width
) 
7712     if (m_cellHighlightPenWidth 
!= width
) { 
7713         m_cellHighlightPenWidth 
= width
; 
7715         // Just redrawing the cell highlight is not enough since that won't 
7716         // make any visible change if the the thickness is getting smaller. 
7717         int row 
= m_currentCellCoords
.GetRow(); 
7718         int col 
= m_currentCellCoords
.GetCol(); 
7719         if ( GetColWidth(col
) <= 0 || GetRowHeight(row
) <= 0 ) 
7721         wxRect rect 
= CellToRect(row
, col
); 
7722         m_gridWin
->Refresh(TRUE
, &rect
); 
7726 void wxGrid::SetCellHighlightROPenWidth(int width
) 
7728     if (m_cellHighlightROPenWidth 
!= width
) { 
7729         m_cellHighlightROPenWidth 
= width
; 
7731         // Just redrawing the cell highlight is not enough since that won't 
7732         // make any visible change if the the thickness is getting smaller. 
7733         int row 
= m_currentCellCoords
.GetRow(); 
7734         int col 
= m_currentCellCoords
.GetCol(); 
7735         if ( GetColWidth(col
) <= 0 || GetRowHeight(row
) <= 0 ) 
7737         wxRect rect 
= CellToRect(row
, col
); 
7738         m_gridWin
->Refresh(TRUE
, &rect
); 
7742 void wxGrid::EnableGridLines( bool enable 
) 
7744     if ( enable 
!= m_gridLinesEnabled 
) 
7746         m_gridLinesEnabled 
= enable
; 
7748         if ( !GetBatchCount() ) 
7752                 wxClientDC 
dc( m_gridWin 
); 
7754                 DrawAllGridLines( dc
, wxRegion() ); 
7758                 m_gridWin
->Refresh(); 
7765 int wxGrid::GetDefaultRowSize() 
7767     return m_defaultRowHeight
; 
7770 int wxGrid::GetRowSize( int row 
) 
7772     wxCHECK_MSG( row 
>= 0 && row 
< m_numRows
, 0, _T("invalid row index") ); 
7774     return GetRowHeight(row
); 
7777 int wxGrid::GetDefaultColSize() 
7779     return m_defaultColWidth
; 
7782 int wxGrid::GetColSize( int col 
) 
7784     wxCHECK_MSG( col 
>= 0 && col 
< m_numCols
, 0, _T("invalid column index") ); 
7786     return GetColWidth(col
); 
7789 // ============================================================================ 
7790 // access to the grid attributes: each of them has a default value in the grid 
7791 // itself and may be overidden on a per-cell basis 
7792 // ============================================================================ 
7794 // ---------------------------------------------------------------------------- 
7795 // setting default attributes 
7796 // ---------------------------------------------------------------------------- 
7798 void wxGrid::SetDefaultCellBackgroundColour( const wxColour
& col 
) 
7800     m_defaultCellAttr
->SetBackgroundColour(col
); 
7802     m_gridWin
->SetBackgroundColour(col
); 
7806 void wxGrid::SetDefaultCellTextColour( const wxColour
& col 
) 
7808     m_defaultCellAttr
->SetTextColour(col
); 
7811 void wxGrid::SetDefaultCellAlignment( int horiz
, int vert 
) 
7813     m_defaultCellAttr
->SetAlignment(horiz
, vert
); 
7816 void wxGrid::SetDefaultCellFont( const wxFont
& font 
) 
7818     m_defaultCellAttr
->SetFont(font
); 
7821 void wxGrid::SetDefaultRenderer(wxGridCellRenderer 
*renderer
) 
7823     m_defaultCellAttr
->SetRenderer(renderer
); 
7826 void wxGrid::SetDefaultEditor(wxGridCellEditor 
*editor
) 
7828     m_defaultCellAttr
->SetEditor(editor
); 
7831 // ---------------------------------------------------------------------------- 
7832 // access to the default attrbiutes 
7833 // ---------------------------------------------------------------------------- 
7835 wxColour 
wxGrid::GetDefaultCellBackgroundColour() 
7837     return m_defaultCellAttr
->GetBackgroundColour(); 
7840 wxColour 
wxGrid::GetDefaultCellTextColour() 
7842     return m_defaultCellAttr
->GetTextColour(); 
7845 wxFont 
wxGrid::GetDefaultCellFont() 
7847     return m_defaultCellAttr
->GetFont(); 
7850 void wxGrid::GetDefaultCellAlignment( int *horiz
, int *vert 
) 
7852     m_defaultCellAttr
->GetAlignment(horiz
, vert
); 
7855 wxGridCellRenderer 
*wxGrid::GetDefaultRenderer() const 
7857     return m_defaultCellAttr
->GetRenderer(NULL
, 0, 0); 
7860 wxGridCellEditor 
*wxGrid::GetDefaultEditor() const 
7862     return m_defaultCellAttr
->GetEditor(NULL
,0,0); 
7865 // ---------------------------------------------------------------------------- 
7866 // access to cell attributes 
7867 // ---------------------------------------------------------------------------- 
7869 wxColour 
wxGrid::GetCellBackgroundColour(int row
, int col
) 
7871     wxGridCellAttr 
*attr 
= GetCellAttr(row
, col
); 
7872     wxColour colour 
= attr
->GetBackgroundColour(); 
7877 wxColour 
wxGrid::GetCellTextColour( int row
, int col 
) 
7879     wxGridCellAttr 
*attr 
= GetCellAttr(row
, col
); 
7880     wxColour colour 
= attr
->GetTextColour(); 
7885 wxFont 
wxGrid::GetCellFont( int row
, int col 
) 
7887     wxGridCellAttr 
*attr 
= GetCellAttr(row
, col
); 
7888     wxFont font 
= attr
->GetFont(); 
7893 void wxGrid::GetCellAlignment( int row
, int col
, int *horiz
, int *vert 
) 
7895     wxGridCellAttr 
*attr 
= GetCellAttr(row
, col
); 
7896     attr
->GetAlignment(horiz
, vert
); 
7900 wxGridCellRenderer
* wxGrid::GetCellRenderer(int row
, int col
) 
7902     wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
7903     wxGridCellRenderer
* renderer 
= attr
->GetRenderer(this, row
, col
); 
7909 wxGridCellEditor
* wxGrid::GetCellEditor(int row
, int col
) 
7911     wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
7912     wxGridCellEditor
* editor 
= attr
->GetEditor(this, row
, col
); 
7918 bool wxGrid::IsReadOnly(int row
, int col
) const 
7920     wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
7921     bool isReadOnly 
= attr
->IsReadOnly(); 
7926 // ---------------------------------------------------------------------------- 
7927 // attribute support: cache, automatic provider creation, ... 
7928 // ---------------------------------------------------------------------------- 
7930 bool wxGrid::CanHaveAttributes() 
7937     return m_table
->CanHaveAttributes(); 
7940 void wxGrid::ClearAttrCache() 
7942     if ( m_attrCache
.row 
!= -1 ) 
7944         wxSafeDecRef(m_attrCache
.attr
); 
7945         m_attrCache
.attr 
= NULL
; 
7946         m_attrCache
.row 
= -1; 
7950 void wxGrid::CacheAttr(int row
, int col
, wxGridCellAttr 
*attr
) const 
7952     wxGrid 
*self 
= (wxGrid 
*)this;  // const_cast 
7954     self
->ClearAttrCache(); 
7955     self
->m_attrCache
.row 
= row
; 
7956     self
->m_attrCache
.col 
= col
; 
7957     self
->m_attrCache
.attr 
= attr
; 
7961 bool wxGrid::LookupAttr(int row
, int col
, wxGridCellAttr 
**attr
) const 
7963     if ( row 
== m_attrCache
.row 
&& col 
== m_attrCache
.col 
) 
7965         *attr 
= m_attrCache
.attr
; 
7966         wxSafeIncRef(m_attrCache
.attr
); 
7968 #ifdef DEBUG_ATTR_CACHE 
7969         gs_nAttrCacheHits
++; 
7976 #ifdef DEBUG_ATTR_CACHE 
7977         gs_nAttrCacheMisses
++; 
7983 wxGridCellAttr 
*wxGrid::GetCellAttr(int row
, int col
) const 
7985     wxGridCellAttr 
*attr
; 
7986     if ( !LookupAttr(row
, col
, &attr
) ) 
7988         attr 
= m_table 
? m_table
->GetAttr(row
, col 
, wxGridCellAttr::Any
) : (wxGridCellAttr 
*)NULL
; 
7989         CacheAttr(row
, col
, attr
); 
7993         attr
->SetDefAttr(m_defaultCellAttr
); 
7997         attr 
= m_defaultCellAttr
; 
8004 wxGridCellAttr 
*wxGrid::GetOrCreateCellAttr(int row
, int col
) const 
8006     wxGridCellAttr 
*attr 
= (wxGridCellAttr 
*)NULL
; 
8007         wxASSERT_MSG( m_table
, 
8008                       _T("we may only be called if CanHaveAttributes() returned TRUE and then m_table should be !NULL") ); 
8010     attr 
= m_table
->GetAttr(row
, col
, wxGridCellAttr::Cell 
); 
8013             attr 
= new wxGridCellAttr
; 
8015             // artificially inc the ref count to match DecRef() in caller 
8017             m_table
->SetAttr(attr
, row
, col
); 
8019     attr
->SetDefAttr(m_defaultCellAttr
); 
8023 // ---------------------------------------------------------------------------- 
8024 // setting column attributes (wrappers around SetColAttr) 
8025 // ---------------------------------------------------------------------------- 
8027 void wxGrid::SetColFormatBool(int col
) 
8029     SetColFormatCustom(col
, wxGRID_VALUE_BOOL
); 
8032 void wxGrid::SetColFormatNumber(int col
) 
8034     SetColFormatCustom(col
, wxGRID_VALUE_NUMBER
); 
8037 void wxGrid::SetColFormatFloat(int col
, int width
, int precision
) 
8039     wxString typeName 
= wxGRID_VALUE_FLOAT
; 
8040     if ( (width 
!= -1) || (precision 
!= -1) ) 
8042         typeName 
<< _T(':') << width 
<< _T(',') << precision
; 
8045     SetColFormatCustom(col
, typeName
); 
8048 void wxGrid::SetColFormatCustom(int col
, const wxString
& typeName
) 
8050     wxGridCellAttr 
*attr 
= (wxGridCellAttr 
*)NULL
; 
8052     attr 
= m_table
->GetAttr(-1, col
, wxGridCellAttr::Col 
); 
8054         attr 
= new wxGridCellAttr
; 
8055     wxGridCellRenderer 
*renderer 
= GetDefaultRendererForType(typeName
); 
8056     attr
->SetRenderer(renderer
); 
8058     SetColAttr(col
, attr
); 
8062 // ---------------------------------------------------------------------------- 
8063 // setting cell attributes: this is forwarded to the table 
8064 // ---------------------------------------------------------------------------- 
8066 void wxGrid::SetRowAttr(int row
, wxGridCellAttr 
*attr
) 
8068     if ( CanHaveAttributes() ) 
8070         m_table
->SetRowAttr(attr
, row
); 
8079 void wxGrid::SetColAttr(int col
, wxGridCellAttr 
*attr
) 
8081     if ( CanHaveAttributes() ) 
8083         m_table
->SetColAttr(attr
, col
); 
8092 void wxGrid::SetCellBackgroundColour( int row
, int col
, const wxColour
& colour 
) 
8094     if ( CanHaveAttributes() ) 
8096         wxGridCellAttr 
*attr 
= GetOrCreateCellAttr(row
, col
); 
8097         attr
->SetBackgroundColour(colour
); 
8102 void wxGrid::SetCellTextColour( int row
, int col
, const wxColour
& colour 
) 
8104     if ( CanHaveAttributes() ) 
8106         wxGridCellAttr 
*attr 
= GetOrCreateCellAttr(row
, col
); 
8107         attr
->SetTextColour(colour
); 
8112 void wxGrid::SetCellFont( int row
, int col
, const wxFont
& font 
) 
8114     if ( CanHaveAttributes() ) 
8116         wxGridCellAttr 
*attr 
= GetOrCreateCellAttr(row
, col
); 
8117         attr
->SetFont(font
); 
8122 void wxGrid::SetCellAlignment( int row
, int col
, int horiz
, int vert 
) 
8124     if ( CanHaveAttributes() ) 
8126         wxGridCellAttr 
*attr 
= GetOrCreateCellAttr(row
, col
); 
8127         attr
->SetAlignment(horiz
, vert
); 
8132 void wxGrid::SetCellRenderer(int row
, int col
, wxGridCellRenderer 
*renderer
) 
8134     if ( CanHaveAttributes() ) 
8136         wxGridCellAttr 
*attr 
= GetOrCreateCellAttr(row
, col
); 
8137         attr
->SetRenderer(renderer
); 
8142 void wxGrid::SetCellEditor(int row
, int col
, wxGridCellEditor
* editor
) 
8144     if ( CanHaveAttributes() ) 
8146         wxGridCellAttr 
*attr 
= GetOrCreateCellAttr(row
, col
); 
8147         attr
->SetEditor(editor
); 
8152 void wxGrid::SetReadOnly(int row
, int col
, bool isReadOnly
) 
8154     if ( CanHaveAttributes() ) 
8156         wxGridCellAttr 
*attr 
= GetOrCreateCellAttr(row
, col
); 
8157         attr
->SetReadOnly(isReadOnly
); 
8162 // ---------------------------------------------------------------------------- 
8163 // Data type registration 
8164 // ---------------------------------------------------------------------------- 
8166 void wxGrid::RegisterDataType(const wxString
& typeName
, 
8167                               wxGridCellRenderer
* renderer
, 
8168                               wxGridCellEditor
* editor
) 
8170     m_typeRegistry
->RegisterDataType(typeName
, renderer
, editor
); 
8174 wxGridCellEditor
* wxGrid::GetDefaultEditorForCell(int row
, int col
) const 
8176     wxString typeName 
= m_table
->GetTypeName(row
, col
); 
8177     return GetDefaultEditorForType(typeName
); 
8180 wxGridCellRenderer
* wxGrid::GetDefaultRendererForCell(int row
, int col
) const 
8182     wxString typeName 
= m_table
->GetTypeName(row
, col
); 
8183     return GetDefaultRendererForType(typeName
); 
8187 wxGrid::GetDefaultEditorForType(const wxString
& typeName
) const 
8189     int index 
= m_typeRegistry
->FindOrCloneDataType(typeName
); 
8190     if ( index 
== wxNOT_FOUND 
) 
8192         wxFAIL_MSG(wxT("Unknown data type name")); 
8197     return m_typeRegistry
->GetEditor(index
); 
8201 wxGrid::GetDefaultRendererForType(const wxString
& typeName
) const 
8203     int index 
= m_typeRegistry
->FindOrCloneDataType(typeName
); 
8204     if ( index 
== wxNOT_FOUND 
) 
8206         wxFAIL_MSG(wxT("Unknown data type name")); 
8211     return m_typeRegistry
->GetRenderer(index
); 
8215 // ---------------------------------------------------------------------------- 
8217 // ---------------------------------------------------------------------------- 
8219 void wxGrid::EnableDragRowSize( bool enable 
) 
8221     m_canDragRowSize 
= enable
; 
8225 void wxGrid::EnableDragColSize( bool enable 
) 
8227     m_canDragColSize 
= enable
; 
8230 void wxGrid::EnableDragGridSize( bool enable 
) 
8232     m_canDragGridSize 
= enable
; 
8236 void wxGrid::SetDefaultRowSize( int height
, bool resizeExistingRows 
) 
8238     m_defaultRowHeight 
= wxMax( height
, WXGRID_MIN_ROW_HEIGHT 
); 
8240     if ( resizeExistingRows 
) 
8243         if ( !GetBatchCount() ) 
8248 void wxGrid::SetRowSize( int row
, int height 
) 
8250     wxCHECK_RET( row 
>= 0 && row 
< m_numRows
, _T("invalid row index") ); 
8252     if ( m_rowHeights
.IsEmpty() ) 
8254         // need to really create the array 
8258     int h 
= wxMax( 0, height 
); 
8259     int diff 
= h 
- m_rowHeights
[row
]; 
8261     m_rowHeights
[row
] = h
; 
8263     for ( i 
= row
;  i 
< m_numRows
;  i
++ ) 
8265         m_rowBottoms
[i
] += diff
; 
8267     if ( !GetBatchCount() ) 
8271 void wxGrid::SetDefaultColSize( int width
, bool resizeExistingCols 
) 
8273     m_defaultColWidth 
= wxMax( width
, WXGRID_MIN_COL_WIDTH 
); 
8275     if ( resizeExistingCols 
) 
8278         if ( !GetBatchCount() ) 
8283 void wxGrid::SetColSize( int col
, int width 
) 
8285     wxCHECK_RET( col 
>= 0 && col 
< m_numCols
, _T("invalid column index") ); 
8287     // should we check that it's bigger than GetColMinimalWidth(col) here? 
8289     if ( m_colWidths
.IsEmpty() ) 
8291         // need to really create the array 
8295     int w 
= wxMax( 0, width 
); 
8296     int diff 
= w 
- m_colWidths
[col
]; 
8297     m_colWidths
[col
] = w
; 
8300     for ( i 
= col
;  i 
< m_numCols
;  i
++ ) 
8302         m_colRights
[i
] += diff
; 
8304     if ( !GetBatchCount() ) 
8309 void wxGrid::SetColMinimalWidth( int col
, int width 
) 
8311     m_colMinWidths
.Put(col
, width
); 
8314 void wxGrid::SetRowMinimalHeight( int row
, int width 
) 
8316     m_rowMinHeights
.Put(row
, width
); 
8319 int wxGrid::GetColMinimalWidth(int col
) const 
8321     long value 
= m_colMinWidths
.Get(col
); 
8322     return value 
!= wxNOT_FOUND 
? (int)value 
: WXGRID_MIN_COL_WIDTH
; 
8325 int wxGrid::GetRowMinimalHeight(int row
) const 
8327     long value 
= m_rowMinHeights
.Get(row
); 
8328     return value 
!= wxNOT_FOUND 
? (int)value 
: WXGRID_MIN_ROW_HEIGHT
; 
8331 // ---------------------------------------------------------------------------- 
8333 // ---------------------------------------------------------------------------- 
8335 void wxGrid::AutoSizeColOrRow( int colOrRow
, bool setAsMin
, bool column 
) 
8337     wxClientDC 
dc(m_gridWin
); 
8339     // init both of them to avoid compiler warnings, even if weo nly need one 
8347     wxCoord extent
, extentMax 
= 0; 
8348     int max 
= column 
? m_numRows 
: m_numCols
; 
8349     for ( int rowOrCol 
= 0; rowOrCol 
< max
; rowOrCol
++ ) 
8356         wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
8357         wxGridCellRenderer
* renderer 
= attr
->GetRenderer(this, row
, col
); 
8360             wxSize size 
= renderer
->GetBestSize(*this, *attr
, dc
, row
, col
); 
8361             extent 
= column 
? size
.x 
: size
.y
; 
8362             if ( extent 
> extentMax 
) 
8373     // now also compare with the column label extent 
8375     dc
.SetFont( GetLabelFont() ); 
8378         dc
.GetTextExtent( GetColLabelValue(col
), &w
, &h 
); 
8380         dc
.GetTextExtent( GetRowLabelValue(row
), &w
, &h 
); 
8382     extent 
= column 
? w 
: h
; 
8383     if ( extent 
> extentMax 
) 
8390         // empty column - give default extent (notice that if extentMax is less 
8391         // than default extent but != 0, it's ok) 
8392         extentMax 
= column 
? m_defaultColWidth 
: m_defaultRowHeight
; 
8398             // leave some space around text 
8409         SetColSize(col
, extentMax
); 
8410         if ( !GetBatchCount() ) 
8413             m_gridWin
->GetClientSize( &cw
, &ch 
); 
8414             wxRect 
rect ( CellToRect( 0, col 
) ); 
8416             CalcScrolledPosition(rect
.x
, 0, &rect
.x
, &dummy
); 
8417             rect
.width 
= cw 
- rect
.x
; 
8418             rect
.height 
= m_colLabelHeight
; 
8419             m_colLabelWin
->Refresh( TRUE
, &rect 
); 
8424         SetRowSize(row
, extentMax
); 
8425         if ( !GetBatchCount() ) 
8428             m_gridWin
->GetClientSize( &cw
, &ch 
); 
8429             wxRect 
rect ( CellToRect( row
, 0 ) ); 
8431             CalcScrolledPosition(0, rect
.y
, &dummy
, &rect
.y
); 
8432             rect
.width 
= m_rowLabelWidth
; 
8433             rect
.height 
= ch 
- rect
.y
; 
8434             m_rowLabelWin
->Refresh( TRUE
, &rect 
); 
8440             SetColMinimalWidth(col
, extentMax
); 
8442             SetRowMinimalHeight(row
, extentMax
); 
8446 int wxGrid::SetOrCalcColumnSizes(bool calcOnly
, bool setAsMin
) 
8448     int width 
= m_rowLabelWidth
; 
8452     for ( int col 
= 0; col 
< m_numCols
; col
++ ) 
8456             AutoSizeColumn(col
, setAsMin
); 
8459         width 
+= GetColWidth(col
); 
8466 int wxGrid::SetOrCalcRowSizes(bool calcOnly
, bool setAsMin
) 
8468     int height 
= m_colLabelHeight
; 
8472     for ( int row 
= 0; row 
< m_numRows
; row
++ ) 
8476             AutoSizeRow(row
, setAsMin
); 
8479         height 
+= GetRowHeight(row
); 
8486 void wxGrid::AutoSize() 
8489     SetClientSize(SetOrCalcColumnSizes(FALSE
), SetOrCalcRowSizes(FALSE
)); 
8492 wxSize 
wxGrid::DoGetBestSize() const 
8494     // don't set sizes, only calculate them 
8495     wxGrid 
*self 
= (wxGrid 
*)this;  // const_cast 
8497     return wxSize(self
->SetOrCalcColumnSizes(TRUE
), 
8498                   self
->SetOrCalcRowSizes(TRUE
)); 
8507 wxPen
& wxGrid::GetDividerPen() const 
8512 // ---------------------------------------------------------------------------- 
8513 // cell value accessor functions 
8514 // ---------------------------------------------------------------------------- 
8516 void wxGrid::SetCellValue( int row
, int col
, const wxString
& s 
) 
8520         m_table
->SetValue( row
, col
, s 
); 
8521         if ( !GetBatchCount() ) 
8523             wxClientDC 
dc( m_gridWin 
); 
8525             DrawCell( dc
, wxGridCellCoords(row
, col
) ); 
8528         if ( m_currentCellCoords
.GetRow() == row 
&& 
8529              m_currentCellCoords
.GetCol() == col 
&& 
8530              IsCellEditControlShown()) 
8531              // Note: If we are using IsCellEditControlEnabled, 
8532              // this interacts badly with calling SetCellValue from 
8533              // an EVT_GRID_CELL_CHANGE handler. 
8535             HideCellEditControl(); 
8536             ShowCellEditControl(); // will reread data from table 
8543 // ------ Block, row and col selection 
8546 void wxGrid::SelectRow( int row
, bool addToSelected 
) 
8548     if ( IsSelection() && !addToSelected 
) 
8551     m_selection
->SelectRow( row
, FALSE
, addToSelected 
); 
8555 void wxGrid::SelectCol( int col
, bool addToSelected 
) 
8557     if ( IsSelection() && !addToSelected 
) 
8560     m_selection
->SelectCol( col
, FALSE
, addToSelected 
); 
8564 void wxGrid::SelectBlock( int topRow
, int leftCol
, int bottomRow
, int rightCol
, 
8565                           bool addToSelected 
) 
8567     if ( IsSelection() && !addToSelected 
) 
8570     m_selection
->SelectBlock( topRow
, leftCol
, bottomRow
, rightCol
, 
8571                               FALSE
, addToSelected 
); 
8575 void wxGrid::SelectAll() 
8577     if ( m_numRows 
> 0 && m_numCols 
> 0 ) 
8578         m_selection
->SelectBlock( 0, 0, m_numRows
-1, m_numCols
-1 ); 
8582 // ------ Cell, row and col deselection 
8585 void wxGrid::DeselectRow( int row 
) 
8587     if ( m_selection
->GetSelectionMode() == wxGrid::wxGridSelectRows 
) 
8589         if ( m_selection
->IsInSelection(row
, 0 ) ) 
8590             m_selection
->ToggleCellSelection( row
, 0); 
8594         int nCols 
= GetNumberCols(); 
8595         for ( int i 
= 0; i 
< nCols 
; i
++ ) 
8597             if ( m_selection
->IsInSelection(row
, i 
) ) 
8598                 m_selection
->ToggleCellSelection( row
, i
); 
8603 void wxGrid::DeselectCol( int col 
) 
8605     if ( m_selection
->GetSelectionMode() == wxGrid::wxGridSelectColumns 
) 
8607         if ( m_selection
->IsInSelection(0, col 
) ) 
8608             m_selection
->ToggleCellSelection( 0, col
); 
8612         int nRows 
= GetNumberRows(); 
8613         for ( int i 
= 0; i 
< nRows 
; i
++ ) 
8615             if ( m_selection
->IsInSelection(i
, col 
) ) 
8616                 m_selection
->ToggleCellSelection(i
, col
); 
8621 void wxGrid::DeselectCell( int row
, int col 
) 
8623     if ( m_selection
->IsInSelection(row
, col
) ) 
8624         m_selection
->ToggleCellSelection(row
, col
); 
8627 bool wxGrid::IsSelection() 
8629     return ( m_selection
->IsSelection() || 
8630              ( m_selectingTopLeft 
!= wxGridNoCellCoords 
&& 
8631                m_selectingBottomRight 
!= wxGridNoCellCoords 
) ); 
8634 bool wxGrid::IsInSelection( int row
, int col 
) 
8636     return ( m_selection
->IsInSelection( row
, col 
) || 
8637              ( row 
>= m_selectingTopLeft
.GetRow() && 
8638                col 
>= m_selectingTopLeft
.GetCol() && 
8639                row 
<= m_selectingBottomRight
.GetRow() && 
8640                col 
<= m_selectingBottomRight
.GetCol() ) ); 
8643 void wxGrid::ClearSelection() 
8645     m_selectingTopLeft 
= wxGridNoCellCoords
; 
8646     m_selectingBottomRight 
= wxGridNoCellCoords
; 
8647     m_selection
->ClearSelection(); 
8651 // This function returns the rectangle that encloses the given block 
8652 // in device coords clipped to the client size of the grid window. 
8654 wxRect 
wxGrid::BlockToDeviceRect( const wxGridCellCoords 
&topLeft
, 
8655                                   const wxGridCellCoords 
&bottomRight 
) 
8657     wxRect 
rect( wxGridNoCellRect 
); 
8660     cellRect 
= CellToRect( topLeft 
); 
8661     if ( cellRect 
!= wxGridNoCellRect 
) 
8667         rect 
= wxRect( 0, 0, 0, 0 ); 
8670     cellRect 
= CellToRect( bottomRight 
); 
8671     if ( cellRect 
!= wxGridNoCellRect 
) 
8677         return wxGridNoCellRect
; 
8680     // convert to scrolled coords 
8682     int left
, top
, right
, bottom
; 
8683     CalcScrolledPosition( rect
.GetLeft(), rect
.GetTop(), &left
, &top 
); 
8684     CalcScrolledPosition( rect
.GetRight(), rect
.GetBottom(), &right
, &bottom 
); 
8687     m_gridWin
->GetClientSize( &cw
, &ch 
); 
8689     if (right 
< 0 || bottom 
< 0 || left 
> cw 
|| top 
> ch
) 
8690         return wxRect( 0, 0, 0, 0); 
8692     rect
.SetLeft( wxMax(0, left
) ); 
8693     rect
.SetTop( wxMax(0, top
) ); 
8694     rect
.SetRight( wxMin(cw
, right
) ); 
8695     rect
.SetBottom( wxMin(ch
, bottom
) ); 
8703 // ------ Grid event classes 
8706 IMPLEMENT_DYNAMIC_CLASS( wxGridEvent
, wxNotifyEvent 
) 
8708 wxGridEvent::wxGridEvent( int id
, wxEventType type
, wxObject
* obj
, 
8709                           int row
, int col
, int x
, int y
, bool sel
, 
8710                           bool control
, bool shift
, bool alt
, bool meta 
) 
8711         : wxNotifyEvent( type
, id 
) 
8718     m_control 
= control
; 
8723     SetEventObject(obj
); 
8727 IMPLEMENT_DYNAMIC_CLASS( wxGridSizeEvent
, wxNotifyEvent 
) 
8729 wxGridSizeEvent::wxGridSizeEvent( int id
, wxEventType type
, wxObject
* obj
, 
8730                                   int rowOrCol
, int x
, int y
, 
8731                                   bool control
, bool shift
, bool alt
, bool meta 
) 
8732         : wxNotifyEvent( type
, id 
) 
8734     m_rowOrCol 
= rowOrCol
; 
8737     m_control 
= control
; 
8742     SetEventObject(obj
); 
8746 IMPLEMENT_DYNAMIC_CLASS( wxGridRangeSelectEvent
, wxNotifyEvent 
) 
8748 wxGridRangeSelectEvent::wxGridRangeSelectEvent(int id
, wxEventType type
, wxObject
* obj
, 
8749                                                const wxGridCellCoords
& topLeft
, 
8750                                                const wxGridCellCoords
& bottomRight
, 
8751                                                bool sel
, bool control
, 
8752                                                bool shift
, bool alt
, bool meta 
) 
8753         : wxNotifyEvent( type
, id 
) 
8755     m_topLeft     
= topLeft
; 
8756     m_bottomRight 
= bottomRight
; 
8758     m_control     
= control
; 
8763     SetEventObject(obj
); 
8767 IMPLEMENT_DYNAMIC_CLASS(wxGridEditorCreatedEvent
, wxCommandEvent
) 
8769 wxGridEditorCreatedEvent::wxGridEditorCreatedEvent(int id
, wxEventType type
, 
8770                                                    wxObject
* obj
, int row
, 
8771                                                    int col
, wxControl
* ctrl
) 
8772     : wxCommandEvent(type
, id
) 
8774     SetEventObject(obj
); 
8781 #endif // !wxUSE_NEW_GRID/wxUSE_NEW_GRID 
8783 #endif // wxUSE_GRID