1 /////////////////////////////////////////////////////////////////////////// 
   2 // Name:        generic/grid.cpp 
   3 // Purpose:     wxGrid and related classes 
   4 // Author:      Michael Bedward (based on code by Julian Smart, Robin Dunn) 
   5 // Modified by: Robin Dunn, Vadim Zeitlin 
   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 wxWindow
 
 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!!! 
 392 //       Well, it's still seriously broken so it might be better but needs 
 395 static const size_t GRID_SCROLL_LINE_X 
= 15;  // 1; 
 396 static const size_t GRID_SCROLL_LINE_Y 
= GRID_SCROLL_LINE_X
; 
 398 // the size of hash tables used a bit everywhere (the max number of elements 
 399 // in these hash tables is the number of rows/columns) 
 400 static const int GRID_HASH_SIZE 
= 100; 
 402 // ---------------------------------------------------------------------------- 
 404 // ---------------------------------------------------------------------------- 
 406 static inline int GetScrollX(int x
) 
 408     return (x 
+ GRID_SCROLL_LINE_X 
- 1) / GRID_SCROLL_LINE_X
; 
 411 static inline int GetScrollY(int y
) 
 413     return (y 
+ GRID_SCROLL_LINE_Y 
- 1) / GRID_SCROLL_LINE_Y
; 
 416 // ============================================================================ 
 418 // ============================================================================ 
 420 // ---------------------------------------------------------------------------- 
 422 // ---------------------------------------------------------------------------- 
 424 wxGridCellEditor::wxGridCellEditor() 
 430 wxGridCellEditor::~wxGridCellEditor() 
 435 void wxGridCellEditor::Create(wxWindow
* WXUNUSED(parent
), 
 436                               wxWindowID 
WXUNUSED(id
), 
 437                               wxEvtHandler
* evtHandler
) 
 440         m_control
->PushEventHandler(evtHandler
); 
 443 void wxGridCellEditor::PaintBackground(const wxRect
& rectCell
, 
 444                                        wxGridCellAttr 
*attr
) 
 446     // erase the background because we might not fill the cell 
 447     wxClientDC 
dc(m_control
->GetParent()); 
 448     dc
.SetPen(*wxTRANSPARENT_PEN
); 
 449     dc
.SetBrush(wxBrush(attr
->GetBackgroundColour(), wxSOLID
)); 
 450     dc
.DrawRectangle(rectCell
); 
 452     // redraw the control we just painted over 
 453     m_control
->Refresh(); 
 456 void wxGridCellEditor::Destroy() 
 460         m_control
->PopEventHandler(TRUE 
/* delete it*/); 
 462         m_control
->Destroy(); 
 467 void wxGridCellEditor::Show(bool show
, wxGridCellAttr 
*attr
) 
 469     wxASSERT_MSG(m_control
, 
 470                  wxT("The wxGridCellEditor must be Created first!")); 
 471     m_control
->Show(show
); 
 475         // set the colours/fonts if we have any 
 478             m_colFgOld 
= m_control
->GetForegroundColour(); 
 479             m_control
->SetForegroundColour(attr
->GetTextColour()); 
 481             m_colBgOld 
= m_control
->GetBackgroundColour(); 
 482             m_control
->SetBackgroundColour(attr
->GetBackgroundColour()); 
 484             m_fontOld 
= m_control
->GetFont(); 
 485             m_control
->SetFont(attr
->GetFont()); 
 487             // can't do anything more in the base class version, the other 
 488             // attributes may only be used by the derived classes 
 493         // restore the standard colours fonts 
 494         if ( m_colFgOld
.Ok() ) 
 496             m_control
->SetForegroundColour(m_colFgOld
); 
 497             m_colFgOld 
= wxNullColour
; 
 500         if ( m_colBgOld
.Ok() ) 
 502             m_control
->SetBackgroundColour(m_colBgOld
); 
 503             m_colBgOld 
= wxNullColour
; 
 506         if ( m_fontOld
.Ok() ) 
 508             m_control
->SetFont(m_fontOld
); 
 509             m_fontOld 
= wxNullFont
; 
 514 void wxGridCellEditor::SetSize(const wxRect
& rect
) 
 516     wxASSERT_MSG(m_control
, 
 517                  wxT("The wxGridCellEditor must be Created first!")); 
 518     m_control
->SetSize(rect
, wxSIZE_ALLOW_MINUS_ONE
); 
 521 void wxGridCellEditor::HandleReturn(wxKeyEvent
& event
) 
 526 bool wxGridCellEditor::IsAcceptedKey(wxKeyEvent
& event
) 
 528     // accept the simple key presses, not anything with Ctrl/Alt/Meta 
 529     return !(event
.ControlDown() || event
.AltDown()); 
 532 void wxGridCellEditor::StartingKey(wxKeyEvent
& event
) 
 537 void wxGridCellEditor::StartingClick() 
 543 // ---------------------------------------------------------------------------- 
 544 // wxGridCellTextEditor 
 545 // ---------------------------------------------------------------------------- 
 547 wxGridCellTextEditor::wxGridCellTextEditor() 
 552 void wxGridCellTextEditor::Create(wxWindow
* parent
, 
 554                                   wxEvtHandler
* evtHandler
) 
 556     m_control 
= new wxTextCtrl(parent
, id
, wxEmptyString
, 
 557                                wxDefaultPosition
, wxDefaultSize
 
 558 #if defined(__WXMSW__) 
 559                                , wxTE_PROCESS_TAB 
| wxTE_MULTILINE 
| 
 560                                  wxTE_NO_VSCROLL 
| wxTE_AUTO_SCROLL
 
 564     // TODO: use m_maxChars 
 566     wxGridCellEditor::Create(parent
, id
, evtHandler
); 
 569 void wxGridCellTextEditor::PaintBackground(const wxRect
& WXUNUSED(rectCell
), 
 570                                            wxGridCellAttr 
* WXUNUSED(attr
)) 
 572     // as we fill the entire client area, don't do anything here to minimize 
 576 void wxGridCellTextEditor::SetSize(const wxRect
& rectOrig
) 
 578     wxRect 
rect(rectOrig
); 
 580     // Make the edit control large enough to allow for internal 
 583     // TODO: remove this if the text ctrl sizing is improved esp. for 
 586 #if defined(__WXGTK__) 
 595     int extra_x 
= ( rect
.x 
> 2 )? 2 : 1; 
 597 // MB: treat MSW separately here otherwise the caret doesn't show 
 598 // when the editor is in the first row. 
 599 #if defined(__WXMSW__) 
 602     int extra_y 
= ( rect
.y 
> 2 )? 2 : 1; 
 605 #if defined(__WXMOTIF__) 
 609     rect
.SetLeft( wxMax(0, rect
.x 
- extra_x
) ); 
 610     rect
.SetTop( wxMax(0, rect
.y 
- extra_y
) ); 
 611     rect
.SetRight( rect
.GetRight() + 2*extra_x 
); 
 612     rect
.SetBottom( rect
.GetBottom() + 2*extra_y 
); 
 615     wxGridCellEditor::SetSize(rect
); 
 618 void wxGridCellTextEditor::BeginEdit(int row
, int col
, wxGrid
* grid
) 
 620     wxASSERT_MSG(m_control
, 
 621                  wxT("The wxGridCellEditor must be Created first!")); 
 623     m_startValue 
= grid
->GetTable()->GetValue(row
, col
); 
 625     DoBeginEdit(m_startValue
); 
 628 void wxGridCellTextEditor::DoBeginEdit(const wxString
& startValue
) 
 630     Text()->SetValue(startValue
); 
 631     Text()->SetInsertionPointEnd(); 
 635 bool wxGridCellTextEditor::EndEdit(int row
, int col
, 
 638     wxASSERT_MSG(m_control
, 
 639                  wxT("The wxGridCellEditor must be Created first!")); 
 641     bool changed 
= FALSE
; 
 642     wxString value 
= Text()->GetValue(); 
 643     if (value 
!= m_startValue
) 
 647         grid
->GetTable()->SetValue(row
, col
, value
); 
 649     m_startValue 
= wxEmptyString
; 
 650     Text()->SetValue(m_startValue
); 
 656 void wxGridCellTextEditor::Reset() 
 658     wxASSERT_MSG(m_control
, 
 659                  wxT("The wxGridCellEditor must be Created first!")); 
 661     DoReset(m_startValue
); 
 664 void wxGridCellTextEditor::DoReset(const wxString
& startValue
) 
 666     Text()->SetValue(startValue
); 
 667     Text()->SetInsertionPointEnd(); 
 670 bool wxGridCellTextEditor::IsAcceptedKey(wxKeyEvent
& event
) 
 672     if ( wxGridCellEditor::IsAcceptedKey(event
) ) 
 674         int keycode 
= event
.GetKeyCode(); 
 688             case WXK_NUMPAD_MULTIPLY
: 
 692             case WXK_NUMPAD_SUBTRACT
: 
 694             case WXK_NUMPAD_DECIMAL
: 
 696             case WXK_NUMPAD_DIVIDE
: 
 700                 // accept 8 bit chars too if isprint() agrees 
 701                 if ( (keycode 
< 255) && (isprint(keycode
)) ) 
 709 void wxGridCellTextEditor::StartingKey(wxKeyEvent
& event
) 
 711     if ( !Text()->EmulateKeyPress(event
) ) 
 717 void wxGridCellTextEditor::HandleReturn( wxKeyEvent
& 
 718                                          WXUNUSED_GTK(WXUNUSED_MOTIF(event
)) ) 
 720 #if defined(__WXMOTIF__) || defined(__WXGTK__) 
 721     // wxMotif needs a little extra help... 
 722     size_t pos 
= (size_t)( Text()->GetInsertionPoint() ); 
 723     wxString 
s( Text()->GetValue() ); 
 724     s 
= s
.Left(pos
) + "\n" + s
.Mid(pos
); 
 726     Text()->SetInsertionPoint( pos 
); 
 728     // the other ports can handle a Return key press 
 734 void wxGridCellTextEditor::SetParameters(const wxString
& params
) 
 744         if ( !params
.ToLong(&tmp
) ) 
 746             wxLogDebug(_T("Invalid wxGridCellTextEditor parameter string '%s' ignored"), params
.c_str()); 
 750             m_maxChars 
= (size_t)tmp
; 
 755 // ---------------------------------------------------------------------------- 
 756 // wxGridCellNumberEditor 
 757 // ---------------------------------------------------------------------------- 
 759 wxGridCellNumberEditor::wxGridCellNumberEditor(int min
, int max
) 
 765 void wxGridCellNumberEditor::Create(wxWindow
* parent
, 
 767                                     wxEvtHandler
* evtHandler
) 
 771         // create a spin ctrl 
 772         m_control 
= new wxSpinCtrl(parent
, -1, wxEmptyString
, 
 773                                    wxDefaultPosition
, wxDefaultSize
, 
 777         wxGridCellEditor::Create(parent
, id
, evtHandler
); 
 781         // just a text control 
 782         wxGridCellTextEditor::Create(parent
, id
, evtHandler
); 
 785         Text()->SetValidator(wxTextValidator(wxFILTER_NUMERIC
)); 
 786 #endif // wxUSE_VALIDATORS 
 790 void wxGridCellNumberEditor::BeginEdit(int row
, int col
, wxGrid
* grid
) 
 792     // first get the value 
 793     wxGridTableBase 
*table 
= grid
->GetTable(); 
 794     if ( table
->CanGetValueAs(row
, col
, wxGRID_VALUE_NUMBER
) ) 
 796         m_valueOld 
= table
->GetValueAsLong(row
, col
); 
 800         wxString sValue 
= table
->GetValue(row
, col
); 
 801         if (! sValue
.ToLong(&m_valueOld
)) 
 803             wxFAIL_MSG( _T("this cell doesn't have numeric value") ); 
 810         Spin()->SetValue((int)m_valueOld
); 
 815         DoBeginEdit(GetString()); 
 819 bool wxGridCellNumberEditor::EndEdit(int row
, int col
, 
 827         value 
= Spin()->GetValue(); 
 828         changed 
= value 
!= m_valueOld
; 
 832         changed 
= Text()->GetValue().ToLong(&value
) && (value 
!= m_valueOld
); 
 837         if (grid
->GetTable()->CanSetValueAs(row
, col
, wxGRID_VALUE_NUMBER
)) 
 838             grid
->GetTable()->SetValueAsLong(row
, col
, value
); 
 840             grid
->GetTable()->SetValue(row
, col
, wxString::Format(wxT("%ld"), value
)); 
 846 void wxGridCellNumberEditor::Reset() 
 850         Spin()->SetValue((int)m_valueOld
); 
 854         DoReset(GetString()); 
 858 bool wxGridCellNumberEditor::IsAcceptedKey(wxKeyEvent
& event
) 
 860     if ( wxGridCellEditor::IsAcceptedKey(event
) ) 
 862         int keycode 
= event
.GetKeyCode(); 
 878             case WXK_NUMPAD_SUBTRACT
: 
 884                 if ( (keycode 
< 128) && isdigit(keycode
) ) 
 892 void wxGridCellNumberEditor::StartingKey(wxKeyEvent
& event
) 
 896         int keycode 
= (int) event
.KeyCode(); 
 897         if ( isdigit(keycode
) || keycode 
== '+' || keycode 
== '-' ) 
 899             wxGridCellTextEditor::StartingKey(event
); 
 909 void wxGridCellNumberEditor::SetParameters(const wxString
& params
) 
 920         if ( params
.BeforeFirst(_T(',')).ToLong(&tmp
) ) 
 924             if ( params
.AfterFirst(_T(',')).ToLong(&tmp
) ) 
 928                 // skip the error message below 
 933         wxLogDebug(_T("Invalid wxGridCellNumberEditor parameter string '%s' ignored"), params
.c_str()); 
 937 // ---------------------------------------------------------------------------- 
 938 // wxGridCellFloatEditor 
 939 // ---------------------------------------------------------------------------- 
 941 wxGridCellFloatEditor::wxGridCellFloatEditor(int width
, int precision
) 
 944     m_precision 
= precision
; 
 947 void wxGridCellFloatEditor::Create(wxWindow
* parent
, 
 949                                    wxEvtHandler
* evtHandler
) 
 951     wxGridCellTextEditor::Create(parent
, id
, evtHandler
); 
 954     Text()->SetValidator(wxTextValidator(wxFILTER_NUMERIC
)); 
 955 #endif // wxUSE_VALIDATORS 
 958 void wxGridCellFloatEditor::BeginEdit(int row
, int col
, wxGrid
* grid
) 
 960     // first get the value 
 961     wxGridTableBase 
*table 
= grid
->GetTable(); 
 962     if ( table
->CanGetValueAs(row
, col
, wxGRID_VALUE_FLOAT
) ) 
 964         m_valueOld 
= table
->GetValueAsDouble(row
, col
); 
 968         wxString sValue 
= table
->GetValue(row
, col
); 
 969         if (! sValue
.ToDouble(&m_valueOld
)) 
 971             wxFAIL_MSG( _T("this cell doesn't have float value") ); 
 976     DoBeginEdit(GetString()); 
 979 bool wxGridCellFloatEditor::EndEdit(int row
, int col
, 
 983     if ( Text()->GetValue().ToDouble(&value
) && (value 
!= m_valueOld
) ) 
 985         if (grid
->GetTable()->CanSetValueAs(row
, col
, wxGRID_VALUE_FLOAT
)) 
 986             grid
->GetTable()->SetValueAsDouble(row
, col
, value
); 
 988             grid
->GetTable()->SetValue(row
, col
, wxString::Format(wxT("%f"), value
)); 
 998 void wxGridCellFloatEditor::Reset() 
1000     DoReset(GetString()); 
1003 void wxGridCellFloatEditor::StartingKey(wxKeyEvent
& event
) 
1005     int keycode 
= (int)event
.KeyCode(); 
1006     if ( isdigit(keycode
) || 
1007          keycode 
== '+' || keycode 
== '-' || keycode 
== '.' ) 
1009         wxGridCellTextEditor::StartingKey(event
); 
1011         // skip Skip() below 
1018 void wxGridCellFloatEditor::SetParameters(const wxString
& params
) 
1029         if ( params
.BeforeFirst(_T(',')).ToLong(&tmp
) ) 
1033             if ( params
.AfterFirst(_T(',')).ToLong(&tmp
) ) 
1035                 m_precision 
= (int)tmp
; 
1037                 // skip the error message below 
1042         wxLogDebug(_T("Invalid wxGridCellFloatEditor parameter string '%s' ignored"), params
.c_str()); 
1046 wxString 
wxGridCellFloatEditor::GetString() const 
1049     if ( m_width 
== -1 ) 
1051         // default width/precision 
1054     else if ( m_precision 
== -1 ) 
1056         // default precision 
1057         fmt
.Printf(_T("%%%d.g"), m_width
); 
1061         fmt
.Printf(_T("%%%d.%dg"), m_width
, m_precision
); 
1064     return wxString::Format(fmt
, m_valueOld
); 
1067 bool wxGridCellFloatEditor::IsAcceptedKey(wxKeyEvent
& event
) 
1069     if ( wxGridCellEditor::IsAcceptedKey(event
) ) 
1071         int keycode 
= event
.GetKeyCode(); 
1085             case WXK_NUMPAD_ADD
: 
1087             case WXK_NUMPAD_SUBTRACT
: 
1089             case WXK_NUMPAD_DECIMAL
: 
1093                 // additionally accept 'e' as in '1e+6' 
1094                 if ( (keycode 
< 128) && 
1095                      (isdigit(keycode
) || tolower(keycode
) == 'e') ) 
1103 #endif // wxUSE_TEXTCTRL 
1107 // ---------------------------------------------------------------------------- 
1108 // wxGridCellBoolEditor 
1109 // ---------------------------------------------------------------------------- 
1111 void wxGridCellBoolEditor::Create(wxWindow
* parent
, 
1113                                   wxEvtHandler
* evtHandler
) 
1115     m_control 
= new wxCheckBox(parent
, id
, wxEmptyString
, 
1116                                wxDefaultPosition
, wxDefaultSize
, 
1119     wxGridCellEditor::Create(parent
, id
, evtHandler
); 
1122 void wxGridCellBoolEditor::SetSize(const wxRect
& r
) 
1124     bool resize 
= FALSE
; 
1125     wxSize size 
= m_control
->GetSize(); 
1126     wxCoord minSize 
= wxMin(r
.width
, r
.height
); 
1128     // check if the checkbox is not too big/small for this cell 
1129     wxSize sizeBest 
= m_control
->GetBestSize(); 
1130     if ( !(size 
== sizeBest
) ) 
1132         // reset to default size if it had been made smaller 
1138     if ( size
.x 
>= minSize 
|| size
.y 
>= minSize 
) 
1140         // leave 1 pixel margin 
1141         size
.x 
= size
.y 
= minSize 
- 2; 
1148         m_control
->SetSize(size
); 
1151     // position it in the centre of the rectangle (TODO: support alignment?) 
1153 #if defined(__WXGTK__) || defined (__WXMOTIF__) 
1154     // the checkbox without label still has some space to the right in wxGTK, 
1155     // so shift it to the right 
1157 #elif defined(__WXMSW__) 
1158     // here too, but in other way 
1163     m_control
->Move(r
.x 
+ r
.width
/2 - size
.x
/2, r
.y 
+ r
.height
/2 - size
.y
/2); 
1166 void wxGridCellBoolEditor::Show(bool show
, wxGridCellAttr 
*attr
) 
1168     m_control
->Show(show
); 
1172         wxColour colBg 
= attr 
? attr
->GetBackgroundColour() : *wxLIGHT_GREY
; 
1173         CBox()->SetBackgroundColour(colBg
); 
1177 void wxGridCellBoolEditor::BeginEdit(int row
, int col
, wxGrid
* grid
) 
1179     wxASSERT_MSG(m_control
, 
1180                  wxT("The wxGridCellEditor must be Created first!")); 
1182     if (grid
->GetTable()->CanGetValueAs(row
, col
, wxGRID_VALUE_BOOL
)) 
1183         m_startValue 
= grid
->GetTable()->GetValueAsBool(row
, col
); 
1186         wxString 
cellval( grid
->GetTable()->GetValue(row
, col
) ); 
1187         m_startValue 
= !( !cellval 
|| (cellval 
== "0") ); 
1189     CBox()->SetValue(m_startValue
); 
1193 bool wxGridCellBoolEditor::EndEdit(int row
, int col
, 
1196     wxASSERT_MSG(m_control
, 
1197                  wxT("The wxGridCellEditor must be Created first!")); 
1199     bool changed 
= FALSE
; 
1200     bool value 
= CBox()->GetValue(); 
1201     if ( value 
!= m_startValue 
) 
1206         if (grid
->GetTable()->CanGetValueAs(row
, col
, wxGRID_VALUE_BOOL
)) 
1207             grid
->GetTable()->SetValueAsBool(row
, col
, value
); 
1209             grid
->GetTable()->SetValue(row
, col
, value 
? _T("1") : wxEmptyString
); 
1215 void wxGridCellBoolEditor::Reset() 
1217     wxASSERT_MSG(m_control
, 
1218                  wxT("The wxGridCellEditor must be Created first!")); 
1220     CBox()->SetValue(m_startValue
); 
1223 void wxGridCellBoolEditor::StartingClick() 
1225     CBox()->SetValue(!CBox()->GetValue()); 
1228 bool wxGridCellBoolEditor::IsAcceptedKey(wxKeyEvent
& event
) 
1230     if ( wxGridCellEditor::IsAcceptedKey(event
) ) 
1232         int keycode 
= event
.GetKeyCode(); 
1236             case WXK_NUMPAD_MULTIPLY
: 
1238             case WXK_NUMPAD_ADD
: 
1240             case WXK_NUMPAD_SUBTRACT
: 
1251 #endif // wxUSE_CHECKBOX 
1255 // ---------------------------------------------------------------------------- 
1256 // wxGridCellChoiceEditor 
1257 // ---------------------------------------------------------------------------- 
1259 wxGridCellChoiceEditor::wxGridCellChoiceEditor(size_t count
, 
1260                                                const wxString choices
[], 
1262                       : m_allowOthers(allowOthers
) 
1266         m_choices
.Alloc(count
); 
1267         for ( size_t n 
= 0; n 
< count
; n
++ ) 
1269             m_choices
.Add(choices
[n
]); 
1274 wxGridCellEditor 
*wxGridCellChoiceEditor::Clone() const 
1276     wxGridCellChoiceEditor 
*editor 
= new wxGridCellChoiceEditor
; 
1277     editor
->m_allowOthers 
= m_allowOthers
; 
1278     editor
->m_choices 
= m_choices
; 
1283 void wxGridCellChoiceEditor::Create(wxWindow
* parent
, 
1285                                     wxEvtHandler
* evtHandler
) 
1287     size_t count 
= m_choices
.GetCount(); 
1288     wxString 
*choices 
= new wxString
[count
]; 
1289     for ( size_t n 
= 0; n 
< count
; n
++ ) 
1291         choices
[n
] = m_choices
[n
]; 
1294     m_control 
= new wxComboBox(parent
, id
, wxEmptyString
, 
1295                                wxDefaultPosition
, wxDefaultSize
, 
1297                                m_allowOthers 
? 0 : wxCB_READONLY
); 
1301     wxGridCellEditor::Create(parent
, id
, evtHandler
); 
1304 void wxGridCellChoiceEditor::PaintBackground(const wxRect
& rectCell
, 
1305                                              wxGridCellAttr 
* attr
) 
1307     // as we fill the entire client area, don't do anything here to minimize 
1310     // TODO: It doesn't actually fill the client area since the height of a 
1311     // combo always defaults to the standard...  Until someone has time to 
1312     // figure out the right rectangle to paint, just do it the normal way... 
1313     wxGridCellEditor::PaintBackground(rectCell
, attr
); 
1316 void wxGridCellChoiceEditor::BeginEdit(int row
, int col
, wxGrid
* grid
) 
1318     wxASSERT_MSG(m_control
, 
1319                  wxT("The wxGridCellEditor must be Created first!")); 
1321     m_startValue 
= grid
->GetTable()->GetValue(row
, col
); 
1323     Combo()->SetValue(m_startValue
); 
1324     size_t count 
= m_choices
.GetCount(); 
1325     for (size_t i
=0; i
<count
; i
++) 
1327         if (m_startValue 
== m_choices
[i
]) 
1329             Combo()->SetSelection(i
); 
1333     Combo()->SetInsertionPointEnd(); 
1334     Combo()->SetFocus(); 
1337 bool wxGridCellChoiceEditor::EndEdit(int row
, int col
, 
1340     wxString value 
= Combo()->GetValue(); 
1341     bool changed 
= value 
!= m_startValue
; 
1344         grid
->GetTable()->SetValue(row
, col
, value
); 
1346     m_startValue 
= wxEmptyString
; 
1347     Combo()->SetValue(m_startValue
); 
1352 void wxGridCellChoiceEditor::Reset() 
1354     Combo()->SetValue(m_startValue
); 
1355     Combo()->SetInsertionPointEnd(); 
1358 void wxGridCellChoiceEditor::SetParameters(const wxString
& params
) 
1368     wxStringTokenizer 
tk(params
, _T(',')); 
1369     while ( tk
.HasMoreTokens() ) 
1371         m_choices
.Add(tk
.GetNextToken()); 
1375 #endif // wxUSE_COMBOBOX 
1377 // ---------------------------------------------------------------------------- 
1378 // wxGridCellEditorEvtHandler 
1379 // ---------------------------------------------------------------------------- 
1381 void wxGridCellEditorEvtHandler::OnKeyDown(wxKeyEvent
& event
) 
1383     switch ( event
.KeyCode() ) 
1387             m_grid
->DisableCellEditControl(); 
1391             m_grid
->GetEventHandler()->ProcessEvent( event 
); 
1395         case WXK_NUMPAD_ENTER
: 
1396             if (!m_grid
->GetEventHandler()->ProcessEvent(event
)) 
1397                 m_editor
->HandleReturn(event
); 
1406 void wxGridCellEditorEvtHandler::OnChar(wxKeyEvent
& event
) 
1408     switch ( event
.KeyCode() ) 
1413         case WXK_NUMPAD_ENTER
: 
1421 // ---------------------------------------------------------------------------- 
1422 // wxGridCellWorker is an (almost) empty common base class for 
1423 // wxGridCellRenderer and wxGridCellEditor managing ref counting 
1424 // ---------------------------------------------------------------------------- 
1426 void wxGridCellWorker::SetParameters(const wxString
& WXUNUSED(params
)) 
1431 wxGridCellWorker::~wxGridCellWorker() 
1435 // ============================================================================ 
1437 // ============================================================================ 
1439 // ---------------------------------------------------------------------------- 
1440 // wxGridCellRenderer 
1441 // ---------------------------------------------------------------------------- 
1443 void wxGridCellRenderer::Draw(wxGrid
& grid
, 
1444                               wxGridCellAttr
& attr
, 
1447                               int WXUNUSED(row
), int WXUNUSED(col
), 
1450     dc
.SetBackgroundMode( wxSOLID 
); 
1454         dc
.SetBrush( wxBrush(grid
.GetSelectionBackground(), wxSOLID
) ); 
1458         dc
.SetBrush( wxBrush(attr
.GetBackgroundColour(), wxSOLID
) ); 
1461     dc
.SetPen( *wxTRANSPARENT_PEN 
); 
1462     dc
.DrawRectangle(rect
); 
1465 // ---------------------------------------------------------------------------- 
1466 // wxGridCellStringRenderer 
1467 // ---------------------------------------------------------------------------- 
1469 void wxGridCellStringRenderer::SetTextColoursAndFont(wxGrid
& grid
, 
1470                                                      wxGridCellAttr
& attr
, 
1474     dc
.SetBackgroundMode( wxTRANSPARENT 
); 
1476     // TODO some special colours for attr.IsReadOnly() case? 
1480         dc
.SetTextBackground( grid
.GetSelectionBackground() ); 
1481         dc
.SetTextForeground( grid
.GetSelectionForeground() ); 
1485         dc
.SetTextBackground( attr
.GetBackgroundColour() ); 
1486         dc
.SetTextForeground( attr
.GetTextColour() ); 
1489     dc
.SetFont( attr
.GetFont() ); 
1492 wxSize 
wxGridCellStringRenderer::DoGetBestSize(wxGridCellAttr
& attr
, 
1494                                                const wxString
& text
) 
1496     wxCoord x 
= 0, y 
= 0, max_x 
= 0; 
1497     dc
.SetFont(attr
.GetFont()); 
1498     wxStringTokenizer 
tk(text
, _T('\n')); 
1499     while ( tk
.HasMoreTokens() ) 
1501         dc
.GetTextExtent(tk
.GetNextToken(), &x
, &y
); 
1502         max_x 
= wxMax(max_x
, x
); 
1505     y 
*= 1 + text
.Freq(wxT('\n')); // multiply by the number of lines. 
1507     return wxSize(max_x
, y
); 
1510 wxSize 
wxGridCellStringRenderer::GetBestSize(wxGrid
& grid
, 
1511                                              wxGridCellAttr
& attr
, 
1515     return DoGetBestSize(attr
, dc
, grid
.GetCellValue(row
, col
)); 
1518 void wxGridCellStringRenderer::Draw(wxGrid
& grid
, 
1519                                     wxGridCellAttr
& attr
, 
1521                                     const wxRect
& rectCell
, 
1525     wxGridCellRenderer::Draw(grid
, attr
, dc
, rectCell
, row
, col
, isSelected
); 
1527     // now we only have to draw the text 
1528     SetTextColoursAndFont(grid
, attr
, dc
, isSelected
); 
1531     attr
.GetAlignment(&hAlign
, &vAlign
); 
1533     wxRect rect 
= rectCell
; 
1536     grid
.DrawTextRectangle(dc
, grid
.GetCellValue(row
, col
), 
1537                            rect
, hAlign
, vAlign
); 
1540 // ---------------------------------------------------------------------------- 
1541 // wxGridCellNumberRenderer 
1542 // ---------------------------------------------------------------------------- 
1544 wxString 
wxGridCellNumberRenderer::GetString(wxGrid
& grid
, int row
, int col
) 
1546     wxGridTableBase 
*table 
= grid
.GetTable(); 
1548     if ( table
->CanGetValueAs(row
, col
, wxGRID_VALUE_NUMBER
) ) 
1550         text
.Printf(_T("%ld"), table
->GetValueAsLong(row
, col
)); 
1554         text 
= table
->GetValue(row
, col
); 
1560 void wxGridCellNumberRenderer::Draw(wxGrid
& grid
, 
1561                                     wxGridCellAttr
& attr
, 
1563                                     const wxRect
& rectCell
, 
1567     wxGridCellRenderer::Draw(grid
, attr
, dc
, rectCell
, row
, col
, isSelected
); 
1569     SetTextColoursAndFont(grid
, attr
, dc
, isSelected
); 
1571     // draw the text right aligned by default 
1573     attr
.GetAlignment(&hAlign
, &vAlign
); 
1574     hAlign 
= wxALIGN_RIGHT
; 
1576     wxRect rect 
= rectCell
; 
1579     grid
.DrawTextRectangle(dc
, GetString(grid
, row
, col
), rect
, hAlign
, vAlign
); 
1582 wxSize 
wxGridCellNumberRenderer::GetBestSize(wxGrid
& grid
, 
1583                                              wxGridCellAttr
& attr
, 
1587     return DoGetBestSize(attr
, dc
, GetString(grid
, row
, col
)); 
1590 // ---------------------------------------------------------------------------- 
1591 // wxGridCellFloatRenderer 
1592 // ---------------------------------------------------------------------------- 
1594 wxGridCellFloatRenderer::wxGridCellFloatRenderer(int width
, int precision
) 
1597     SetPrecision(precision
); 
1600 wxGridCellRenderer 
*wxGridCellFloatRenderer::Clone() const 
1602     wxGridCellFloatRenderer 
*renderer 
= new wxGridCellFloatRenderer
; 
1603     renderer
->m_width 
= m_width
; 
1604     renderer
->m_precision 
= m_precision
; 
1605     renderer
->m_format 
= m_format
; 
1610 wxString 
wxGridCellFloatRenderer::GetString(wxGrid
& grid
, int row
, int col
) 
1612     wxGridTableBase 
*table 
= grid
.GetTable(); 
1617     if ( table
->CanGetValueAs(row
, col
, wxGRID_VALUE_FLOAT
) ) 
1619         val 
= table
->GetValueAsDouble(row
, col
); 
1624         text 
= table
->GetValue(row
, col
); 
1625         hasDouble 
= text
.ToDouble(&val
); 
1632             if ( m_width 
== -1 ) 
1634                 if ( m_precision 
== -1 ) 
1636                 // default width/precision 
1637                 m_format 
= _T("%f"); 
1641                     m_format
.Printf(_T("%%.%df"), m_precision
); 
1644             else if ( m_precision 
== -1 ) 
1646                 // default precision 
1647                 m_format
.Printf(_T("%%%d.f"), m_width
); 
1651                 m_format
.Printf(_T("%%%d.%df"), m_width
, m_precision
); 
1655         text
.Printf(m_format
, val
); 
1658     //else: text already contains the string 
1663 void wxGridCellFloatRenderer::Draw(wxGrid
& grid
, 
1664                                    wxGridCellAttr
& attr
, 
1666                                    const wxRect
& rectCell
, 
1670     wxGridCellRenderer::Draw(grid
, attr
, dc
, rectCell
, row
, col
, isSelected
); 
1672     SetTextColoursAndFont(grid
, attr
, dc
, isSelected
); 
1674     // draw the text right aligned by default 
1676     attr
.GetAlignment(&hAlign
, &vAlign
); 
1677     hAlign 
= wxALIGN_RIGHT
; 
1679     wxRect rect 
= rectCell
; 
1682     grid
.DrawTextRectangle(dc
, GetString(grid
, row
, col
), rect
, hAlign
, vAlign
); 
1685 wxSize 
wxGridCellFloatRenderer::GetBestSize(wxGrid
& grid
, 
1686                                             wxGridCellAttr
& attr
, 
1690     return DoGetBestSize(attr
, dc
, GetString(grid
, row
, col
)); 
1693 void wxGridCellFloatRenderer::SetParameters(const wxString
& params
) 
1697         // reset to defaults 
1703         wxString tmp 
= params
.BeforeFirst(_T(',')); 
1707             if ( tmp
.ToLong(&width
) ) 
1709                 SetWidth((int)width
); 
1713                 wxLogDebug(_T("Invalid wxGridCellFloatRenderer width parameter string '%s ignored"), params
.c_str()); 
1717                 tmp 
= params
.AfterFirst(_T(',')); 
1721             if ( tmp
.ToLong(&precision
) ) 
1723                 SetPrecision((int)precision
); 
1727                 wxLogDebug(_T("Invalid wxGridCellFloatRenderer precision parameter string '%s ignored"), params
.c_str()); 
1735 // ---------------------------------------------------------------------------- 
1736 // wxGridCellBoolRenderer 
1737 // ---------------------------------------------------------------------------- 
1739 wxSize 
wxGridCellBoolRenderer::ms_sizeCheckMark
; 
1741 // FIXME these checkbox size calculations are really ugly... 
1743 // between checkmark and box 
1744 static const wxCoord wxGRID_CHECKMARK_MARGIN 
= 2; 
1746 wxSize 
wxGridCellBoolRenderer::GetBestSize(wxGrid
& grid
, 
1747                                            wxGridCellAttr
& WXUNUSED(attr
), 
1752     // compute it only once (no locks for MT safeness in GUI thread...) 
1753     if ( !ms_sizeCheckMark
.x 
) 
1755         // get checkbox size 
1756         wxCoord checkSize 
= 0; 
1757         wxCheckBox 
*checkbox 
= new wxCheckBox(&grid
, -1, wxEmptyString
); 
1758         wxSize size 
= checkbox
->GetBestSize(); 
1759         checkSize 
= size
.y 
+ 2*wxGRID_CHECKMARK_MARGIN
; 
1761         // FIXME wxGTK::wxCheckBox::GetBestSize() gives "wrong" result 
1762 #if defined(__WXGTK__) || defined(__WXMOTIF__) 
1763         checkSize 
-= size
.y 
/ 2; 
1768         ms_sizeCheckMark
.x 
= ms_sizeCheckMark
.y 
= checkSize
; 
1771     return ms_sizeCheckMark
; 
1774 void wxGridCellBoolRenderer::Draw(wxGrid
& grid
, 
1775                                   wxGridCellAttr
& attr
, 
1781     wxGridCellRenderer::Draw(grid
, attr
, dc
, rect
, row
, col
, isSelected
); 
1783     // draw a check mark in the centre (ignoring alignment - TODO) 
1784     wxSize size 
= GetBestSize(grid
, attr
, dc
, row
, col
); 
1786     // don't draw outside the cell 
1787     wxCoord minSize 
= wxMin(rect
.width
, rect
.height
); 
1788     if ( size
.x 
>= minSize 
|| size
.y 
>= minSize 
) 
1790         // and even leave (at least) 1 pixel margin 
1791         size
.x 
= size
.y 
= minSize 
- 2; 
1794     // draw a border around checkmark 
1796     rectBorder
.x 
= rect
.x 
+ rect
.width
/2 - size
.x
/2; 
1797     rectBorder
.y 
= rect
.y 
+ rect
.height
/2 - size
.y
/2; 
1798     rectBorder
.width 
= size
.x
; 
1799     rectBorder
.height 
= size
.y
; 
1802     if ( grid
.GetTable()->CanGetValueAs(row
, col
, wxGRID_VALUE_BOOL
) ) 
1803         value 
= grid
.GetTable()->GetValueAsBool(row
, col
); 
1806         wxString 
cellval( grid
.GetTable()->GetValue(row
, col
) ); 
1807         value 
= !( !cellval 
|| (cellval 
== "0") ); 
1812         wxRect rectMark 
= rectBorder
; 
1814         // MSW DrawCheckMark() is weird (and should probably be changed...) 
1815         rectMark
.Inflate(-wxGRID_CHECKMARK_MARGIN
/2); 
1819         rectMark
.Inflate(-wxGRID_CHECKMARK_MARGIN
); 
1822         dc
.SetTextForeground(attr
.GetTextColour()); 
1823         dc
.DrawCheckMark(rectMark
); 
1826     dc
.SetBrush(*wxTRANSPARENT_BRUSH
); 
1827     dc
.SetPen(wxPen(attr
.GetTextColour(), 1, wxSOLID
)); 
1828     dc
.DrawRectangle(rectBorder
); 
1831 // ---------------------------------------------------------------------------- 
1833 // ---------------------------------------------------------------------------- 
1835 void wxGridCellAttr::Init(wxGridCellAttr 
*attrDefault
) 
1839     m_isReadOnly 
= Unset
; 
1844     m_attrkind 
= wxGridCellAttr::Cell
; 
1846     SetDefAttr(attrDefault
); 
1849 wxGridCellAttr 
*wxGridCellAttr::Clone() const 
1851     wxGridCellAttr 
*attr 
= new wxGridCellAttr(m_defGridAttr
); 
1853     if ( HasTextColour() ) 
1854         attr
->SetTextColour(GetTextColour()); 
1855     if ( HasBackgroundColour() ) 
1856         attr
->SetBackgroundColour(GetBackgroundColour()); 
1858         attr
->SetFont(GetFont()); 
1859     if ( HasAlignment() ) 
1860         attr
->SetAlignment(m_hAlign
, m_vAlign
); 
1864         attr
->SetRenderer(m_renderer
); 
1865         m_renderer
->IncRef(); 
1869         attr
->SetEditor(m_editor
); 
1874         attr
->SetReadOnly(); 
1876     attr
->SetKind( m_attrkind 
); 
1881 void wxGridCellAttr::MergeWith(wxGridCellAttr 
*mergefrom
) 
1883     if ( !HasTextColour() && mergefrom
->HasTextColour() ) 
1884         SetTextColour(mergefrom
->GetTextColour()); 
1885     if ( !HasBackgroundColour() && mergefrom
->HasBackgroundColour() ) 
1886         SetBackgroundColour(mergefrom
->GetBackgroundColour()); 
1887     if ( !HasFont() && mergefrom
->HasFont() ) 
1888         SetFont(mergefrom
->GetFont()); 
1889     if ( !!HasAlignment() && mergefrom
->HasAlignment() ){ 
1891         mergefrom
->GetAlignment( &hAlign
, &vAlign
); 
1892         SetAlignment(hAlign
, vAlign
); 
1895     // Directly access member functions as GetRender/Editor don't just return 
1896     // m_renderer/m_editor 
1898     // Maybe add support for merge of Render and Editor? 
1899     if (!HasRenderer() && mergefrom
->HasRenderer() ) 
1901         m_renderer 
= mergefrom
->m_renderer
; 
1902         m_renderer
->IncRef(); 
1904     if ( !HasEditor() && mergefrom
->HasEditor() ) 
1906         m_editor 
=  mergefrom
->m_editor
; 
1909     if ( !HasReadWriteMode()  && mergefrom
->HasReadWriteMode() ) 
1910         SetReadOnly(mergefrom
->IsReadOnly()); 
1912     SetDefAttr(mergefrom
->m_defGridAttr
); 
1915 const wxColour
& wxGridCellAttr::GetTextColour() const 
1917     if (HasTextColour()) 
1921     else if (m_defGridAttr 
&& m_defGridAttr 
!= this) 
1923         return m_defGridAttr
->GetTextColour(); 
1927         wxFAIL_MSG(wxT("Missing default cell attribute")); 
1928         return wxNullColour
; 
1933 const wxColour
& wxGridCellAttr::GetBackgroundColour() const 
1935     if (HasBackgroundColour()) 
1937     else if (m_defGridAttr 
&& m_defGridAttr 
!= this) 
1938         return m_defGridAttr
->GetBackgroundColour(); 
1941         wxFAIL_MSG(wxT("Missing default cell attribute")); 
1942         return wxNullColour
; 
1947 const wxFont
& wxGridCellAttr::GetFont() const 
1951     else if (m_defGridAttr 
&& m_defGridAttr 
!= this) 
1952         return m_defGridAttr
->GetFont(); 
1955         wxFAIL_MSG(wxT("Missing default cell attribute")); 
1961 void wxGridCellAttr::GetAlignment(int *hAlign
, int *vAlign
) const 
1965         if ( hAlign 
) *hAlign 
= m_hAlign
; 
1966         if ( vAlign 
) *vAlign 
= m_vAlign
; 
1968     else if (m_defGridAttr 
&& m_defGridAttr 
!= this) 
1969         m_defGridAttr
->GetAlignment(hAlign
, vAlign
); 
1972         wxFAIL_MSG(wxT("Missing default cell attribute")); 
1977 // GetRenderer and GetEditor use a slightly different decision path about 
1978 // which attribute to use.  If a non-default attr object has one then it is 
1979 // used, otherwise the default editor or renderer is fetched from the grid and 
1980 // used.  It should be the default for the data type of the cell.  If it is 
1981 // NULL (because the table has a type that the grid does not have in its 
1982 // registry,) then the grid's default editor or renderer is used. 
1984 wxGridCellRenderer
* wxGridCellAttr::GetRenderer(wxGrid
* grid
, int row
, int col
) const 
1986     wxGridCellRenderer 
*renderer
; 
1988     if ( m_renderer 
&& this != m_defGridAttr 
) 
1990         // use the cells renderer if it has one 
1991         renderer 
= m_renderer
; 
1994     else // no non default cell renderer 
1996         // get default renderer for the data type 
1999             // GetDefaultRendererForCell() will do IncRef() for us 
2000             renderer 
= grid
->GetDefaultRendererForCell(row
, col
); 
2009             if (m_defGridAttr 
&&  this != m_defGridAttr 
) 
2011                 // if we still don't have one then use the grid default 
2012                 // (no need for IncRef() here neither) 
2013                 renderer 
= m_defGridAttr
->GetRenderer(NULL
, 0, 0); 
2015             else // default grid attr 
2017                 // use m_renderer which we had decided not to use initially 
2018                 renderer 
= m_renderer
; 
2025     // we're supposed to always find something 
2026     wxASSERT_MSG(renderer
, wxT("Missing default cell renderer")); 
2031 // same as above, except for s/renderer/editor/g 
2032 wxGridCellEditor
* wxGridCellAttr::GetEditor(wxGrid
* grid
, int row
, int col
) const 
2034     wxGridCellEditor 
*editor
; 
2036     if ( m_editor 
&& this != m_defGridAttr 
) 
2038         // use the cells editor if it has one 
2042     else // no non default cell editor 
2044         // get default editor for the data type 
2047             // GetDefaultEditorForCell() will do IncRef() for us 
2048             editor 
= grid
->GetDefaultEditorForCell(row
, col
); 
2057             if ( m_defGridAttr 
&& this != m_defGridAttr 
) 
2059                 // if we still don't have one then use the grid default 
2060                 // (no need for IncRef() here neither) 
2061                 editor 
= m_defGridAttr
->GetEditor(NULL
, 0, 0); 
2063             else // default grid attr 
2065                 // use m_editor which we had decided not to use initially 
2073     // we're supposed to always find something 
2074     wxASSERT_MSG(editor
, wxT("Missing default cell editor")); 
2079 // ---------------------------------------------------------------------------- 
2080 // wxGridCellAttrData 
2081 // ---------------------------------------------------------------------------- 
2083 void wxGridCellAttrData::SetAttr(wxGridCellAttr 
*attr
, int row
, int col
) 
2085     int n 
= FindIndex(row
, col
); 
2086     if ( n 
== wxNOT_FOUND 
) 
2088         // add the attribute 
2089         m_attrs
.Add(new wxGridCellWithAttr(row
, col
, attr
)); 
2093         // free the old attribute 
2094         m_attrs
[(size_t)n
].attr
->DecRef(); 
2098             // change the attribute 
2099             m_attrs
[(size_t)n
].attr 
= attr
; 
2103             // remove this attribute 
2104             m_attrs
.RemoveAt((size_t)n
); 
2109 wxGridCellAttr 
*wxGridCellAttrData::GetAttr(int row
, int col
) const 
2111     wxGridCellAttr 
*attr 
= (wxGridCellAttr 
*)NULL
; 
2113     int n 
= FindIndex(row
, col
); 
2114     if ( n 
!= wxNOT_FOUND 
) 
2116         attr 
= m_attrs
[(size_t)n
].attr
; 
2123 void wxGridCellAttrData::UpdateAttrRows( size_t pos
, int numRows 
) 
2125     size_t count 
= m_attrs
.GetCount(); 
2126     for ( size_t n 
= 0; n 
< count
; n
++ ) 
2128         wxGridCellCoords
& coords 
= m_attrs
[n
].coords
; 
2129         wxCoord row 
= coords
.GetRow(); 
2130         if ((size_t)row 
>= pos
) 
2134                 // If rows inserted, include row counter where necessary 
2135                 coords
.SetRow(row 
+ numRows
); 
2137             else if (numRows 
< 0) 
2139                 // If rows deleted ... 
2140                 if ((size_t)row 
>= pos 
- numRows
) 
2142                     // ...either decrement row counter (if row still exists)... 
2143                     coords
.SetRow(row 
+ numRows
); 
2147                     // ...or remove the attribute 
2148                     m_attrs
.RemoveAt((size_t)n
); 
2156 void wxGridCellAttrData::UpdateAttrCols( size_t pos
, int numCols 
) 
2158     size_t count 
= m_attrs
.GetCount(); 
2159     for ( size_t n 
= 0; n 
< count
; n
++ ) 
2161         wxGridCellCoords
& coords 
= m_attrs
[n
].coords
; 
2162         wxCoord col 
= coords
.GetCol(); 
2163         if ( (size_t)col 
>= pos 
) 
2167                 // If rows inserted, include row counter where necessary 
2168                 coords
.SetCol(col 
+ numCols
); 
2170             else if (numCols 
< 0) 
2172                 // If rows deleted ... 
2173                 if ((size_t)col 
>= pos 
- numCols
) 
2175                     // ...either decrement row counter (if row still exists)... 
2176                     coords
.SetCol(col 
+ numCols
); 
2180                     // ...or remove the attribute 
2181                     m_attrs
.RemoveAt((size_t)n
); 
2189 int wxGridCellAttrData::FindIndex(int row
, int col
) const 
2191     size_t count 
= m_attrs
.GetCount(); 
2192     for ( size_t n 
= 0; n 
< count
; n
++ ) 
2194         const wxGridCellCoords
& coords 
= m_attrs
[n
].coords
; 
2195         if ( (coords
.GetRow() == row
) && (coords
.GetCol() == col
) ) 
2204 // ---------------------------------------------------------------------------- 
2205 // wxGridRowOrColAttrData 
2206 // ---------------------------------------------------------------------------- 
2208 wxGridRowOrColAttrData::~wxGridRowOrColAttrData() 
2210     size_t count 
= m_attrs
.Count(); 
2211     for ( size_t n 
= 0; n 
< count
; n
++ ) 
2213         m_attrs
[n
]->DecRef(); 
2217 wxGridCellAttr 
*wxGridRowOrColAttrData::GetAttr(int rowOrCol
) const 
2219     wxGridCellAttr 
*attr 
= (wxGridCellAttr 
*)NULL
; 
2221     int n 
= m_rowsOrCols
.Index(rowOrCol
); 
2222     if ( n 
!= wxNOT_FOUND 
) 
2224         attr 
= m_attrs
[(size_t)n
]; 
2231 void wxGridRowOrColAttrData::SetAttr(wxGridCellAttr 
*attr
, int rowOrCol
) 
2233     int i 
= m_rowsOrCols
.Index(rowOrCol
); 
2234     if ( i 
== wxNOT_FOUND 
) 
2236         // add the attribute 
2237         m_rowsOrCols
.Add(rowOrCol
); 
2242         size_t n 
= (size_t)i
; 
2245             // change the attribute 
2246             m_attrs
[n
]->DecRef(); 
2251             // remove this attribute 
2252             m_attrs
[n
]->DecRef(); 
2253             m_rowsOrCols
.RemoveAt(n
); 
2254             m_attrs
.RemoveAt(n
); 
2259 void wxGridRowOrColAttrData::UpdateAttrRowsOrCols( size_t pos
, int numRowsOrCols 
) 
2261     size_t count 
= m_attrs
.GetCount(); 
2262     for ( size_t n 
= 0; n 
< count
; n
++ ) 
2264         int & rowOrCol 
= m_rowsOrCols
[n
]; 
2265         if ( (size_t)rowOrCol 
>= pos 
) 
2267             if ( numRowsOrCols 
> 0 ) 
2269                 // If rows inserted, include row counter where necessary 
2270                 rowOrCol 
+= numRowsOrCols
; 
2272             else if ( numRowsOrCols 
< 0) 
2274                 // If rows deleted, either decrement row counter (if row still exists) 
2275                 if ((size_t)rowOrCol 
>= pos 
- numRowsOrCols
) 
2276                     rowOrCol 
+= numRowsOrCols
; 
2279                     m_rowsOrCols
.RemoveAt((size_t)n
); 
2280                     m_attrs
.RemoveAt((size_t)n
); 
2288 // ---------------------------------------------------------------------------- 
2289 // wxGridCellAttrProvider 
2290 // ---------------------------------------------------------------------------- 
2292 wxGridCellAttrProvider::wxGridCellAttrProvider() 
2294     m_data 
= (wxGridCellAttrProviderData 
*)NULL
; 
2297 wxGridCellAttrProvider::~wxGridCellAttrProvider() 
2302 void wxGridCellAttrProvider::InitData() 
2304     m_data 
= new wxGridCellAttrProviderData
; 
2307 wxGridCellAttr 
*wxGridCellAttrProvider::GetAttr(int row
, int col
, 
2308                                                 wxGridCellAttr::wxAttrKind  kind 
) const 
2310     wxGridCellAttr 
*attr 
= (wxGridCellAttr 
*)NULL
; 
2315             case (wxGridCellAttr::Any
): 
2316                 //Get cached merge attributes. 
2317                 // Currenlty not used as no cache implemented as not mutiable 
2318                 // attr = m_data->m_mergeAttr.GetAttr(row, col); 
2321                     //Basicaly implement old version. 
2322                     //Also check merge cache, so we don't have to re-merge every time.. 
2323                     wxGridCellAttr 
*attrcell 
= (wxGridCellAttr 
*)NULL
, 
2324                                    *attrrow 
= (wxGridCellAttr 
*)NULL
, 
2325                                    *attrcol 
= (wxGridCellAttr 
*)NULL
; 
2327                     attrcell 
= m_data
->m_cellAttrs
.GetAttr(row
, col
); 
2328                     attrcol 
= m_data
->m_colAttrs
.GetAttr(col
); 
2329                     attrrow 
= m_data
->m_rowAttrs
.GetAttr(row
); 
2331                     if((attrcell 
!= attrrow
) && (attrrow 
!=attrcol
) && (attrcell 
!= attrcol
)){ 
2332                         // Two or move are non NULL 
2333                         attr 
= new wxGridCellAttr
; 
2334                         attr
->SetKind(wxGridCellAttr::Merged
); 
2338                             attr
->MergeWith(attrcell
); 
2342                             attr
->MergeWith(attrcol
); 
2346                             attr
->MergeWith(attrrow
); 
2349                         //store merge attr if cache implemented 
2351                         //m_data->m_mergeAttr.SetAttr(attr, row, col); 
2355                         // one or none is non null return it or null. 
2356                         if(attrrow
) attr 
= attrrow
; 
2357                         if(attrcol
) attr 
= attrcol
; 
2358                         if(attrcell
) attr 
= attrcell
; 
2362             case (wxGridCellAttr::Cell
): 
2363                 attr 
= m_data
->m_cellAttrs
.GetAttr(row
, col
); 
2365             case (wxGridCellAttr::Col
): 
2366                  attr 
= m_data
->m_colAttrs
.GetAttr(col
); 
2368             case (wxGridCellAttr::Row
): 
2369             attr 
= m_data
->m_rowAttrs
.GetAttr(row
); 
2373                 // (wxGridCellAttr::Default): 
2374                 // (wxGridCellAttr::Merged): 
2381 void wxGridCellAttrProvider::SetAttr(wxGridCellAttr 
*attr
, 
2387     m_data
->m_cellAttrs
.SetAttr(attr
, row
, col
); 
2390 void wxGridCellAttrProvider::SetRowAttr(wxGridCellAttr 
*attr
, int row
) 
2395     m_data
->m_rowAttrs
.SetAttr(attr
, row
); 
2398 void wxGridCellAttrProvider::SetColAttr(wxGridCellAttr 
*attr
, int col
) 
2403     m_data
->m_colAttrs
.SetAttr(attr
, col
); 
2406 void wxGridCellAttrProvider::UpdateAttrRows( size_t pos
, int numRows 
) 
2410         m_data
->m_cellAttrs
.UpdateAttrRows( pos
, numRows 
); 
2412         m_data
->m_rowAttrs
.UpdateAttrRowsOrCols( pos
, numRows 
); 
2416 void wxGridCellAttrProvider::UpdateAttrCols( size_t pos
, int numCols 
) 
2420         m_data
->m_cellAttrs
.UpdateAttrCols( pos
, numCols 
); 
2422         m_data
->m_colAttrs
.UpdateAttrRowsOrCols( pos
, numCols 
); 
2426 // ---------------------------------------------------------------------------- 
2427 // wxGridTypeRegistry 
2428 // ---------------------------------------------------------------------------- 
2430 wxGridTypeRegistry::~wxGridTypeRegistry() 
2432     size_t count 
= m_typeinfo
.Count(); 
2433     for ( size_t i 
= 0; i 
< count
; i
++ ) 
2434         delete m_typeinfo
[i
]; 
2438 void wxGridTypeRegistry::RegisterDataType(const wxString
& typeName
, 
2439                                           wxGridCellRenderer
* renderer
, 
2440                                           wxGridCellEditor
* editor
) 
2442     wxGridDataTypeInfo
* info 
= new wxGridDataTypeInfo(typeName
, renderer
, editor
); 
2444     // is it already registered? 
2445     int loc 
= FindRegisteredDataType(typeName
); 
2446     if ( loc 
!= wxNOT_FOUND 
) 
2448         delete m_typeinfo
[loc
]; 
2449         m_typeinfo
[loc
] = info
; 
2453         m_typeinfo
.Add(info
); 
2457 int wxGridTypeRegistry::FindRegisteredDataType(const wxString
& typeName
) 
2459     size_t count 
= m_typeinfo
.GetCount(); 
2460     for ( size_t i 
= 0; i 
< count
; i
++ ) 
2462         if ( typeName 
== m_typeinfo
[i
]->m_typeName 
) 
2471 int wxGridTypeRegistry::FindDataType(const wxString
& typeName
) 
2473     int index 
= FindRegisteredDataType(typeName
); 
2474     if ( index 
== wxNOT_FOUND 
) 
2476         // check whether this is one of the standard ones, in which case 
2477         // register it "on the fly" 
2479         if ( typeName 
== wxGRID_VALUE_STRING 
) 
2481             RegisterDataType(wxGRID_VALUE_STRING
, 
2482                              new wxGridCellStringRenderer
, 
2483                              new wxGridCellTextEditor
); 
2485 #endif // wxUSE_TEXTCTRL 
2487         if ( typeName 
== wxGRID_VALUE_BOOL 
) 
2489             RegisterDataType(wxGRID_VALUE_BOOL
, 
2490                              new wxGridCellBoolRenderer
, 
2491                              new wxGridCellBoolEditor
); 
2493 #endif // wxUSE_CHECKBOX 
2495         if ( typeName 
== wxGRID_VALUE_NUMBER 
) 
2497             RegisterDataType(wxGRID_VALUE_NUMBER
, 
2498                              new wxGridCellNumberRenderer
, 
2499                              new wxGridCellNumberEditor
); 
2501         else if ( typeName 
== wxGRID_VALUE_FLOAT 
) 
2503             RegisterDataType(wxGRID_VALUE_FLOAT
, 
2504                              new wxGridCellFloatRenderer
, 
2505                              new wxGridCellFloatEditor
); 
2507 #endif // wxUSE_TEXTCTRL 
2509         if ( typeName 
== wxGRID_VALUE_CHOICE 
) 
2511             RegisterDataType(wxGRID_VALUE_CHOICE
, 
2512                              new wxGridCellStringRenderer
, 
2513                              new wxGridCellChoiceEditor
); 
2515 #endif // wxUSE_COMBOBOX 
2520         // we get here only if just added the entry for this type, so return 
2522         index 
= m_typeinfo
.GetCount() - 1; 
2528 int wxGridTypeRegistry::FindOrCloneDataType(const wxString
& typeName
) 
2530     int index 
= FindDataType(typeName
); 
2531     if ( index 
== wxNOT_FOUND 
) 
2533         // the first part of the typename is the "real" type, anything after ':' 
2534         // are the parameters for the renderer 
2535         index 
= FindDataType(typeName
.BeforeFirst(_T(':'))); 
2536         if ( index 
== wxNOT_FOUND 
) 
2541         wxGridCellRenderer 
*renderer 
= GetRenderer(index
); 
2542         wxGridCellRenderer 
*rendererOld 
= renderer
; 
2543         renderer 
= renderer
->Clone(); 
2544         rendererOld
->DecRef(); 
2546         wxGridCellEditor 
*editor 
= GetEditor(index
); 
2547         wxGridCellEditor 
*editorOld 
= editor
; 
2548         editor 
= editor
->Clone(); 
2549         editorOld
->DecRef(); 
2551         // do it even if there are no parameters to reset them to defaults 
2552         wxString params 
= typeName
.AfterFirst(_T(':')); 
2553         renderer
->SetParameters(params
); 
2554         editor
->SetParameters(params
); 
2556         // register the new typename 
2557         RegisterDataType(typeName
, renderer
, editor
); 
2559         // we just registered it, it's the last one 
2560         index 
= m_typeinfo
.GetCount() - 1; 
2566 wxGridCellRenderer
* wxGridTypeRegistry::GetRenderer(int index
) 
2568     wxGridCellRenderer
* renderer 
= m_typeinfo
[index
]->m_renderer
; 
2574 wxGridCellEditor
* wxGridTypeRegistry::GetEditor(int index
) 
2576     wxGridCellEditor
* editor 
= m_typeinfo
[index
]->m_editor
; 
2582 // ---------------------------------------------------------------------------- 
2584 // ---------------------------------------------------------------------------- 
2586 IMPLEMENT_ABSTRACT_CLASS( wxGridTableBase
, wxObject 
) 
2589 wxGridTableBase::wxGridTableBase() 
2591     m_view 
= (wxGrid 
*) NULL
; 
2592     m_attrProvider 
= (wxGridCellAttrProvider 
*) NULL
; 
2595 wxGridTableBase::~wxGridTableBase() 
2597     delete m_attrProvider
; 
2600 void wxGridTableBase::SetAttrProvider(wxGridCellAttrProvider 
*attrProvider
) 
2602     delete m_attrProvider
; 
2603     m_attrProvider 
= attrProvider
; 
2606 bool wxGridTableBase::CanHaveAttributes() 
2608     if ( ! GetAttrProvider() ) 
2610         // use the default attr provider by default 
2611         SetAttrProvider(new wxGridCellAttrProvider
); 
2616 wxGridCellAttr 
*wxGridTableBase::GetAttr(int row
, int col
, wxGridCellAttr::wxAttrKind  kind
) 
2618     if ( m_attrProvider 
) 
2619         return m_attrProvider
->GetAttr(row
, col
, kind
); 
2621         return (wxGridCellAttr 
*)NULL
; 
2624 void wxGridTableBase::SetAttr(wxGridCellAttr
* attr
, int row
, int col
) 
2626     if ( m_attrProvider 
) 
2628         attr
->SetKind(wxGridCellAttr::Cell
); 
2629         m_attrProvider
->SetAttr(attr
, row
, col
); 
2633         // as we take ownership of the pointer and don't store it, we must 
2639 void wxGridTableBase::SetRowAttr(wxGridCellAttr 
*attr
, int row
) 
2641     if ( m_attrProvider 
) 
2643         attr
->SetKind(wxGridCellAttr::Row
); 
2644         m_attrProvider
->SetRowAttr(attr
, row
); 
2648         // as we take ownership of the pointer and don't store it, we must 
2654 void wxGridTableBase::SetColAttr(wxGridCellAttr 
*attr
, int col
) 
2656     if ( m_attrProvider 
) 
2658         attr
->SetKind(wxGridCellAttr::Col
); 
2659         m_attrProvider
->SetColAttr(attr
, col
); 
2663         // as we take ownership of the pointer and don't store it, we must 
2669 bool wxGridTableBase::InsertRows( size_t WXUNUSED(pos
), 
2670                                   size_t WXUNUSED(numRows
) ) 
2672     wxFAIL_MSG( wxT("Called grid table class function InsertRows\nbut your derived table class does not override this function") ); 
2677 bool wxGridTableBase::AppendRows( size_t WXUNUSED(numRows
) ) 
2679     wxFAIL_MSG( wxT("Called grid table class function AppendRows\nbut your derived table class does not override this function")); 
2684 bool wxGridTableBase::DeleteRows( size_t WXUNUSED(pos
), 
2685                                   size_t WXUNUSED(numRows
) ) 
2687     wxFAIL_MSG( wxT("Called grid table class function DeleteRows\nbut your derived table class does not override this function")); 
2692 bool wxGridTableBase::InsertCols( size_t WXUNUSED(pos
), 
2693                                   size_t WXUNUSED(numCols
) ) 
2695     wxFAIL_MSG( wxT("Called grid table class function InsertCols\nbut your derived table class does not override this function")); 
2700 bool wxGridTableBase::AppendCols( size_t WXUNUSED(numCols
) ) 
2702     wxFAIL_MSG(wxT("Called grid table class function AppendCols\nbut your derived table class does not override this function")); 
2707 bool wxGridTableBase::DeleteCols( size_t WXUNUSED(pos
), 
2708                                   size_t WXUNUSED(numCols
) ) 
2710     wxFAIL_MSG( wxT("Called grid table class function DeleteCols\nbut your derived table class does not override this function")); 
2716 wxString 
wxGridTableBase::GetRowLabelValue( int row 
) 
2719     s 
<< row 
+ 1; // RD: Starting the rows at zero confuses users, no matter 
2720                   //     how much it makes sense to us geeks. 
2724 wxString 
wxGridTableBase::GetColLabelValue( int col 
) 
2726     // default col labels are: 
2727     //   cols 0 to 25   : A-Z 
2728     //   cols 26 to 675 : AA-ZZ 
2733     for ( n 
= 1; ; n
++ ) 
2735         s 
+= (_T('A') + (wxChar
)( col%26 
)); 
2737         if ( col 
< 0 ) break; 
2740     // reverse the string... 
2742     for ( i 
= 0;  i 
< n
;  i
++ ) 
2751 wxString 
wxGridTableBase::GetTypeName( int WXUNUSED(row
), int WXUNUSED(col
) ) 
2753     return wxGRID_VALUE_STRING
; 
2756 bool wxGridTableBase::CanGetValueAs( int WXUNUSED(row
), int WXUNUSED(col
), 
2757                                      const wxString
& typeName 
) 
2759     return typeName 
== wxGRID_VALUE_STRING
; 
2762 bool wxGridTableBase::CanSetValueAs( int row
, int col
, const wxString
& typeName 
) 
2764     return CanGetValueAs(row
, col
, typeName
); 
2767 long wxGridTableBase::GetValueAsLong( int WXUNUSED(row
), int WXUNUSED(col
) ) 
2772 double wxGridTableBase::GetValueAsDouble( int WXUNUSED(row
), int WXUNUSED(col
) ) 
2777 bool wxGridTableBase::GetValueAsBool( int WXUNUSED(row
), int WXUNUSED(col
) ) 
2782 void wxGridTableBase::SetValueAsLong( int WXUNUSED(row
), int WXUNUSED(col
), 
2783                                       long WXUNUSED(value
) ) 
2787 void wxGridTableBase::SetValueAsDouble( int WXUNUSED(row
), int WXUNUSED(col
), 
2788                                         double WXUNUSED(value
) ) 
2792 void wxGridTableBase::SetValueAsBool( int WXUNUSED(row
), int WXUNUSED(col
), 
2793                                       bool WXUNUSED(value
) ) 
2798 void* wxGridTableBase::GetValueAsCustom( int WXUNUSED(row
), int WXUNUSED(col
), 
2799                                          const wxString
& WXUNUSED(typeName
) ) 
2804 void  wxGridTableBase::SetValueAsCustom( int WXUNUSED(row
), int WXUNUSED(col
), 
2805                                          const wxString
& WXUNUSED(typeName
), 
2806                                          void* WXUNUSED(value
) ) 
2810 ////////////////////////////////////////////////////////////////////// 
2812 // Message class for the grid table to send requests and notifications 
2816 wxGridTableMessage::wxGridTableMessage() 
2818     m_table 
= (wxGridTableBase 
*) NULL
; 
2824 wxGridTableMessage::wxGridTableMessage( wxGridTableBase 
*table
, int id
, 
2825                                         int commandInt1
, int commandInt2 
) 
2829     m_comInt1 
= commandInt1
; 
2830     m_comInt2 
= commandInt2
; 
2835 ////////////////////////////////////////////////////////////////////// 
2837 // A basic grid table for string data. An object of this class will 
2838 // created by wxGrid if you don't specify an alternative table class. 
2841 WX_DEFINE_OBJARRAY(wxGridStringArray
) 
2843 IMPLEMENT_DYNAMIC_CLASS( wxGridStringTable
, wxGridTableBase 
) 
2845 wxGridStringTable::wxGridStringTable() 
2850 wxGridStringTable::wxGridStringTable( int numRows
, int numCols 
) 
2855     m_data
.Alloc( numRows 
); 
2858     sa
.Alloc( numCols 
); 
2859     for ( col 
= 0;  col 
< numCols
;  col
++ ) 
2861         sa
.Add( wxEmptyString 
); 
2864     for ( row 
= 0;  row 
< numRows
;  row
++ ) 
2870 wxGridStringTable::~wxGridStringTable() 
2874 int wxGridStringTable::GetNumberRows() 
2876     return m_data
.GetCount(); 
2879 int wxGridStringTable::GetNumberCols() 
2881     if ( m_data
.GetCount() > 0 ) 
2882         return m_data
[0].GetCount(); 
2887 wxString 
wxGridStringTable::GetValue( int row
, int col 
) 
2889     wxASSERT_MSG( (row 
< GetNumberRows()) && (col 
< GetNumberCols()), 
2890                   _T("invalid row or column index in wxGridStringTable") ); 
2892     return m_data
[row
][col
]; 
2895 void wxGridStringTable::SetValue( int row
, int col
, const wxString
& value 
) 
2897     wxASSERT_MSG( (row 
< GetNumberRows()) && (col 
< GetNumberCols()), 
2898                   _T("invalid row or column index in wxGridStringTable") ); 
2900     m_data
[row
][col
] = value
; 
2903 bool wxGridStringTable::IsEmptyCell( int row
, int col 
) 
2905     wxASSERT_MSG( (row 
< GetNumberRows()) && (col 
< GetNumberCols()), 
2906                   _T("invalid row or column index in wxGridStringTable") ); 
2908     return (m_data
[row
][col
] == wxEmptyString
); 
2911 void wxGridStringTable::Clear() 
2914     int numRows
, numCols
; 
2916     numRows 
= m_data
.GetCount(); 
2919         numCols 
= m_data
[0].GetCount(); 
2921         for ( row 
= 0;  row 
< numRows
;  row
++ ) 
2923             for ( col 
= 0;  col 
< numCols
;  col
++ ) 
2925                 m_data
[row
][col
] = wxEmptyString
; 
2932 bool wxGridStringTable::InsertRows( size_t pos
, size_t numRows 
) 
2936     size_t curNumRows 
= m_data
.GetCount(); 
2937     size_t curNumCols 
= ( curNumRows 
> 0 ? m_data
[0].GetCount() : 
2938                           ( GetView() ? GetView()->GetNumberCols() : 0 ) ); 
2940     if ( pos 
>= curNumRows 
) 
2942         return AppendRows( numRows 
); 
2946     sa
.Alloc( curNumCols 
); 
2947     for ( col 
= 0;  col 
< curNumCols
;  col
++ ) 
2949         sa
.Add( wxEmptyString 
); 
2952     for ( row 
= pos
;  row 
< pos 
+ numRows
;  row
++ ) 
2954         m_data
.Insert( sa
, row 
); 
2958         wxGridTableMessage 
msg( this, 
2959                                 wxGRIDTABLE_NOTIFY_ROWS_INSERTED
, 
2963         GetView()->ProcessTableMessage( msg 
); 
2969 bool wxGridStringTable::AppendRows( size_t numRows 
) 
2973     size_t curNumRows 
= m_data
.GetCount(); 
2974     size_t curNumCols 
= ( curNumRows 
> 0 ? m_data
[0].GetCount() : 
2975                           ( GetView() ? GetView()->GetNumberCols() : 0 ) ); 
2978     if ( curNumCols 
> 0 ) 
2980         sa
.Alloc( curNumCols 
); 
2981         for ( col 
= 0;  col 
< curNumCols
;  col
++ ) 
2983             sa
.Add( wxEmptyString 
); 
2987     for ( row 
= 0;  row 
< numRows
;  row
++ ) 
2994         wxGridTableMessage 
msg( this, 
2995                                 wxGRIDTABLE_NOTIFY_ROWS_APPENDED
, 
2998         GetView()->ProcessTableMessage( msg 
); 
3004 bool wxGridStringTable::DeleteRows( size_t pos
, size_t numRows 
) 
3008     size_t curNumRows 
= m_data
.GetCount(); 
3010     if ( pos 
>= curNumRows 
) 
3013         errmsg
.Printf(wxT("Called wxGridStringTable::DeleteRows(pos=%d, N=%d)\nPos value is invalid for present table with %d rows"), 
3014                       pos
, numRows
, curNumRows 
); 
3015         wxFAIL_MSG( errmsg 
); 
3019     if ( numRows 
> curNumRows 
- pos 
) 
3021         numRows 
= curNumRows 
- pos
; 
3024     if ( numRows 
>= curNumRows 
) 
3026         m_data
.Empty();  // don't release memory just yet 
3030         for ( n 
= 0;  n 
< numRows
;  n
++ ) 
3032             m_data
.RemoveAt( pos 
); 
3037         wxGridTableMessage 
msg( this, 
3038                                 wxGRIDTABLE_NOTIFY_ROWS_DELETED
, 
3042         GetView()->ProcessTableMessage( msg 
); 
3048 bool wxGridStringTable::InsertCols( size_t pos
, size_t numCols 
) 
3052     size_t curNumRows 
= m_data
.GetCount(); 
3053     size_t curNumCols 
= ( curNumRows 
> 0 ? m_data
[0].GetCount() : 
3054                           ( GetView() ? GetView()->GetNumberCols() : 0 ) ); 
3056     if ( pos 
>= curNumCols 
) 
3058         return AppendCols( numCols 
); 
3061     for ( row 
= 0;  row 
< curNumRows
;  row
++ ) 
3063         for ( col 
= pos
;  col 
< pos 
+ numCols
;  col
++ ) 
3065             m_data
[row
].Insert( wxEmptyString
, col 
); 
3070         wxGridTableMessage 
msg( this, 
3071                                 wxGRIDTABLE_NOTIFY_COLS_INSERTED
, 
3075         GetView()->ProcessTableMessage( msg 
); 
3081 bool wxGridStringTable::AppendCols( size_t numCols 
) 
3085     size_t curNumRows 
= m_data
.GetCount(); 
3089         // TODO: something better than this ? 
3091         wxFAIL_MSG( wxT("Unable to append cols to a grid table with no rows.\nCall AppendRows() first") ); 
3096     for ( row 
= 0;  row 
< curNumRows
;  row
++ ) 
3098         for ( n 
= 0;  n 
< numCols
;  n
++ ) 
3100             m_data
[row
].Add( wxEmptyString 
); 
3106         wxGridTableMessage 
msg( this, 
3107                                 wxGRIDTABLE_NOTIFY_COLS_APPENDED
, 
3110         GetView()->ProcessTableMessage( msg 
); 
3116 bool wxGridStringTable::DeleteCols( size_t pos
, size_t numCols 
) 
3120     size_t curNumRows 
= m_data
.GetCount(); 
3121     size_t curNumCols 
= ( curNumRows 
> 0 ? m_data
[0].GetCount() : 
3122                           ( GetView() ? GetView()->GetNumberCols() : 0 ) ); 
3124     if ( pos 
>= curNumCols 
) 
3127         errmsg
.Printf( wxT("Called wxGridStringTable::DeleteCols(pos=%d, N=%d)...\nPos value is invalid for present table with %d cols"), 
3128                         pos
, numCols
, curNumCols 
); 
3129         wxFAIL_MSG( errmsg 
); 
3133     if ( numCols 
> curNumCols 
- pos 
) 
3135         numCols 
= curNumCols 
- pos
; 
3138     for ( row 
= 0;  row 
< curNumRows
;  row
++ ) 
3140         if ( numCols 
>= curNumCols 
) 
3142             m_data
[row
].Clear(); 
3146             for ( n 
= 0;  n 
< numCols
;  n
++ ) 
3148                 m_data
[row
].RemoveAt( pos 
); 
3154         wxGridTableMessage 
msg( this, 
3155                                 wxGRIDTABLE_NOTIFY_COLS_DELETED
, 
3159         GetView()->ProcessTableMessage( msg 
); 
3165 wxString 
wxGridStringTable::GetRowLabelValue( int row 
) 
3167     if ( row 
> (int)(m_rowLabels
.GetCount()) - 1 ) 
3169         // using default label 
3171         return wxGridTableBase::GetRowLabelValue( row 
); 
3175         return m_rowLabels
[ row 
]; 
3179 wxString 
wxGridStringTable::GetColLabelValue( int col 
) 
3181     if ( col 
> (int)(m_colLabels
.GetCount()) - 1 ) 
3183         // using default label 
3185         return wxGridTableBase::GetColLabelValue( col 
); 
3189         return m_colLabels
[ col 
]; 
3193 void wxGridStringTable::SetRowLabelValue( int row
, const wxString
& value 
) 
3195     if ( row 
> (int)(m_rowLabels
.GetCount()) - 1 ) 
3197         int n 
= m_rowLabels
.GetCount(); 
3199         for ( i 
= n
;  i 
<= row
;  i
++ ) 
3201             m_rowLabels
.Add( wxGridTableBase::GetRowLabelValue(i
) ); 
3205     m_rowLabels
[row
] = value
; 
3208 void wxGridStringTable::SetColLabelValue( int col
, const wxString
& value 
) 
3210     if ( col 
> (int)(m_colLabels
.GetCount()) - 1 ) 
3212         int n 
= m_colLabels
.GetCount(); 
3214         for ( i 
= n
;  i 
<= col
;  i
++ ) 
3216             m_colLabels
.Add( wxGridTableBase::GetColLabelValue(i
) ); 
3220     m_colLabels
[col
] = value
; 
3225 ////////////////////////////////////////////////////////////////////// 
3226 ////////////////////////////////////////////////////////////////////// 
3228 IMPLEMENT_DYNAMIC_CLASS( wxGridRowLabelWindow
, wxWindow 
) 
3230 BEGIN_EVENT_TABLE( wxGridRowLabelWindow
, wxWindow 
) 
3231     EVT_PAINT( wxGridRowLabelWindow::OnPaint 
) 
3232     EVT_MOUSEWHEEL( wxGridRowLabelWindow::OnMouseWheel
) 
3233     EVT_MOUSE_EVENTS( wxGridRowLabelWindow::OnMouseEvent 
) 
3234     EVT_KEY_DOWN( wxGridRowLabelWindow::OnKeyDown 
) 
3235     EVT_KEY_UP( wxGridRowLabelWindow::OnKeyUp 
) 
3238 wxGridRowLabelWindow::wxGridRowLabelWindow( wxGrid 
*parent
, 
3240                                             const wxPoint 
&pos
, const wxSize 
&size 
) 
3241   : wxWindow( parent
, id
, pos
, size
, wxWANTS_CHARS 
) 
3246 void wxGridRowLabelWindow::OnPaint( wxPaintEvent
& WXUNUSED(event
) ) 
3250     // NO - don't do this because it will set both the x and y origin 
3251     // coords to match the parent scrolled window and we just want to 
3252     // set the y coord  - MB 
3254     // m_owner->PrepareDC( dc ); 
3257     m_owner
->CalcUnscrolledPosition( 0, 0, &x
, &y 
); 
3258     dc
.SetDeviceOrigin( 0, -y 
); 
3260     wxArrayInt rows 
= m_owner
->CalcRowLabelsExposed( GetUpdateRegion() ); 
3261     m_owner
->DrawRowLabels( dc 
, rows 
); 
3265 void wxGridRowLabelWindow::OnMouseEvent( wxMouseEvent
& event 
) 
3267     m_owner
->ProcessRowLabelMouseEvent( event 
); 
3271 void wxGridRowLabelWindow::OnMouseWheel( wxMouseEvent
& event 
) 
3273     m_owner
->GetEventHandler()->ProcessEvent(event
); 
3277 // This seems to be required for wxMotif otherwise the mouse 
3278 // cursor must be in the cell edit control to get key events 
3280 void wxGridRowLabelWindow::OnKeyDown( wxKeyEvent
& event 
) 
3282     if ( !m_owner
->GetEventHandler()->ProcessEvent( event 
) ) event
.Skip(); 
3285 void wxGridRowLabelWindow::OnKeyUp( wxKeyEvent
& event 
) 
3287     if ( !m_owner
->GetEventHandler()->ProcessEvent( event 
) ) event
.Skip(); 
3292 ////////////////////////////////////////////////////////////////////// 
3294 IMPLEMENT_DYNAMIC_CLASS( wxGridColLabelWindow
, wxWindow 
) 
3296 BEGIN_EVENT_TABLE( wxGridColLabelWindow
, wxWindow 
) 
3297     EVT_PAINT( wxGridColLabelWindow::OnPaint 
) 
3298     EVT_MOUSEWHEEL( wxGridColLabelWindow::OnMouseWheel
) 
3299     EVT_MOUSE_EVENTS( wxGridColLabelWindow::OnMouseEvent 
) 
3300     EVT_KEY_DOWN( wxGridColLabelWindow::OnKeyDown 
) 
3301     EVT_KEY_UP( wxGridColLabelWindow::OnKeyUp 
) 
3304 wxGridColLabelWindow::wxGridColLabelWindow( wxGrid 
*parent
, 
3306                                             const wxPoint 
&pos
, const wxSize 
&size 
) 
3307   : wxWindow( parent
, id
, pos
, size
, wxWANTS_CHARS 
) 
3312 void wxGridColLabelWindow::OnPaint( wxPaintEvent
& WXUNUSED(event
) ) 
3316     // NO - don't do this because it will set both the x and y origin 
3317     // coords to match the parent scrolled window and we just want to 
3318     // set the x coord  - MB 
3320     // m_owner->PrepareDC( dc ); 
3323     m_owner
->CalcUnscrolledPosition( 0, 0, &x
, &y 
); 
3324     dc
.SetDeviceOrigin( -x
, 0 ); 
3326     wxArrayInt cols 
= m_owner
->CalcColLabelsExposed( GetUpdateRegion() ); 
3327     m_owner
->DrawColLabels( dc 
, cols 
); 
3331 void wxGridColLabelWindow::OnMouseEvent( wxMouseEvent
& event 
) 
3333     m_owner
->ProcessColLabelMouseEvent( event 
); 
3336 void wxGridColLabelWindow::OnMouseWheel( wxMouseEvent
& event 
) 
3338     m_owner
->GetEventHandler()->ProcessEvent(event
); 
3342 // This seems to be required for wxMotif otherwise the mouse 
3343 // cursor must be in the cell edit control to get key events 
3345 void wxGridColLabelWindow::OnKeyDown( wxKeyEvent
& event 
) 
3347     if ( !m_owner
->GetEventHandler()->ProcessEvent( event 
) ) event
.Skip(); 
3350 void wxGridColLabelWindow::OnKeyUp( wxKeyEvent
& event 
) 
3352     if ( !m_owner
->GetEventHandler()->ProcessEvent( event 
) ) event
.Skip(); 
3357 ////////////////////////////////////////////////////////////////////// 
3359 IMPLEMENT_DYNAMIC_CLASS( wxGridCornerLabelWindow
, wxWindow 
) 
3361 BEGIN_EVENT_TABLE( wxGridCornerLabelWindow
, wxWindow 
) 
3362     EVT_MOUSEWHEEL( wxGridCornerLabelWindow::OnMouseWheel
) 
3363     EVT_MOUSE_EVENTS( wxGridCornerLabelWindow::OnMouseEvent 
) 
3364     EVT_PAINT( wxGridCornerLabelWindow::OnPaint
) 
3365     EVT_KEY_DOWN( wxGridCornerLabelWindow::OnKeyDown 
) 
3366     EVT_KEY_UP( wxGridCornerLabelWindow::OnKeyUp 
) 
3369 wxGridCornerLabelWindow::wxGridCornerLabelWindow( wxGrid 
*parent
, 
3371                                                   const wxPoint 
&pos
, const wxSize 
&size 
) 
3372   : wxWindow( parent
, id
, pos
, size
, wxWANTS_CHARS 
) 
3377 void wxGridCornerLabelWindow::OnPaint( wxPaintEvent
& WXUNUSED(event
) ) 
3381     int client_height 
= 0; 
3382     int client_width 
= 0; 
3383     GetClientSize( &client_width
, &client_height 
); 
3385     dc
.SetPen( *wxBLACK_PEN 
); 
3386     dc
.DrawLine( client_width
-1, client_height
-1, client_width
-1, 0 ); 
3387     dc
.DrawLine( client_width
-1, client_height
-1, 0, client_height
-1 ); 
3389     dc
.SetPen( *wxWHITE_PEN 
); 
3390     dc
.DrawLine( 0, 0, client_width
, 0 ); 
3391     dc
.DrawLine( 0, 0, 0, client_height 
); 
3395 void wxGridCornerLabelWindow::OnMouseEvent( wxMouseEvent
& event 
) 
3397     m_owner
->ProcessCornerLabelMouseEvent( event 
); 
3401 void wxGridCornerLabelWindow::OnMouseWheel( wxMouseEvent
& event 
) 
3403     m_owner
->GetEventHandler()->ProcessEvent(event
); 
3406 // This seems to be required for wxMotif otherwise the mouse 
3407 // cursor must be in the cell edit control to get key events 
3409 void wxGridCornerLabelWindow::OnKeyDown( wxKeyEvent
& event 
) 
3411     if ( !m_owner
->GetEventHandler()->ProcessEvent( event 
) ) event
.Skip(); 
3414 void wxGridCornerLabelWindow::OnKeyUp( wxKeyEvent
& event 
) 
3416     if ( !m_owner
->GetEventHandler()->ProcessEvent( event 
) ) event
.Skip(); 
3421 ////////////////////////////////////////////////////////////////////// 
3423 IMPLEMENT_DYNAMIC_CLASS( wxGridWindow
, wxWindow 
) 
3425 BEGIN_EVENT_TABLE( wxGridWindow
, wxWindow 
) 
3426     EVT_PAINT( wxGridWindow::OnPaint 
) 
3427     EVT_MOUSEWHEEL( wxGridWindow::OnMouseWheel
) 
3428     EVT_MOUSE_EVENTS( wxGridWindow::OnMouseEvent 
) 
3429     EVT_KEY_DOWN( wxGridWindow::OnKeyDown 
) 
3430     EVT_KEY_UP( wxGridWindow::OnKeyUp 
) 
3431     EVT_ERASE_BACKGROUND( wxGridWindow::OnEraseBackground 
) 
3434 wxGridWindow::wxGridWindow( wxGrid 
*parent
, 
3435                             wxGridRowLabelWindow 
*rowLblWin
, 
3436                             wxGridColLabelWindow 
*colLblWin
, 
3437                             wxWindowID id
, const wxPoint 
&pos
, const wxSize 
&size 
) 
3438         : wxWindow( parent
, id
, pos
, size
, wxWANTS_CHARS
, "grid window" ) 
3441     m_rowLabelWin 
= rowLblWin
; 
3442     m_colLabelWin 
= colLblWin
; 
3443     SetBackgroundColour(_T("WHITE")); 
3447 wxGridWindow::~wxGridWindow() 
3452 void wxGridWindow::OnPaint( wxPaintEvent 
&WXUNUSED(event
) ) 
3454     wxPaintDC 
dc( this ); 
3455     m_owner
->PrepareDC( dc 
); 
3456     wxRegion reg 
= GetUpdateRegion(); 
3457     wxGridCellCoordsArray DirtyCells 
= m_owner
->CalcCellsExposed( reg 
); 
3458     m_owner
->DrawGridCellArea( dc 
, DirtyCells
); 
3459 #if WXGRID_DRAW_LINES 
3460     m_owner
->DrawAllGridLines( dc
, reg 
); 
3462     m_owner
->DrawGridSpace( dc 
); 
3463     m_owner
->DrawHighlight( dc 
, DirtyCells 
); 
3467 void wxGridWindow::ScrollWindow( int dx
, int dy
, const wxRect 
*rect 
) 
3469     wxWindow::ScrollWindow( dx
, dy
, rect 
); 
3470     m_rowLabelWin
->ScrollWindow( 0, dy
, rect 
); 
3471     m_colLabelWin
->ScrollWindow( dx
, 0, rect 
); 
3475 void wxGridWindow::OnMouseEvent( wxMouseEvent
& event 
) 
3477     m_owner
->ProcessGridCellMouseEvent( event 
); 
3480 void wxGridWindow::OnMouseWheel( wxMouseEvent
& event 
) 
3482     m_owner
->GetEventHandler()->ProcessEvent(event
); 
3485 // This seems to be required for wxMotif/wxGTK otherwise the mouse 
3486 // cursor must be in the cell edit control to get key events 
3488 void wxGridWindow::OnKeyDown( wxKeyEvent
& event 
) 
3490     if ( !m_owner
->GetEventHandler()->ProcessEvent( event 
) ) event
.Skip(); 
3493 void wxGridWindow::OnKeyUp( wxKeyEvent
& event 
) 
3495     if ( !m_owner
->GetEventHandler()->ProcessEvent( event 
) ) event
.Skip(); 
3498 void wxGridWindow::OnEraseBackground( wxEraseEvent
& WXUNUSED(event
) ) 
3503 ////////////////////////////////////////////////////////////////////// 
3506 IMPLEMENT_DYNAMIC_CLASS( wxGrid
, wxScrolledWindow 
) 
3508 BEGIN_EVENT_TABLE( wxGrid
, wxScrolledWindow 
) 
3509     EVT_PAINT( wxGrid::OnPaint 
) 
3510     EVT_SIZE( wxGrid::OnSize 
) 
3511     EVT_KEY_DOWN( wxGrid::OnKeyDown 
) 
3512     EVT_KEY_UP( wxGrid::OnKeyUp 
) 
3513     EVT_ERASE_BACKGROUND( wxGrid::OnEraseBackground 
) 
3516 wxGrid::wxGrid( wxWindow 
*parent
, 
3521                  const wxString
& name 
) 
3522   : wxScrolledWindow( parent
, id
, pos
, size
, (style 
| wxWANTS_CHARS
), name 
), 
3523     m_colMinWidths(GRID_HASH_SIZE
), 
3524     m_rowMinHeights(GRID_HASH_SIZE
) 
3532     // Must do this or ~wxScrollHelper will pop the wrong event handler 
3533     SetTargetWindow(this); 
3535     wxSafeDecRef(m_defaultCellAttr
); 
3537 #ifdef DEBUG_ATTR_CACHE 
3538     size_t total 
= gs_nAttrCacheHits 
+ gs_nAttrCacheMisses
; 
3539     wxPrintf(_T("wxGrid attribute cache statistics: " 
3540                 "total: %u, hits: %u (%u%%)\n"), 
3541              total
, gs_nAttrCacheHits
, 
3542              total 
? (gs_nAttrCacheHits
*100) / total 
: 0); 
3548     delete m_typeRegistry
; 
3554 // ----- internal init and update functions 
3557 void wxGrid::Create() 
3559     m_created 
= FALSE
;    // set to TRUE by CreateGrid 
3561     m_table        
= (wxGridTableBase 
*) NULL
; 
3564     m_cellEditCtrlEnabled 
= FALSE
; 
3566     m_defaultCellAttr 
= new wxGridCellAttr(); 
3568     // Set default cell attributes 
3569     m_defaultCellAttr
->SetDefAttr(m_defaultCellAttr
); 
3570     m_defaultCellAttr
->SetKind(wxGridCellAttr::Default
); 
3571     m_defaultCellAttr
->SetFont(GetFont()); 
3572     m_defaultCellAttr
->SetAlignment(wxALIGN_LEFT
, wxALIGN_TOP
); 
3573     m_defaultCellAttr
->SetTextColour( 
3574         wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT
)); 
3575     m_defaultCellAttr
->SetBackgroundColour( 
3576         wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW
)); 
3577     m_defaultCellAttr
->SetRenderer(new wxGridCellStringRenderer
); 
3578     m_defaultCellAttr
->SetEditor(new wxGridCellTextEditor
); 
3583     m_currentCellCoords 
= wxGridNoCellCoords
; 
3585     m_rowLabelWidth 
= WXGRID_DEFAULT_ROW_LABEL_WIDTH
; 
3586     m_colLabelHeight 
= WXGRID_DEFAULT_COL_LABEL_HEIGHT
; 
3588     // create the type registry 
3589     m_typeRegistry 
= new wxGridTypeRegistry
; 
3591     // subwindow components that make up the wxGrid 
3592     m_cornerLabelWin 
= new wxGridCornerLabelWindow( this, 
3597     m_rowLabelWin 
= new wxGridRowLabelWindow( this, 
3602     m_colLabelWin 
= new wxGridColLabelWindow( this, 
3607     m_gridWin 
= new wxGridWindow( this, 
3614     SetTargetWindow( m_gridWin 
); 
3620 bool wxGrid::CreateGrid( int numRows
, int numCols
, 
3621                          wxGrid::wxGridSelectionModes selmode 
) 
3623     wxCHECK_MSG( !m_created
, 
3625                  wxT("wxGrid::CreateGrid or wxGrid::SetTable called more than once") ); 
3627     m_numRows 
= numRows
; 
3628     m_numCols 
= numCols
; 
3630     m_table 
= new wxGridStringTable( m_numRows
, m_numCols 
); 
3631     m_table
->SetView( this ); 
3633     m_selection 
= new wxGridSelection( this, selmode 
); 
3642 void wxGrid::SetSelectionMode(wxGrid::wxGridSelectionModes selmode
) 
3644     wxCHECK_RET( m_created
, 
3645                  wxT("Called wxGrid::SetSelectionMode() before calling CreateGrid()") ); 
3647     m_selection
->SetSelectionMode( selmode 
); 
3650 bool wxGrid::SetTable( wxGridTableBase 
*table
, bool takeOwnership
, 
3651                        wxGrid::wxGridSelectionModes selmode 
) 
3655         // RD: Actually, this should probably be allowed.  I think it would be 
3656         // nice to be able to switch multiple Tables in and out of a single 
3657         // View at runtime.  Is there anything in the implmentation that would 
3660         // At least, you now have to cope with m_selection 
3661         wxFAIL_MSG( wxT("wxGrid::CreateGrid or wxGrid::SetTable called more than once") ); 
3666         m_numRows 
= table
->GetNumberRows(); 
3667         m_numCols 
= table
->GetNumberCols(); 
3670         m_table
->SetView( this ); 
3673         m_selection 
= new wxGridSelection( this, selmode 
); 
3686     m_rowLabelWidth  
= WXGRID_DEFAULT_ROW_LABEL_WIDTH
; 
3687     m_colLabelHeight 
= WXGRID_DEFAULT_COL_LABEL_HEIGHT
; 
3689     if ( m_rowLabelWin 
) 
3691         m_labelBackgroundColour 
= m_rowLabelWin
->GetBackgroundColour(); 
3695         m_labelBackgroundColour 
= wxColour( _T("WHITE") ); 
3698     m_labelTextColour 
= wxColour( _T("BLACK") ); 
3701     m_attrCache
.row 
= -1; 
3703     // TODO: something better than this ? 
3705     m_labelFont 
= this->GetFont(); 
3706     m_labelFont
.SetWeight( m_labelFont
.GetWeight() + 2 ); 
3708     m_rowLabelHorizAlign 
= wxALIGN_LEFT
; 
3709     m_rowLabelVertAlign  
= wxALIGN_CENTRE
; 
3711     m_colLabelHorizAlign 
= wxALIGN_CENTRE
; 
3712     m_colLabelVertAlign  
= wxALIGN_TOP
; 
3714     m_defaultColWidth  
= WXGRID_DEFAULT_COL_WIDTH
; 
3715     m_defaultRowHeight 
= m_gridWin
->GetCharHeight(); 
3717 #if defined(__WXMOTIF__) || defined(__WXGTK__)  // see also text ctrl sizing in ShowCellEditControl() 
3718     m_defaultRowHeight 
+= 8; 
3720     m_defaultRowHeight 
+= 4; 
3723     m_gridLineColour 
= wxColour( 128, 128, 255 ); 
3724     m_gridLinesEnabled 
= TRUE
; 
3725     m_cellHighlightColour 
= m_gridLineColour
; 
3726     m_cellHighlightPenWidth 
= 2; 
3727     m_cellHighlightROPenWidth 
= 1; 
3729     m_cursorMode  
= WXGRID_CURSOR_SELECT_CELL
; 
3730     m_winCapture 
= (wxWindow 
*)NULL
; 
3731     m_canDragRowSize 
= TRUE
; 
3732     m_canDragColSize 
= TRUE
; 
3733     m_canDragGridSize 
= TRUE
; 
3735     m_dragRowOrCol 
= -1; 
3736     m_isDragging 
= FALSE
; 
3737     m_startDragPos 
= wxDefaultPosition
; 
3739     m_waitForSlowClick 
= FALSE
; 
3741     m_rowResizeCursor 
= wxCursor( wxCURSOR_SIZENS 
); 
3742     m_colResizeCursor 
= wxCursor( wxCURSOR_SIZEWE 
); 
3744     m_currentCellCoords 
= wxGridNoCellCoords
; 
3746     m_selectingTopLeft 
= wxGridNoCellCoords
; 
3747     m_selectingBottomRight 
= wxGridNoCellCoords
; 
3748     m_selectionBackground 
= wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT
); 
3749     m_selectionForeground 
= wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHTTEXT
); 
3751     m_editable 
= TRUE
;  // default for whole grid 
3753     m_inOnKeyDown 
= FALSE
; 
3760 // ---------------------------------------------------------------------------- 
3761 // the idea is to call these functions only when necessary because they create 
3762 // quite big arrays which eat memory mostly unnecessary - in particular, if 
3763 // default widths/heights are used for all rows/columns, we may not use these 
3766 // with some extra code, it should be possible to only store the 
3767 // widths/heights different from default ones but this will be done later... 
3768 // ---------------------------------------------------------------------------- 
3770 void wxGrid::InitRowHeights() 
3772     m_rowHeights
.Empty(); 
3773     m_rowBottoms
.Empty(); 
3775     m_rowHeights
.Alloc( m_numRows 
); 
3776     m_rowBottoms
.Alloc( m_numRows 
); 
3779     for ( int i 
= 0;  i 
< m_numRows
;  i
++ ) 
3781         m_rowHeights
.Add( m_defaultRowHeight 
); 
3782         rowBottom 
+= m_defaultRowHeight
; 
3783         m_rowBottoms
.Add( rowBottom 
); 
3787 void wxGrid::InitColWidths() 
3789     m_colWidths
.Empty(); 
3790     m_colRights
.Empty(); 
3792     m_colWidths
.Alloc( m_numCols 
); 
3793     m_colRights
.Alloc( m_numCols 
); 
3795     for ( int i 
= 0;  i 
< m_numCols
;  i
++ ) 
3797         m_colWidths
.Add( m_defaultColWidth 
); 
3798         colRight 
+= m_defaultColWidth
; 
3799         m_colRights
.Add( colRight 
); 
3803 int wxGrid::GetColWidth(int col
) const 
3805     return m_colWidths
.IsEmpty() ? m_defaultColWidth 
: m_colWidths
[col
]; 
3808 int wxGrid::GetColLeft(int col
) const 
3810     return m_colRights
.IsEmpty() ? col 
* m_defaultColWidth
 
3811                                  : m_colRights
[col
] - m_colWidths
[col
]; 
3814 int wxGrid::GetColRight(int col
) const 
3816     return m_colRights
.IsEmpty() ? (col 
+ 1) * m_defaultColWidth
 
3820 int wxGrid::GetRowHeight(int row
) const 
3822     return m_rowHeights
.IsEmpty() ? m_defaultRowHeight 
: m_rowHeights
[row
]; 
3825 int wxGrid::GetRowTop(int row
) const 
3827     return m_rowBottoms
.IsEmpty() ? row 
* m_defaultRowHeight
 
3828                                   : m_rowBottoms
[row
] - m_rowHeights
[row
]; 
3831 int wxGrid::GetRowBottom(int row
) const 
3833     return m_rowBottoms
.IsEmpty() ? (row 
+ 1) * m_defaultRowHeight
 
3834                                   : m_rowBottoms
[row
]; 
3837 void wxGrid::CalcDimensions() 
3840     GetClientSize( &cw
, &ch 
); 
3842     if ( m_rowLabelWin
->IsShown() ) 
3843         cw 
-= m_rowLabelWidth
; 
3844     if ( m_colLabelWin
->IsShown() ) 
3845         ch 
-= m_colLabelHeight
; 
3848     int w 
= m_numCols 
> 0 ? GetColRight(m_numCols 
- 1) + m_extraWidth 
+ 1 : 0; 
3849     int h 
= m_numRows 
> 0 ? GetRowBottom(m_numRows 
- 1) + m_extraHeight 
+ 1 : 0; 
3851     // preserve (more or less) the previous position 
3853     GetViewStart( &x
, &y 
); 
3855     // maybe we don't need scrollbars at all? 
3857     // also adjust the position to be valid for the new scroll rangs 
3878     // do set scrollbar parameters 
3879     SetScrollbars( GRID_SCROLL_LINE_X
, GRID_SCROLL_LINE_Y
, 
3880                    GetScrollX(w
), GetScrollY(h
), x
, y
, 
3881                    GetBatchCount() != 0); 
3883     // if our OnSize() hadn't been called (it would if we have scrollbars), we 
3884     // still must reposition the children 
3889 void wxGrid::CalcWindowSizes() 
3892     GetClientSize( &cw
, &ch 
); 
3894     if ( m_cornerLabelWin
->IsShown() ) 
3895         m_cornerLabelWin
->SetSize( 0, 0, m_rowLabelWidth
, m_colLabelHeight 
); 
3897     if ( m_colLabelWin
->IsShown() ) 
3898         m_colLabelWin
->SetSize( m_rowLabelWidth
, 0, cw
-m_rowLabelWidth
, m_colLabelHeight
); 
3900     if ( m_rowLabelWin
->IsShown() ) 
3901         m_rowLabelWin
->SetSize( 0, m_colLabelHeight
, m_rowLabelWidth
, ch
-m_colLabelHeight
); 
3903     if ( m_gridWin
->IsShown() ) 
3904         m_gridWin
->SetSize( m_rowLabelWidth
, m_colLabelHeight
, cw
-m_rowLabelWidth
, ch
-m_colLabelHeight
); 
3908 // this is called when the grid table sends a message to say that it 
3909 // has been redimensioned 
3911 bool wxGrid::Redimension( wxGridTableMessage
& msg 
) 
3914     bool result 
= FALSE
; 
3917     // if we were using the default widths/heights so far, we must change them 
3919     if ( m_colWidths
.IsEmpty() ) 
3924     if ( m_rowHeights
.IsEmpty() ) 
3930     switch ( msg
.GetId() ) 
3932         case wxGRIDTABLE_NOTIFY_ROWS_INSERTED
: 
3934             size_t pos 
= msg
.GetCommandInt(); 
3935             int numRows 
= msg
.GetCommandInt2(); 
3937             m_numRows 
+= numRows
; 
3939             if ( !m_rowHeights
.IsEmpty() ) 
3941                 for ( i 
= 0;  i 
< numRows
;  i
++ ) 
3943                     m_rowHeights
.Insert( m_defaultRowHeight
, pos 
); 
3944                     m_rowBottoms
.Insert( 0, pos 
); 
3948                 if ( pos 
> 0 ) bottom 
= m_rowBottoms
[pos
-1]; 
3950                 for ( i 
= pos
;  i 
< m_numRows
;  i
++ ) 
3952                     bottom 
+= m_rowHeights
[i
]; 
3953                     m_rowBottoms
[i
] = bottom
; 
3956             if ( m_currentCellCoords 
== wxGridNoCellCoords 
) 
3958                 // if we have just inserted cols into an empty grid the current 
3959                 // cell will be undefined... 
3961                 SetCurrentCell( 0, 0 ); 
3963             m_selection
->UpdateRows( pos
, numRows 
); 
3964             wxGridCellAttrProvider 
* attrProvider 
= m_table
->GetAttrProvider(); 
3966                 attrProvider
->UpdateAttrRows( pos
, numRows 
); 
3968             if ( !GetBatchCount() ) 
3971                 m_rowLabelWin
->Refresh(); 
3977         case wxGRIDTABLE_NOTIFY_ROWS_APPENDED
: 
3979             int numRows 
= msg
.GetCommandInt(); 
3980             int oldNumRows 
= m_numRows
; 
3981             m_numRows 
+= numRows
; 
3983             if ( !m_rowHeights
.IsEmpty() ) 
3985                 for ( i 
= 0;  i 
< numRows
;  i
++ ) 
3987                     m_rowHeights
.Add( m_defaultRowHeight 
); 
3988                     m_rowBottoms
.Add( 0 ); 
3992                 if ( oldNumRows 
> 0 ) bottom 
= m_rowBottoms
[oldNumRows
-1]; 
3994                 for ( i 
= oldNumRows
;  i 
< m_numRows
;  i
++ ) 
3996                     bottom 
+= m_rowHeights
[i
]; 
3997                     m_rowBottoms
[i
] = bottom
; 
4000             if ( m_currentCellCoords 
== wxGridNoCellCoords 
) 
4002                 // if we have just inserted cols into an empty grid the current 
4003                 // cell will be undefined... 
4005                 SetCurrentCell( 0, 0 ); 
4007             if ( !GetBatchCount() ) 
4010                 m_rowLabelWin
->Refresh(); 
4016         case wxGRIDTABLE_NOTIFY_ROWS_DELETED
: 
4018             size_t pos 
= msg
.GetCommandInt(); 
4019             int numRows 
= msg
.GetCommandInt2(); 
4020             m_numRows 
-= numRows
; 
4022             if ( !m_rowHeights
.IsEmpty() ) 
4024                 for ( i 
= 0;  i 
< numRows
;  i
++ ) 
4026                     m_rowHeights
.RemoveAt( pos 
); 
4027                     m_rowBottoms
.RemoveAt( pos 
); 
4031                 for ( i 
= 0;  i 
< m_numRows
;  i
++ ) 
4033                     h 
+= m_rowHeights
[i
]; 
4034                     m_rowBottoms
[i
] = h
; 
4039                 m_currentCellCoords 
= wxGridNoCellCoords
; 
4043                 if ( m_currentCellCoords
.GetRow() >= m_numRows 
) 
4044                     m_currentCellCoords
.Set( 0, 0 ); 
4046             m_selection
->UpdateRows( pos
, -((int)numRows
) ); 
4047             wxGridCellAttrProvider 
* attrProvider 
= m_table
->GetAttrProvider(); 
4049                 attrProvider
->UpdateAttrRows( pos
, -((int)numRows
) ); 
4050 // ifdef'd out following patch from Paul Gammans 
4052                 // No need to touch column attributes, unless we 
4053                 // removed _all_ rows, in this case, we remove 
4054                 // all column attributes. 
4055                 // I hate to do this here, but the 
4056                 // needed data is not available inside UpdateAttrRows. 
4057                 if ( !GetNumberRows() ) 
4058                     attrProvider
->UpdateAttrCols( 0, -GetNumberCols() ); 
4061             if ( !GetBatchCount() ) 
4064                 m_rowLabelWin
->Refresh(); 
4070         case wxGRIDTABLE_NOTIFY_COLS_INSERTED
: 
4072             size_t pos 
= msg
.GetCommandInt(); 
4073             int numCols 
= msg
.GetCommandInt2(); 
4074             m_numCols 
+= numCols
; 
4076             if ( !m_colWidths
.IsEmpty() ) 
4078                 for ( i 
= 0;  i 
< numCols
;  i
++ ) 
4080                     m_colWidths
.Insert( m_defaultColWidth
, pos 
); 
4081                     m_colRights
.Insert( 0, pos 
); 
4085                 if ( pos 
> 0 ) right 
= m_colRights
[pos
-1]; 
4087                 for ( i 
= pos
;  i 
< m_numCols
;  i
++ ) 
4089                     right 
+= m_colWidths
[i
]; 
4090                     m_colRights
[i
] = right
; 
4093             if ( m_currentCellCoords 
== wxGridNoCellCoords 
) 
4095                 // if we have just inserted cols into an empty grid the current 
4096                 // cell will be undefined... 
4098                 SetCurrentCell( 0, 0 ); 
4100             m_selection
->UpdateCols( pos
, numCols 
); 
4101             wxGridCellAttrProvider 
* attrProvider 
= m_table
->GetAttrProvider(); 
4103                 attrProvider
->UpdateAttrCols( pos
, numCols 
); 
4104             if ( !GetBatchCount() ) 
4107                 m_colLabelWin
->Refresh(); 
4114         case wxGRIDTABLE_NOTIFY_COLS_APPENDED
: 
4116             int numCols 
= msg
.GetCommandInt(); 
4117             int oldNumCols 
= m_numCols
; 
4118             m_numCols 
+= numCols
; 
4119             if ( !m_colWidths
.IsEmpty() ) 
4121                 for ( i 
= 0;  i 
< numCols
;  i
++ ) 
4123                     m_colWidths
.Add( m_defaultColWidth 
); 
4124                     m_colRights
.Add( 0 ); 
4128                 if ( oldNumCols 
> 0 ) right 
= m_colRights
[oldNumCols
-1]; 
4130                 for ( i 
= oldNumCols
;  i 
< m_numCols
;  i
++ ) 
4132                     right 
+= m_colWidths
[i
]; 
4133                     m_colRights
[i
] = right
; 
4136             if ( m_currentCellCoords 
== wxGridNoCellCoords 
) 
4138                 // if we have just inserted cols into an empty grid the current 
4139                 // cell will be undefined... 
4141                 SetCurrentCell( 0, 0 ); 
4143             if ( !GetBatchCount() ) 
4146                 m_colLabelWin
->Refresh(); 
4152         case wxGRIDTABLE_NOTIFY_COLS_DELETED
: 
4154             size_t pos 
= msg
.GetCommandInt(); 
4155             int numCols 
= msg
.GetCommandInt2(); 
4156             m_numCols 
-= numCols
; 
4158             if ( !m_colWidths
.IsEmpty() ) 
4160                 for ( i 
= 0;  i 
< numCols
;  i
++ ) 
4162                     m_colWidths
.RemoveAt( pos 
); 
4163                     m_colRights
.RemoveAt( pos 
); 
4167                 for ( i 
= 0;  i 
< m_numCols
;  i
++ ) 
4169                     w 
+= m_colWidths
[i
]; 
4175                 m_currentCellCoords 
= wxGridNoCellCoords
; 
4179                 if ( m_currentCellCoords
.GetCol() >= m_numCols 
) 
4180                   m_currentCellCoords
.Set( 0, 0 ); 
4182             m_selection
->UpdateCols( pos
, -((int)numCols
) ); 
4183             wxGridCellAttrProvider 
* attrProvider 
= m_table
->GetAttrProvider(); 
4185                 attrProvider
->UpdateAttrCols( pos
, -((int)numCols
) ); 
4186 // ifdef'd out following patch from Paul Gammans 
4188                 // No need to touch row attributes, unless we 
4189                 // removed _all_ columns, in this case, we remove 
4190                 // all row attributes. 
4191                 // I hate to do this here, but the 
4192                 // needed data is not available inside UpdateAttrCols. 
4193                 if ( !GetNumberCols() ) 
4194                     attrProvider
->UpdateAttrRows( 0, -GetNumberRows() ); 
4197             if ( !GetBatchCount() ) 
4200                 m_colLabelWin
->Refresh(); 
4207     if (result 
&& !GetBatchCount() ) 
4208         m_gridWin
->Refresh(); 
4213 wxArrayInt 
wxGrid::CalcRowLabelsExposed( const wxRegion
& reg 
) 
4215     wxRegionIterator 
iter( reg 
); 
4218     wxArrayInt  rowlabels
; 
4225         // TODO: remove this when we can... 
4226         // There is a bug in wxMotif that gives garbage update 
4227         // rectangles if you jump-scroll a long way by clicking the 
4228         // scrollbar with middle button.  This is a work-around 
4230 #if defined(__WXMOTIF__) 
4232         m_gridWin
->GetClientSize( &cw
, &ch 
); 
4233         if ( r
.GetTop() > ch 
) r
.SetTop( 0 ); 
4234         r
.SetBottom( wxMin( r
.GetBottom(), ch 
) ); 
4237         // logical bounds of update region 
4240         CalcUnscrolledPosition( 0, r
.GetTop(), &dummy
, &top 
); 
4241         CalcUnscrolledPosition( 0, r
.GetBottom(), &dummy
, &bottom 
); 
4243         // find the row labels within these bounds 
4246         for ( row 
= YToRow(top
);  row 
< m_numRows
;  row
++ ) 
4248             if ( GetRowBottom(row
) < top 
) 
4251             if ( GetRowTop(row
) > bottom 
) 
4254             rowlabels
.Add( row 
); 
4264 wxArrayInt 
wxGrid::CalcColLabelsExposed( const wxRegion
& reg 
) 
4266     wxRegionIterator 
iter( reg 
); 
4269     wxArrayInt colLabels
; 
4276         // TODO: remove this when we can... 
4277         // There is a bug in wxMotif that gives garbage update 
4278         // rectangles if you jump-scroll a long way by clicking the 
4279         // scrollbar with middle button.  This is a work-around 
4281 #if defined(__WXMOTIF__) 
4283         m_gridWin
->GetClientSize( &cw
, &ch 
); 
4284         if ( r
.GetLeft() > cw 
) r
.SetLeft( 0 ); 
4285         r
.SetRight( wxMin( r
.GetRight(), cw 
) ); 
4288         // logical bounds of update region 
4291         CalcUnscrolledPosition( r
.GetLeft(), 0, &left
, &dummy 
); 
4292         CalcUnscrolledPosition( r
.GetRight(), 0, &right
, &dummy 
); 
4294         // find the cells within these bounds 
4297         for ( col 
= XToCol(left
);  col 
< m_numCols
;  col
++ ) 
4299             if ( GetColRight(col
) < left 
) 
4302             if ( GetColLeft(col
) > right 
) 
4305             colLabels
.Add( col 
); 
4314 wxGridCellCoordsArray 
wxGrid::CalcCellsExposed( const wxRegion
& reg 
) 
4316     wxRegionIterator 
iter( reg 
); 
4319     wxGridCellCoordsArray  cellsExposed
; 
4321     int left
, top
, right
, bottom
; 
4326         // TODO: remove this when we can... 
4327         // There is a bug in wxMotif that gives garbage update 
4328         // rectangles if you jump-scroll a long way by clicking the 
4329         // scrollbar with middle button.  This is a work-around 
4331 #if defined(__WXMOTIF__) 
4333         m_gridWin
->GetClientSize( &cw
, &ch 
); 
4334         if ( r
.GetTop() > ch 
) r
.SetTop( 0 ); 
4335         if ( r
.GetLeft() > cw 
) r
.SetLeft( 0 ); 
4336         r
.SetRight( wxMin( r
.GetRight(), cw 
) ); 
4337         r
.SetBottom( wxMin( r
.GetBottom(), ch 
) ); 
4340         // logical bounds of update region 
4342         CalcUnscrolledPosition( r
.GetLeft(), r
.GetTop(), &left
, &top 
); 
4343         CalcUnscrolledPosition( r
.GetRight(), r
.GetBottom(), &right
, &bottom 
); 
4345         // find the cells within these bounds 
4348         for ( row 
= YToRow(top
);  row 
< m_numRows
;  row
++ ) 
4350             if ( GetRowBottom(row
) <= top 
) 
4353             if ( GetRowTop(row
) > bottom 
) 
4356             for ( col 
= XToCol(left
);  col 
< m_numCols
;  col
++ ) 
4358                 if ( GetColRight(col
) <= left 
) 
4361                 if ( GetColLeft(col
) > right 
) 
4364                 cellsExposed
.Add( wxGridCellCoords( row
, col 
) ); 
4371     return cellsExposed
; 
4375 void wxGrid::ProcessRowLabelMouseEvent( wxMouseEvent
& event 
) 
4378     wxPoint 
pos( event
.GetPosition() ); 
4379     CalcUnscrolledPosition( pos
.x
, pos
.y
, &x
, &y 
); 
4381     if ( event
.Dragging() ) 
4383         m_isDragging 
= TRUE
; 
4385         if ( event
.LeftIsDown() ) 
4387             switch( m_cursorMode 
) 
4389                 case WXGRID_CURSOR_RESIZE_ROW
: 
4391                     int cw
, ch
, left
, dummy
; 
4392                     m_gridWin
->GetClientSize( &cw
, &ch 
); 
4393                     CalcUnscrolledPosition( 0, 0, &left
, &dummy 
); 
4395                     wxClientDC 
dc( m_gridWin 
); 
4398                                GetRowTop(m_dragRowOrCol
) + 
4399                                GetRowMinimalHeight(m_dragRowOrCol
) ); 
4400                     dc
.SetLogicalFunction(wxINVERT
); 
4401                     if ( m_dragLastPos 
>= 0 ) 
4403                         dc
.DrawLine( left
, m_dragLastPos
, left
+cw
, m_dragLastPos 
); 
4405                     dc
.DrawLine( left
, y
, left
+cw
, y 
); 
4410                 case WXGRID_CURSOR_SELECT_ROW
: 
4411                     if ( (row 
= YToRow( y 
)) >= 0 ) 
4413                         m_selection
->SelectRow( row
, 
4414                                                 event
.ControlDown(), 
4420                 // default label to suppress warnings about "enumeration value 
4421                 // 'xxx' not handled in switch 
4429     m_isDragging 
= FALSE
; 
4432     // ------------ Entering or leaving the window 
4434     if ( event
.Entering() || event
.Leaving() ) 
4436         ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
, m_rowLabelWin
); 
4440     // ------------ Left button pressed 
4442     else if ( event
.LeftDown() ) 
4444         // don't send a label click event for a hit on the 
4445         // edge of the row label - this is probably the user 
4446         // wanting to resize the row 
4448         if ( YToEdgeOfRow(y
) < 0 ) 
4452                  !SendEvent( wxEVT_GRID_LABEL_LEFT_CLICK
, row
, -1, event 
) ) 
4454                 if ( !event
.ShiftDown() && !event
.ControlDown() ) 
4456                 if ( event
.ShiftDown() ) 
4457                     m_selection
->SelectBlock( m_currentCellCoords
.GetRow(), 
4460                                               GetNumberCols() - 1, 
4461                                               event
.ControlDown(), 
4466                     m_selection
->SelectRow( row
, 
4467                                             event
.ControlDown(), 
4471                 ChangeCursorMode(WXGRID_CURSOR_SELECT_ROW
, m_rowLabelWin
); 
4476             // starting to drag-resize a row 
4478             if ( CanDragRowSize() ) 
4479                 ChangeCursorMode(WXGRID_CURSOR_RESIZE_ROW
, m_rowLabelWin
); 
4484     // ------------ Left double click 
4486     else if (event
.LeftDClick() ) 
4488         if ( YToEdgeOfRow(y
) < 0 ) 
4491             SendEvent( wxEVT_GRID_LABEL_LEFT_DCLICK
, row
, -1, event 
); 
4496     // ------------ Left button released 
4498     else if ( event
.LeftUp() ) 
4500         if ( m_cursorMode 
== WXGRID_CURSOR_RESIZE_ROW 
) 
4502             DoEndDragResizeRow(); 
4504             // Note: we are ending the event *after* doing 
4505             // default processing in this case 
4507             SendEvent( wxEVT_GRID_ROW_SIZE
, m_dragRowOrCol
, -1, event 
); 
4510         ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
, m_rowLabelWin
); 
4515     // ------------ Right button down 
4517     else if ( event
.RightDown() ) 
4520         if ( !SendEvent( wxEVT_GRID_LABEL_RIGHT_CLICK
, row
, -1, event 
) ) 
4522             // no default action at the moment 
4527     // ------------ Right double click 
4529     else if ( event
.RightDClick() ) 
4532         if ( !SendEvent( wxEVT_GRID_LABEL_RIGHT_DCLICK
, row
, -1, event 
) ) 
4534             // no default action at the moment 
4539     // ------------ No buttons down and mouse moving 
4541     else if ( event
.Moving() ) 
4543         m_dragRowOrCol 
= YToEdgeOfRow( y 
); 
4544         if ( m_dragRowOrCol 
>= 0 ) 
4546             if ( m_cursorMode 
== WXGRID_CURSOR_SELECT_CELL 
) 
4548                 // don't capture the mouse yet 
4549                 if ( CanDragRowSize() ) 
4550                     ChangeCursorMode(WXGRID_CURSOR_RESIZE_ROW
, m_rowLabelWin
, FALSE
); 
4553         else if ( m_cursorMode 
!= WXGRID_CURSOR_SELECT_CELL 
) 
4555             ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
, m_rowLabelWin
, FALSE
); 
4561 void wxGrid::ProcessColLabelMouseEvent( wxMouseEvent
& event 
) 
4564     wxPoint 
pos( event
.GetPosition() ); 
4565     CalcUnscrolledPosition( pos
.x
, pos
.y
, &x
, &y 
); 
4567     if ( event
.Dragging() ) 
4569         m_isDragging 
= TRUE
; 
4571         if ( event
.LeftIsDown() ) 
4573             switch( m_cursorMode 
) 
4575                 case WXGRID_CURSOR_RESIZE_COL
: 
4577                     int cw
, ch
, dummy
, top
; 
4578                     m_gridWin
->GetClientSize( &cw
, &ch 
); 
4579                     CalcUnscrolledPosition( 0, 0, &dummy
, &top 
); 
4581                     wxClientDC 
dc( m_gridWin 
); 
4584                     x 
= wxMax( x
, GetColLeft(m_dragRowOrCol
) + 
4585                                   GetColMinimalWidth(m_dragRowOrCol
)); 
4586                     dc
.SetLogicalFunction(wxINVERT
); 
4587                     if ( m_dragLastPos 
>= 0 ) 
4589                         dc
.DrawLine( m_dragLastPos
, top
, m_dragLastPos
, top
+ch 
); 
4591                     dc
.DrawLine( x
, top
, x
, top
+ch 
); 
4596                 case WXGRID_CURSOR_SELECT_COL
: 
4597                     if ( (col 
= XToCol( x 
)) >= 0 ) 
4599                         m_selection
->SelectCol( col
, 
4600                                                 event
.ControlDown(), 
4606                 // default label to suppress warnings about "enumeration value 
4607                 // 'xxx' not handled in switch 
4615     m_isDragging 
= FALSE
; 
4618     // ------------ Entering or leaving the window 
4620     if ( event
.Entering() || event
.Leaving() ) 
4622         ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
, m_colLabelWin
); 
4626     // ------------ Left button pressed 
4628     else if ( event
.LeftDown() ) 
4630         // don't send a label click event for a hit on the 
4631         // edge of the col label - this is probably the user 
4632         // wanting to resize the col 
4634         if ( XToEdgeOfCol(x
) < 0 ) 
4638                  !SendEvent( wxEVT_GRID_LABEL_LEFT_CLICK
, -1, col
, event 
) ) 
4640                 if ( !event
.ShiftDown() && !event
.ControlDown() ) 
4642                 if ( event
.ShiftDown() ) 
4643                     m_selection
->SelectBlock( 0, 
4644                                               m_currentCellCoords
.GetCol(), 
4645                                               GetNumberRows() - 1, col
, 
4646                                               event
.ControlDown(), 
4651                     m_selection
->SelectCol( col
, 
4652                                             event
.ControlDown(), 
4656                 ChangeCursorMode(WXGRID_CURSOR_SELECT_COL
, m_colLabelWin
); 
4661             // starting to drag-resize a col 
4663             if ( CanDragColSize() ) 
4664                 ChangeCursorMode(WXGRID_CURSOR_RESIZE_COL
, m_colLabelWin
); 
4669     // ------------ Left double click 
4671     if ( event
.LeftDClick() ) 
4673         if ( XToEdgeOfCol(x
) < 0 ) 
4676             SendEvent( wxEVT_GRID_LABEL_LEFT_DCLICK
, -1, col
, event 
); 
4681     // ------------ Left button released 
4683     else if ( event
.LeftUp() ) 
4685         if ( m_cursorMode 
== WXGRID_CURSOR_RESIZE_COL 
) 
4687             DoEndDragResizeCol(); 
4689             // Note: we are ending the event *after* doing 
4690             // default processing in this case 
4692             SendEvent( wxEVT_GRID_COL_SIZE
, -1, m_dragRowOrCol
, event 
); 
4695         ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
, m_colLabelWin
); 
4700     // ------------ Right button down 
4702     else if ( event
.RightDown() ) 
4705         if ( !SendEvent( wxEVT_GRID_LABEL_RIGHT_CLICK
, -1, col
, event 
) ) 
4707             // no default action at the moment 
4712     // ------------ Right double click 
4714     else if ( event
.RightDClick() ) 
4717         if ( !SendEvent( wxEVT_GRID_LABEL_RIGHT_DCLICK
, -1, col
, event 
) ) 
4719             // no default action at the moment 
4724     // ------------ No buttons down and mouse moving 
4726     else if ( event
.Moving() ) 
4728         m_dragRowOrCol 
= XToEdgeOfCol( x 
); 
4729         if ( m_dragRowOrCol 
>= 0 ) 
4731             if ( m_cursorMode 
== WXGRID_CURSOR_SELECT_CELL 
) 
4733                 // don't capture the cursor yet 
4734                 if ( CanDragColSize() ) 
4735                     ChangeCursorMode(WXGRID_CURSOR_RESIZE_COL
, m_colLabelWin
, FALSE
); 
4738         else if ( m_cursorMode 
!= WXGRID_CURSOR_SELECT_CELL 
) 
4740             ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
, m_colLabelWin
, FALSE
); 
4746 void wxGrid::ProcessCornerLabelMouseEvent( wxMouseEvent
& event 
) 
4748     if ( event
.LeftDown() ) 
4750         // indicate corner label by having both row and 
4753         if ( !SendEvent( wxEVT_GRID_LABEL_LEFT_CLICK
, -1, -1, event 
) ) 
4759     else if ( event
.LeftDClick() ) 
4761         SendEvent( wxEVT_GRID_LABEL_LEFT_DCLICK
, -1, -1, event 
); 
4764     else if ( event
.RightDown() ) 
4766         if ( !SendEvent( wxEVT_GRID_LABEL_RIGHT_CLICK
, -1, -1, event 
) ) 
4768             // no default action at the moment 
4772     else if ( event
.RightDClick() ) 
4774         if ( !SendEvent( wxEVT_GRID_LABEL_RIGHT_DCLICK
, -1, -1, event 
) ) 
4776             // no default action at the moment 
4781 void wxGrid::ChangeCursorMode(CursorMode mode
, 
4786     static const wxChar 
*cursorModes
[] = 
4795     wxLogTrace(_T("grid"), 
4796                _T("wxGrid cursor mode (mouse capture for %s): %s -> %s"), 
4797                win 
== m_colLabelWin 
? _T("colLabelWin") 
4798                                     : win 
? _T("rowLabelWin") 
4800                cursorModes
[m_cursorMode
], cursorModes
[mode
]); 
4801 #endif // __WXDEBUG__ 
4803     if ( mode 
== m_cursorMode 
&& 
4804          win 
== m_winCapture 
&& 
4805          captureMouse 
== (m_winCapture 
!= NULL
)) 
4810         // by default use the grid itself 
4816         m_winCapture
->ReleaseMouse(); 
4817         m_winCapture 
= (wxWindow 
*)NULL
; 
4820     m_cursorMode 
= mode
; 
4822     switch ( m_cursorMode 
) 
4824         case WXGRID_CURSOR_RESIZE_ROW
: 
4825             win
->SetCursor( m_rowResizeCursor 
); 
4828         case WXGRID_CURSOR_RESIZE_COL
: 
4829             win
->SetCursor( m_colResizeCursor 
); 
4833             win
->SetCursor( *wxSTANDARD_CURSOR 
); 
4836     // we need to capture mouse when resizing 
4837     bool resize 
= m_cursorMode 
== WXGRID_CURSOR_RESIZE_ROW 
|| 
4838                   m_cursorMode 
== WXGRID_CURSOR_RESIZE_COL
; 
4840     if ( captureMouse 
&& resize 
) 
4842         win
->CaptureMouse(); 
4847 void wxGrid::ProcessGridCellMouseEvent( wxMouseEvent
& event 
) 
4850     wxPoint 
pos( event
.GetPosition() ); 
4851     CalcUnscrolledPosition( pos
.x
, pos
.y
, &x
, &y 
); 
4853     wxGridCellCoords coords
; 
4854     XYToCell( x
, y
, coords 
); 
4856     if ( event
.Dragging() ) 
4858         //wxLogDebug("pos(%d, %d) coords(%d, %d)", pos.x, pos.y, coords.GetRow(), coords.GetCol()); 
4860         // Don't start doing anything until the mouse has been drug at 
4861         // least 3 pixels in any direction... 
4864             if (m_startDragPos 
== wxDefaultPosition
) 
4866                 m_startDragPos 
= pos
; 
4869             if (abs(m_startDragPos
.x 
- pos
.x
) < 4 && abs(m_startDragPos
.y 
- pos
.y
) < 4) 
4873         m_isDragging 
= TRUE
; 
4874         if ( m_cursorMode 
== WXGRID_CURSOR_SELECT_CELL 
) 
4876             // Hide the edit control, so it 
4877             // won't interfer with drag-shrinking. 
4878             if ( IsCellEditControlShown() ) 
4880                 HideCellEditControl(); 
4881                 SaveEditControlValue(); 
4884             // Have we captured the mouse yet? 
4887                 m_winCapture 
= m_gridWin
; 
4888                 m_winCapture
->CaptureMouse(); 
4891             if ( coords 
!= wxGridNoCellCoords 
) 
4893                 if ( event
.ControlDown() ) 
4895                     if ( m_selectingKeyboard 
== wxGridNoCellCoords
) 
4896                         m_selectingKeyboard 
= coords
; 
4897                     HighlightBlock ( m_selectingKeyboard
, coords 
); 
4901                     if ( !IsSelection() ) 
4903                         HighlightBlock( coords
, coords 
); 
4907                         HighlightBlock( m_currentCellCoords
, coords 
); 
4911                 if (! IsVisible(coords
)) 
4913                     MakeCellVisible(coords
); 
4914                     // TODO: need to introduce a delay or something here.  The 
4915                     // scrolling is way to fast, at least on MSW - also on GTK. 
4919         else if ( m_cursorMode 
== WXGRID_CURSOR_RESIZE_ROW 
) 
4921             int cw
, ch
, left
, dummy
; 
4922             m_gridWin
->GetClientSize( &cw
, &ch 
); 
4923             CalcUnscrolledPosition( 0, 0, &left
, &dummy 
); 
4925             wxClientDC 
dc( m_gridWin 
); 
4927             y 
= wxMax( y
, GetRowTop(m_dragRowOrCol
) + 
4928                           GetRowMinimalHeight(m_dragRowOrCol
) ); 
4929             dc
.SetLogicalFunction(wxINVERT
); 
4930             if ( m_dragLastPos 
>= 0 ) 
4932                 dc
.DrawLine( left
, m_dragLastPos
, left
+cw
, m_dragLastPos 
); 
4934             dc
.DrawLine( left
, y
, left
+cw
, y 
); 
4937         else if ( m_cursorMode 
== WXGRID_CURSOR_RESIZE_COL 
) 
4939             int cw
, ch
, dummy
, top
; 
4940             m_gridWin
->GetClientSize( &cw
, &ch 
); 
4941             CalcUnscrolledPosition( 0, 0, &dummy
, &top 
); 
4943             wxClientDC 
dc( m_gridWin 
); 
4945             x 
= wxMax( x
, GetColLeft(m_dragRowOrCol
) + 
4946                           GetColMinimalWidth(m_dragRowOrCol
) ); 
4947             dc
.SetLogicalFunction(wxINVERT
); 
4948             if ( m_dragLastPos 
>= 0 ) 
4950                 dc
.DrawLine( m_dragLastPos
, top
, m_dragLastPos
, top
+ch 
); 
4952             dc
.DrawLine( x
, top
, x
, top
+ch 
); 
4959     m_isDragging 
= FALSE
; 
4960     m_startDragPos 
= wxDefaultPosition
; 
4962     // VZ: if we do this, the mode is reset to WXGRID_CURSOR_SELECT_CELL 
4963     //     immediately after it becomes WXGRID_CURSOR_RESIZE_ROW/COL under 
4966     if ( event
.Entering() || event
.Leaving() ) 
4968         ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
); 
4969         m_gridWin
->SetCursor( *wxSTANDARD_CURSOR 
); 
4974     // ------------ Left button pressed 
4976     if ( event
.LeftDown() && coords 
!= wxGridNoCellCoords 
) 
4978         if ( !SendEvent( wxEVT_GRID_CELL_LEFT_CLICK
, 
4983             if ( !event
.ControlDown() ) 
4985             if ( event
.ShiftDown() ) 
4987                 m_selection
->SelectBlock( m_currentCellCoords
.GetRow(), 
4988                                           m_currentCellCoords
.GetCol(), 
4991                                           event
.ControlDown(), 
4996             else if ( XToEdgeOfCol(x
) < 0  && 
4997                       YToEdgeOfRow(y
) < 0 ) 
4999                 DisableCellEditControl(); 
5000                 MakeCellVisible( coords 
); 
5002                 // if this is the second click on this cell then start 
5004                 if ( m_waitForSlowClick 
&& 
5005                      (coords 
== m_currentCellCoords
) && 
5006                      CanEnableCellControl()) 
5008                     EnableCellEditControl(); 
5010                     wxGridCellAttr
* attr 
= GetCellAttr(m_currentCellCoords
); 
5011                     wxGridCellEditor 
*editor 
= attr
->GetEditor(this, 
5014                     editor
->StartingClick(); 
5018                     m_waitForSlowClick 
= FALSE
; 
5022                     if ( event
.ControlDown() ) 
5024                         m_selection
->ToggleCellSelection( coords
.GetRow(), 
5026                                                           event
.ControlDown(), 
5030                         m_selectingTopLeft 
= wxGridNoCellCoords
; 
5031                         m_selectingBottomRight 
= wxGridNoCellCoords
; 
5032                         m_selectingKeyboard 
= coords
; 
5036                         SetCurrentCell( coords 
); 
5037                         if ( m_selection
->GetSelectionMode() 
5038                              != wxGrid::wxGridSelectCells
) 
5039                             HighlightBlock( coords
, coords 
); 
5041                     m_waitForSlowClick 
= TRUE
; 
5048     // ------------ Left double click 
5050     else if ( event
.LeftDClick() && coords 
!= wxGridNoCellCoords 
) 
5052         DisableCellEditControl(); 
5054         if ( XToEdgeOfCol(x
) < 0  &&  YToEdgeOfRow(y
) < 0 ) 
5056             SendEvent( wxEVT_GRID_CELL_LEFT_DCLICK
, 
5064     // ------------ Left button released 
5066     else if ( event
.LeftUp() ) 
5068         if ( m_cursorMode 
== WXGRID_CURSOR_SELECT_CELL 
) 
5070             if ( m_selectingTopLeft 
!= wxGridNoCellCoords 
&& 
5071                  m_selectingBottomRight 
!= wxGridNoCellCoords 
) 
5075                     m_winCapture
->ReleaseMouse(); 
5076                     m_winCapture 
= NULL
; 
5078                 m_selection
->SelectBlock( m_selectingTopLeft
.GetRow(), 
5079                                           m_selectingTopLeft
.GetCol(), 
5080                                           m_selectingBottomRight
.GetRow(), 
5081                                           m_selectingBottomRight
.GetCol(), 
5082                                           event
.ControlDown(), 
5086                 m_selectingTopLeft 
= wxGridNoCellCoords
; 
5087                 m_selectingBottomRight 
= wxGridNoCellCoords
; 
5090             // Show the edit control, if it has been hidden for 
5092             ShowCellEditControl(); 
5094         else if ( m_cursorMode 
== WXGRID_CURSOR_RESIZE_ROW 
) 
5096             ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
); 
5097             DoEndDragResizeRow(); 
5099             // Note: we are ending the event *after* doing 
5100             // default processing in this case 
5102             SendEvent( wxEVT_GRID_ROW_SIZE
, m_dragRowOrCol
, -1, event 
); 
5104         else if ( m_cursorMode 
== WXGRID_CURSOR_RESIZE_COL 
) 
5106             ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
); 
5107             DoEndDragResizeCol(); 
5109             // Note: we are ending the event *after* doing 
5110             // default processing in this case 
5112             SendEvent( wxEVT_GRID_COL_SIZE
, -1, m_dragRowOrCol
, event 
); 
5119     // ------------ Right button down 
5121     else if ( event
.RightDown() && coords 
!= wxGridNoCellCoords 
) 
5123         DisableCellEditControl(); 
5124         if ( !SendEvent( wxEVT_GRID_CELL_RIGHT_CLICK
, 
5129             // no default action at the moment 
5134     // ------------ Right double click 
5136     else if ( event
.RightDClick() && coords 
!= wxGridNoCellCoords 
) 
5138         DisableCellEditControl(); 
5139         if ( !SendEvent( wxEVT_GRID_CELL_RIGHT_DCLICK
, 
5144             // no default action at the moment 
5148     // ------------ Moving and no button action 
5150     else if ( event
.Moving() && !event
.IsButton() ) 
5152         int dragRow 
= YToEdgeOfRow( y 
); 
5153         int dragCol 
= XToEdgeOfCol( x 
); 
5155         // Dragging on the corner of a cell to resize in both 
5156         // directions is not implemented yet... 
5158         if ( dragRow 
>= 0  &&  dragCol 
>= 0 ) 
5160             ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
); 
5166             m_dragRowOrCol 
= dragRow
; 
5168             if ( m_cursorMode 
== WXGRID_CURSOR_SELECT_CELL 
) 
5170                 if ( CanDragRowSize() && CanDragGridSize() ) 
5171                     ChangeCursorMode(WXGRID_CURSOR_RESIZE_ROW
); 
5176                 m_dragRowOrCol 
= dragCol
; 
5184             m_dragRowOrCol 
= dragCol
; 
5186             if ( m_cursorMode 
== WXGRID_CURSOR_SELECT_CELL 
) 
5188                 if ( CanDragColSize() && CanDragGridSize() ) 
5189                     ChangeCursorMode(WXGRID_CURSOR_RESIZE_COL
); 
5195         // Neither on a row or col edge 
5197         if ( m_cursorMode 
!= WXGRID_CURSOR_SELECT_CELL 
) 
5199             ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
); 
5205 void wxGrid::DoEndDragResizeRow() 
5207     if ( m_dragLastPos 
>= 0 ) 
5209         // erase the last line and resize the row 
5211         int cw
, ch
, left
, dummy
; 
5212         m_gridWin
->GetClientSize( &cw
, &ch 
); 
5213         CalcUnscrolledPosition( 0, 0, &left
, &dummy 
); 
5215         wxClientDC 
dc( m_gridWin 
); 
5217         dc
.SetLogicalFunction( wxINVERT 
); 
5218         dc
.DrawLine( left
, m_dragLastPos
, left
+cw
, m_dragLastPos 
); 
5219         HideCellEditControl(); 
5220         SaveEditControlValue(); 
5222         int rowTop 
= GetRowTop(m_dragRowOrCol
); 
5223         SetRowSize( m_dragRowOrCol
, 
5224                     wxMax( m_dragLastPos 
- rowTop
, WXGRID_MIN_ROW_HEIGHT 
) ); 
5226         if ( !GetBatchCount() ) 
5228             // Only needed to get the correct rect.y: 
5229             wxRect 
rect ( CellToRect( m_dragRowOrCol
, 0 ) ); 
5231             CalcScrolledPosition(0, rect
.y
, &dummy
, &rect
.y
); 
5232             rect
.width 
= m_rowLabelWidth
; 
5233             rect
.height 
= ch 
- rect
.y
; 
5234             m_rowLabelWin
->Refresh( TRUE
, &rect 
); 
5236             m_gridWin
->Refresh( FALSE
, &rect 
); 
5239         ShowCellEditControl(); 
5244 void wxGrid::DoEndDragResizeCol() 
5246     if ( m_dragLastPos 
>= 0 ) 
5248         // erase the last line and resize the col 
5250         int cw
, ch
, dummy
, top
; 
5251         m_gridWin
->GetClientSize( &cw
, &ch 
); 
5252         CalcUnscrolledPosition( 0, 0, &dummy
, &top 
); 
5254         wxClientDC 
dc( m_gridWin 
); 
5256         dc
.SetLogicalFunction( wxINVERT 
); 
5257         dc
.DrawLine( m_dragLastPos
, top
, m_dragLastPos
, top
+ch 
); 
5258         HideCellEditControl(); 
5259         SaveEditControlValue(); 
5261         int colLeft 
= GetColLeft(m_dragRowOrCol
); 
5262         SetColSize( m_dragRowOrCol
, 
5263                     wxMax( m_dragLastPos 
- colLeft
, 
5264                            GetColMinimalWidth(m_dragRowOrCol
) ) ); 
5266         if ( !GetBatchCount() ) 
5268             // Only needed to get the correct rect.x: 
5269             wxRect 
rect ( CellToRect( 0, m_dragRowOrCol 
) ); 
5271             CalcScrolledPosition(rect
.x
, 0, &rect
.x
, &dummy
); 
5272             rect
.width 
= cw 
- rect
.x
; 
5273             rect
.height 
= m_colLabelHeight
; 
5274             m_colLabelWin
->Refresh( TRUE
, &rect 
); 
5276             m_gridWin
->Refresh( FALSE
, &rect 
); 
5279         ShowCellEditControl(); 
5286 // ------ interaction with data model 
5288 bool wxGrid::ProcessTableMessage( wxGridTableMessage
& msg 
) 
5290     switch ( msg
.GetId() ) 
5292         case wxGRIDTABLE_REQUEST_VIEW_GET_VALUES
: 
5293             return GetModelValues(); 
5295         case wxGRIDTABLE_REQUEST_VIEW_SEND_VALUES
: 
5296             return SetModelValues(); 
5298         case wxGRIDTABLE_NOTIFY_ROWS_INSERTED
: 
5299         case wxGRIDTABLE_NOTIFY_ROWS_APPENDED
: 
5300         case wxGRIDTABLE_NOTIFY_ROWS_DELETED
: 
5301         case wxGRIDTABLE_NOTIFY_COLS_INSERTED
: 
5302         case wxGRIDTABLE_NOTIFY_COLS_APPENDED
: 
5303         case wxGRIDTABLE_NOTIFY_COLS_DELETED
: 
5304             return Redimension( msg 
); 
5313 // The behaviour of this function depends on the grid table class 
5314 // Clear() function.  For the default wxGridStringTable class the 
5315 // behavious is to replace all cell contents with wxEmptyString but 
5316 // not to change the number of rows or cols. 
5318 void wxGrid::ClearGrid() 
5322         if (IsCellEditControlEnabled()) 
5323             DisableCellEditControl(); 
5326         if ( !GetBatchCount() ) m_gridWin
->Refresh(); 
5331 bool wxGrid::InsertRows( int pos
, int numRows
, bool WXUNUSED(updateLabels
) ) 
5333     // TODO: something with updateLabels flag 
5337         wxFAIL_MSG( wxT("Called wxGrid::InsertRows() before calling CreateGrid()") ); 
5343         if (IsCellEditControlEnabled()) 
5344             DisableCellEditControl(); 
5346         return m_table
->InsertRows( pos
, numRows 
); 
5348         // the table will have sent the results of the insert row 
5349         // operation to this view object as a grid table message 
5355 bool wxGrid::AppendRows( int numRows
, bool WXUNUSED(updateLabels
) ) 
5357     // TODO: something with updateLabels flag 
5361         wxFAIL_MSG( wxT("Called wxGrid::AppendRows() before calling CreateGrid()") ); 
5365     return ( m_table 
&& m_table
->AppendRows( numRows 
) ); 
5366     // the table will have sent the results of the append row 
5367     // operation to this view object as a grid table message 
5371 bool wxGrid::DeleteRows( int pos
, int numRows
, bool WXUNUSED(updateLabels
) ) 
5373     // TODO: something with updateLabels flag 
5377         wxFAIL_MSG( wxT("Called wxGrid::DeleteRows() before calling CreateGrid()") ); 
5383         if (IsCellEditControlEnabled()) 
5384             DisableCellEditControl(); 
5386         return (m_table
->DeleteRows( pos
, numRows 
)); 
5387         // the table will have sent the results of the delete row 
5388         // operation to this view object as a grid table message 
5394 bool wxGrid::InsertCols( int pos
, int numCols
, bool WXUNUSED(updateLabels
) ) 
5396     // TODO: something with updateLabels flag 
5400         wxFAIL_MSG( wxT("Called wxGrid::InsertCols() before calling CreateGrid()") ); 
5406         if (IsCellEditControlEnabled()) 
5407             DisableCellEditControl(); 
5409         return m_table
->InsertCols( pos
, numCols 
); 
5410         // the table will have sent the results of the insert col 
5411         // operation to this view object as a grid table message 
5417 bool wxGrid::AppendCols( int numCols
, bool WXUNUSED(updateLabels
) ) 
5419     // TODO: something with updateLabels flag 
5423         wxFAIL_MSG( wxT("Called wxGrid::AppendCols() before calling CreateGrid()") ); 
5427     return ( m_table 
&& m_table
->AppendCols( numCols 
) ); 
5428     // the table will have sent the results of the append col 
5429     // operation to this view object as a grid table message 
5433 bool wxGrid::DeleteCols( int pos
, int numCols
, bool WXUNUSED(updateLabels
) ) 
5435     // TODO: something with updateLabels flag 
5439         wxFAIL_MSG( wxT("Called wxGrid::DeleteCols() before calling CreateGrid()") ); 
5445         if (IsCellEditControlEnabled()) 
5446             DisableCellEditControl(); 
5448         return ( m_table
->DeleteCols( pos
, numCols 
) ); 
5449         // the table will have sent the results of the delete col 
5450         // operation to this view object as a grid table message 
5458 // ----- event handlers 
5461 // Generate a grid event based on a mouse event and 
5462 // return the result of ProcessEvent() 
5464 int wxGrid::SendEvent( const wxEventType type
, 
5466                         wxMouseEvent
& mouseEv 
) 
5471    if ( type 
== wxEVT_GRID_ROW_SIZE 
|| type 
== wxEVT_GRID_COL_SIZE 
) 
5473        int rowOrCol 
= (row 
== -1 ? col 
: row
); 
5475        wxGridSizeEvent 
gridEvt( GetId(), 
5479                mouseEv
.GetX() + GetRowLabelSize(), 
5480                mouseEv
.GetY() + GetColLabelSize(), 
5481                mouseEv
.ControlDown(), 
5482                mouseEv
.ShiftDown(), 
5484                mouseEv
.MetaDown() ); 
5486        claimed 
= GetEventHandler()->ProcessEvent(gridEvt
); 
5487        vetoed 
= !gridEvt
.IsAllowed(); 
5489    else if ( type 
== wxEVT_GRID_RANGE_SELECT 
) 
5491        // Right now, it should _never_ end up here! 
5492        wxGridRangeSelectEvent 
gridEvt( GetId(), 
5496                m_selectingBottomRight
, 
5498                mouseEv
.ControlDown(), 
5499                mouseEv
.ShiftDown(), 
5501                mouseEv
.MetaDown() ); 
5503        claimed 
= GetEventHandler()->ProcessEvent(gridEvt
); 
5504        vetoed 
= !gridEvt
.IsAllowed(); 
5508        wxGridEvent 
gridEvt( GetId(), 
5512                mouseEv
.GetX() + GetRowLabelSize(), 
5513                mouseEv
.GetY() + GetColLabelSize(), 
5515                mouseEv
.ControlDown(), 
5516                mouseEv
.ShiftDown(), 
5518                mouseEv
.MetaDown() ); 
5519        claimed 
= GetEventHandler()->ProcessEvent(gridEvt
); 
5520        vetoed 
= !gridEvt
.IsAllowed(); 
5523    // A Veto'd event may not be `claimed' so test this first 
5524    if (vetoed
) return -1; 
5525    return claimed 
? 1 : 0; 
5529 // Generate a grid event of specified type and return the result 
5530 // of ProcessEvent(). 
5532 int wxGrid::SendEvent( const wxEventType type
, 
5538     if ( type 
== wxEVT_GRID_ROW_SIZE 
|| type 
== wxEVT_GRID_COL_SIZE 
) 
5540         int rowOrCol 
= (row 
== -1 ? col 
: row
); 
5542         wxGridSizeEvent 
gridEvt( GetId(), 
5547         claimed 
= GetEventHandler()->ProcessEvent(gridEvt
); 
5548         vetoed  
= !gridEvt
.IsAllowed(); 
5552         wxGridEvent 
gridEvt( GetId(), 
5557         claimed 
= GetEventHandler()->ProcessEvent(gridEvt
); 
5558         vetoed  
= !gridEvt
.IsAllowed(); 
5561     // A Veto'd event may not be `claimed' so test this first 
5562     if (vetoed
) return -1; 
5563     return claimed 
? 1 : 0; 
5567 void wxGrid::OnPaint( wxPaintEvent
& WXUNUSED(event
) ) 
5569     wxPaintDC 
dc(this);  // needed to prevent zillions of paint events on MSW 
5573 void wxGrid::OnSize( wxSizeEvent
& event 
) 
5575     // position the child windows 
5578     // don't call CalcDimensions() from here, the base class handles the size 
5584 void wxGrid::OnKeyDown( wxKeyEvent
& event 
) 
5586     if ( m_inOnKeyDown 
) 
5588         // shouldn't be here - we are going round in circles... 
5590         wxFAIL_MSG( wxT("wxGrid::OnKeyDown called while already active") ); 
5593     m_inOnKeyDown 
= TRUE
; 
5595     // propagate the event up and see if it gets processed 
5597     wxWindow 
*parent 
= GetParent(); 
5598     wxKeyEvent 
keyEvt( event 
); 
5599     keyEvt
.SetEventObject( parent 
); 
5601     if ( !parent
->GetEventHandler()->ProcessEvent( keyEvt 
) ) 
5604         // try local handlers 
5606         switch ( event
.KeyCode() ) 
5609                 if ( event
.ControlDown() ) 
5611                     MoveCursorUpBlock( event
.ShiftDown() ); 
5615                     MoveCursorUp( event
.ShiftDown() ); 
5620                 if ( event
.ControlDown() ) 
5622                     MoveCursorDownBlock( event
.ShiftDown() ); 
5626                     MoveCursorDown( event
.ShiftDown() ); 
5631                 if ( event
.ControlDown() ) 
5633                     MoveCursorLeftBlock( event
.ShiftDown() ); 
5637                     MoveCursorLeft( event
.ShiftDown() ); 
5642                 if ( event
.ControlDown() ) 
5644                     MoveCursorRightBlock( event
.ShiftDown() ); 
5648                     MoveCursorRight( event
.ShiftDown() ); 
5653             case WXK_NUMPAD_ENTER
: 
5654                 if ( event
.ControlDown() ) 
5656                     event
.Skip();  // to let the edit control have the return 
5660                     if ( GetGridCursorRow() < GetNumberRows()-1 ) 
5662                         MoveCursorDown( event
.ShiftDown() ); 
5666                         // at the bottom of a column 
5667                         HideCellEditControl(); 
5668                         SaveEditControlValue(); 
5678                 if (event
.ShiftDown()) 
5680                     if ( GetGridCursorCol() > 0 ) 
5682                         MoveCursorLeft( FALSE 
); 
5687                         HideCellEditControl(); 
5688                         SaveEditControlValue(); 
5693                     if ( GetGridCursorCol() < GetNumberCols()-1 ) 
5695                         MoveCursorRight( FALSE 
); 
5700                         HideCellEditControl(); 
5701                         SaveEditControlValue(); 
5707                 if ( event
.ControlDown() ) 
5709                     MakeCellVisible( 0, 0 ); 
5710                     SetCurrentCell( 0, 0 ); 
5719                 if ( event
.ControlDown() ) 
5721                     MakeCellVisible( m_numRows
-1, m_numCols
-1 ); 
5722                     SetCurrentCell( m_numRows
-1, m_numCols
-1 ); 
5739                 if ( event
.ControlDown() ) 
5741                     m_selection
->ToggleCellSelection( m_currentCellCoords
.GetRow(), 
5742                                                       m_currentCellCoords
.GetCol(), 
5743                                                       event
.ControlDown(), 
5749                 if ( !IsEditable() ) 
5751                     MoveCursorRight( FALSE 
); 
5754                 // Otherwise fall through to default 
5757                 // is it possible to edit the current cell at all? 
5758                 if ( !IsCellEditControlEnabled() && CanEnableCellControl() ) 
5760                     // yes, now check whether the cells editor accepts the key 
5761                     int row 
= m_currentCellCoords
.GetRow(); 
5762                     int col 
= m_currentCellCoords
.GetCol(); 
5763                     wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
5764                     wxGridCellEditor 
*editor 
= attr
->GetEditor(this, row
, col
); 
5766                     // <F2> is special and will always start editing, for 
5767                     // other keys - ask the editor itself 
5768                     if ( (event
.KeyCode() == WXK_F2 
&& !event
.HasModifiers()) 
5769                          || editor
->IsAcceptedKey(event
) ) 
5771                         EnableCellEditControl(); 
5773                         // the editor could be not shown for a variety of 
5774                         // reasons (i.e. blocked by the app or whatever), so 
5775                         // check if it really was created 
5776                         if ( m_cellEditCtrlEnabled 
) 
5778                             editor
->StartingKey(event
); 
5791                     // let others process char events with modifiers or all 
5792                     // char events for readonly cells 
5799     m_inOnKeyDown 
= FALSE
; 
5802 void wxGrid::OnKeyUp( wxKeyEvent
& event 
) 
5804     // try local handlers 
5806     if ( event
.KeyCode() == WXK_SHIFT 
) 
5808         if ( m_selectingTopLeft 
!= wxGridNoCellCoords 
&& 
5809              m_selectingBottomRight 
!= wxGridNoCellCoords 
) 
5810             m_selection
->SelectBlock( m_selectingTopLeft
.GetRow(), 
5811                                       m_selectingTopLeft
.GetCol(), 
5812                                       m_selectingBottomRight
.GetRow(), 
5813                                       m_selectingBottomRight
.GetCol(), 
5814                                       event
.ControlDown(), 
5818         m_selectingTopLeft 
= wxGridNoCellCoords
; 
5819         m_selectingBottomRight 
= wxGridNoCellCoords
; 
5820         m_selectingKeyboard 
= wxGridNoCellCoords
; 
5824 void wxGrid::OnEraseBackground(wxEraseEvent
&) 
5828 void wxGrid::SetCurrentCell( const wxGridCellCoords
& coords 
) 
5830     if ( SendEvent( wxEVT_GRID_SELECT_CELL
, coords
.GetRow(), coords
.GetCol() ) ) 
5832         // the event has been intercepted - do nothing 
5836     wxClientDC 
dc(m_gridWin
); 
5839     if ( m_currentCellCoords 
!= wxGridNoCellCoords 
) 
5841         HideCellEditControl(); 
5842         DisableCellEditControl(); 
5844         if ( IsVisible( m_currentCellCoords
, FALSE 
) ) 
5847             r 
= BlockToDeviceRect(m_currentCellCoords
, coords
); 
5848             if ( !m_gridLinesEnabled 
) 
5856              wxGridCellCoordsArray cells 
= CalcCellsExposed( r 
); 
5858             // Otherwise refresh redraws the highlight! 
5859             m_currentCellCoords 
= coords
; 
5861             DrawGridCellArea(dc
,cells
); 
5862             DrawAllGridLines( dc
, r 
); 
5866     m_currentCellCoords 
= coords
; 
5868     wxGridCellAttr
* attr 
= GetCellAttr(coords
); 
5869     DrawCellHighlight(dc
, attr
); 
5874 void wxGrid::HighlightBlock( int topRow
, int leftCol
, int bottomRow
, int rightCol 
) 
5877     wxGridCellCoords updateTopLeft
, updateBottomRight
; 
5879     if ( m_selection
->GetSelectionMode() == wxGrid::wxGridSelectRows 
) 
5882         rightCol 
= GetNumberCols() - 1; 
5884     else if ( m_selection
->GetSelectionMode() == wxGrid::wxGridSelectColumns 
) 
5887         bottomRow 
= GetNumberRows() - 1; 
5889     if ( topRow 
> bottomRow 
) 
5896     if ( leftCol 
> rightCol 
) 
5903     updateTopLeft 
= wxGridCellCoords( topRow
, leftCol 
); 
5904     updateBottomRight 
= wxGridCellCoords( bottomRow
, rightCol 
); 
5906     if ( m_selectingTopLeft 
!= updateTopLeft 
|| 
5907          m_selectingBottomRight 
!= updateBottomRight 
) 
5909         // Compute two optimal update rectangles: 
5910         // Either one rectangle is a real subset of the 
5911         // other, or they are (almost) disjoint! 
5913         bool    need_refresh
[4]; 
5917         need_refresh
[3] = FALSE
; 
5920         // Store intermediate values 
5921         wxCoord oldLeft   
= m_selectingTopLeft
.GetCol(); 
5922         wxCoord oldTop    
= m_selectingTopLeft
.GetRow(); 
5923         wxCoord oldRight  
= m_selectingBottomRight
.GetCol(); 
5924         wxCoord oldBottom 
= m_selectingBottomRight
.GetRow(); 
5926         // Determine the outer/inner coordinates. 
5927         if (oldLeft 
> leftCol
) 
5933         if (oldTop 
> topRow 
) 
5939         if (oldRight 
< rightCol 
) 
5942             oldRight 
= rightCol
; 
5945         if (oldBottom 
< bottomRow
) 
5948             oldBottom 
= bottomRow
; 
5952         // Now, either the stuff marked old is the outer 
5953         // rectangle or we don't have a situation where one 
5954         // is contained in the other. 
5956         if ( oldLeft 
< leftCol 
) 
5958             need_refresh
[0] = TRUE
; 
5959             rect
[0] = BlockToDeviceRect( wxGridCellCoords ( oldTop
, 
5961                                          wxGridCellCoords ( oldBottom
, 
5965         if ( oldTop  
< topRow 
) 
5967             need_refresh
[1] = TRUE
; 
5968             rect
[1] = BlockToDeviceRect( wxGridCellCoords ( oldTop
, 
5970                                          wxGridCellCoords ( topRow 
- 1, 
5974         if ( oldRight 
> rightCol 
) 
5976             need_refresh
[2] = TRUE
; 
5977             rect
[2] = BlockToDeviceRect( wxGridCellCoords ( oldTop
, 
5979                                          wxGridCellCoords ( oldBottom
, 
5983         if ( oldBottom 
> bottomRow 
) 
5985             need_refresh
[3] = TRUE
; 
5986             rect
[3] = BlockToDeviceRect( wxGridCellCoords ( bottomRow 
+ 1, 
5988                                          wxGridCellCoords ( oldBottom
, 
5994         m_selectingTopLeft 
= updateTopLeft
; 
5995         m_selectingBottomRight 
= updateBottomRight
; 
5997         // various Refresh() calls 
5998         for (i 
= 0; i 
< 4; i
++ ) 
5999             if ( need_refresh
[i
] && rect
[i
] != wxGridNoCellRect 
) 
6000                 m_gridWin
->Refresh( FALSE
, &(rect
[i
]) ); 
6003     // never generate an event as it will be generated from 
6004     // wxGridSelection::SelectBlock! 
6005     // (old comment from when this was the body of SelectBlock) 
6009 // ------ functions to get/send data (see also public functions) 
6012 bool wxGrid::GetModelValues() 
6016         // all we need to do is repaint the grid 
6018         m_gridWin
->Refresh(); 
6026 bool wxGrid::SetModelValues() 
6032         for ( row 
= 0;  row 
< m_numRows
;  row
++ ) 
6034             for ( col 
= 0;  col 
< m_numCols
;  col
++ ) 
6036                 m_table
->SetValue( row
, col
, GetCellValue(row
, col
) ); 
6048 // Note - this function only draws cells that are in the list of 
6049 // exposed cells (usually set from the update region by 
6050 // CalcExposedCells) 
6052 void wxGrid::DrawGridCellArea( wxDC
& dc
, const wxGridCellCoordsArray
& cells 
) 
6054     if ( !m_numRows 
|| !m_numCols 
) return; 
6057     size_t numCells 
= cells
.GetCount(); 
6059     for ( i 
= 0;  i 
< numCells
;  i
++ ) 
6061         DrawCell( dc
, cells
[i
] ); 
6066 void wxGrid::DrawGridSpace( wxDC
& dc 
) 
6069   m_gridWin
->GetClientSize( &cw
, &ch 
); 
6072   CalcUnscrolledPosition( cw
, ch
, &right
, &bottom 
); 
6074   int rightCol 
= m_numCols 
> 0 ? GetColRight(m_numCols 
- 1) : 0; 
6075   int bottomRow 
= m_numRows 
> 0 ? GetRowBottom(m_numRows 
- 1) : 0 ; 
6077   if ( right 
> rightCol 
|| bottom 
> bottomRow 
) 
6080       CalcUnscrolledPosition( 0, 0, &left
, &top 
); 
6082       dc
.SetBrush( wxBrush(GetDefaultCellBackgroundColour(), wxSOLID
) ); 
6083       dc
.SetPen( *wxTRANSPARENT_PEN 
); 
6085       if ( right 
> rightCol 
) 
6087           dc
.DrawRectangle( rightCol
, top
, right 
- rightCol
, ch
); 
6090       if ( bottom 
> bottomRow 
) 
6092           dc
.DrawRectangle( left
, bottomRow
, cw
, bottom 
- bottomRow
); 
6098 void wxGrid::DrawCell( wxDC
& dc
, const wxGridCellCoords
& coords 
) 
6100     int row 
= coords
.GetRow(); 
6101     int col 
= coords
.GetCol(); 
6103     if ( GetColWidth(col
) <= 0 || GetRowHeight(row
) <= 0 ) 
6106     // we draw the cell border ourselves 
6107 #if !WXGRID_DRAW_LINES 
6108     if ( m_gridLinesEnabled 
) 
6109         DrawCellBorder( dc
, coords 
); 
6112     wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
6114     bool isCurrent 
= coords 
== m_currentCellCoords
; 
6116     wxRect rect 
= CellToRect( row
, col 
); 
6118     // if the editor is shown, we should use it and not the renderer 
6119     // Note: However, only if it is really _shown_, i.e. not hidden! 
6120     if ( isCurrent 
&& IsCellEditControlShown() ) 
6122         wxGridCellEditor 
*editor 
= attr
->GetEditor(this, row
, col
); 
6123         editor
->PaintBackground(rect
, attr
); 
6128         // but all the rest is drawn by the cell renderer and hence may be 
6130         wxGridCellRenderer 
*renderer 
= attr
->GetRenderer(this, row
, col
); 
6131         renderer
->Draw(*this, *attr
, dc
, rect
, row
, col
, IsInSelection(coords
)); 
6138 void wxGrid::DrawCellHighlight( wxDC
& dc
, const wxGridCellAttr 
*attr 
) 
6140     int row 
= m_currentCellCoords
.GetRow(); 
6141     int col 
= m_currentCellCoords
.GetCol(); 
6143     if ( GetColWidth(col
) <= 0 || GetRowHeight(row
) <= 0 ) 
6146     wxRect rect 
= CellToRect(row
, col
); 
6148     // hmmm... what could we do here to show that the cell is disabled? 
6149     // for now, I just draw a thinner border than for the other ones, but 
6150     // it doesn't look really good 
6152     int penWidth 
= attr
->IsReadOnly() ? m_cellHighlightROPenWidth 
: m_cellHighlightPenWidth
; 
6156         // The center of th drawn line is where the position/width/height of 
6157         // the rectangle is actually at, (on wxMSW atr least,) so we will 
6158         // reduce the size of the rectangle to compensate for the thickness of 
6159         // the line.  If this is too strange on non wxMSW platforms then 
6160         // please #ifdef this appropriately. 
6161         rect
.x 
+= penWidth
/2; 
6162         rect
.y 
+= penWidth
/2; 
6163         rect
.width 
-= penWidth
-1; 
6164         rect
.height 
-= penWidth
-1; 
6167         // Now draw the rectangle 
6168         dc
.SetPen(wxPen(m_cellHighlightColour
, penWidth
, wxSOLID
)); 
6169         dc
.SetBrush(*wxTRANSPARENT_BRUSH
); 
6170         dc
.DrawRectangle(rect
); 
6174         // VZ: my experiments with 3d borders... 
6176         // how to properly set colours for arbitrary bg? 
6177         wxCoord x1 
= rect
.x
, 
6179                 x2 
= rect
.x 
+ rect
.width 
-1, 
6180                 y2 
= rect
.y 
+ rect
.height 
-1; 
6182         dc
.SetPen(*wxWHITE_PEN
); 
6183         dc
.DrawLine(x1
, y1
, x2
, y1
); 
6184         dc
.DrawLine(x1
, y1
, x1
, y2
); 
6186         dc
.DrawLine(x1 
+ 1, y2 
- 1, x2 
- 1, y2 
- 1); 
6187         dc
.DrawLine(x2 
- 1, y1 
+ 1, x2 
- 1, y2 
); 
6189         dc
.SetPen(*wxBLACK_PEN
); 
6190         dc
.DrawLine(x1
, y2
, x2
, y2
); 
6191         dc
.DrawLine(x2
, y1
, x2
, y2
+1); 
6196 void wxGrid::DrawCellBorder( wxDC
& dc
, const wxGridCellCoords
& coords 
) 
6198     int row 
= coords
.GetRow(); 
6199     int col 
= coords
.GetCol(); 
6200     if ( GetColWidth(col
) <= 0 || GetRowHeight(row
) <= 0 ) 
6203     dc
.SetPen( wxPen(GetGridLineColour(), 1, wxSOLID
) ); 
6205     // right hand border 
6207     dc
.DrawLine( GetColRight(col
), GetRowTop(row
), 
6208                  GetColRight(col
), GetRowBottom(row
) ); 
6212     dc
.DrawLine( GetColLeft(col
), GetRowBottom(row
), 
6213                  GetColRight(col
), GetRowBottom(row
) ); 
6216 void wxGrid::DrawHighlight(wxDC
& dc
,const  wxGridCellCoordsArray
& cells
) 
6218     // This if block was previously in wxGrid::OnPaint but that doesn't 
6219     // seem to get called under wxGTK - MB 
6221     if ( m_currentCellCoords 
== wxGridNoCellCoords  
&& 
6222          m_numRows 
&& m_numCols 
) 
6224         m_currentCellCoords
.Set(0, 0); 
6227     if ( IsCellEditControlShown() ) 
6229         // don't show highlight when the edit control is shown 
6233     // if the active cell was repainted, repaint its highlight too because it 
6234     // might have been damaged by the grid lines 
6235     size_t count 
= cells
.GetCount(); 
6236     for ( size_t n 
= 0; n 
< count
; n
++ ) 
6238         if ( cells
[n
] == m_currentCellCoords 
) 
6240             wxGridCellAttr
* attr 
= GetCellAttr(m_currentCellCoords
); 
6241             DrawCellHighlight(dc
, attr
); 
6249 // TODO: remove this ??? 
6250 // This is used to redraw all grid lines e.g. when the grid line colour 
6253 void wxGrid::DrawAllGridLines( wxDC
& dc
, const wxRegion 
& WXUNUSED(reg
) ) 
6255     if ( !m_gridLinesEnabled 
|| 
6257          !m_numCols 
) return; 
6259     int top
, bottom
, left
, right
; 
6261 #if 0  //#ifndef __WXGTK__ 
6265       m_gridWin
->GetClientSize(&cw
, &ch
); 
6267       // virtual coords of visible area 
6269       CalcUnscrolledPosition( 0, 0, &left
, &top 
); 
6270       CalcUnscrolledPosition( cw
, ch
, &right
, &bottom 
); 
6275       reg
.GetBox(x
, y
, w
, h
); 
6276       CalcUnscrolledPosition( x
, y
, &left
, &top 
); 
6277       CalcUnscrolledPosition( x 
+ w
, y 
+ h
, &right
, &bottom 
); 
6281       m_gridWin
->GetClientSize(&cw
, &ch
); 
6282       CalcUnscrolledPosition( 0, 0, &left
, &top 
); 
6283       CalcUnscrolledPosition( cw
, ch
, &right
, &bottom 
); 
6286     // avoid drawing grid lines past the last row and col 
6288     right 
= wxMin( right
, GetColRight(m_numCols 
- 1) ); 
6289     bottom 
= wxMin( bottom
, GetRowBottom(m_numRows 
- 1) ); 
6291     dc
.SetPen( wxPen(GetGridLineColour(), 1, wxSOLID
) ); 
6293     // horizontal grid lines 
6296     for ( i 
= YToRow(top
); i 
< m_numRows
; i
++ ) 
6298         int bot 
= GetRowBottom(i
) - 1; 
6307             dc
.DrawLine( left
, bot
, right
, bot 
); 
6312     // vertical grid lines 
6314     for ( i 
= XToCol(left
); i 
< m_numCols
; i
++ ) 
6316         int colRight 
= GetColRight(i
) - 1; 
6317         if ( colRight 
> right 
) 
6322         if ( colRight 
>= left 
) 
6324             dc
.DrawLine( colRight
, top
, colRight
, bottom 
); 
6330 void wxGrid::DrawRowLabels( wxDC
& dc 
,const wxArrayInt
& rows
) 
6332     if ( !m_numRows 
) return; 
6335     size_t numLabels 
= rows
.GetCount(); 
6337     for ( i 
= 0;  i 
< numLabels
;  i
++ ) 
6339         DrawRowLabel( dc
, rows
[i
] ); 
6344 void wxGrid::DrawRowLabel( wxDC
& dc
, int row 
) 
6346     if ( GetRowHeight(row
) <= 0 ) 
6349     int rowTop 
= GetRowTop(row
), 
6350         rowBottom 
= GetRowBottom(row
) - 1; 
6352     dc
.SetPen( *wxBLACK_PEN 
); 
6353     dc
.DrawLine( m_rowLabelWidth
-1, rowTop
, 
6354                  m_rowLabelWidth
-1, rowBottom 
); 
6356     dc
.DrawLine( 0, rowBottom
, m_rowLabelWidth
-1, rowBottom 
); 
6358     dc
.SetPen( *wxWHITE_PEN 
); 
6359     dc
.DrawLine( 0, rowTop
, 0, rowBottom 
); 
6360     dc
.DrawLine( 0, rowTop
, m_rowLabelWidth
-1, rowTop 
); 
6362     dc
.SetBackgroundMode( wxTRANSPARENT 
); 
6363     dc
.SetTextForeground( GetLabelTextColour() ); 
6364     dc
.SetFont( GetLabelFont() ); 
6367     GetRowLabelAlignment( &hAlign
, &vAlign 
); 
6371     rect
.SetY( GetRowTop(row
) + 2 ); 
6372     rect
.SetWidth( m_rowLabelWidth 
- 4 ); 
6373     rect
.SetHeight( GetRowHeight(row
) - 4 ); 
6374     DrawTextRectangle( dc
, GetRowLabelValue( row 
), rect
, hAlign
, vAlign 
); 
6378 void wxGrid::DrawColLabels( wxDC
& dc
,const wxArrayInt
& cols 
) 
6380     if ( !m_numCols 
) return; 
6383     size_t numLabels 
= cols
.GetCount(); 
6385     for ( i 
= 0;  i 
< numLabels
;  i
++ ) 
6387         DrawColLabel( dc
, cols
[i
] ); 
6392 void wxGrid::DrawColLabel( wxDC
& dc
, int col 
) 
6394     if ( GetColWidth(col
) <= 0 ) 
6397     int colLeft 
= GetColLeft(col
), 
6398         colRight 
= GetColRight(col
) - 1; 
6400     dc
.SetPen( *wxBLACK_PEN 
); 
6401     dc
.DrawLine( colRight
, 0, 
6402                  colRight
, m_colLabelHeight
-1 ); 
6404     dc
.DrawLine( colLeft
, m_colLabelHeight
-1, 
6405                  colRight
, m_colLabelHeight
-1 ); 
6407     dc
.SetPen( *wxWHITE_PEN 
); 
6408     dc
.DrawLine( colLeft
, 0, colLeft
, m_colLabelHeight
-1 ); 
6409     dc
.DrawLine( colLeft
, 0, colRight
, 0 ); 
6411     dc
.SetBackgroundMode( wxTRANSPARENT 
); 
6412     dc
.SetTextForeground( GetLabelTextColour() ); 
6413     dc
.SetFont( GetLabelFont() ); 
6415     dc
.SetBackgroundMode( wxTRANSPARENT 
); 
6416     dc
.SetTextForeground( GetLabelTextColour() ); 
6417     dc
.SetFont( GetLabelFont() ); 
6420     GetColLabelAlignment( &hAlign
, &vAlign 
); 
6423     rect
.SetX( colLeft 
+ 2 ); 
6425     rect
.SetWidth( GetColWidth(col
) - 4 ); 
6426     rect
.SetHeight( m_colLabelHeight 
- 4 ); 
6427     DrawTextRectangle( dc
, GetColLabelValue( col 
), rect
, hAlign
, vAlign 
); 
6430 void wxGrid::DrawTextRectangle( wxDC
& dc
, 
6431                                 const wxString
& value
, 
6436     wxArrayString lines
; 
6438     dc
.SetClippingRegion( rect 
); 
6439     StringToLines( value
, lines 
); 
6442     //Forward to new API. 
6443     DrawTextRectangle(  dc
, 
6451 void wxGrid::DrawTextRectangle( wxDC
& dc
, 
6452                                 const wxArrayString
& lines
, 
6457     long textWidth
, textHeight
; 
6458     long lineWidth
, lineHeight
; 
6460     if ( lines
.GetCount() ) 
6462         GetTextBoxSize( dc
, lines
, &textWidth
, &textHeight 
); 
6463         dc
.GetTextExtent( lines
[0], &lineWidth
, &lineHeight 
); 
6466         switch ( horizAlign 
) 
6469                 x 
= rect
.x 
+ (rect
.width 
- textWidth 
- 1); 
6472             case wxALIGN_CENTRE
: 
6473                 x 
= rect
.x 
+ ((rect
.width 
- textWidth
)/2); 
6482         switch ( vertAlign 
) 
6484             case wxALIGN_BOTTOM
: 
6485                 y 
= rect
.y 
+ (rect
.height 
- textHeight 
- 1); 
6488             case wxALIGN_CENTRE
: 
6489                 y 
= rect
.y 
+ ((rect
.height 
- textHeight
)/2); 
6498         for ( size_t i 
= 0;  i 
< lines
.GetCount();  i
++ ) 
6500             dc
.DrawText( lines
[i
], (int)x
, (int)y 
); 
6505     dc
.DestroyClippingRegion(); 
6509 // Split multi line text up into an array of strings.  Any existing 
6510 // contents of the string array are preserved. 
6512 void wxGrid::StringToLines( const wxString
& value
, wxArrayString
& lines 
) 
6516     wxString eol 
= wxTextFile::GetEOL( wxTextFileType_Unix 
); 
6517     wxString tVal 
= wxTextFile::Translate( value
, wxTextFileType_Unix 
); 
6519     while ( startPos 
< (int)tVal
.Length() ) 
6521         pos 
= tVal
.Mid(startPos
).Find( eol 
); 
6526         else if ( pos 
== 0 ) 
6528             lines
.Add( wxEmptyString 
); 
6532             lines
.Add( value
.Mid(startPos
, pos
) ); 
6536     if ( startPos 
< (int)value
.Length() ) 
6538         lines
.Add( value
.Mid( startPos 
) ); 
6543 void wxGrid::GetTextBoxSize( wxDC
& dc
, 
6544                              const wxArrayString
& lines
, 
6545                              long *width
, long *height 
) 
6552     for ( i 
= 0;  i 
< lines
.GetCount();  i
++ ) 
6554         dc
.GetTextExtent( lines
[i
], &lineW
, &lineH 
); 
6555         w 
= wxMax( w
, lineW 
); 
6564 // ------ Batch processing. 
6566 void wxGrid::EndBatch() 
6568     if ( m_batchCount 
> 0 ) 
6571         if ( !m_batchCount 
) 
6574             m_rowLabelWin
->Refresh(); 
6575             m_colLabelWin
->Refresh(); 
6576             m_cornerLabelWin
->Refresh(); 
6577             m_gridWin
->Refresh(); 
6582 // Use this, rather than wxWindow::Refresh(), to force an immediate 
6583 // repainting of the grid. Has no effect if you are already inside a 
6584 // BeginBatch / EndBatch block. 
6586 void wxGrid::ForceRefresh() 
6594 // ------ Edit control functions 
6598 void wxGrid::EnableEditing( bool edit 
) 
6600     // TODO: improve this ? 
6602     if ( edit 
!= m_editable 
) 
6604         if(!edit
) EnableCellEditControl(edit
); 
6610 void wxGrid::EnableCellEditControl( bool enable 
) 
6615     if ( m_currentCellCoords 
== wxGridNoCellCoords 
) 
6616         SetCurrentCell( 0, 0 ); 
6618     if ( enable 
!= m_cellEditCtrlEnabled 
) 
6622             if (SendEvent( wxEVT_GRID_EDITOR_SHOWN
) <0) 
6625             // this should be checked by the caller! 
6626             wxASSERT_MSG( CanEnableCellControl(), 
6627                           _T("can't enable editing for this cell!") ); 
6629             // do it before ShowCellEditControl() 
6630             m_cellEditCtrlEnabled 
= enable
; 
6632             ShowCellEditControl(); 
6636             //FIXME:add veto support 
6637             SendEvent( wxEVT_GRID_EDITOR_HIDDEN
); 
6639             HideCellEditControl(); 
6640             SaveEditControlValue(); 
6642             // do it after HideCellEditControl() 
6643             m_cellEditCtrlEnabled 
= enable
; 
6648 bool wxGrid::IsCurrentCellReadOnly() const 
6651     wxGridCellAttr
* attr 
= ((wxGrid 
*)this)->GetCellAttr(m_currentCellCoords
); 
6652     bool readonly 
= attr
->IsReadOnly(); 
6658 bool wxGrid::CanEnableCellControl() const 
6660     return m_editable 
&& !IsCurrentCellReadOnly(); 
6663 bool wxGrid::IsCellEditControlEnabled() const 
6665     // the cell edit control might be disable for all cells or just for the 
6666     // current one if it's read only 
6667     return m_cellEditCtrlEnabled 
? !IsCurrentCellReadOnly() : FALSE
; 
6670 bool wxGrid::IsCellEditControlShown() const 
6672     bool isShown 
= FALSE
; 
6674     if ( m_cellEditCtrlEnabled 
) 
6676         int row 
= m_currentCellCoords
.GetRow(); 
6677         int col 
= m_currentCellCoords
.GetCol(); 
6678         wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
6679         wxGridCellEditor
* editor 
= attr
->GetEditor((wxGrid
*) this, row
, col
); 
6684             if ( editor
->IsCreated() ) 
6686                 isShown 
= editor
->GetControl()->IsShown(); 
6696 void wxGrid::ShowCellEditControl() 
6698     if ( IsCellEditControlEnabled() ) 
6700         if ( !IsVisible( m_currentCellCoords 
) ) 
6702             m_cellEditCtrlEnabled 
= FALSE
; 
6707             wxRect rect 
= CellToRect( m_currentCellCoords 
); 
6708             int row 
= m_currentCellCoords
.GetRow(); 
6709             int col 
= m_currentCellCoords
.GetCol(); 
6711             // convert to scrolled coords 
6713             CalcScrolledPosition( rect
.x
, rect
.y
, &rect
.x
, &rect
.y 
); 
6715             // done in PaintBackground() 
6717             // erase the highlight and the cell contents because the editor 
6718             // might not cover the entire cell 
6719             wxClientDC 
dc( m_gridWin 
); 
6721             dc
.SetBrush(*wxLIGHT_GREY_BRUSH
); //wxBrush(attr->GetBackgroundColour(), wxSOLID)); 
6722             dc
.SetPen(*wxTRANSPARENT_PEN
); 
6723             dc
.DrawRectangle(rect
); 
6726             // cell is shifted by one pixel 
6730             wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
6731             wxGridCellEditor
* editor 
= attr
->GetEditor(this, row
, col
); 
6732             if ( !editor
->IsCreated() ) 
6734                 editor
->Create(m_gridWin
, -1, 
6735                                new wxGridCellEditorEvtHandler(this, editor
)); 
6737                 wxGridEditorCreatedEvent 
evt(GetId(), 
6738                                              wxEVT_GRID_EDITOR_CREATED
, 
6742                                              editor
->GetControl()); 
6743                 GetEventHandler()->ProcessEvent(evt
); 
6746             editor
->Show( TRUE
, attr 
); 
6748             editor
->SetSize( rect 
); 
6750             editor
->BeginEdit(row
, col
, this); 
6759 void wxGrid::HideCellEditControl() 
6761     if ( IsCellEditControlEnabled() ) 
6763         int row 
= m_currentCellCoords
.GetRow(); 
6764         int col 
= m_currentCellCoords
.GetCol(); 
6766         wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
6767         wxGridCellEditor 
*editor 
= attr
->GetEditor(this, row
, col
); 
6768         editor
->Show( FALSE 
); 
6771         m_gridWin
->SetFocus(); 
6772         wxRect 
rect( CellToRect( row
, col 
) ); 
6773         m_gridWin
->Refresh( FALSE
, &rect 
); 
6778 void wxGrid::SaveEditControlValue() 
6780     if ( IsCellEditControlEnabled() ) 
6782         int row 
= m_currentCellCoords
.GetRow(); 
6783         int col 
= m_currentCellCoords
.GetCol(); 
6785         wxString oldval 
= GetCellValue(row
,col
); 
6787         wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
6788         wxGridCellEditor
* editor 
= attr
->GetEditor(this, row
, col
); 
6789         bool changed 
= editor
->EndEdit(row
, col
, this); 
6796             if ( SendEvent( wxEVT_GRID_CELL_CHANGE
, 
6797                        m_currentCellCoords
.GetRow(), 
6798                        m_currentCellCoords
.GetCol() ) < 0 ) { 
6800                 // Event has been vetoed, set the data back. 
6801                 SetCellValue(row
,col
,oldval
); 
6809 // ------ Grid location functions 
6810 //  Note that all of these functions work with the logical coordinates of 
6811 //  grid cells and labels so you will need to convert from device 
6812 //  coordinates for mouse events etc. 
6815 void wxGrid::XYToCell( int x
, int y
, wxGridCellCoords
& coords 
) 
6817     int row 
= YToRow(y
); 
6818     int col 
= XToCol(x
); 
6820     if ( row 
== -1  ||  col 
== -1 ) 
6822         coords 
= wxGridNoCellCoords
; 
6826         coords
.Set( row
, col 
); 
6831 // Internal Helper function for computing row or column from some 
6832 // (unscrolled) coordinate value, using either 
6833 // m_defaultRowHeight/m_defaultColWidth or binary search on array  
6834 // of m_rowBottoms/m_ColRights to speed up the search! 
6836 static int CoordToRowOrCol(int coord
, int defaultDist
, int minDist
, 
6837                            wxArrayInt BorderArray
) 
6841     unsigned int i_max 
= coord 
/ defaultDist
, 
6843     if (BorderArray
.IsEmpty()) 
6848     if ( i_max 
>= BorderArray
.GetCount()) 
6849         i_max 
= BorderArray
.GetCount() - 1; 
6852         if ( coord 
>= BorderArray
[i_max
]) 
6855             i_max 
= coord 
/ minDist
; 
6857         if ( i_max 
>= BorderArray
.GetCount()) 
6858             i_max 
= BorderArray
.GetCount() - 1; 
6860     if ( coord 
> BorderArray
[i_max
])     
6863     while ( i_max 
- i_min 
> 1 ) 
6865         wxCHECK_MSG(BorderArray
[i_min
] <= coord 
&& coord 
< BorderArray
[i_max
], 
6866                     -1, _T("wxGrid: internal error in CoordToRowOrCol")); 
6867         if (coord 
>=  BorderArray
[ i_max 
- 1]) 
6873         int median 
= i_min 
+ (i_max 
- i_min 
+ 1) / 2; 
6874         if (coord 
< BorderArray
[median
]) 
6882 int wxGrid::YToRow( int y 
) 
6884     return CoordToRowOrCol(y
, m_defaultRowHeight
, 
6885                            WXGRID_MIN_ROW_HEIGHT
, m_rowBottoms
); 
6889 int wxGrid::XToCol( int x 
) 
6891     return CoordToRowOrCol(x
, m_defaultColWidth
, 
6892                            WXGRID_MIN_COL_WIDTH
, m_colRights
); 
6896 // return the row number that that the y coord is near the edge of, or 
6897 // -1 if not near an edge 
6899 int wxGrid::YToEdgeOfRow( int y 
) 
6903     for ( i 
= YToRow( y 
) - 1;  i 
< m_numRows
;  i
++ ) 
6905         if ( GetRowHeight(i
) > WXGRID_LABEL_EDGE_ZONE 
) 
6907             d 
= abs( y 
- GetRowBottom(i
) ); 
6908             if ( d 
< WXGRID_LABEL_EDGE_ZONE 
) 
6917 // return the col number that that the x coord is near the edge of, or 
6918 // -1 if not near an edge 
6920 int wxGrid::XToEdgeOfCol( int x 
) 
6924     for (i 
= XToCol( x 
) - 1;  i 
< m_numCols
;  i
++ ) 
6926         if ( GetColWidth(i
) > WXGRID_LABEL_EDGE_ZONE 
) 
6928             d 
= abs( x 
- GetColRight(i
) ); 
6929             if ( d 
< WXGRID_LABEL_EDGE_ZONE 
) 
6938 wxRect 
wxGrid::CellToRect( int row
, int col 
) 
6940     wxRect 
rect( -1, -1, -1, -1 ); 
6942     if ( row 
>= 0  &&  row 
< m_numRows  
&& 
6943          col 
>= 0  &&  col 
< m_numCols 
) 
6945         rect
.x 
= GetColLeft(col
); 
6946         rect
.y 
= GetRowTop(row
); 
6947         rect
.width 
= GetColWidth(col
); 
6948         rect
.height 
= GetRowHeight(row
); 
6951     // if grid lines are enabled, then the area of the cell is a bit smaller 
6952     if (m_gridLinesEnabled
) { 
6960 bool wxGrid::IsVisible( int row
, int col
, bool wholeCellVisible 
) 
6962     // get the cell rectangle in logical coords 
6964     wxRect 
r( CellToRect( row
, col 
) ); 
6966     // convert to device coords 
6968     int left
, top
, right
, bottom
; 
6969     CalcScrolledPosition( r
.GetLeft(), r
.GetTop(), &left
, &top 
); 
6970     CalcScrolledPosition( r
.GetRight(), r
.GetBottom(), &right
, &bottom 
); 
6972     // check against the client area of the grid window 
6975     m_gridWin
->GetClientSize( &cw
, &ch 
); 
6977     if ( wholeCellVisible 
) 
6979         // is the cell wholly visible ? 
6981         return ( left 
>= 0  &&  right 
<= cw  
&& 
6982                  top 
>= 0  &&  bottom 
<= ch 
); 
6986         // is the cell partly visible ? 
6988         return ( ((left 
>=0 && left 
< cw
) || (right 
> 0 && right 
<= cw
))  && 
6989                  ((top 
>=0 && top 
< ch
) || (bottom 
> 0 && bottom 
<= ch
)) ); 
6994 // make the specified cell location visible by doing a minimal amount 
6997 void wxGrid::MakeCellVisible( int row
, int col 
) 
7001     int xpos 
= -1, ypos 
= -1; 
7003     if ( row 
>= 0  &&  row 
< m_numRows  
&& 
7004          col 
>= 0  &&  col 
< m_numCols 
) 
7006         // get the cell rectangle in logical coords 
7008         wxRect 
r( CellToRect( row
, col 
) ); 
7010         // convert to device coords 
7012         int left
, top
, right
, bottom
; 
7013         CalcScrolledPosition( r
.GetLeft(), r
.GetTop(), &left
, &top 
); 
7014         CalcScrolledPosition( r
.GetRight(), r
.GetBottom(), &right
, &bottom 
); 
7017         m_gridWin
->GetClientSize( &cw
, &ch 
); 
7023         else if ( bottom 
> ch 
) 
7025             int h 
= r
.GetHeight(); 
7027             for ( i 
= row
-1;  i 
>= 0;  i
-- ) 
7029                 int rowHeight 
= GetRowHeight(i
); 
7030                 if ( h 
+ rowHeight 
> ch 
) 
7037             // we divide it later by GRID_SCROLL_LINE, make sure that we don't 
7038             // have rounding errors (this is important, because if we do, we 
7039             // might not scroll at all and some cells won't be redrawn) 
7041             // Sometimes GRID_SCROLL_LINE/2 is not enough, so just add a full 
7043             ypos 
+= GRID_SCROLL_LINE_Y
; 
7050         else if ( right 
> cw 
) 
7052             int w 
= r
.GetWidth(); 
7054             for ( i 
= col
-1;  i 
>= 0;  i
-- ) 
7056                 int colWidth 
= GetColWidth(i
); 
7057                 if ( w 
+ colWidth 
> cw 
) 
7064             // see comment for ypos above 
7065             xpos 
+= GRID_SCROLL_LINE_X
; 
7068         if ( xpos 
!= -1  ||  ypos 
!= -1 ) 
7071                 xpos 
/= GRID_SCROLL_LINE_X
; 
7073                 ypos 
/= GRID_SCROLL_LINE_Y
; 
7074             Scroll( xpos
, ypos 
); 
7082 // ------ Grid cursor movement functions 
7085 bool wxGrid::MoveCursorUp( bool expandSelection 
) 
7087     if ( m_currentCellCoords 
!= wxGridNoCellCoords  
&& 
7088          m_currentCellCoords
.GetRow() >= 0 ) 
7090         if ( expandSelection
) 
7092             if ( m_selectingKeyboard 
== wxGridNoCellCoords 
) 
7093                 m_selectingKeyboard 
= m_currentCellCoords
; 
7094             if ( m_selectingKeyboard
.GetRow() > 0 ) 
7096                 m_selectingKeyboard
.SetRow( m_selectingKeyboard
.GetRow() - 1 ); 
7097                 MakeCellVisible( m_selectingKeyboard
.GetRow(), 
7098                                  m_selectingKeyboard
.GetCol() ); 
7099                 HighlightBlock( m_currentCellCoords
, m_selectingKeyboard 
); 
7102         else if ( m_currentCellCoords
.GetRow() > 0 ) 
7105             MakeCellVisible( m_currentCellCoords
.GetRow() - 1, 
7106                              m_currentCellCoords
.GetCol() ); 
7107             SetCurrentCell( m_currentCellCoords
.GetRow() - 1, 
7108                             m_currentCellCoords
.GetCol() ); 
7119 bool wxGrid::MoveCursorDown( bool expandSelection 
) 
7121     if ( m_currentCellCoords 
!= wxGridNoCellCoords  
&& 
7122          m_currentCellCoords
.GetRow() < m_numRows 
) 
7124         if ( expandSelection 
) 
7126             if ( m_selectingKeyboard 
== wxGridNoCellCoords 
) 
7127                 m_selectingKeyboard 
= m_currentCellCoords
; 
7128             if ( m_selectingKeyboard
.GetRow() < m_numRows
-1 ) 
7130                 m_selectingKeyboard
.SetRow( m_selectingKeyboard
.GetRow() + 1 ); 
7131                 MakeCellVisible( m_selectingKeyboard
.GetRow(), 
7132                         m_selectingKeyboard
.GetCol() ); 
7133                 HighlightBlock( m_currentCellCoords
, m_selectingKeyboard 
); 
7136         else if ( m_currentCellCoords
.GetRow() < m_numRows 
- 1 ) 
7139             MakeCellVisible( m_currentCellCoords
.GetRow() + 1, 
7140                              m_currentCellCoords
.GetCol() ); 
7141             SetCurrentCell( m_currentCellCoords
.GetRow() + 1, 
7142                             m_currentCellCoords
.GetCol() ); 
7153 bool wxGrid::MoveCursorLeft( bool expandSelection 
) 
7155     if ( m_currentCellCoords 
!= wxGridNoCellCoords  
&& 
7156          m_currentCellCoords
.GetCol() >= 0 ) 
7158         if ( expandSelection 
) 
7160             if ( m_selectingKeyboard 
== wxGridNoCellCoords 
) 
7161                 m_selectingKeyboard 
= m_currentCellCoords
; 
7162             if ( m_selectingKeyboard
.GetCol() > 0 ) 
7164                 m_selectingKeyboard
.SetCol( m_selectingKeyboard
.GetCol() - 1 ); 
7165                 MakeCellVisible( m_selectingKeyboard
.GetRow(), 
7166                         m_selectingKeyboard
.GetCol() ); 
7167                 HighlightBlock( m_currentCellCoords
, m_selectingKeyboard 
); 
7170         else if ( m_currentCellCoords
.GetCol() > 0 ) 
7173             MakeCellVisible( m_currentCellCoords
.GetRow(), 
7174                              m_currentCellCoords
.GetCol() - 1 ); 
7175             SetCurrentCell( m_currentCellCoords
.GetRow(), 
7176                             m_currentCellCoords
.GetCol() - 1 ); 
7187 bool wxGrid::MoveCursorRight( bool expandSelection 
) 
7189     if ( m_currentCellCoords 
!= wxGridNoCellCoords  
&& 
7190          m_currentCellCoords
.GetCol() < m_numCols 
) 
7192         if ( expandSelection 
) 
7194             if ( m_selectingKeyboard 
== wxGridNoCellCoords 
) 
7195                 m_selectingKeyboard 
= m_currentCellCoords
; 
7196             if ( m_selectingKeyboard
.GetCol() < m_numCols 
- 1 ) 
7198                 m_selectingKeyboard
.SetCol( m_selectingKeyboard
.GetCol() + 1 ); 
7199                 MakeCellVisible( m_selectingKeyboard
.GetRow(), 
7200                         m_selectingKeyboard
.GetCol() ); 
7201                 HighlightBlock( m_currentCellCoords
, m_selectingKeyboard 
); 
7204         else if ( m_currentCellCoords
.GetCol() < m_numCols 
- 1 ) 
7207             MakeCellVisible( m_currentCellCoords
.GetRow(), 
7208                              m_currentCellCoords
.GetCol() + 1 ); 
7209             SetCurrentCell( m_currentCellCoords
.GetRow(), 
7210                             m_currentCellCoords
.GetCol() + 1 ); 
7221 bool wxGrid::MovePageUp() 
7223     if ( m_currentCellCoords 
== wxGridNoCellCoords 
) return FALSE
; 
7225     int row 
= m_currentCellCoords
.GetRow(); 
7229         m_gridWin
->GetClientSize( &cw
, &ch 
); 
7231         int y 
= GetRowTop(row
); 
7232         int newRow 
= YToRow( y 
- ch 
+ 1 ); 
7237         else if ( newRow 
== row 
) 
7242         MakeCellVisible( newRow
, m_currentCellCoords
.GetCol() ); 
7243         SetCurrentCell( newRow
, m_currentCellCoords
.GetCol() ); 
7251 bool wxGrid::MovePageDown() 
7253     if ( m_currentCellCoords 
== wxGridNoCellCoords 
) return FALSE
; 
7255     int row 
= m_currentCellCoords
.GetRow(); 
7256     if ( row 
< m_numRows 
) 
7259         m_gridWin
->GetClientSize( &cw
, &ch 
); 
7261         int y 
= GetRowTop(row
); 
7262         int newRow 
= YToRow( y 
+ ch 
); 
7265             newRow 
= m_numRows 
- 1; 
7267         else if ( newRow 
== row 
) 
7272         MakeCellVisible( newRow
, m_currentCellCoords
.GetCol() ); 
7273         SetCurrentCell( newRow
, m_currentCellCoords
.GetCol() ); 
7281 bool wxGrid::MoveCursorUpBlock( bool expandSelection 
) 
7284          m_currentCellCoords 
!= wxGridNoCellCoords  
&& 
7285          m_currentCellCoords
.GetRow() > 0 ) 
7287         int row 
= m_currentCellCoords
.GetRow(); 
7288         int col 
= m_currentCellCoords
.GetCol(); 
7290         if ( m_table
->IsEmptyCell(row
, col
) ) 
7292             // starting in an empty cell: find the next block of 
7298                 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break; 
7301         else if ( m_table
->IsEmptyCell(row
-1, col
) ) 
7303             // starting at the top of a block: find the next block 
7309                 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break; 
7314             // starting within a block: find the top of the block 
7319                 if ( m_table
->IsEmptyCell(row
, col
) ) 
7327         MakeCellVisible( row
, col 
); 
7328         if ( expandSelection 
) 
7330             m_selectingKeyboard 
= wxGridCellCoords( row
, col 
); 
7331             HighlightBlock( m_currentCellCoords
, m_selectingKeyboard 
); 
7336             SetCurrentCell( row
, col 
); 
7344 bool wxGrid::MoveCursorDownBlock( bool expandSelection 
) 
7347          m_currentCellCoords 
!= wxGridNoCellCoords  
&& 
7348          m_currentCellCoords
.GetRow() < m_numRows
-1 ) 
7350         int row 
= m_currentCellCoords
.GetRow(); 
7351         int col 
= m_currentCellCoords
.GetCol(); 
7353         if ( m_table
->IsEmptyCell(row
, col
) ) 
7355             // starting in an empty cell: find the next block of 
7358             while ( row 
< m_numRows
-1 ) 
7361                 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break; 
7364         else if ( m_table
->IsEmptyCell(row
+1, col
) ) 
7366             // starting at the bottom of a block: find the next block 
7369             while ( row 
< m_numRows
-1 ) 
7372                 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break; 
7377             // starting within a block: find the bottom of the block 
7379             while ( row 
< m_numRows
-1 ) 
7382                 if ( m_table
->IsEmptyCell(row
, col
) ) 
7390         MakeCellVisible( row
, col 
); 
7391         if ( expandSelection 
) 
7393             m_selectingKeyboard 
= wxGridCellCoords( row
, col 
); 
7394             HighlightBlock( m_currentCellCoords
, m_selectingKeyboard 
); 
7399             SetCurrentCell( row
, col 
); 
7408 bool wxGrid::MoveCursorLeftBlock( bool expandSelection 
) 
7411          m_currentCellCoords 
!= wxGridNoCellCoords  
&& 
7412          m_currentCellCoords
.GetCol() > 0 ) 
7414         int row 
= m_currentCellCoords
.GetRow(); 
7415         int col 
= m_currentCellCoords
.GetCol(); 
7417         if ( m_table
->IsEmptyCell(row
, col
) ) 
7419             // starting in an empty cell: find the next block of 
7425                 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break; 
7428         else if ( m_table
->IsEmptyCell(row
, col
-1) ) 
7430             // starting at the left of a block: find the next block 
7436                 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break; 
7441             // starting within a block: find the left of the block 
7446                 if ( m_table
->IsEmptyCell(row
, col
) ) 
7454         MakeCellVisible( row
, col 
); 
7455         if ( expandSelection 
) 
7457             m_selectingKeyboard 
= wxGridCellCoords( row
, col 
); 
7458             HighlightBlock( m_currentCellCoords
, m_selectingKeyboard 
); 
7463             SetCurrentCell( row
, col 
); 
7472 bool wxGrid::MoveCursorRightBlock( bool expandSelection 
) 
7475          m_currentCellCoords 
!= wxGridNoCellCoords  
&& 
7476          m_currentCellCoords
.GetCol() < m_numCols
-1 ) 
7478         int row 
= m_currentCellCoords
.GetRow(); 
7479         int col 
= m_currentCellCoords
.GetCol(); 
7481         if ( m_table
->IsEmptyCell(row
, col
) ) 
7483             // starting in an empty cell: find the next block of 
7486             while ( col 
< m_numCols
-1 ) 
7489                 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break; 
7492         else if ( m_table
->IsEmptyCell(row
, col
+1) ) 
7494             // starting at the right of a block: find the next block 
7497             while ( col 
< m_numCols
-1 ) 
7500                 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break; 
7505             // starting within a block: find the right of the block 
7507             while ( col 
< m_numCols
-1 ) 
7510                 if ( m_table
->IsEmptyCell(row
, col
) ) 
7518         MakeCellVisible( row
, col 
); 
7519         if ( expandSelection 
) 
7521             m_selectingKeyboard 
= wxGridCellCoords( row
, col 
); 
7522             HighlightBlock( m_currentCellCoords
, m_selectingKeyboard 
); 
7527             SetCurrentCell( row
, col 
); 
7539 // ------ Label values and formatting 
7542 void wxGrid::GetRowLabelAlignment( int *horiz
, int *vert 
) 
7544     *horiz 
= m_rowLabelHorizAlign
; 
7545     *vert  
= m_rowLabelVertAlign
; 
7548 void wxGrid::GetColLabelAlignment( int *horiz
, int *vert 
) 
7550     *horiz 
= m_colLabelHorizAlign
; 
7551     *vert  
= m_colLabelVertAlign
; 
7554 wxString 
wxGrid::GetRowLabelValue( int row 
) 
7558         return m_table
->GetRowLabelValue( row 
); 
7568 wxString 
wxGrid::GetColLabelValue( int col 
) 
7572         return m_table
->GetColLabelValue( col 
); 
7583 void wxGrid::SetRowLabelSize( int width 
) 
7585     width 
= wxMax( width
, 0 ); 
7586     if ( width 
!= m_rowLabelWidth 
) 
7590             m_rowLabelWin
->Show( FALSE 
); 
7591             m_cornerLabelWin
->Show( FALSE 
); 
7593         else if ( m_rowLabelWidth 
== 0 ) 
7595             m_rowLabelWin
->Show( TRUE 
); 
7596             if ( m_colLabelHeight 
> 0 ) m_cornerLabelWin
->Show( TRUE 
); 
7599         m_rowLabelWidth 
= width
; 
7606 void wxGrid::SetColLabelSize( int height 
) 
7608     height 
= wxMax( height
, 0 ); 
7609     if ( height 
!= m_colLabelHeight 
) 
7613             m_colLabelWin
->Show( FALSE 
); 
7614             m_cornerLabelWin
->Show( FALSE 
); 
7616         else if ( m_colLabelHeight 
== 0 ) 
7618             m_colLabelWin
->Show( TRUE 
); 
7619             if ( m_rowLabelWidth 
> 0 ) m_cornerLabelWin
->Show( TRUE 
); 
7622         m_colLabelHeight 
= height
; 
7629 void wxGrid::SetLabelBackgroundColour( const wxColour
& colour 
) 
7631     if ( m_labelBackgroundColour 
!= colour 
) 
7633         m_labelBackgroundColour 
= colour
; 
7634         m_rowLabelWin
->SetBackgroundColour( colour 
); 
7635         m_colLabelWin
->SetBackgroundColour( colour 
); 
7636         m_cornerLabelWin
->SetBackgroundColour( colour 
); 
7638         if ( !GetBatchCount() ) 
7640             m_rowLabelWin
->Refresh(); 
7641             m_colLabelWin
->Refresh(); 
7642             m_cornerLabelWin
->Refresh(); 
7647 void wxGrid::SetLabelTextColour( const wxColour
& colour 
) 
7649     if ( m_labelTextColour 
!= colour 
) 
7651         m_labelTextColour 
= colour
; 
7652         if ( !GetBatchCount() ) 
7654             m_rowLabelWin
->Refresh(); 
7655             m_colLabelWin
->Refresh(); 
7660 void wxGrid::SetLabelFont( const wxFont
& font 
) 
7663     if ( !GetBatchCount() ) 
7665         m_rowLabelWin
->Refresh(); 
7666         m_colLabelWin
->Refresh(); 
7670 void wxGrid::SetRowLabelAlignment( int horiz
, int vert 
) 
7672     // allow old (incorrect) defs to be used 
7675         case wxLEFT
:   horiz 
= wxALIGN_LEFT
; break; 
7676         case wxRIGHT
:  horiz 
= wxALIGN_RIGHT
; break; 
7677         case wxCENTRE
: horiz 
= wxALIGN_CENTRE
; break; 
7682         case wxTOP
:    vert 
= wxALIGN_TOP
;    break; 
7683         case wxBOTTOM
: vert 
= wxALIGN_BOTTOM
; break; 
7684         case wxCENTRE
: vert 
= wxALIGN_CENTRE
; break; 
7687     if ( horiz 
== wxALIGN_LEFT 
|| horiz 
== wxALIGN_CENTRE 
|| horiz 
== wxALIGN_RIGHT 
) 
7689         m_rowLabelHorizAlign 
= horiz
; 
7692     if ( vert 
== wxALIGN_TOP 
|| vert 
== wxALIGN_CENTRE 
|| vert 
== wxALIGN_BOTTOM 
) 
7694         m_rowLabelVertAlign 
= vert
; 
7697     if ( !GetBatchCount() ) 
7699         m_rowLabelWin
->Refresh(); 
7703 void wxGrid::SetColLabelAlignment( int horiz
, int vert 
) 
7705     // allow old (incorrect) defs to be used 
7708         case wxLEFT
:   horiz 
= wxALIGN_LEFT
; break; 
7709         case wxRIGHT
:  horiz 
= wxALIGN_RIGHT
; break; 
7710         case wxCENTRE
: horiz 
= wxALIGN_CENTRE
; break; 
7715         case wxTOP
:    vert 
= wxALIGN_TOP
;    break; 
7716         case wxBOTTOM
: vert 
= wxALIGN_BOTTOM
; break; 
7717         case wxCENTRE
: vert 
= wxALIGN_CENTRE
; break; 
7720     if ( horiz 
== wxALIGN_LEFT 
|| horiz 
== wxALIGN_CENTRE 
|| horiz 
== wxALIGN_RIGHT 
) 
7722         m_colLabelHorizAlign 
= horiz
; 
7725     if ( vert 
== wxALIGN_TOP 
|| vert 
== wxALIGN_CENTRE 
|| vert 
== wxALIGN_BOTTOM 
) 
7727         m_colLabelVertAlign 
= vert
; 
7730     if ( !GetBatchCount() ) 
7732         m_colLabelWin
->Refresh(); 
7736 void wxGrid::SetRowLabelValue( int row
, const wxString
& s 
) 
7740         m_table
->SetRowLabelValue( row
, s 
); 
7741         if ( !GetBatchCount() ) 
7743             wxRect rect 
= CellToRect( row
, 0); 
7744             if ( rect
.height 
> 0 ) 
7746                 CalcScrolledPosition(0, rect
.y
, &rect
.x
, &rect
.y
); 
7748                 rect
.width 
= m_rowLabelWidth
; 
7749                 m_rowLabelWin
->Refresh( TRUE
, &rect 
); 
7755 void wxGrid::SetColLabelValue( int col
, const wxString
& s 
) 
7759         m_table
->SetColLabelValue( col
, s 
); 
7760         if ( !GetBatchCount() ) 
7762             wxRect rect 
= CellToRect( 0, col 
); 
7763             if ( rect
.width 
> 0 ) 
7765                 CalcScrolledPosition(rect
.x
, 0, &rect
.x
, &rect
.y
); 
7767                 rect
.height 
= m_colLabelHeight
; 
7768                 m_colLabelWin
->Refresh( TRUE
, &rect 
); 
7774 void wxGrid::SetGridLineColour( const wxColour
& colour 
) 
7776     if ( m_gridLineColour 
!= colour 
) 
7778         m_gridLineColour 
= colour
; 
7780         wxClientDC 
dc( m_gridWin 
); 
7782         DrawAllGridLines( dc
, wxRegion() ); 
7787 void wxGrid::SetCellHighlightColour( const wxColour
& colour 
) 
7789     if ( m_cellHighlightColour 
!= colour 
) 
7791         m_cellHighlightColour 
= colour
; 
7793         wxClientDC 
dc( m_gridWin 
); 
7795         wxGridCellAttr
* attr 
= GetCellAttr(m_currentCellCoords
); 
7796         DrawCellHighlight(dc
, attr
); 
7801 void wxGrid::SetCellHighlightPenWidth(int width
) 
7803     if (m_cellHighlightPenWidth 
!= width
) { 
7804         m_cellHighlightPenWidth 
= width
; 
7806         // Just redrawing the cell highlight is not enough since that won't 
7807         // make any visible change if the the thickness is getting smaller. 
7808         int row 
= m_currentCellCoords
.GetRow(); 
7809         int col 
= m_currentCellCoords
.GetCol(); 
7810         if ( GetColWidth(col
) <= 0 || GetRowHeight(row
) <= 0 ) 
7812         wxRect rect 
= CellToRect(row
, col
); 
7813         m_gridWin
->Refresh(TRUE
, &rect
); 
7817 void wxGrid::SetCellHighlightROPenWidth(int width
) 
7819     if (m_cellHighlightROPenWidth 
!= width
) { 
7820         m_cellHighlightROPenWidth 
= width
; 
7822         // Just redrawing the cell highlight is not enough since that won't 
7823         // make any visible change if the the thickness is getting smaller. 
7824         int row 
= m_currentCellCoords
.GetRow(); 
7825         int col 
= m_currentCellCoords
.GetCol(); 
7826         if ( GetColWidth(col
) <= 0 || GetRowHeight(row
) <= 0 ) 
7828         wxRect rect 
= CellToRect(row
, col
); 
7829         m_gridWin
->Refresh(TRUE
, &rect
); 
7833 void wxGrid::EnableGridLines( bool enable 
) 
7835     if ( enable 
!= m_gridLinesEnabled 
) 
7837         m_gridLinesEnabled 
= enable
; 
7839         if ( !GetBatchCount() ) 
7843                 wxClientDC 
dc( m_gridWin 
); 
7845                 DrawAllGridLines( dc
, wxRegion() ); 
7849                 m_gridWin
->Refresh(); 
7856 int wxGrid::GetDefaultRowSize() 
7858     return m_defaultRowHeight
; 
7861 int wxGrid::GetRowSize( int row 
) 
7863     wxCHECK_MSG( row 
>= 0 && row 
< m_numRows
, 0, _T("invalid row index") ); 
7865     return GetRowHeight(row
); 
7868 int wxGrid::GetDefaultColSize() 
7870     return m_defaultColWidth
; 
7873 int wxGrid::GetColSize( int col 
) 
7875     wxCHECK_MSG( col 
>= 0 && col 
< m_numCols
, 0, _T("invalid column index") ); 
7877     return GetColWidth(col
); 
7880 // ============================================================================ 
7881 // access to the grid attributes: each of them has a default value in the grid 
7882 // itself and may be overidden on a per-cell basis 
7883 // ============================================================================ 
7885 // ---------------------------------------------------------------------------- 
7886 // setting default attributes 
7887 // ---------------------------------------------------------------------------- 
7889 void wxGrid::SetDefaultCellBackgroundColour( const wxColour
& col 
) 
7891     m_defaultCellAttr
->SetBackgroundColour(col
); 
7893     m_gridWin
->SetBackgroundColour(col
); 
7897 void wxGrid::SetDefaultCellTextColour( const wxColour
& col 
) 
7899     m_defaultCellAttr
->SetTextColour(col
); 
7902 void wxGrid::SetDefaultCellAlignment( int horiz
, int vert 
) 
7904     m_defaultCellAttr
->SetAlignment(horiz
, vert
); 
7907 void wxGrid::SetDefaultCellFont( const wxFont
& font 
) 
7909     m_defaultCellAttr
->SetFont(font
); 
7912 void wxGrid::SetDefaultRenderer(wxGridCellRenderer 
*renderer
) 
7914     m_defaultCellAttr
->SetRenderer(renderer
); 
7917 void wxGrid::SetDefaultEditor(wxGridCellEditor 
*editor
) 
7919     m_defaultCellAttr
->SetEditor(editor
); 
7922 // ---------------------------------------------------------------------------- 
7923 // access to the default attrbiutes 
7924 // ---------------------------------------------------------------------------- 
7926 wxColour 
wxGrid::GetDefaultCellBackgroundColour() 
7928     return m_defaultCellAttr
->GetBackgroundColour(); 
7931 wxColour 
wxGrid::GetDefaultCellTextColour() 
7933     return m_defaultCellAttr
->GetTextColour(); 
7936 wxFont 
wxGrid::GetDefaultCellFont() 
7938     return m_defaultCellAttr
->GetFont(); 
7941 void wxGrid::GetDefaultCellAlignment( int *horiz
, int *vert 
) 
7943     m_defaultCellAttr
->GetAlignment(horiz
, vert
); 
7946 wxGridCellRenderer 
*wxGrid::GetDefaultRenderer() const 
7948     return m_defaultCellAttr
->GetRenderer(NULL
, 0, 0); 
7951 wxGridCellEditor 
*wxGrid::GetDefaultEditor() const 
7953     return m_defaultCellAttr
->GetEditor(NULL
,0,0); 
7956 // ---------------------------------------------------------------------------- 
7957 // access to cell attributes 
7958 // ---------------------------------------------------------------------------- 
7960 wxColour 
wxGrid::GetCellBackgroundColour(int row
, int col
) 
7962     wxGridCellAttr 
*attr 
= GetCellAttr(row
, col
); 
7963     wxColour colour 
= attr
->GetBackgroundColour(); 
7968 wxColour 
wxGrid::GetCellTextColour( int row
, int col 
) 
7970     wxGridCellAttr 
*attr 
= GetCellAttr(row
, col
); 
7971     wxColour colour 
= attr
->GetTextColour(); 
7976 wxFont 
wxGrid::GetCellFont( int row
, int col 
) 
7978     wxGridCellAttr 
*attr 
= GetCellAttr(row
, col
); 
7979     wxFont font 
= attr
->GetFont(); 
7984 void wxGrid::GetCellAlignment( int row
, int col
, int *horiz
, int *vert 
) 
7986     wxGridCellAttr 
*attr 
= GetCellAttr(row
, col
); 
7987     attr
->GetAlignment(horiz
, vert
); 
7991 wxGridCellRenderer
* wxGrid::GetCellRenderer(int row
, int col
) 
7993     wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
7994     wxGridCellRenderer
* renderer 
= attr
->GetRenderer(this, row
, col
); 
8000 wxGridCellEditor
* wxGrid::GetCellEditor(int row
, int col
) 
8002     wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
8003     wxGridCellEditor
* editor 
= attr
->GetEditor(this, row
, col
); 
8009 bool wxGrid::IsReadOnly(int row
, int col
) const 
8011     wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
8012     bool isReadOnly 
= attr
->IsReadOnly(); 
8017 // ---------------------------------------------------------------------------- 
8018 // attribute support: cache, automatic provider creation, ... 
8019 // ---------------------------------------------------------------------------- 
8021 bool wxGrid::CanHaveAttributes() 
8028     return m_table
->CanHaveAttributes(); 
8031 void wxGrid::ClearAttrCache() 
8033     if ( m_attrCache
.row 
!= -1 ) 
8035         wxSafeDecRef(m_attrCache
.attr
); 
8036         m_attrCache
.attr 
= NULL
; 
8037         m_attrCache
.row 
= -1; 
8041 void wxGrid::CacheAttr(int row
, int col
, wxGridCellAttr 
*attr
) const 
8043     wxGrid 
*self 
= (wxGrid 
*)this;  // const_cast 
8045     self
->ClearAttrCache(); 
8046     self
->m_attrCache
.row 
= row
; 
8047     self
->m_attrCache
.col 
= col
; 
8048     self
->m_attrCache
.attr 
= attr
; 
8052 bool wxGrid::LookupAttr(int row
, int col
, wxGridCellAttr 
**attr
) const 
8054     if ( row 
== m_attrCache
.row 
&& col 
== m_attrCache
.col 
) 
8056         *attr 
= m_attrCache
.attr
; 
8057         wxSafeIncRef(m_attrCache
.attr
); 
8059 #ifdef DEBUG_ATTR_CACHE 
8060         gs_nAttrCacheHits
++; 
8067 #ifdef DEBUG_ATTR_CACHE 
8068         gs_nAttrCacheMisses
++; 
8074 wxGridCellAttr 
*wxGrid::GetCellAttr(int row
, int col
) const 
8076     wxGridCellAttr 
*attr
; 
8077     if ( !LookupAttr(row
, col
, &attr
) ) 
8079         attr 
= m_table 
? m_table
->GetAttr(row
, col 
, wxGridCellAttr::Any
) : (wxGridCellAttr 
*)NULL
; 
8080         CacheAttr(row
, col
, attr
); 
8084         attr
->SetDefAttr(m_defaultCellAttr
); 
8088         attr 
= m_defaultCellAttr
; 
8095 wxGridCellAttr 
*wxGrid::GetOrCreateCellAttr(int row
, int col
) const 
8097     wxGridCellAttr 
*attr 
= (wxGridCellAttr 
*)NULL
; 
8099     wxCHECK_MSG( m_table
, attr
, 
8100                   _T("we may only be called if CanHaveAttributes() returned TRUE and then m_table should be !NULL") ); 
8102     attr 
= m_table
->GetAttr(row
, col
, wxGridCellAttr::Cell
); 
8105         attr 
= new wxGridCellAttr(m_defaultCellAttr
); 
8107         // artificially inc the ref count to match DecRef() in caller 
8109         m_table
->SetAttr(attr
, row
, col
); 
8115 // ---------------------------------------------------------------------------- 
8116 // setting column attributes (wrappers around SetColAttr) 
8117 // ---------------------------------------------------------------------------- 
8119 void wxGrid::SetColFormatBool(int col
) 
8121     SetColFormatCustom(col
, wxGRID_VALUE_BOOL
); 
8124 void wxGrid::SetColFormatNumber(int col
) 
8126     SetColFormatCustom(col
, wxGRID_VALUE_NUMBER
); 
8129 void wxGrid::SetColFormatFloat(int col
, int width
, int precision
) 
8131     wxString typeName 
= wxGRID_VALUE_FLOAT
; 
8132     if ( (width 
!= -1) || (precision 
!= -1) ) 
8134         typeName 
<< _T(':') << width 
<< _T(',') << precision
; 
8137     SetColFormatCustom(col
, typeName
); 
8140 void wxGrid::SetColFormatCustom(int col
, const wxString
& typeName
) 
8142     wxGridCellAttr 
*attr 
= (wxGridCellAttr 
*)NULL
; 
8144     attr 
= m_table
->GetAttr(-1, col
, wxGridCellAttr::Col 
); 
8146         attr 
= new wxGridCellAttr
; 
8147     wxGridCellRenderer 
*renderer 
= GetDefaultRendererForType(typeName
); 
8148     attr
->SetRenderer(renderer
); 
8150     SetColAttr(col
, attr
); 
8154 // ---------------------------------------------------------------------------- 
8155 // setting cell attributes: this is forwarded to the table 
8156 // ---------------------------------------------------------------------------- 
8158 void wxGrid::SetRowAttr(int row
, wxGridCellAttr 
*attr
) 
8160     if ( CanHaveAttributes() ) 
8162         m_table
->SetRowAttr(attr
, row
); 
8171 void wxGrid::SetColAttr(int col
, wxGridCellAttr 
*attr
) 
8173     if ( CanHaveAttributes() ) 
8175         m_table
->SetColAttr(attr
, col
); 
8184 void wxGrid::SetCellBackgroundColour( int row
, int col
, const wxColour
& colour 
) 
8186     if ( CanHaveAttributes() ) 
8188         wxGridCellAttr 
*attr 
= GetOrCreateCellAttr(row
, col
); 
8189         attr
->SetBackgroundColour(colour
); 
8194 void wxGrid::SetCellTextColour( int row
, int col
, const wxColour
& colour 
) 
8196     if ( CanHaveAttributes() ) 
8198         wxGridCellAttr 
*attr 
= GetOrCreateCellAttr(row
, col
); 
8199         attr
->SetTextColour(colour
); 
8204 void wxGrid::SetCellFont( int row
, int col
, const wxFont
& font 
) 
8206     if ( CanHaveAttributes() ) 
8208         wxGridCellAttr 
*attr 
= GetOrCreateCellAttr(row
, col
); 
8209         attr
->SetFont(font
); 
8214 void wxGrid::SetCellAlignment( int row
, int col
, int horiz
, int vert 
) 
8216     if ( CanHaveAttributes() ) 
8218         wxGridCellAttr 
*attr 
= GetOrCreateCellAttr(row
, col
); 
8219         attr
->SetAlignment(horiz
, vert
); 
8224 void wxGrid::SetCellRenderer(int row
, int col
, wxGridCellRenderer 
*renderer
) 
8226     if ( CanHaveAttributes() ) 
8228         wxGridCellAttr 
*attr 
= GetOrCreateCellAttr(row
, col
); 
8229         attr
->SetRenderer(renderer
); 
8234 void wxGrid::SetCellEditor(int row
, int col
, wxGridCellEditor
* editor
) 
8236     if ( CanHaveAttributes() ) 
8238         wxGridCellAttr 
*attr 
= GetOrCreateCellAttr(row
, col
); 
8239         attr
->SetEditor(editor
); 
8244 void wxGrid::SetReadOnly(int row
, int col
, bool isReadOnly
) 
8246     if ( CanHaveAttributes() ) 
8248         wxGridCellAttr 
*attr 
= GetOrCreateCellAttr(row
, col
); 
8249         attr
->SetReadOnly(isReadOnly
); 
8254 // ---------------------------------------------------------------------------- 
8255 // Data type registration 
8256 // ---------------------------------------------------------------------------- 
8258 void wxGrid::RegisterDataType(const wxString
& typeName
, 
8259                               wxGridCellRenderer
* renderer
, 
8260                               wxGridCellEditor
* editor
) 
8262     m_typeRegistry
->RegisterDataType(typeName
, renderer
, editor
); 
8266 wxGridCellEditor
* wxGrid::GetDefaultEditorForCell(int row
, int col
) const 
8268     wxString typeName 
= m_table
->GetTypeName(row
, col
); 
8269     return GetDefaultEditorForType(typeName
); 
8272 wxGridCellRenderer
* wxGrid::GetDefaultRendererForCell(int row
, int col
) const 
8274     wxString typeName 
= m_table
->GetTypeName(row
, col
); 
8275     return GetDefaultRendererForType(typeName
); 
8279 wxGrid::GetDefaultEditorForType(const wxString
& typeName
) const 
8281     int index 
= m_typeRegistry
->FindOrCloneDataType(typeName
); 
8282     if ( index 
== wxNOT_FOUND 
) 
8284         wxFAIL_MSG(wxT("Unknown data type name")); 
8289     return m_typeRegistry
->GetEditor(index
); 
8293 wxGrid::GetDefaultRendererForType(const wxString
& typeName
) const 
8295     int index 
= m_typeRegistry
->FindOrCloneDataType(typeName
); 
8296     if ( index 
== wxNOT_FOUND 
) 
8298         wxFAIL_MSG(wxT("Unknown data type name")); 
8303     return m_typeRegistry
->GetRenderer(index
); 
8307 // ---------------------------------------------------------------------------- 
8309 // ---------------------------------------------------------------------------- 
8311 void wxGrid::EnableDragRowSize( bool enable 
) 
8313     m_canDragRowSize 
= enable
; 
8317 void wxGrid::EnableDragColSize( bool enable 
) 
8319     m_canDragColSize 
= enable
; 
8322 void wxGrid::EnableDragGridSize( bool enable 
) 
8324     m_canDragGridSize 
= enable
; 
8328 void wxGrid::SetDefaultRowSize( int height
, bool resizeExistingRows 
) 
8330     m_defaultRowHeight 
= wxMax( height
, WXGRID_MIN_ROW_HEIGHT 
); 
8332     if ( resizeExistingRows 
) 
8334         // since we are resizing all rows to the default row size, 
8335         // we can simply clear the row heights and row bottoms 
8336         // arrays (which also allows us to take advantage of 
8337         // some speed optimisations) 
8338         m_rowHeights
.Empty(); 
8339         m_rowBottoms
.Empty(); 
8340         if ( !GetBatchCount() ) 
8345 void wxGrid::SetRowSize( int row
, int height 
) 
8347     wxCHECK_RET( row 
>= 0 && row 
< m_numRows
, _T("invalid row index") ); 
8349     if ( m_rowHeights
.IsEmpty() ) 
8351         // need to really create the array 
8355     int h 
= wxMax( 0, height 
); 
8356     int diff 
= h 
- m_rowHeights
[row
]; 
8358     m_rowHeights
[row
] = h
; 
8360     for ( i 
= row
;  i 
< m_numRows
;  i
++ ) 
8362         m_rowBottoms
[i
] += diff
; 
8364     if ( !GetBatchCount() ) 
8368 void wxGrid::SetDefaultColSize( int width
, bool resizeExistingCols 
) 
8370     m_defaultColWidth 
= wxMax( width
, WXGRID_MIN_COL_WIDTH 
); 
8372     if ( resizeExistingCols 
) 
8374         // since we are resizing all columns to the default column size, 
8375         // we can simply clear the col widths and col rights 
8376         // arrays (which also allows us to take advantage of 
8377         // some speed optimisations) 
8378         m_colWidths
.Empty(); 
8379         m_colRights
.Empty(); 
8380         if ( !GetBatchCount() ) 
8385 void wxGrid::SetColSize( int col
, int width 
) 
8387     wxCHECK_RET( col 
>= 0 && col 
< m_numCols
, _T("invalid column index") ); 
8389     // should we check that it's bigger than GetColMinimalWidth(col) here? 
8391     if ( m_colWidths
.IsEmpty() ) 
8393         // need to really create the array 
8397     int w 
= wxMax( 0, width 
); 
8398     int diff 
= w 
- m_colWidths
[col
]; 
8399     m_colWidths
[col
] = w
; 
8402     for ( i 
= col
;  i 
< m_numCols
;  i
++ ) 
8404         m_colRights
[i
] += diff
; 
8406     if ( !GetBatchCount() ) 
8411 void wxGrid::SetColMinimalWidth( int col
, int width 
) 
8413     m_colMinWidths
.Put(col
, width
); 
8416 void wxGrid::SetRowMinimalHeight( int row
, int width 
) 
8418     m_rowMinHeights
.Put(row
, width
); 
8421 int wxGrid::GetColMinimalWidth(int col
) const 
8423     long value 
= m_colMinWidths
.Get(col
); 
8424     return value 
!= wxNOT_FOUND 
? (int)value 
: WXGRID_MIN_COL_WIDTH
; 
8427 int wxGrid::GetRowMinimalHeight(int row
) const 
8429     long value 
= m_rowMinHeights
.Get(row
); 
8430     return value 
!= wxNOT_FOUND 
? (int)value 
: WXGRID_MIN_ROW_HEIGHT
; 
8433 // ---------------------------------------------------------------------------- 
8435 // ---------------------------------------------------------------------------- 
8437 void wxGrid::AutoSizeColOrRow( int colOrRow
, bool setAsMin
, bool column 
) 
8439     wxClientDC 
dc(m_gridWin
); 
8441     // init both of them to avoid compiler warnings, even if weo nly need one 
8449     wxCoord extent
, extentMax 
= 0; 
8450     int max 
= column 
? m_numRows 
: m_numCols
; 
8451     for ( int rowOrCol 
= 0; rowOrCol 
< max
; rowOrCol
++ ) 
8458         wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
8459         wxGridCellRenderer
* renderer 
= attr
->GetRenderer(this, row
, col
); 
8462             wxSize size 
= renderer
->GetBestSize(*this, *attr
, dc
, row
, col
); 
8463             extent 
= column 
? size
.x 
: size
.y
; 
8464             if ( extent 
> extentMax 
) 
8475     // now also compare with the column label extent 
8477     dc
.SetFont( GetLabelFont() ); 
8480         dc
.GetTextExtent( GetColLabelValue(col
), &w
, &h 
); 
8482         dc
.GetTextExtent( GetRowLabelValue(row
), &w
, &h 
); 
8484     extent 
= column 
? w 
: h
; 
8485     if ( extent 
> extentMax 
) 
8492         // empty column - give default extent (notice that if extentMax is less 
8493         // than default extent but != 0, it's ok) 
8494         extentMax 
= column 
? m_defaultColWidth 
: m_defaultRowHeight
; 
8500             // leave some space around text 
8511         SetColSize(col
, extentMax
); 
8512         if ( !GetBatchCount() ) 
8515             m_gridWin
->GetClientSize( &cw
, &ch 
); 
8516             wxRect 
rect ( CellToRect( 0, col 
) ); 
8518             CalcScrolledPosition(rect
.x
, 0, &rect
.x
, &dummy
); 
8519             rect
.width 
= cw 
- rect
.x
; 
8520             rect
.height 
= m_colLabelHeight
; 
8521             m_colLabelWin
->Refresh( TRUE
, &rect 
); 
8526         SetRowSize(row
, extentMax
); 
8527         if ( !GetBatchCount() ) 
8530             m_gridWin
->GetClientSize( &cw
, &ch 
); 
8531             wxRect 
rect ( CellToRect( row
, 0 ) ); 
8533             CalcScrolledPosition(0, rect
.y
, &dummy
, &rect
.y
); 
8534             rect
.width 
= m_rowLabelWidth
; 
8535             rect
.height 
= ch 
- rect
.y
; 
8536             m_rowLabelWin
->Refresh( TRUE
, &rect 
); 
8542             SetColMinimalWidth(col
, extentMax
); 
8544             SetRowMinimalHeight(row
, extentMax
); 
8548 int wxGrid::SetOrCalcColumnSizes(bool calcOnly
, bool setAsMin
) 
8550     int width 
= m_rowLabelWidth
; 
8555     for ( int col 
= 0; col 
< m_numCols
; col
++ ) 
8559             AutoSizeColumn(col
, setAsMin
); 
8562         width 
+= GetColWidth(col
); 
8571 int wxGrid::SetOrCalcRowSizes(bool calcOnly
, bool setAsMin
) 
8573     int height 
= m_colLabelHeight
; 
8578     for ( int row 
= 0; row 
< m_numRows
; row
++ ) 
8582             AutoSizeRow(row
, setAsMin
); 
8585         height 
+= GetRowHeight(row
); 
8594 void wxGrid::AutoSize() 
8598     wxSize 
size(SetOrCalcColumnSizes(FALSE
), SetOrCalcRowSizes(FALSE
)); 
8600     // round up the size to a multiple of scroll step - this ensures that we 
8601     // won't get the scrollbars if we're sized exactly to this width 
8602     wxSize 
sizeFit(GetScrollX(size
.x
) * GRID_SCROLL_LINE_X
, 
8603                    GetScrollY(size
.y
) * GRID_SCROLL_LINE_Y
); 
8605     // distribute the extra space between teh columns/rows to avoid having 
8606     // extra white space 
8607     wxCoord diff 
= sizeFit
.x 
- size
.x
; 
8610         // try to resize the columns uniformly 
8611         wxCoord diffPerCol 
= diff 
/ m_numCols
; 
8614             for ( int col 
= 0; col 
< m_numCols
; col
++ ) 
8616                 SetColSize(col
, GetColWidth(col
) + diffPerCol
); 
8620         // add remaining amount to the last columns 
8621         diff 
-= diffPerCol 
* m_numCols
; 
8624             for ( int col 
= m_numCols 
- 1; col 
>= m_numCols 
- diff
; col
-- ) 
8626                 SetColSize(col
, GetColWidth(col
) + 1); 
8632     diff 
= sizeFit
.y 
- size
.y
; 
8635         // try to resize the columns uniformly 
8636         wxCoord diffPerRow 
= diff 
/ m_numRows
; 
8639             for ( int row 
= 0; row 
< m_numRows
; row
++ ) 
8641                 SetRowSize(row
, GetRowHeight(row
) + diffPerRow
); 
8645         // add remaining amount to the last rows 
8646         diff 
-= diffPerRow 
* m_numRows
; 
8649             for ( int row 
= m_numRows 
- 1; row 
>= m_numRows 
- diff
; row
-- ) 
8651                 SetRowSize(row
, GetRowHeight(row
) + 1); 
8658     SetClientSize(sizeFit
); 
8661 wxSize 
wxGrid::DoGetBestSize() const 
8663     // don't set sizes, only calculate them 
8664     wxGrid 
*self 
= (wxGrid 
*)this;  // const_cast 
8666     return wxSize(self
->SetOrCalcColumnSizes(TRUE
), 
8667                   self
->SetOrCalcRowSizes(TRUE
)); 
8676 wxPen
& wxGrid::GetDividerPen() const 
8681 // ---------------------------------------------------------------------------- 
8682 // cell value accessor functions 
8683 // ---------------------------------------------------------------------------- 
8685 void wxGrid::SetCellValue( int row
, int col
, const wxString
& s 
) 
8689         m_table
->SetValue( row
, col
, s 
); 
8690         if ( !GetBatchCount() ) 
8692             wxClientDC 
dc( m_gridWin 
); 
8694             DrawCell( dc
, wxGridCellCoords(row
, col
) ); 
8697         if ( m_currentCellCoords
.GetRow() == row 
&& 
8698              m_currentCellCoords
.GetCol() == col 
&& 
8699              IsCellEditControlShown()) 
8700              // Note: If we are using IsCellEditControlEnabled, 
8701              // this interacts badly with calling SetCellValue from 
8702              // an EVT_GRID_CELL_CHANGE handler. 
8704             HideCellEditControl(); 
8705             ShowCellEditControl(); // will reread data from table 
8712 // ------ Block, row and col selection 
8715 void wxGrid::SelectRow( int row
, bool addToSelected 
) 
8717     if ( IsSelection() && !addToSelected 
) 
8720     m_selection
->SelectRow( row
, FALSE
, addToSelected 
); 
8724 void wxGrid::SelectCol( int col
, bool addToSelected 
) 
8726     if ( IsSelection() && !addToSelected 
) 
8729     m_selection
->SelectCol( col
, FALSE
, addToSelected 
); 
8733 void wxGrid::SelectBlock( int topRow
, int leftCol
, int bottomRow
, int rightCol
, 
8734                           bool addToSelected 
) 
8736     if ( IsSelection() && !addToSelected 
) 
8739     m_selection
->SelectBlock( topRow
, leftCol
, bottomRow
, rightCol
, 
8740                               FALSE
, addToSelected 
); 
8744 void wxGrid::SelectAll() 
8746     if ( m_numRows 
> 0 && m_numCols 
> 0 ) 
8747         m_selection
->SelectBlock( 0, 0, m_numRows
-1, m_numCols
-1 ); 
8751 // ------ Cell, row and col deselection 
8754 void wxGrid::DeselectRow( int row 
) 
8756     if ( m_selection
->GetSelectionMode() == wxGrid::wxGridSelectRows 
) 
8758         if ( m_selection
->IsInSelection(row
, 0 ) ) 
8759             m_selection
->ToggleCellSelection( row
, 0); 
8763         int nCols 
= GetNumberCols(); 
8764         for ( int i 
= 0; i 
< nCols 
; i
++ ) 
8766             if ( m_selection
->IsInSelection(row
, i 
) ) 
8767                 m_selection
->ToggleCellSelection( row
, i
); 
8772 void wxGrid::DeselectCol( int col 
) 
8774     if ( m_selection
->GetSelectionMode() == wxGrid::wxGridSelectColumns 
) 
8776         if ( m_selection
->IsInSelection(0, col 
) ) 
8777             m_selection
->ToggleCellSelection( 0, col
); 
8781         int nRows 
= GetNumberRows(); 
8782         for ( int i 
= 0; i 
< nRows 
; i
++ ) 
8784             if ( m_selection
->IsInSelection(i
, col 
) ) 
8785                 m_selection
->ToggleCellSelection(i
, col
); 
8790 void wxGrid::DeselectCell( int row
, int col 
) 
8792     if ( m_selection
->IsInSelection(row
, col
) ) 
8793         m_selection
->ToggleCellSelection(row
, col
); 
8796 bool wxGrid::IsSelection() 
8798     return ( m_selection
->IsSelection() || 
8799              ( m_selectingTopLeft 
!= wxGridNoCellCoords 
&& 
8800                m_selectingBottomRight 
!= wxGridNoCellCoords 
) ); 
8803 bool wxGrid::IsInSelection( int row
, int col 
) 
8805     return ( m_selection
->IsInSelection( row
, col 
) || 
8806              ( row 
>= m_selectingTopLeft
.GetRow() && 
8807                col 
>= m_selectingTopLeft
.GetCol() && 
8808                row 
<= m_selectingBottomRight
.GetRow() && 
8809                col 
<= m_selectingBottomRight
.GetCol() ) ); 
8812 void wxGrid::ClearSelection() 
8814     m_selectingTopLeft 
= wxGridNoCellCoords
; 
8815     m_selectingBottomRight 
= wxGridNoCellCoords
; 
8816     m_selection
->ClearSelection(); 
8820 // This function returns the rectangle that encloses the given block 
8821 // in device coords clipped to the client size of the grid window. 
8823 wxRect 
wxGrid::BlockToDeviceRect( const wxGridCellCoords 
&topLeft
, 
8824                                   const wxGridCellCoords 
&bottomRight 
) 
8826     wxRect 
rect( wxGridNoCellRect 
); 
8829     cellRect 
= CellToRect( topLeft 
); 
8830     if ( cellRect 
!= wxGridNoCellRect 
) 
8836         rect 
= wxRect( 0, 0, 0, 0 ); 
8839     cellRect 
= CellToRect( bottomRight 
); 
8840     if ( cellRect 
!= wxGridNoCellRect 
) 
8846         return wxGridNoCellRect
; 
8849     // convert to scrolled coords 
8851     int left
, top
, right
, bottom
; 
8852     CalcScrolledPosition( rect
.GetLeft(), rect
.GetTop(), &left
, &top 
); 
8853     CalcScrolledPosition( rect
.GetRight(), rect
.GetBottom(), &right
, &bottom 
); 
8856     m_gridWin
->GetClientSize( &cw
, &ch 
); 
8858     if (right 
< 0 || bottom 
< 0 || left 
> cw 
|| top 
> ch
) 
8859         return wxRect( 0, 0, 0, 0); 
8861     rect
.SetLeft( wxMax(0, left
) ); 
8862     rect
.SetTop( wxMax(0, top
) ); 
8863     rect
.SetRight( wxMin(cw
, right
) ); 
8864     rect
.SetBottom( wxMin(ch
, bottom
) ); 
8872 // ------ Grid event classes 
8875 IMPLEMENT_DYNAMIC_CLASS( wxGridEvent
, wxNotifyEvent 
) 
8877 wxGridEvent::wxGridEvent( int id
, wxEventType type
, wxObject
* obj
, 
8878                           int row
, int col
, int x
, int y
, bool sel
, 
8879                           bool control
, bool shift
, bool alt
, bool meta 
) 
8880         : wxNotifyEvent( type
, id 
) 
8887     m_control 
= control
; 
8892     SetEventObject(obj
); 
8896 IMPLEMENT_DYNAMIC_CLASS( wxGridSizeEvent
, wxNotifyEvent 
) 
8898 wxGridSizeEvent::wxGridSizeEvent( int id
, wxEventType type
, wxObject
* obj
, 
8899                                   int rowOrCol
, int x
, int y
, 
8900                                   bool control
, bool shift
, bool alt
, bool meta 
) 
8901         : wxNotifyEvent( type
, id 
) 
8903     m_rowOrCol 
= rowOrCol
; 
8906     m_control 
= control
; 
8911     SetEventObject(obj
); 
8915 IMPLEMENT_DYNAMIC_CLASS( wxGridRangeSelectEvent
, wxNotifyEvent 
) 
8917 wxGridRangeSelectEvent::wxGridRangeSelectEvent(int id
, wxEventType type
, wxObject
* obj
, 
8918                                                const wxGridCellCoords
& topLeft
, 
8919                                                const wxGridCellCoords
& bottomRight
, 
8920                                                bool sel
, bool control
, 
8921                                                bool shift
, bool alt
, bool meta 
) 
8922         : wxNotifyEvent( type
, id 
) 
8924     m_topLeft     
= topLeft
; 
8925     m_bottomRight 
= bottomRight
; 
8927     m_control     
= control
; 
8932     SetEventObject(obj
); 
8936 IMPLEMENT_DYNAMIC_CLASS(wxGridEditorCreatedEvent
, wxCommandEvent
) 
8938 wxGridEditorCreatedEvent::wxGridEditorCreatedEvent(int id
, wxEventType type
, 
8939                                                    wxObject
* obj
, int row
, 
8940                                                    int col
, wxControl
* ctrl
) 
8941     : wxCommandEvent(type
, id
) 
8943     SetEventObject(obj
); 
8950 #endif // !wxUSE_NEW_GRID/wxUSE_NEW_GRID 
8952 #endif // wxUSE_GRID