1 /////////////////////////////////////////////////////////////////////////// 
   2 // Name:        generic/grid.cpp 
   3 // Purpose:     wxGrid and related classes 
   4 // Author:      Michael Bedward (based on code by Julian Smart, Robin Dunn) 
   8 // Copyright:   (c) Michael Bedward (mbedward@ozemail.com.au) 
   9 // Licence:     wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////////// 
  12 // ============================================================================ 
  14 // ============================================================================ 
  16 // ---------------------------------------------------------------------------- 
  18 // ---------------------------------------------------------------------------- 
  21     #pragma implementation "grid.h" 
  24 // For compilers that support precompilation, includes "wx/wx.h". 
  25 #include "wx/wxprec.h" 
  33 #if !defined(wxUSE_NEW_GRID) || !(wxUSE_NEW_GRID) 
  39     #include "wx/dcclient.h" 
  40     #include "wx/settings.h" 
  42     #include "wx/textctrl.h" 
  43     #include "wx/checkbox.h" 
  46 // this include needs to be outside precomp for BCC 
  47 #include "wx/textfile.h" 
  51 // ---------------------------------------------------------------------------- 
  53 // ---------------------------------------------------------------------------- 
  55 WX_DEFINE_ARRAY(wxGridCellAttr 
*, wxArrayAttrs
); 
  57 struct wxGridCellWithAttr
 
  59     wxGridCellWithAttr(int row
, int col
, wxGridCellAttr 
*attr_
) 
  60         : coords(row
, col
), attr(attr_
) 
  69     wxGridCellCoords coords
; 
  73 WX_DECLARE_OBJARRAY(wxGridCellWithAttr
, wxGridCellWithAttrArray
); 
  75 #include "wx/arrimpl.cpp" 
  77 WX_DEFINE_OBJARRAY(wxGridCellCoordsArray
) 
  78 WX_DEFINE_OBJARRAY(wxGridCellWithAttrArray
) 
  80 // ---------------------------------------------------------------------------- 
  82 // ---------------------------------------------------------------------------- 
  84 class WXDLLEXPORT wxGridRowLabelWindow 
: public wxWindow
 
  87     wxGridRowLabelWindow() { m_owner 
= (wxGrid 
*)NULL
; } 
  88     wxGridRowLabelWindow( wxGrid 
*parent
, wxWindowID id
, 
  89                           const wxPoint 
&pos
, const wxSize 
&size 
); 
  94     void OnPaint( wxPaintEvent
& event 
); 
  95     void OnMouseEvent( wxMouseEvent
& event 
); 
  96     void OnKeyDown( wxKeyEvent
& event 
); 
  98     DECLARE_DYNAMIC_CLASS(wxGridRowLabelWindow
) 
 103 class WXDLLEXPORT wxGridColLabelWindow 
: public wxWindow
 
 106     wxGridColLabelWindow() { m_owner 
= (wxGrid 
*)NULL
; } 
 107     wxGridColLabelWindow( wxGrid 
*parent
, wxWindowID id
, 
 108                           const wxPoint 
&pos
, const wxSize 
&size 
); 
 113     void OnPaint( wxPaintEvent 
&event 
); 
 114     void OnMouseEvent( wxMouseEvent
& event 
); 
 115     void OnKeyDown( wxKeyEvent
& event 
); 
 117     DECLARE_DYNAMIC_CLASS(wxGridColLabelWindow
) 
 118     DECLARE_EVENT_TABLE() 
 122 class WXDLLEXPORT wxGridCornerLabelWindow 
: public wxWindow
 
 125     wxGridCornerLabelWindow() { m_owner 
= (wxGrid 
*)NULL
; } 
 126     wxGridCornerLabelWindow( wxGrid 
*parent
, wxWindowID id
, 
 127                              const wxPoint 
&pos
, const wxSize 
&size 
); 
 132     void OnMouseEvent( wxMouseEvent
& event 
); 
 133     void OnKeyDown( wxKeyEvent
& event 
); 
 134     void OnPaint( wxPaintEvent
& event 
); 
 136     DECLARE_DYNAMIC_CLASS(wxGridCornerLabelWindow
) 
 137     DECLARE_EVENT_TABLE() 
 140 class WXDLLEXPORT wxGridWindow 
: public wxPanel
 
 145         m_owner 
= (wxGrid 
*)NULL
; 
 146         m_rowLabelWin 
= (wxGridRowLabelWindow 
*)NULL
; 
 147         m_colLabelWin 
= (wxGridColLabelWindow 
*)NULL
; 
 150     wxGridWindow( wxGrid 
*parent
, 
 151                   wxGridRowLabelWindow 
*rowLblWin
, 
 152                   wxGridColLabelWindow 
*colLblWin
, 
 153                   wxWindowID id
, const wxPoint 
&pos
, const wxSize 
&size 
); 
 156     void ScrollWindow( int dx
, int dy
, const wxRect 
*rect 
); 
 160     wxGridRowLabelWindow     
*m_rowLabelWin
; 
 161     wxGridColLabelWindow     
*m_colLabelWin
; 
 163     void OnPaint( wxPaintEvent 
&event 
); 
 164     void OnMouseEvent( wxMouseEvent
& event 
); 
 165     void OnKeyDown( wxKeyEvent
& ); 
 166     void OnEraseBackground( wxEraseEvent
& ); 
 169     DECLARE_DYNAMIC_CLASS(wxGridWindow
) 
 170     DECLARE_EVENT_TABLE() 
 175 class wxGridCellEditorEvtHandler 
: public wxEvtHandler
 
 178     wxGridCellEditorEvtHandler() 
 179         : m_grid(0), m_editor(0) 
 181     wxGridCellEditorEvtHandler(wxGrid
* grid
, wxGridCellEditor
* editor
) 
 182         : m_grid(grid
), m_editor(editor
) 
 185     void OnKeyDown(wxKeyEvent
& event
); 
 186     void OnChar(wxKeyEvent
& event
); 
 190     wxGridCellEditor
*   m_editor
; 
 191     DECLARE_DYNAMIC_CLASS(wxGridCellEditorEvtHandler
) 
 192     DECLARE_EVENT_TABLE() 
 196 IMPLEMENT_DYNAMIC_CLASS( wxGridCellEditorEvtHandler
, wxEvtHandler 
) 
 197 BEGIN_EVENT_TABLE( wxGridCellEditorEvtHandler
, wxEvtHandler 
) 
 198     EVT_KEY_DOWN( wxGridCellEditorEvtHandler::OnKeyDown 
) 
 199     EVT_CHAR( wxGridCellEditorEvtHandler::OnChar 
) 
 204 // ---------------------------------------------------------------------------- 
 205 // the internal data representation used by wxGridCellAttrProvider 
 206 // ---------------------------------------------------------------------------- 
 208 // this class stores attributes set for cells 
 209 class WXDLLEXPORT wxGridCellAttrData
 
 212     void SetAttr(wxGridCellAttr 
*attr
, int row
, int col
); 
 213     wxGridCellAttr 
*GetAttr(int row
, int col
) const; 
 214     void UpdateAttrRows( size_t pos
, int numRows 
); 
 215     void UpdateAttrCols( size_t pos
, int numCols 
); 
 218     // searches for the attr for given cell, returns wxNOT_FOUND if not found 
 219     int FindIndex(int row
, int col
) const; 
 221     wxGridCellWithAttrArray m_attrs
; 
 224 // this class stores attributes set for rows or columns 
 225 class WXDLLEXPORT wxGridRowOrColAttrData
 
 228     // empty ctor to suppress warnings 
 229     wxGridRowOrColAttrData() { } 
 230     ~wxGridRowOrColAttrData(); 
 232     void SetAttr(wxGridCellAttr 
*attr
, int rowOrCol
); 
 233     wxGridCellAttr 
*GetAttr(int rowOrCol
) const; 
 234     void UpdateAttrRowsOrCols( size_t pos
, int numRowsOrCols 
); 
 237     wxArrayInt m_rowsOrCols
; 
 238     wxArrayAttrs m_attrs
; 
 241 // NB: this is just a wrapper around 3 objects: one which stores cell 
 242 //     attributes, and 2 others for row/col ones 
 243 class WXDLLEXPORT wxGridCellAttrProviderData
 
 246     wxGridCellAttrData m_cellAttrs
; 
 247     wxGridRowOrColAttrData m_rowAttrs
, 
 252 // ---------------------------------------------------------------------------- 
 253 // data structures used for the data type registry 
 254 // ---------------------------------------------------------------------------- 
 256 struct wxGridDataTypeInfo 
{ 
 257     wxGridDataTypeInfo(const wxString
& typeName
, 
 258                        wxGridCellRenderer
* renderer
, 
 259                        wxGridCellEditor
* editor
) 
 260         : m_typeName(typeName
), m_renderer(renderer
), m_editor(editor
) 
 263     ~wxGridDataTypeInfo() { delete m_renderer
; delete m_editor
; } 
 266     wxGridCellRenderer
* m_renderer
; 
 267     wxGridCellEditor
*   m_editor
; 
 271 WX_DEFINE_ARRAY(wxGridDataTypeInfo
*, wxGridDataTypeInfoArray
); 
 274 class WXDLLEXPORT wxGridTypeRegistry 
{ 
 276     ~wxGridTypeRegistry(); 
 277     void RegisterDataType(const wxString
& typeName
, 
 278                      wxGridCellRenderer
* renderer
, 
 279                      wxGridCellEditor
* editor
); 
 280     int FindDataType(const wxString
& typeName
); 
 281     wxGridCellRenderer
* GetRenderer(int index
); 
 282     wxGridCellEditor
*   GetEditor(int index
); 
 285     wxGridDataTypeInfoArray m_typeinfo
; 
 291 // ---------------------------------------------------------------------------- 
 292 // conditional compilation 
 293 // ---------------------------------------------------------------------------- 
 295 #ifndef WXGRID_DRAW_LINES 
 296 #define WXGRID_DRAW_LINES 1 
 299 // ---------------------------------------------------------------------------- 
 301 // ---------------------------------------------------------------------------- 
 303 //#define DEBUG_ATTR_CACHE 
 304 #ifdef DEBUG_ATTR_CACHE 
 305     static size_t gs_nAttrCacheHits 
= 0; 
 306     static size_t gs_nAttrCacheMisses 
= 0; 
 307 #endif // DEBUG_ATTR_CACHE 
 309 // ---------------------------------------------------------------------------- 
 311 // ---------------------------------------------------------------------------- 
 313 wxGridCellCoords 
wxGridNoCellCoords( -1, -1 ); 
 314 wxRect           
wxGridNoCellRect( -1, -1, -1, -1 ); 
 317 // TODO: fixed so far - make configurable later (and also different for x/y) 
 318 static const size_t GRID_SCROLL_LINE 
= 10; 
 320 // the size of hash tables used a bit everywhere (the max number of elements 
 321 // in these hash tables is the number of rows/columns) 
 322 static const int GRID_HASH_SIZE 
= 100; 
 324 // ============================================================================ 
 326 // ============================================================================ 
 328 // ---------------------------------------------------------------------------- 
 330 // ---------------------------------------------------------------------------- 
 332 wxGridCellEditor::wxGridCellEditor() 
 338 wxGridCellEditor::~wxGridCellEditor() 
 343 void wxGridCellEditor::Create(wxWindow
* WXUNUSED(parent
), 
 344                               wxWindowID 
WXUNUSED(id
), 
 345                               wxEvtHandler
* evtHandler
) 
 348         m_control
->PushEventHandler(evtHandler
); 
 351 void wxGridCellEditor::PaintBackground(const wxRect
& rectCell
, 
 352                                        wxGridCellAttr 
*attr
) 
 354     // erase the background because we might not fill the cell 
 355     wxClientDC 
dc(m_control
->GetParent()); 
 356     dc
.SetPen(*wxTRANSPARENT_PEN
); 
 357     dc
.SetBrush(wxBrush(attr
->GetBackgroundColour(), wxSOLID
)); 
 358     dc
.DrawRectangle(rectCell
); 
 360     // redraw the control we just painted over 
 361     m_control
->Refresh(); 
 364 void wxGridCellEditor::Destroy() 
 368         m_control
->Destroy(); 
 373 void wxGridCellEditor::Show(bool show
, wxGridCellAttr 
*attr
) 
 375     wxASSERT_MSG(m_control
, 
 376                  wxT("The wxGridCellEditor must be Created first!")); 
 377     m_control
->Show(show
); 
 381         // set the colours/fonts if we have any 
 384             m_colFgOld 
= m_control
->GetForegroundColour(); 
 385             m_control
->SetForegroundColour(attr
->GetTextColour()); 
 387             m_colBgOld 
= m_control
->GetBackgroundColour(); 
 388             m_control
->SetBackgroundColour(attr
->GetBackgroundColour()); 
 390             m_fontOld 
= m_control
->GetFont(); 
 391             m_control
->SetFont(attr
->GetFont()); 
 393             // can't do anything more in the base class version, the other 
 394             // attributes may only be used by the derived classes 
 399         // restore the standard colours fonts 
 400         if ( m_colFgOld
.Ok() ) 
 402             m_control
->SetForegroundColour(m_colFgOld
); 
 403             m_colFgOld 
= wxNullColour
; 
 406         if ( m_colBgOld
.Ok() ) 
 408             m_control
->SetBackgroundColour(m_colBgOld
); 
 409             m_colBgOld 
= wxNullColour
; 
 412         if ( m_fontOld
.Ok() ) 
 414             m_control
->SetFont(m_fontOld
); 
 415             m_fontOld 
= wxNullFont
; 
 420 void wxGridCellEditor::SetSize(const wxRect
& rect
) 
 422     wxASSERT_MSG(m_control
, 
 423                  wxT("The wxGridCellEditor must be Created first!")); 
 424     m_control
->SetSize(rect
); 
 427 void wxGridCellEditor::HandleReturn(wxKeyEvent
& event
) 
 433 void wxGridCellEditor::StartingKey(wxKeyEvent
& event
) 
 438 void wxGridCellEditor::StartingClick() 
 442 // ---------------------------------------------------------------------------- 
 443 // wxGridCellTextEditor 
 444 // ---------------------------------------------------------------------------- 
 446 wxGridCellTextEditor::wxGridCellTextEditor() 
 450 void wxGridCellTextEditor::Create(wxWindow
* parent
, 
 452                                   wxEvtHandler
* evtHandler
) 
 454     m_control 
= new wxTextCtrl(parent
, id
, wxEmptyString
, 
 455                                wxDefaultPosition
, wxDefaultSize
 
 456 #if defined(__WXMSW__) 
 457                                , wxTE_MULTILINE 
| wxTE_NO_VSCROLL 
// necessary ??? 
 461     wxGridCellEditor::Create(parent
, id
, evtHandler
); 
 464 void wxGridCellTextEditor::PaintBackground(const wxRect
& WXUNUSED(rectCell
), 
 465                                            wxGridCellAttr 
* WXUNUSED(attr
)) 
 467     // as we fill the entire client area, don't do anything here to minimize 
 471 void wxGridCellTextEditor::BeginEdit(int row
, int col
, wxGrid
* grid
) 
 473     wxASSERT_MSG(m_control
, 
 474                  wxT("The wxGridCellEditor must be Created first!")); 
 476     m_startValue 
= grid
->GetTable()->GetValue(row
, col
); 
 477     Text()->SetValue(m_startValue
); 
 478     Text()->SetInsertionPointEnd(); 
 483 bool wxGridCellTextEditor::EndEdit(int row
, int col
, bool saveValue
, 
 486     wxASSERT_MSG(m_control
, 
 487                  wxT("The wxGridCellEditor must be Created first!")); 
 489     bool changed 
= FALSE
; 
 490     wxString value 
= Text()->GetValue(); 
 491     if (value 
!= m_startValue
) 
 495         grid
->GetTable()->SetValue(row
, col
, value
); 
 497     m_startValue 
= wxEmptyString
; 
 498     Text()->SetValue(m_startValue
); 
 504 void wxGridCellTextEditor::Reset() 
 506     wxASSERT_MSG(m_control
, 
 507                  wxT("The wxGridCellEditor must be Created first!")); 
 509     Text()->SetValue(m_startValue
); 
 510     Text()->SetInsertionPointEnd(); 
 513 void wxGridCellTextEditor::StartingKey(wxKeyEvent
& event
) 
 515     if ( !event
.AltDown() && !event
.MetaDown() && !event
.ControlDown() ) 
 517         // insert the key in the control 
 518         long keycode 
= event
.KeyCode(); 
 519         if ( isprint(keycode
) ) 
 521             // FIXME this is not going to work for non letters... 
 522             if ( !event
.ShiftDown() ) 
 524                 keycode 
= tolower(keycode
); 
 527             Text()->AppendText((wxChar
)keycode
); 
 537 void wxGridCellTextEditor::HandleReturn(wxKeyEvent
& event
) 
 539 #if defined(__WXMOTIF__) || defined(__WXGTK__) 
 540     // wxMotif needs a little extra help... 
 541     int pos 
= Text()->GetInsertionPoint(); 
 542     wxString 
s( Text()->GetValue() ); 
 543     s 
= s
.Left(pos
) + "\n" + s
.Mid(pos
); 
 545     Text()->SetInsertionPoint( pos 
); 
 547     // the other ports can handle a Return key press 
 553 // ---------------------------------------------------------------------------- 
 554 // wxGridCellBoolEditor 
 555 // ---------------------------------------------------------------------------- 
 557 void wxGridCellBoolEditor::Create(wxWindow
* parent
, 
 559                                   wxEvtHandler
* evtHandler
) 
 561     m_control 
= new wxCheckBox(parent
, id
, wxEmptyString
, 
 562                                wxDefaultPosition
, wxDefaultSize
, 
 565     wxGridCellEditor::Create(parent
, id
, evtHandler
); 
 568 void wxGridCellBoolEditor::SetSize(const wxRect
& r
) 
 570     // position it in the centre of the rectangle (TODO: support alignment?) 
 572     m_control
->GetSize(&w
, &h
); 
 574     // the checkbox without label still has some space to the right in wxGTK, 
 575     // so shift it to the right 
 580     m_control
->Move(r
.x 
+ r
.width
/2 - w
/2, r
.y 
+ r
.height
/2 - h
/2); 
 583 void wxGridCellBoolEditor::Show(bool show
, wxGridCellAttr 
*attr
) 
 585     wxGridCellEditor::Show(show
, attr
); 
 588         // VZ: normally base class already does it, but it doesn't work (FIXME) 
 589         wxColour colBg 
= attr 
? attr
->GetBackgroundColour() : *wxLIGHT_GREY
; 
 590         CBox()->SetBackgroundColour(colBg
); 
 594 void wxGridCellBoolEditor::BeginEdit(int row
, int col
, wxGrid
* grid
) 
 596     wxASSERT_MSG(m_control
, 
 597                  wxT("The wxGridCellEditor must be Created first!")); 
 599     if (grid
->GetTable()->CanGetValueAs(row
, col
, wxT("bool"))) 
 600         m_startValue 
= grid
->GetTable()->GetValueAsBool(row
, col
); 
 602         m_startValue 
= !!grid
->GetTable()->GetValue(row
, col
); 
 603     CBox()->SetValue(m_startValue
); 
 607 bool wxGridCellBoolEditor::EndEdit(int row
, int col
, 
 611     wxASSERT_MSG(m_control
, 
 612                  wxT("The wxGridCellEditor must be Created first!")); 
 614     bool changed 
= FALSE
; 
 615     bool value 
= CBox()->GetValue(); 
 616     if ( value 
!= m_startValue 
) 
 621         if (grid
->GetTable()->CanGetValueAs(row
, col
, wxT("bool"))) 
 622             grid
->GetTable()->SetValueAsBool(row
, col
, value
); 
 624             grid
->GetTable()->SetValue(row
, col
, value 
? _T("1") : wxEmptyString
); 
 630 void wxGridCellBoolEditor::Reset() 
 632     wxASSERT_MSG(m_control
, 
 633                  wxT("The wxGridCellEditor must be Created first!")); 
 635     CBox()->SetValue(m_startValue
); 
 638 void wxGridCellBoolEditor::StartingClick() 
 640     CBox()->SetValue(!CBox()->GetValue()); 
 643 // ---------------------------------------------------------------------------- 
 644 // wxGridCellEditorEvtHandler 
 645 // ---------------------------------------------------------------------------- 
 647 void wxGridCellEditorEvtHandler::OnKeyDown(wxKeyEvent
& event
) 
 649     switch ( event
.KeyCode() ) 
 653             m_grid
->DisableCellEditControl(); 
 657             event
.Skip( m_grid
->ProcessEvent( event 
) ); 
 661             if (!m_grid
->ProcessEvent(event
)) 
 662                 m_editor
->HandleReturn(event
); 
 671 void wxGridCellEditorEvtHandler::OnChar(wxKeyEvent
& event
) 
 673     switch ( event
.KeyCode() ) 
 685 // ============================================================================ 
 687 // ============================================================================ 
 689 // ---------------------------------------------------------------------------- 
 690 // wxGridCellRenderer 
 691 // ---------------------------------------------------------------------------- 
 693 void wxGridCellRenderer::Draw(wxGrid
& grid
, 
 694                               wxGridCellAttr
& attr
, 
 700     dc
.SetBackgroundMode( wxSOLID 
); 
 704         dc
.SetBrush( wxBrush(grid
.GetSelectionBackground(), wxSOLID
) ); 
 708         dc
.SetBrush( wxBrush(attr
.GetBackgroundColour(), wxSOLID
) ); 
 711     dc
.SetPen( *wxTRANSPARENT_PEN 
); 
 712     dc
.DrawRectangle(rect
); 
 715 // ---------------------------------------------------------------------------- 
 716 // wxGridCellStringRenderer 
 717 // ---------------------------------------------------------------------------- 
 719 void wxGridCellStringRenderer::Draw(wxGrid
& grid
, 
 720                                     wxGridCellAttr
& attr
, 
 722                                     const wxRect
& rectCell
, 
 726     wxGridCellRenderer::Draw(grid
, attr
, dc
, rectCell
, row
, col
, isSelected
); 
 728     // now we only have to draw the text 
 729     dc
.SetBackgroundMode( wxTRANSPARENT 
); 
 731     // TODO some special colours for attr.IsReadOnly() case? 
 735         dc
.SetTextBackground( grid
.GetSelectionBackground() ); 
 736         dc
.SetTextForeground( grid
.GetSelectionForeground() ); 
 740         dc
.SetTextBackground( attr
.GetBackgroundColour() ); 
 741         dc
.SetTextForeground( attr
.GetTextColour() ); 
 743     dc
.SetFont( attr
.GetFont() ); 
 746     attr
.GetAlignment(&hAlign
, &vAlign
); 
 748     wxRect rect 
= rectCell
; 
 754     grid
.DrawTextRectangle(dc
, grid
.GetCellValue(row
, col
), 
 755                            rect
, hAlign
, vAlign
); 
 758 // ---------------------------------------------------------------------------- 
 759 // wxGridCellBoolRenderer 
 760 // ---------------------------------------------------------------------------- 
 762 void wxGridCellBoolRenderer::Draw(wxGrid
& grid
, 
 763                                   wxGridCellAttr
& attr
, 
 769     wxGridCellRenderer::Draw(grid
, attr
, dc
, rect
, row
, col
, isSelected
); 
 771     // between checkmark and box 
 772     static const wxCoord margin 
= 4; 
 775     static wxCoord s_checkSize 
= 0; 
 776     if ( s_checkSize 
== 0 ) 
 778         // compute it only once (no locks for MT safeness in GUI thread...) 
 779         wxCheckBox 
*checkbox 
= new wxCheckBox(&grid
, -1, wxEmptyString
); 
 780         wxSize size 
= checkbox
->GetBestSize(); 
 781         s_checkSize 
= size
.y 
+ margin
; 
 783         // FIXME wxGTK::wxCheckBox::GetBestSize() is really weird... 
 785         s_checkSize 
-= size
.y 
/ 2; 
 791     // draw a check mark in the centre (ignoring alignment - TODO) 
 793     rectMark
.x 
= rect
.x 
+ rect
.width
/2 - s_checkSize
/2; 
 794     rectMark
.y 
= rect
.y 
+ rect
.height
/2 - s_checkSize
/2; 
 795     rectMark
.width 
= rectMark
.height 
= s_checkSize
; 
 797     dc
.SetBrush(*wxTRANSPARENT_BRUSH
); 
 798     dc
.SetPen(wxPen(attr
.GetTextColour(), 1, wxSOLID
)); 
 799     dc
.DrawRectangle(rectMark
); 
 801     rectMark
.Inflate(-margin
); 
 804     if (grid
.GetTable()->CanGetValueAs(row
, col
, wxT("bool"))) 
 805         value 
= grid
.GetTable()->GetValueAsBool(row
, col
); 
 807         value 
= !!grid
.GetTable()->GetValue(row
, col
); 
 811         dc
.SetTextForeground(attr
.GetTextColour()); 
 812         dc
.DrawCheckMark(rectMark
); 
 816 // ---------------------------------------------------------------------------- 
 818 // ---------------------------------------------------------------------------- 
 820 const wxColour
& wxGridCellAttr::GetTextColour() const 
 826     else if (m_defGridAttr 
!= this) 
 828         return m_defGridAttr
->GetTextColour(); 
 832         wxFAIL_MSG(wxT("Missing default cell attribute")); 
 838 const wxColour
& wxGridCellAttr::GetBackgroundColour() const 
 840     if (HasBackgroundColour()) 
 842     else if (m_defGridAttr 
!= this) 
 843         return m_defGridAttr
->GetBackgroundColour(); 
 846         wxFAIL_MSG(wxT("Missing default cell attribute")); 
 852 const wxFont
& wxGridCellAttr::GetFont() const 
 856     else if (m_defGridAttr 
!= this) 
 857         return m_defGridAttr
->GetFont(); 
 860         wxFAIL_MSG(wxT("Missing default cell attribute")); 
 866 void wxGridCellAttr::GetAlignment(int *hAlign
, int *vAlign
) const 
 870         if ( hAlign 
) *hAlign 
= m_hAlign
; 
 871         if ( vAlign 
) *vAlign 
= m_vAlign
; 
 873     else if (m_defGridAttr 
!= this) 
 874         m_defGridAttr
->GetAlignment(hAlign
, vAlign
); 
 877         wxFAIL_MSG(wxT("Missing default cell attribute")); 
 882 // GetRenderer and GetEditor use a slightly different decision path about 
 883 // which to use.  If a non-default attr object has one then it is used, 
 884 // otherwise the default editor or renderer passed in is used.  It should be 
 885 // the default for the data type of the cell.  If it is NULL (because the 
 886 // table has a type that the grid does not have in its registry,) then the 
 887 // grid's default editor or renderer is used. 
 889 wxGridCellRenderer
* wxGridCellAttr::GetRenderer(wxGridCellRenderer
* def
) const 
 891     if ((m_defGridAttr 
!= this || def 
== NULL
) && HasRenderer()) 
 895     else if (m_defGridAttr 
!= this) 
 896         return m_defGridAttr
->GetRenderer(NULL
); 
 899         wxFAIL_MSG(wxT("Missing default cell attribute")); 
 904 wxGridCellEditor
* wxGridCellAttr::GetEditor(wxGridCellEditor
* def
) const 
 906     if ((m_defGridAttr 
!= this || def 
== NULL
) && HasEditor()) 
 910     else if (m_defGridAttr 
!= this) 
 911         return m_defGridAttr
->GetEditor(NULL
); 
 914         wxFAIL_MSG(wxT("Missing default cell attribute")); 
 919 // ---------------------------------------------------------------------------- 
 920 // wxGridCellAttrData 
 921 // ---------------------------------------------------------------------------- 
 923 void wxGridCellAttrData::SetAttr(wxGridCellAttr 
*attr
, int row
, int col
) 
 925     int n 
= FindIndex(row
, col
); 
 926     if ( n 
== wxNOT_FOUND 
) 
 929         m_attrs
.Add(new wxGridCellWithAttr(row
, col
, attr
)); 
 935             // change the attribute 
 936             m_attrs
[(size_t)n
].attr 
= attr
; 
 940             // remove this attribute 
 941             m_attrs
.RemoveAt((size_t)n
); 
 946 wxGridCellAttr 
*wxGridCellAttrData::GetAttr(int row
, int col
) const 
 948     wxGridCellAttr 
*attr 
= (wxGridCellAttr 
*)NULL
; 
 950     int n 
= FindIndex(row
, col
); 
 951     if ( n 
!= wxNOT_FOUND 
) 
 953         attr 
= m_attrs
[(size_t)n
].attr
; 
 960 void wxGridCellAttrData::UpdateAttrRows( size_t pos
, int numRows 
) 
 962     size_t count 
= m_attrs
.GetCount(); 
 963     for ( size_t n 
= 0; n 
< count
; n
++ ) 
 965         wxGridCellCoords
& coords 
= m_attrs
[n
].coords
; 
 966         wxCoord row 
= coords
.GetRow(); 
 967         if ((size_t)row 
>= pos
) 
 971                 // If rows inserted, include row counter where necessary 
 972                 coords
.SetRow(row 
+ numRows
); 
 974             else if (numRows 
< 0) 
 976                 // If rows deleted ... 
 977                 if ((size_t)row 
>= pos 
- numRows
) 
 979                     // ...either decrement row counter (if row still exists)... 
 980                     coords
.SetRow(row 
+ numRows
); 
 984                     // ...or remove the attribute 
 985                     m_attrs
.RemoveAt((size_t)n
); 
 993 void wxGridCellAttrData::UpdateAttrCols( size_t pos
, int numCols 
) 
 995     size_t count 
= m_attrs
.GetCount(); 
 996     for ( size_t n 
= 0; n 
< count
; n
++ ) 
 998         wxGridCellCoords
& coords 
= m_attrs
[n
].coords
; 
 999         wxCoord col 
= coords
.GetCol(); 
1000         if ( (size_t)col 
>= pos 
) 
1004                 // If rows inserted, include row counter where necessary 
1005                 coords
.SetCol(col 
+ numCols
); 
1007             else if (numCols 
< 0) 
1009                 // If rows deleted ... 
1010                 if ((size_t)col 
>= pos 
- numCols
) 
1012                     // ...either decrement row counter (if row still exists)... 
1013                     coords
.SetCol(col 
+ numCols
); 
1017                     // ...or remove the attribute 
1018                     m_attrs
.RemoveAt((size_t)n
); 
1026 int wxGridCellAttrData::FindIndex(int row
, int col
) const 
1028     size_t count 
= m_attrs
.GetCount(); 
1029     for ( size_t n 
= 0; n 
< count
; n
++ ) 
1031         const wxGridCellCoords
& coords 
= m_attrs
[n
].coords
; 
1032         if ( (coords
.GetRow() == row
) && (coords
.GetCol() == col
) ) 
1041 // ---------------------------------------------------------------------------- 
1042 // wxGridRowOrColAttrData 
1043 // ---------------------------------------------------------------------------- 
1045 wxGridRowOrColAttrData::~wxGridRowOrColAttrData() 
1047     size_t count 
= m_attrs
.Count(); 
1048     for ( size_t n 
= 0; n 
< count
; n
++ ) 
1050         m_attrs
[n
]->DecRef(); 
1054 wxGridCellAttr 
*wxGridRowOrColAttrData::GetAttr(int rowOrCol
) const 
1056     wxGridCellAttr 
*attr 
= (wxGridCellAttr 
*)NULL
; 
1058     int n 
= m_rowsOrCols
.Index(rowOrCol
); 
1059     if ( n 
!= wxNOT_FOUND 
) 
1061         attr 
= m_attrs
[(size_t)n
]; 
1068 void wxGridRowOrColAttrData::SetAttr(wxGridCellAttr 
*attr
, int rowOrCol
) 
1070     int n 
= m_rowsOrCols
.Index(rowOrCol
); 
1071     if ( n 
== wxNOT_FOUND 
) 
1073         // add the attribute 
1074         m_rowsOrCols
.Add(rowOrCol
); 
1081             // change the attribute 
1082             m_attrs
[(size_t)n
] = attr
; 
1086             // remove this attribute 
1087             m_attrs
[(size_t)n
]->DecRef(); 
1088             m_rowsOrCols
.RemoveAt((size_t)n
); 
1089             m_attrs
.RemoveAt((size_t)n
); 
1094 void wxGridRowOrColAttrData::UpdateAttrRowsOrCols( size_t pos
, int numRowsOrCols 
) 
1096     size_t count 
= m_attrs
.GetCount(); 
1097     for ( size_t n 
= 0; n 
< count
; n
++ ) 
1099         int & rowOrCol 
= m_rowsOrCols
[n
]; 
1100         if ( (size_t)rowOrCol 
>= pos 
) 
1102             if ( numRowsOrCols 
> 0 ) 
1104                 // If rows inserted, include row counter where necessary 
1105                 rowOrCol 
+= numRowsOrCols
; 
1107             else if ( numRowsOrCols 
< 0) 
1109                 // If rows deleted, either decrement row counter (if row still exists) 
1110                 if ((size_t)rowOrCol 
>= pos 
- numRowsOrCols
) 
1111                     rowOrCol 
+= numRowsOrCols
; 
1114                     m_rowsOrCols
.RemoveAt((size_t)n
); 
1115                     m_attrs
.RemoveAt((size_t)n
); 
1123 // ---------------------------------------------------------------------------- 
1124 // wxGridCellAttrProvider 
1125 // ---------------------------------------------------------------------------- 
1127 wxGridCellAttrProvider::wxGridCellAttrProvider() 
1129     m_data 
= (wxGridCellAttrProviderData 
*)NULL
; 
1132 wxGridCellAttrProvider::~wxGridCellAttrProvider() 
1137 void wxGridCellAttrProvider::InitData() 
1139     m_data 
= new wxGridCellAttrProviderData
; 
1142 wxGridCellAttr 
*wxGridCellAttrProvider::GetAttr(int row
, int col
) const 
1144     wxGridCellAttr 
*attr 
= (wxGridCellAttr 
*)NULL
; 
1147         // first look for the attribute of this specific cell 
1148         attr 
= m_data
->m_cellAttrs
.GetAttr(row
, col
); 
1152             // then look for the col attr (col attributes are more common than 
1153             // the row ones, hence they have priority) 
1154             attr 
= m_data
->m_colAttrs
.GetAttr(col
); 
1159             // finally try the row attributes 
1160             attr 
= m_data
->m_rowAttrs
.GetAttr(row
); 
1167 void wxGridCellAttrProvider::SetAttr(wxGridCellAttr 
*attr
, 
1173     m_data
->m_cellAttrs
.SetAttr(attr
, row
, col
); 
1176 void wxGridCellAttrProvider::SetRowAttr(wxGridCellAttr 
*attr
, int row
) 
1181     m_data
->m_rowAttrs
.SetAttr(attr
, row
); 
1184 void wxGridCellAttrProvider::SetColAttr(wxGridCellAttr 
*attr
, int col
) 
1189     m_data
->m_colAttrs
.SetAttr(attr
, col
); 
1192 void wxGridCellAttrProvider::UpdateAttrRows( size_t pos
, int numRows 
) 
1196         m_data
->m_cellAttrs
.UpdateAttrRows( pos
, numRows 
); 
1198         m_data
->m_rowAttrs
.UpdateAttrRowsOrCols( pos
, numRows 
); 
1202 void wxGridCellAttrProvider::UpdateAttrCols( size_t pos
, int numCols 
) 
1206         m_data
->m_cellAttrs
.UpdateAttrCols( pos
, numCols 
); 
1208         m_data
->m_colAttrs
.UpdateAttrRowsOrCols( pos
, numCols 
); 
1212 // ---------------------------------------------------------------------------- 
1213 // wxGridTypeRegistry 
1214 // ---------------------------------------------------------------------------- 
1216 wxGridTypeRegistry::~wxGridTypeRegistry() 
1218     for (size_t i
=0; i
<m_typeinfo
.Count(); i
++) 
1219         delete m_typeinfo
[i
]; 
1223 void wxGridTypeRegistry::RegisterDataType(const wxString
& typeName
, 
1224                                           wxGridCellRenderer
* renderer
, 
1225                                           wxGridCellEditor
* editor
) 
1228     wxGridDataTypeInfo
* info 
= new wxGridDataTypeInfo(typeName
, renderer
, editor
); 
1230     // is it already registered? 
1231     if ((loc 
= FindDataType(typeName
)) != -1) { 
1232         delete m_typeinfo
[loc
]; 
1233         m_typeinfo
[loc
] = info
; 
1236         m_typeinfo
.Add(info
); 
1240 int wxGridTypeRegistry::FindDataType(const wxString
& typeName
) 
1244     for (size_t i
=0; i
<m_typeinfo
.Count(); i
++) { 
1245         if (typeName 
== m_typeinfo
[i
]->m_typeName
) { 
1254 wxGridCellRenderer
* wxGridTypeRegistry::GetRenderer(int index
) 
1256     wxGridCellRenderer
* renderer 
= m_typeinfo
[index
]->m_renderer
; 
1260 wxGridCellEditor
*   wxGridTypeRegistry::GetEditor(int index
) 
1262     wxGridCellEditor
* editor 
= m_typeinfo
[index
]->m_editor
; 
1266 // ---------------------------------------------------------------------------- 
1268 // ---------------------------------------------------------------------------- 
1270 IMPLEMENT_ABSTRACT_CLASS( wxGridTableBase
, wxObject 
) 
1273 wxGridTableBase::wxGridTableBase() 
1275     m_view 
= (wxGrid 
*) NULL
; 
1276     m_attrProvider 
= (wxGridCellAttrProvider 
*) NULL
; 
1279 wxGridTableBase::~wxGridTableBase() 
1281     delete m_attrProvider
; 
1284 void wxGridTableBase::SetAttrProvider(wxGridCellAttrProvider 
*attrProvider
) 
1286     delete m_attrProvider
; 
1287     m_attrProvider 
= attrProvider
; 
1290 bool wxGridTableBase::CanHaveAttributes() 
1292     if ( ! GetAttrProvider() ) 
1294         // use the default attr provider by default 
1295         SetAttrProvider(new wxGridCellAttrProvider
); 
1300 wxGridCellAttr 
*wxGridTableBase::GetAttr(int row
, int col
) 
1302     if ( m_attrProvider 
) 
1303         return m_attrProvider
->GetAttr(row
, col
); 
1305         return (wxGridCellAttr 
*)NULL
; 
1308 void wxGridTableBase::SetAttr(wxGridCellAttr
* attr
, int row
, int col
) 
1310     if ( m_attrProvider 
) 
1312         m_attrProvider
->SetAttr(attr
, row
, col
); 
1316         // as we take ownership of the pointer and don't store it, we must 
1322 void wxGridTableBase::SetRowAttr(wxGridCellAttr 
*attr
, int row
) 
1324     if ( m_attrProvider 
) 
1326         m_attrProvider
->SetRowAttr(attr
, row
); 
1330         // as we take ownership of the pointer and don't store it, we must 
1336 void wxGridTableBase::SetColAttr(wxGridCellAttr 
*attr
, int col
) 
1338     if ( m_attrProvider 
) 
1340         m_attrProvider
->SetColAttr(attr
, col
); 
1344         // as we take ownership of the pointer and don't store it, we must 
1350 void wxGridTableBase::UpdateAttrRows( size_t pos
, int numRows 
) 
1352     if ( m_attrProvider 
) 
1354         m_attrProvider
->UpdateAttrRows( pos
, numRows 
); 
1358 void wxGridTableBase::UpdateAttrCols( size_t pos
, int numCols 
) 
1360     if ( m_attrProvider 
) 
1362         m_attrProvider
->UpdateAttrCols( pos
, numCols 
); 
1366 bool wxGridTableBase::InsertRows( size_t pos
, size_t numRows 
) 
1368     wxFAIL_MSG( wxT("Called grid table class function InsertRows\n" 
1369                     "but your derived table class does not override this function") ); 
1374 bool wxGridTableBase::AppendRows( size_t numRows 
) 
1376     wxFAIL_MSG( wxT("Called grid table class function AppendRows\n" 
1377                     "but your derived table class does not override this function")); 
1382 bool wxGridTableBase::DeleteRows( size_t pos
, size_t numRows 
) 
1384     wxFAIL_MSG( wxT("Called grid table class function DeleteRows\n" 
1385                     "but your derived table class does not override this function")); 
1390 bool wxGridTableBase::InsertCols( size_t pos
, size_t numCols 
) 
1392     wxFAIL_MSG( wxT("Called grid table class function InsertCols\n" 
1393                   "but your derived table class does not override this function")); 
1398 bool wxGridTableBase::AppendCols( size_t numCols 
) 
1400     wxFAIL_MSG(wxT("Called grid table class function AppendCols\n" 
1401                    "but your derived table class does not override this function")); 
1406 bool wxGridTableBase::DeleteCols( size_t pos
, size_t numCols 
) 
1408     wxFAIL_MSG( wxT("Called grid table class function DeleteCols\n" 
1409                     "but your derived table class does not override this function")); 
1415 wxString 
wxGridTableBase::GetRowLabelValue( int row 
) 
1418     s 
<< row 
+ 1; // RD: Starting the rows at zero confuses users, no matter 
1419                   //     how much it makes sense to us geeks. 
1423 wxString 
wxGridTableBase::GetColLabelValue( int col 
) 
1425     // default col labels are: 
1426     //   cols 0 to 25   : A-Z 
1427     //   cols 26 to 675 : AA-ZZ 
1432     for ( n 
= 1; ; n
++ ) 
1434         s 
+= (_T('A') + (wxChar
)( col%26 
)); 
1436         if ( col 
< 0 ) break; 
1439     // reverse the string... 
1441     for ( i 
= 0;  i 
< n
;  i
++ ) 
1450 wxString 
wxGridTableBase::GetTypeName( int WXUNUSED(row
), int WXUNUSED(col
) ) 
1452     return wxT("string"); 
1455 bool wxGridTableBase::CanGetValueAs( int WXUNUSED(row
), int WXUNUSED(col
), 
1456                                      const wxString
& typeName 
) 
1458     return typeName 
== wxT("string"); 
1461 bool wxGridTableBase::CanSetValueAs( int row
, int col
, const wxString
& typeName 
) 
1463     return CanGetValueAs(row
, col
, typeName
); 
1466 long wxGridTableBase::GetValueAsLong( int WXUNUSED(row
), int WXUNUSED(col
) ) 
1471 double wxGridTableBase::GetValueAsDouble( int WXUNUSED(row
), int WXUNUSED(col
) ) 
1476 bool wxGridTableBase::GetValueAsBool( int WXUNUSED(row
), int WXUNUSED(col
) ) 
1481 void wxGridTableBase::SetValueAsLong( int WXUNUSED(row
), int WXUNUSED(col
), 
1482                                       long WXUNUSED(value
) ) 
1486 void wxGridTableBase::SetValueAsDouble( int WXUNUSED(row
), int WXUNUSED(col
), 
1487                                         double WXUNUSED(value
) ) 
1491 void wxGridTableBase::SetValueAsBool( int WXUNUSED(row
), int WXUNUSED(col
), 
1492                                       bool WXUNUSED(value
) ) 
1497 void* wxGridTableBase::GetValueAsCustom( int WXUNUSED(row
), int WXUNUSED(col
), 
1498                                          const wxString
& WXUNUSED(typeName
) ) 
1503 void  wxGridTableBase::SetValueAsCustom( int WXUNUSED(row
), int WXUNUSED(col
), 
1504                                          const wxString
& WXUNUSED(typeName
), 
1505                                          void* WXUNUSED(value
) ) 
1510 ////////////////////////////////////////////////////////////////////// 
1512 // Message class for the grid table to send requests and notifications 
1516 wxGridTableMessage::wxGridTableMessage() 
1518     m_table 
= (wxGridTableBase 
*) NULL
; 
1524 wxGridTableMessage::wxGridTableMessage( wxGridTableBase 
*table
, int id
, 
1525                                         int commandInt1
, int commandInt2 
) 
1529     m_comInt1 
= commandInt1
; 
1530     m_comInt2 
= commandInt2
; 
1535 ////////////////////////////////////////////////////////////////////// 
1537 // A basic grid table for string data. An object of this class will 
1538 // created by wxGrid if you don't specify an alternative table class. 
1541 WX_DEFINE_OBJARRAY(wxGridStringArray
) 
1543 IMPLEMENT_DYNAMIC_CLASS( wxGridStringTable
, wxGridTableBase 
) 
1545 wxGridStringTable::wxGridStringTable() 
1550 wxGridStringTable::wxGridStringTable( int numRows
, int numCols 
) 
1555     m_data
.Alloc( numRows 
); 
1558     sa
.Alloc( numCols 
); 
1559     for ( col 
= 0;  col 
< numCols
;  col
++ ) 
1561         sa
.Add( wxEmptyString 
); 
1564     for ( row 
= 0;  row 
< numRows
;  row
++ ) 
1570 wxGridStringTable::~wxGridStringTable() 
1574 long wxGridStringTable::GetNumberRows() 
1576     return m_data
.GetCount(); 
1579 long wxGridStringTable::GetNumberCols() 
1581     if ( m_data
.GetCount() > 0 ) 
1582         return m_data
[0].GetCount(); 
1587 wxString 
wxGridStringTable::GetValue( int row
, int col 
) 
1589     // TODO: bounds checking 
1591     return m_data
[row
][col
]; 
1594 void wxGridStringTable::SetValue( int row
, int col
, const wxString
& value 
) 
1596     // TODO: bounds checking 
1598     m_data
[row
][col
] = value
; 
1601 bool wxGridStringTable::IsEmptyCell( int row
, int col 
) 
1603     // TODO: bounds checking 
1605     return (m_data
[row
][col
] == wxEmptyString
); 
1609 void wxGridStringTable::Clear() 
1612     int numRows
, numCols
; 
1614     numRows 
= m_data
.GetCount(); 
1617         numCols 
= m_data
[0].GetCount(); 
1619         for ( row 
= 0;  row 
< numRows
;  row
++ ) 
1621             for ( col 
= 0;  col 
< numCols
;  col
++ ) 
1623                 m_data
[row
][col
] = wxEmptyString
; 
1630 bool wxGridStringTable::InsertRows( size_t pos
, size_t numRows 
) 
1634     size_t curNumRows 
= m_data
.GetCount(); 
1635     size_t curNumCols 
= ( curNumRows 
> 0 ? m_data
[0].GetCount() : 0 ); 
1637     if ( pos 
>= curNumRows 
) 
1639         return AppendRows( numRows 
); 
1643     sa
.Alloc( curNumCols 
); 
1644     for ( col 
= 0;  col 
< curNumCols
;  col
++ ) 
1646         sa
.Add( wxEmptyString 
); 
1649     for ( row 
= pos
;  row 
< pos 
+ numRows
;  row
++ ) 
1651         m_data
.Insert( sa
, row 
); 
1653     UpdateAttrRows( pos
, numRows 
); 
1656         wxGridTableMessage 
msg( this, 
1657                                 wxGRIDTABLE_NOTIFY_ROWS_INSERTED
, 
1661         GetView()->ProcessTableMessage( msg 
); 
1667 bool wxGridStringTable::AppendRows( size_t numRows 
) 
1671     size_t curNumRows 
= m_data
.GetCount(); 
1672     size_t curNumCols 
= ( curNumRows 
> 0 ? m_data
[0].GetCount() : 0 ); 
1675     if ( curNumCols 
> 0 ) 
1677         sa
.Alloc( curNumCols 
); 
1678         for ( col 
= 0;  col 
< curNumCols
;  col
++ ) 
1680             sa
.Add( wxEmptyString 
); 
1684     for ( row 
= 0;  row 
< numRows
;  row
++ ) 
1691         wxGridTableMessage 
msg( this, 
1692                                 wxGRIDTABLE_NOTIFY_ROWS_APPENDED
, 
1695         GetView()->ProcessTableMessage( msg 
); 
1701 bool wxGridStringTable::DeleteRows( size_t pos
, size_t numRows 
) 
1705     size_t curNumRows 
= m_data
.GetCount(); 
1707     if ( pos 
>= curNumRows 
) 
1710         errmsg
.Printf("Called wxGridStringTable::DeleteRows(pos=%d, N=%d)\n" 
1711                       "Pos value is invalid for present table with %d rows", 
1712                       pos
, numRows
, curNumRows 
); 
1713         wxFAIL_MSG( wxT(errmsg
) ); 
1717     if ( numRows 
> curNumRows 
- pos 
) 
1719         numRows 
= curNumRows 
- pos
; 
1722     if ( numRows 
>= curNumRows 
) 
1724         m_data
.Empty();  // don't release memory just yet 
1728         for ( n 
= 0;  n 
< numRows
;  n
++ ) 
1730             m_data
.Remove( pos 
); 
1733     UpdateAttrRows( pos
, -((int)numRows
) ); 
1736         wxGridTableMessage 
msg( this, 
1737                                 wxGRIDTABLE_NOTIFY_ROWS_DELETED
, 
1741         GetView()->ProcessTableMessage( msg 
); 
1747 bool wxGridStringTable::InsertCols( size_t pos
, size_t numCols 
) 
1751     size_t curNumRows 
= m_data
.GetCount(); 
1752     size_t curNumCols 
= ( curNumRows 
> 0 ? m_data
[0].GetCount() : 0 ); 
1754     if ( pos 
>= curNumCols 
) 
1756         return AppendCols( numCols 
); 
1759     for ( row 
= 0;  row 
< curNumRows
;  row
++ ) 
1761         for ( col 
= pos
;  col 
< pos 
+ numCols
;  col
++ ) 
1763             m_data
[row
].Insert( wxEmptyString
, col 
); 
1766     UpdateAttrCols( pos
, numCols 
); 
1769         wxGridTableMessage 
msg( this, 
1770                                 wxGRIDTABLE_NOTIFY_COLS_INSERTED
, 
1774         GetView()->ProcessTableMessage( msg 
); 
1780 bool wxGridStringTable::AppendCols( size_t numCols 
) 
1784     size_t curNumRows 
= m_data
.GetCount(); 
1787         // TODO: something better than this ? 
1789         wxFAIL_MSG( wxT("Unable to append cols to a grid table with no rows.\n" 
1790                         "Call AppendRows() first") ); 
1794     for ( row 
= 0;  row 
< curNumRows
;  row
++ ) 
1796         for ( n 
= 0;  n 
< numCols
;  n
++ ) 
1798             m_data
[row
].Add( wxEmptyString 
); 
1804         wxGridTableMessage 
msg( this, 
1805                                 wxGRIDTABLE_NOTIFY_COLS_APPENDED
, 
1808         GetView()->ProcessTableMessage( msg 
); 
1814 bool wxGridStringTable::DeleteCols( size_t pos
, size_t numCols 
) 
1818     size_t curNumRows 
= m_data
.GetCount(); 
1819     size_t curNumCols 
= ( curNumRows 
> 0 ? m_data
[0].GetCount() : 0 ); 
1821     if ( pos 
>= curNumCols 
) 
1824         errmsg
.Printf( "Called wxGridStringTable::DeleteCols(pos=%d, N=%d)...\n" 
1825                         "Pos value is invalid for present table with %d cols", 
1826                         pos
, numCols
, curNumCols 
); 
1827         wxFAIL_MSG( wxT( errmsg 
) ); 
1831     if ( numCols 
> curNumCols 
- pos 
) 
1833         numCols 
= curNumCols 
- pos
; 
1836     for ( row 
= 0;  row 
< curNumRows
;  row
++ ) 
1838         if ( numCols 
>= curNumCols 
) 
1840             m_data
[row
].Clear(); 
1844             for ( n 
= 0;  n 
< numCols
;  n
++ ) 
1846                 m_data
[row
].Remove( pos 
); 
1850     UpdateAttrCols( pos
, -((int)numCols
) ); 
1853         wxGridTableMessage 
msg( this, 
1854                                 wxGRIDTABLE_NOTIFY_COLS_DELETED
, 
1858         GetView()->ProcessTableMessage( msg 
); 
1864 wxString 
wxGridStringTable::GetRowLabelValue( int row 
) 
1866     if ( row 
> (int)(m_rowLabels
.GetCount()) - 1 ) 
1868         // using default label 
1870         return wxGridTableBase::GetRowLabelValue( row 
); 
1874         return m_rowLabels
[ row 
]; 
1878 wxString 
wxGridStringTable::GetColLabelValue( int col 
) 
1880     if ( col 
> (int)(m_colLabels
.GetCount()) - 1 ) 
1882         // using default label 
1884         return wxGridTableBase::GetColLabelValue( col 
); 
1888         return m_colLabels
[ col 
]; 
1892 void wxGridStringTable::SetRowLabelValue( int row
, const wxString
& value 
) 
1894     if ( row 
> (int)(m_rowLabels
.GetCount()) - 1 ) 
1896         int n 
= m_rowLabels
.GetCount(); 
1898         for ( i 
= n
;  i 
<= row
;  i
++ ) 
1900             m_rowLabels
.Add( wxGridTableBase::GetRowLabelValue(i
) ); 
1904     m_rowLabels
[row
] = value
; 
1907 void wxGridStringTable::SetColLabelValue( int col
, const wxString
& value 
) 
1909     if ( col 
> (int)(m_colLabels
.GetCount()) - 1 ) 
1911         int n 
= m_colLabels
.GetCount(); 
1913         for ( i 
= n
;  i 
<= col
;  i
++ ) 
1915             m_colLabels
.Add( wxGridTableBase::GetColLabelValue(i
) ); 
1919     m_colLabels
[col
] = value
; 
1924 ////////////////////////////////////////////////////////////////////// 
1925 ////////////////////////////////////////////////////////////////////// 
1927 IMPLEMENT_DYNAMIC_CLASS( wxGridRowLabelWindow
, wxWindow 
) 
1929 BEGIN_EVENT_TABLE( wxGridRowLabelWindow
, wxWindow 
) 
1930     EVT_PAINT( wxGridRowLabelWindow::OnPaint 
) 
1931     EVT_MOUSE_EVENTS( wxGridRowLabelWindow::OnMouseEvent 
) 
1932     EVT_KEY_DOWN( wxGridRowLabelWindow::OnKeyDown 
) 
1935 wxGridRowLabelWindow::wxGridRowLabelWindow( wxGrid 
*parent
, 
1937                                             const wxPoint 
&pos
, const wxSize 
&size 
) 
1938   : wxWindow( parent
, id
, pos
, size 
) 
1943 void wxGridRowLabelWindow::OnPaint( wxPaintEvent 
&event 
) 
1947     // NO - don't do this because it will set both the x and y origin 
1948     // coords to match the parent scrolled window and we just want to 
1949     // set the y coord  - MB 
1951     // m_owner->PrepareDC( dc ); 
1954     m_owner
->CalcUnscrolledPosition( 0, 0, &x
, &y 
); 
1955     dc
.SetDeviceOrigin( 0, -y 
); 
1957     m_owner
->CalcRowLabelsExposed( GetUpdateRegion() ); 
1958     m_owner
->DrawRowLabels( dc 
); 
1962 void wxGridRowLabelWindow::OnMouseEvent( wxMouseEvent
& event 
) 
1964     m_owner
->ProcessRowLabelMouseEvent( event 
); 
1968 // This seems to be required for wxMotif otherwise the mouse 
1969 // cursor must be in the cell edit control to get key events 
1971 void wxGridRowLabelWindow::OnKeyDown( wxKeyEvent
& event 
) 
1973     if ( !m_owner
->ProcessEvent( event 
) ) event
.Skip(); 
1978 ////////////////////////////////////////////////////////////////////// 
1980 IMPLEMENT_DYNAMIC_CLASS( wxGridColLabelWindow
, wxWindow 
) 
1982 BEGIN_EVENT_TABLE( wxGridColLabelWindow
, wxWindow 
) 
1983     EVT_PAINT( wxGridColLabelWindow::OnPaint 
) 
1984     EVT_MOUSE_EVENTS( wxGridColLabelWindow::OnMouseEvent 
) 
1985     EVT_KEY_DOWN( wxGridColLabelWindow::OnKeyDown 
) 
1988 wxGridColLabelWindow::wxGridColLabelWindow( wxGrid 
*parent
, 
1990                                             const wxPoint 
&pos
, const wxSize 
&size 
) 
1991   : wxWindow( parent
, id
, pos
, size 
) 
1996 void wxGridColLabelWindow::OnPaint( wxPaintEvent 
&event 
) 
2000     // NO - don't do this because it will set both the x and y origin 
2001     // coords to match the parent scrolled window and we just want to 
2002     // set the x coord  - MB 
2004     // m_owner->PrepareDC( dc ); 
2007     m_owner
->CalcUnscrolledPosition( 0, 0, &x
, &y 
); 
2008     dc
.SetDeviceOrigin( -x
, 0 ); 
2010     m_owner
->CalcColLabelsExposed( GetUpdateRegion() ); 
2011     m_owner
->DrawColLabels( dc 
); 
2015 void wxGridColLabelWindow::OnMouseEvent( wxMouseEvent
& event 
) 
2017     m_owner
->ProcessColLabelMouseEvent( event 
); 
2021 // This seems to be required for wxMotif otherwise the mouse 
2022 // cursor must be in the cell edit control to get key events 
2024 void wxGridColLabelWindow::OnKeyDown( wxKeyEvent
& event 
) 
2026     if ( !m_owner
->ProcessEvent( event 
) ) event
.Skip(); 
2031 ////////////////////////////////////////////////////////////////////// 
2033 IMPLEMENT_DYNAMIC_CLASS( wxGridCornerLabelWindow
, wxWindow 
) 
2035 BEGIN_EVENT_TABLE( wxGridCornerLabelWindow
, wxWindow 
) 
2036     EVT_MOUSE_EVENTS( wxGridCornerLabelWindow::OnMouseEvent 
) 
2037     EVT_PAINT( wxGridCornerLabelWindow::OnPaint
) 
2038     EVT_KEY_DOWN( wxGridCornerLabelWindow::OnKeyDown 
) 
2041 wxGridCornerLabelWindow::wxGridCornerLabelWindow( wxGrid 
*parent
, 
2043                                                   const wxPoint 
&pos
, const wxSize 
&size 
) 
2044   : wxWindow( parent
, id
, pos
, size 
) 
2049 void wxGridCornerLabelWindow::OnPaint( wxPaintEvent
& WXUNUSED(event
) ) 
2053     int client_height 
= 0; 
2054     int client_width 
= 0; 
2055     GetClientSize( &client_width
, &client_height 
); 
2057     dc
.SetPen( *wxBLACK_PEN 
); 
2058     dc
.DrawLine( client_width
-1, client_height
-1, client_width
-1, 0 ); 
2059     dc
.DrawLine( client_width
-1, client_height
-1, 0, client_height
-1 ); 
2061     dc
.SetPen( *wxWHITE_PEN 
); 
2062     dc
.DrawLine( 0, 0, client_width
, 0 ); 
2063     dc
.DrawLine( 0, 0, 0, client_height 
); 
2067 void wxGridCornerLabelWindow::OnMouseEvent( wxMouseEvent
& event 
) 
2069     m_owner
->ProcessCornerLabelMouseEvent( event 
); 
2073 // This seems to be required for wxMotif otherwise the mouse 
2074 // cursor must be in the cell edit control to get key events 
2076 void wxGridCornerLabelWindow::OnKeyDown( wxKeyEvent
& event 
) 
2078     if ( !m_owner
->ProcessEvent( event 
) ) event
.Skip(); 
2083 ////////////////////////////////////////////////////////////////////// 
2085 IMPLEMENT_DYNAMIC_CLASS( wxGridWindow
, wxPanel 
) 
2087 BEGIN_EVENT_TABLE( wxGridWindow
, wxPanel 
) 
2088     EVT_PAINT( wxGridWindow::OnPaint 
) 
2089     EVT_MOUSE_EVENTS( wxGridWindow::OnMouseEvent 
) 
2090     EVT_KEY_DOWN( wxGridWindow::OnKeyDown 
) 
2091     EVT_ERASE_BACKGROUND( wxGridWindow::OnEraseBackground 
) 
2094 wxGridWindow::wxGridWindow( wxGrid 
*parent
, 
2095                             wxGridRowLabelWindow 
*rowLblWin
, 
2096                             wxGridColLabelWindow 
*colLblWin
, 
2097                             wxWindowID id
, const wxPoint 
&pos
, const wxSize 
&size 
) 
2098         : wxPanel( parent
, id
, pos
, size
, 0, "grid window" ) 
2101     m_rowLabelWin 
= rowLblWin
; 
2102     m_colLabelWin 
= colLblWin
; 
2103     SetBackgroundColour( "WHITE" ); 
2107 wxGridWindow::~wxGridWindow() 
2112 void wxGridWindow::OnPaint( wxPaintEvent 
&WXUNUSED(event
) ) 
2114     wxPaintDC 
dc( this ); 
2115     m_owner
->PrepareDC( dc 
); 
2116     wxRegion reg 
= GetUpdateRegion(); 
2117     m_owner
->CalcCellsExposed( reg 
); 
2118     m_owner
->DrawGridCellArea( dc 
); 
2119 #if WXGRID_DRAW_LINES 
2120     m_owner
->DrawAllGridLines( dc
, reg 
); 
2122     m_owner
->DrawHighlight( dc 
); 
2126 void wxGridWindow::ScrollWindow( int dx
, int dy
, const wxRect 
*rect 
) 
2128     wxPanel::ScrollWindow( dx
, dy
, rect 
); 
2129     m_rowLabelWin
->ScrollWindow( 0, dy
, rect 
); 
2130     m_colLabelWin
->ScrollWindow( dx
, 0, rect 
); 
2134 void wxGridWindow::OnMouseEvent( wxMouseEvent
& event 
) 
2136     m_owner
->ProcessGridCellMouseEvent( event 
); 
2140 // This seems to be required for wxMotif otherwise the mouse 
2141 // cursor must be in the cell edit control to get key events 
2143 void wxGridWindow::OnKeyDown( wxKeyEvent
& event 
) 
2145     if ( !m_owner
->ProcessEvent( event 
) ) event
.Skip(); 
2148 // We are trapping erase background events to reduce flicker under MSW 
2149 // and GTK but this can leave junk in the space beyond the last row and 
2150 // col.  So here we paint these spaces if they are visible. 
2152 void wxGridWindow::OnEraseBackground(wxEraseEvent
& event
) 
2155     GetClientSize( &cw
, &ch 
); 
2158     m_owner
->CalcUnscrolledPosition( cw
, ch
, &right
, &bottom 
); 
2161     rightRect 
= m_owner
->CellToRect( 0, m_owner
->GetNumberCols()-1 ); 
2164     bottomRect 
= m_owner
->CellToRect( m_owner
->GetNumberRows()-1, 0 ); 
2166     if ( right 
> rightRect
.GetRight()  ||  bottom 
> bottomRect
.GetBottom() ) 
2169         m_owner
->CalcUnscrolledPosition( 0, 0, &left
, &top 
); 
2171         wxClientDC 
dc( this ); 
2172         m_owner
->PrepareDC( dc 
); 
2173         dc
.SetBrush( wxBrush(m_owner
->GetDefaultCellBackgroundColour(), wxSOLID
) ); 
2174         dc
.SetPen( *wxTRANSPARENT_PEN 
); 
2176         if ( right 
> rightRect
.GetRight() ) 
2177             dc
.DrawRectangle( rightRect
.GetRight()+1, top
, right 
- rightRect
.GetRight(), ch 
); 
2179         if ( bottom 
> bottomRect
.GetBottom() ) 
2180             dc
.DrawRectangle( left
, bottomRect
.GetBottom()+1, cw
, bottom 
- bottomRect
.GetBottom() ); 
2185 ////////////////////////////////////////////////////////////////////// 
2188 IMPLEMENT_DYNAMIC_CLASS( wxGrid
, wxScrolledWindow 
) 
2190 BEGIN_EVENT_TABLE( wxGrid
, wxScrolledWindow 
) 
2191     EVT_PAINT( wxGrid::OnPaint 
) 
2192     EVT_SIZE( wxGrid::OnSize 
) 
2193     EVT_KEY_DOWN( wxGrid::OnKeyDown 
) 
2194     EVT_ERASE_BACKGROUND( wxGrid::OnEraseBackground 
) 
2197 wxGrid::wxGrid( wxWindow 
*parent
, 
2202                  const wxString
& name 
) 
2203   : wxScrolledWindow( parent
, id
, pos
, size
, style
, name 
), 
2204     m_colMinWidths(wxKEY_INTEGER
, GRID_HASH_SIZE
) 
2213     m_defaultCellAttr
->SafeDecRef(); 
2215 #ifdef DEBUG_ATTR_CACHE 
2216     size_t total 
= gs_nAttrCacheHits 
+ gs_nAttrCacheMisses
; 
2217     wxPrintf(_T("wxGrid attribute cache statistics: " 
2218                 "total: %u, hits: %u (%u%%)\n"), 
2219              total
, gs_nAttrCacheHits
, 
2220              total 
? (gs_nAttrCacheHits
*100) / total 
: 0); 
2226     delete m_typeRegistry
; 
2231 // ----- internal init and update functions 
2234 void wxGrid::Create() 
2236     m_created 
= FALSE
;    // set to TRUE by CreateGrid 
2237     m_displayed 
= TRUE
; // FALSE;  // set to TRUE by OnPaint 
2239     m_table        
= (wxGridTableBase 
*) NULL
; 
2242     m_cellEditCtrlEnabled 
= FALSE
; 
2244     m_defaultCellAttr 
= new wxGridCellAttr
; 
2245     m_defaultCellAttr
->SetDefAttr(m_defaultCellAttr
); 
2247     // Set default cell attributes 
2248     m_defaultCellAttr
->SetFont(GetFont()); 
2249     m_defaultCellAttr
->SetAlignment(wxLEFT
, wxTOP
); 
2250     m_defaultCellAttr
->SetTextColour( 
2251         wxSystemSettings::GetSystemColour(wxSYS_COLOUR_WINDOWTEXT
)); 
2252     m_defaultCellAttr
->SetBackgroundColour( 
2253         wxSystemSettings::GetSystemColour(wxSYS_COLOUR_WINDOW
)); 
2254     m_defaultCellAttr
->SetRenderer(new wxGridCellStringRenderer
); 
2255     m_defaultCellAttr
->SetEditor(new wxGridCellTextEditor
); 
2260     m_currentCellCoords 
= wxGridNoCellCoords
; 
2262     m_rowLabelWidth 
= WXGRID_DEFAULT_ROW_LABEL_WIDTH
; 
2263     m_colLabelHeight 
= WXGRID_DEFAULT_COL_LABEL_HEIGHT
; 
2265     // data type registration 
2266     m_typeRegistry 
= new wxGridTypeRegistry
; 
2267     RegisterDataType(wxT("string"), new wxGridCellStringRenderer
, 
2268                                     new wxGridCellTextEditor
); 
2269     RegisterDataType(wxT("bool"), new wxGridCellBoolRenderer
, 
2270                                   new wxGridCellBoolEditor
); 
2273     // subwindow components that make up the wxGrid 
2274     m_cornerLabelWin 
= new wxGridCornerLabelWindow( this, 
2279     m_rowLabelWin 
= new wxGridRowLabelWindow( this, 
2284     m_colLabelWin 
= new wxGridColLabelWindow( this, 
2289     m_gridWin 
= new wxGridWindow( this, 
2296     SetTargetWindow( m_gridWin 
); 
2300 bool wxGrid::CreateGrid( int numRows
, int numCols 
) 
2304         wxFAIL_MSG( wxT("wxGrid::CreateGrid or wxGrid::SetTable called more than once") ); 
2309         m_numRows 
= numRows
; 
2310         m_numCols 
= numCols
; 
2312         m_table 
= new wxGridStringTable( m_numRows
, m_numCols 
); 
2313         m_table
->SetView( this ); 
2322 bool wxGrid::SetTable( wxGridTableBase 
*table
, bool takeOwnership 
) 
2326         // RD: Actually, this should probably be allowed.  I think it would be 
2327         // nice to be able to switch multiple Tables in and out of a single 
2328         // View at runtime.  Is there anything in the implmentation that would 
2331         wxFAIL_MSG( wxT("wxGrid::CreateGrid or wxGrid::SetTable called more than once") ); 
2336         m_numRows 
= table
->GetNumberRows(); 
2337         m_numCols 
= table
->GetNumberCols(); 
2340         m_table
->SetView( this ); 
2353     if ( m_numRows 
<= 0 ) 
2354         m_numRows 
= WXGRID_DEFAULT_NUMBER_ROWS
; 
2356     if ( m_numCols 
<= 0 ) 
2357         m_numCols 
= WXGRID_DEFAULT_NUMBER_COLS
; 
2359     m_rowLabelWidth  
= WXGRID_DEFAULT_ROW_LABEL_WIDTH
; 
2360     m_colLabelHeight 
= WXGRID_DEFAULT_COL_LABEL_HEIGHT
; 
2362     if ( m_rowLabelWin 
) 
2364         m_labelBackgroundColour 
= m_rowLabelWin
->GetBackgroundColour(); 
2368         m_labelBackgroundColour 
= wxColour( _T("WHITE") ); 
2371     m_labelTextColour 
= wxColour( _T("BLACK") ); 
2374     m_attrCache
.row 
= -1; 
2376     // TODO: something better than this ? 
2378     m_labelFont 
= this->GetFont(); 
2379     m_labelFont
.SetWeight( m_labelFont
.GetWeight() + 2 ); 
2381     m_rowLabelHorizAlign 
= wxLEFT
; 
2382     m_rowLabelVertAlign  
= wxCENTRE
; 
2384     m_colLabelHorizAlign 
= wxCENTRE
; 
2385     m_colLabelVertAlign  
= wxTOP
; 
2387     m_defaultColWidth  
= WXGRID_DEFAULT_COL_WIDTH
; 
2388     m_defaultRowHeight 
= m_gridWin
->GetCharHeight(); 
2390 #if defined(__WXMOTIF__) || defined(__WXGTK__)  // see also text ctrl sizing in ShowCellEditControl() 
2391     m_defaultRowHeight 
+= 8; 
2393     m_defaultRowHeight 
+= 4; 
2396     m_gridLineColour 
= wxColour( 128, 128, 255 ); 
2397     m_gridLinesEnabled 
= TRUE
; 
2399     m_cursorMode  
= WXGRID_CURSOR_SELECT_CELL
; 
2400     m_winCapture 
= (wxWindow 
*)NULL
; 
2402     m_dragRowOrCol 
= -1; 
2403     m_isDragging 
= FALSE
; 
2404     m_startDragPos 
= wxDefaultPosition
; 
2406     m_waitForSlowClick 
= FALSE
; 
2408     m_rowResizeCursor 
= wxCursor( wxCURSOR_SIZENS 
); 
2409     m_colResizeCursor 
= wxCursor( wxCURSOR_SIZEWE 
); 
2411     m_currentCellCoords 
= wxGridNoCellCoords
; 
2413     m_selectedTopLeft 
= wxGridNoCellCoords
; 
2414     m_selectedBottomRight 
= wxGridNoCellCoords
; 
2415     m_selectionBackground 
= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_HIGHLIGHT
); 
2416     m_selectionForeground 
= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_HIGHLIGHTTEXT
); 
2418     m_editable 
= TRUE
;  // default for whole grid 
2420     m_inOnKeyDown 
= FALSE
; 
2424 // ---------------------------------------------------------------------------- 
2425 // the idea is to call these functions only when necessary because they create 
2426 // quite big arrays which eat memory mostly unnecessary - in particular, if 
2427 // default widths/heights are used for all rows/columns, we may not use these 
2430 // with some extra code, it should be possible to only store the 
2431 // widths/heights different from default ones but this will be done later... 
2432 // ---------------------------------------------------------------------------- 
2434 void wxGrid::InitRowHeights() 
2436     m_rowHeights
.Empty(); 
2437     m_rowBottoms
.Empty(); 
2439     m_rowHeights
.Alloc( m_numRows 
); 
2440     m_rowBottoms
.Alloc( m_numRows 
); 
2443     for ( int i 
= 0;  i 
< m_numRows
;  i
++ ) 
2445         m_rowHeights
.Add( m_defaultRowHeight 
); 
2446         rowBottom 
+= m_defaultRowHeight
; 
2447         m_rowBottoms
.Add( rowBottom 
); 
2451 void wxGrid::InitColWidths() 
2453     m_colWidths
.Empty(); 
2454     m_colRights
.Empty(); 
2456     m_colWidths
.Alloc( m_numCols 
); 
2457     m_colRights
.Alloc( m_numCols 
); 
2459     for ( int i 
= 0;  i 
< m_numCols
;  i
++ ) 
2461         m_colWidths
.Add( m_defaultColWidth 
); 
2462         colRight 
+= m_defaultColWidth
; 
2463         m_colRights
.Add( colRight 
); 
2467 int wxGrid::GetColWidth(int col
) const 
2469     return m_colWidths
.IsEmpty() ? m_defaultColWidth 
: m_colWidths
[col
]; 
2472 int wxGrid::GetColLeft(int col
) const 
2474     return m_colRights
.IsEmpty() ? col 
* m_defaultColWidth
 
2475                                  : m_colRights
[col
] - m_colWidths
[col
]; 
2478 int wxGrid::GetColRight(int col
) const 
2480     return m_colRights
.IsEmpty() ? (col 
+ 1) * m_defaultColWidth
 
2484 int wxGrid::GetRowHeight(int row
) const 
2486     return m_rowHeights
.IsEmpty() ? m_defaultRowHeight 
: m_rowHeights
[row
]; 
2489 int wxGrid::GetRowTop(int row
) const 
2491     return m_rowBottoms
.IsEmpty() ? row 
* m_defaultRowHeight
 
2492                                   : m_rowBottoms
[row
] - m_rowHeights
[row
]; 
2495 int wxGrid::GetRowBottom(int row
) const 
2497     return m_rowBottoms
.IsEmpty() ? (row 
+ 1) * m_defaultRowHeight
 
2498                                   : m_rowBottoms
[row
]; 
2501 void wxGrid::CalcDimensions() 
2504     GetClientSize( &cw
, &ch 
); 
2506     if ( m_numRows 
> 0  &&  m_numCols 
> 0 ) 
2508         int right 
= GetColRight( m_numCols
-1 ) + 50; 
2509         int bottom 
= GetRowBottom( m_numRows
-1 ) + 50; 
2511         // TODO: restore the scroll position that we had before sizing 
2514         GetViewStart( &x
, &y 
); 
2515         SetScrollbars( GRID_SCROLL_LINE
, GRID_SCROLL_LINE
, 
2516                        right
/GRID_SCROLL_LINE
, bottom
/GRID_SCROLL_LINE
, 
2522 void wxGrid::CalcWindowSizes() 
2525     GetClientSize( &cw
, &ch 
); 
2527     if ( m_cornerLabelWin
->IsShown() ) 
2528         m_cornerLabelWin
->SetSize( 0, 0, m_rowLabelWidth
, m_colLabelHeight 
); 
2530     if ( m_colLabelWin
->IsShown() ) 
2531         m_colLabelWin
->SetSize( m_rowLabelWidth
, 0, cw
-m_rowLabelWidth
, m_colLabelHeight
); 
2533     if ( m_rowLabelWin
->IsShown() ) 
2534         m_rowLabelWin
->SetSize( 0, m_colLabelHeight
, m_rowLabelWidth
, ch
-m_colLabelHeight
); 
2536     if ( m_gridWin
->IsShown() ) 
2537         m_gridWin
->SetSize( m_rowLabelWidth
, m_colLabelHeight
, cw
-m_rowLabelWidth
, ch
-m_colLabelHeight
); 
2541 // this is called when the grid table sends a message to say that it 
2542 // has been redimensioned 
2544 bool wxGrid::Redimension( wxGridTableMessage
& msg 
) 
2548     // if we were using the default widths/heights so far, we must change them 
2550     if ( m_colWidths
.IsEmpty() ) 
2555     if ( m_rowHeights
.IsEmpty() ) 
2560     switch ( msg
.GetId() ) 
2562         case wxGRIDTABLE_NOTIFY_ROWS_INSERTED
: 
2564             size_t pos 
= msg
.GetCommandInt(); 
2565             int numRows 
= msg
.GetCommandInt2(); 
2566             for ( i 
= 0;  i 
< numRows
;  i
++ ) 
2568                 m_rowHeights
.Insert( m_defaultRowHeight
, pos 
); 
2569                 m_rowBottoms
.Insert( 0, pos 
); 
2571             m_numRows 
+= numRows
; 
2574             if ( pos 
> 0 ) bottom 
= m_rowBottoms
[pos
-1]; 
2576             for ( i 
= pos
;  i 
< m_numRows
;  i
++ ) 
2578                 bottom 
+= m_rowHeights
[i
]; 
2579                 m_rowBottoms
[i
] = bottom
; 
2585         case wxGRIDTABLE_NOTIFY_ROWS_APPENDED
: 
2587             int numRows 
= msg
.GetCommandInt(); 
2588             for ( i 
= 0;  i 
< numRows
;  i
++ ) 
2590                 m_rowHeights
.Add( m_defaultRowHeight 
); 
2591                 m_rowBottoms
.Add( 0 ); 
2594             int oldNumRows 
= m_numRows
; 
2595             m_numRows 
+= numRows
; 
2598             if ( oldNumRows 
> 0 ) bottom 
= m_rowBottoms
[oldNumRows
-1]; 
2600             for ( i 
= oldNumRows
;  i 
< m_numRows
;  i
++ ) 
2602                 bottom 
+= m_rowHeights
[i
]; 
2603                 m_rowBottoms
[i
] = bottom
; 
2609         case wxGRIDTABLE_NOTIFY_ROWS_DELETED
: 
2611             size_t pos 
= msg
.GetCommandInt(); 
2612             int numRows 
= msg
.GetCommandInt2(); 
2613             for ( i 
= 0;  i 
< numRows
;  i
++ ) 
2615                 m_rowHeights
.Remove( pos 
); 
2616                 m_rowBottoms
.Remove( pos 
); 
2618             m_numRows 
-= numRows
; 
2623                 m_colWidths
.Clear(); 
2624                 m_colRights
.Clear(); 
2625                 m_currentCellCoords 
= wxGridNoCellCoords
; 
2629                 if ( m_currentCellCoords
.GetRow() >= m_numRows 
) 
2630                     m_currentCellCoords
.Set( 0, 0 ); 
2633                 for ( i 
= 0;  i 
< m_numRows
;  i
++ ) 
2635                     h 
+= m_rowHeights
[i
]; 
2636                     m_rowBottoms
[i
] = h
; 
2644         case wxGRIDTABLE_NOTIFY_COLS_INSERTED
: 
2646             size_t pos 
= msg
.GetCommandInt(); 
2647             int numCols 
= msg
.GetCommandInt2(); 
2648             for ( i 
= 0;  i 
< numCols
;  i
++ ) 
2650                 m_colWidths
.Insert( m_defaultColWidth
, pos 
); 
2651                 m_colRights
.Insert( 0, pos 
); 
2653             m_numCols 
+= numCols
; 
2656             if ( pos 
> 0 ) right 
= m_colRights
[pos
-1]; 
2658             for ( i 
= pos
;  i 
< m_numCols
;  i
++ ) 
2660                 right 
+= m_colWidths
[i
]; 
2661                 m_colRights
[i
] = right
; 
2667         case wxGRIDTABLE_NOTIFY_COLS_APPENDED
: 
2669             int numCols 
= msg
.GetCommandInt(); 
2670             for ( i 
= 0;  i 
< numCols
;  i
++ ) 
2672                 m_colWidths
.Add( m_defaultColWidth 
); 
2673                 m_colRights
.Add( 0 ); 
2676             int oldNumCols 
= m_numCols
; 
2677             m_numCols 
+= numCols
; 
2680             if ( oldNumCols 
> 0 ) right 
= m_colRights
[oldNumCols
-1]; 
2682             for ( i 
= oldNumCols
;  i 
< m_numCols
;  i
++ ) 
2684                 right 
+= m_colWidths
[i
]; 
2685                 m_colRights
[i
] = right
; 
2691         case wxGRIDTABLE_NOTIFY_COLS_DELETED
: 
2693             size_t pos 
= msg
.GetCommandInt(); 
2694             int numCols 
= msg
.GetCommandInt2(); 
2695             for ( i 
= 0;  i 
< numCols
;  i
++ ) 
2697                 m_colWidths
.Remove( pos 
); 
2698                 m_colRights
.Remove( pos 
); 
2700             m_numCols 
-= numCols
; 
2704 #if 0  // leave the row alone here so that AppendCols will work subsequently 
2706                 m_rowHeights
.Clear(); 
2707                 m_rowBottoms
.Clear(); 
2709                 m_currentCellCoords 
= wxGridNoCellCoords
; 
2713                 if ( m_currentCellCoords
.GetCol() >= m_numCols 
) 
2714                     m_currentCellCoords
.Set( 0, 0 ); 
2717                 for ( i 
= 0;  i 
< m_numCols
;  i
++ ) 
2719                     w 
+= m_colWidths
[i
]; 
2732 void wxGrid::CalcRowLabelsExposed( wxRegion
& reg 
) 
2734     wxRegionIterator 
iter( reg 
); 
2737     m_rowLabelsExposed
.Empty(); 
2744         // TODO: remove this when we can... 
2745         // There is a bug in wxMotif that gives garbage update 
2746         // rectangles if you jump-scroll a long way by clicking the 
2747         // scrollbar with middle button.  This is a work-around 
2749 #if defined(__WXMOTIF__) 
2751         m_gridWin
->GetClientSize( &cw
, &ch 
); 
2752         if ( r
.GetTop() > ch 
) r
.SetTop( 0 ); 
2753         r
.SetBottom( wxMin( r
.GetBottom(), ch 
) ); 
2756         // logical bounds of update region 
2759         CalcUnscrolledPosition( 0, r
.GetTop(), &dummy
, &top 
); 
2760         CalcUnscrolledPosition( 0, r
.GetBottom(), &dummy
, &bottom 
); 
2762         // find the row labels within these bounds 
2765         for ( row 
= 0;  row 
< m_numRows
;  row
++ ) 
2767             if ( GetRowBottom(row
) < top 
) 
2770             if ( GetRowTop(row
) > bottom 
) 
2773             m_rowLabelsExposed
.Add( row 
); 
2781 void wxGrid::CalcColLabelsExposed( wxRegion
& reg 
) 
2783     wxRegionIterator 
iter( reg 
); 
2786     m_colLabelsExposed
.Empty(); 
2793         // TODO: remove this when we can... 
2794         // There is a bug in wxMotif that gives garbage update 
2795         // rectangles if you jump-scroll a long way by clicking the 
2796         // scrollbar with middle button.  This is a work-around 
2798 #if defined(__WXMOTIF__) 
2800         m_gridWin
->GetClientSize( &cw
, &ch 
); 
2801         if ( r
.GetLeft() > cw 
) r
.SetLeft( 0 ); 
2802         r
.SetRight( wxMin( r
.GetRight(), cw 
) ); 
2805         // logical bounds of update region 
2808         CalcUnscrolledPosition( r
.GetLeft(), 0, &left
, &dummy 
); 
2809         CalcUnscrolledPosition( r
.GetRight(), 0, &right
, &dummy 
); 
2811         // find the cells within these bounds 
2814         for ( col 
= 0;  col 
< m_numCols
;  col
++ ) 
2816             if ( GetColRight(col
) < left 
) 
2819             if ( GetColLeft(col
) > right 
) 
2822             m_colLabelsExposed
.Add( col 
); 
2830 void wxGrid::CalcCellsExposed( wxRegion
& reg 
) 
2832     wxRegionIterator 
iter( reg 
); 
2835     m_cellsExposed
.Empty(); 
2836     m_rowsExposed
.Empty(); 
2837     m_colsExposed
.Empty(); 
2839     int left
, top
, right
, bottom
; 
2844         // TODO: remove this when we can... 
2845         // There is a bug in wxMotif that gives garbage update 
2846         // rectangles if you jump-scroll a long way by clicking the 
2847         // scrollbar with middle button.  This is a work-around 
2849 #if defined(__WXMOTIF__) 
2851         m_gridWin
->GetClientSize( &cw
, &ch 
); 
2852         if ( r
.GetTop() > ch 
) r
.SetTop( 0 ); 
2853         if ( r
.GetLeft() > cw 
) r
.SetLeft( 0 ); 
2854         r
.SetRight( wxMin( r
.GetRight(), cw 
) ); 
2855         r
.SetBottom( wxMin( r
.GetBottom(), ch 
) ); 
2858         // logical bounds of update region 
2860         CalcUnscrolledPosition( r
.GetLeft(), r
.GetTop(), &left
, &top 
); 
2861         CalcUnscrolledPosition( r
.GetRight(), r
.GetBottom(), &right
, &bottom 
); 
2863         // find the cells within these bounds 
2866         for ( row 
= 0;  row 
< m_numRows
;  row
++ ) 
2868             if ( GetRowBottom(row
) <= top 
) 
2871             if ( GetRowTop(row
) > bottom 
) 
2874             m_rowsExposed
.Add( row 
); 
2876             for ( col 
= 0;  col 
< m_numCols
;  col
++ ) 
2878                 if ( GetColRight(col
) <= left 
) 
2881                 if ( GetColLeft(col
) > right 
) 
2884                 if ( m_colsExposed
.Index( col 
) == wxNOT_FOUND 
) 
2885                     m_colsExposed
.Add( col 
); 
2886                 m_cellsExposed
.Add( wxGridCellCoords( row
, col 
) ); 
2895 void wxGrid::ProcessRowLabelMouseEvent( wxMouseEvent
& event 
) 
2898     wxPoint 
pos( event
.GetPosition() ); 
2899     CalcUnscrolledPosition( pos
.x
, pos
.y
, &x
, &y 
); 
2901     if ( event
.Dragging() ) 
2903         m_isDragging 
= TRUE
; 
2905         if ( event
.LeftIsDown() ) 
2907             switch( m_cursorMode 
) 
2909                 case WXGRID_CURSOR_RESIZE_ROW
: 
2911                     int cw
, ch
, left
, dummy
; 
2912                     m_gridWin
->GetClientSize( &cw
, &ch 
); 
2913                     CalcUnscrolledPosition( 0, 0, &left
, &dummy 
); 
2915                     wxClientDC 
dc( m_gridWin 
); 
2917                     y 
= wxMax( y
, GetRowTop(m_dragRowOrCol
) + WXGRID_MIN_ROW_HEIGHT 
); 
2918                     dc
.SetLogicalFunction(wxINVERT
); 
2919                     if ( m_dragLastPos 
>= 0 ) 
2921                         dc
.DrawLine( left
, m_dragLastPos
, left
+cw
, m_dragLastPos 
); 
2923                     dc
.DrawLine( left
, y
, left
+cw
, y 
); 
2928                 case WXGRID_CURSOR_SELECT_ROW
: 
2929                     if ( (row 
= YToRow( y 
)) >= 0  && 
2930                          !IsInSelection( row
, 0 ) ) 
2932                         SelectRow( row
, TRUE 
); 
2935                 // default label to suppress warnings about "enumeration value 
2936                 // 'xxx' not handled in switch 
2944     m_isDragging 
= FALSE
; 
2947     // ------------ Entering or leaving the window 
2949     if ( event
.Entering() || event
.Leaving() ) 
2951         ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
, m_rowLabelWin
); 
2955     // ------------ Left button pressed 
2957     else if ( event
.LeftDown() ) 
2959         // don't send a label click event for a hit on the 
2960         // edge of the row label - this is probably the user 
2961         // wanting to resize the row 
2963         if ( YToEdgeOfRow(y
) < 0 ) 
2967                  !SendEvent( wxEVT_GRID_LABEL_LEFT_CLICK
, row
, -1, event 
) ) 
2969                 SelectRow( row
, event
.ShiftDown() ); 
2970                 ChangeCursorMode(WXGRID_CURSOR_SELECT_ROW
, m_rowLabelWin
); 
2975             // starting to drag-resize a row 
2977             ChangeCursorMode(WXGRID_CURSOR_RESIZE_ROW
, m_rowLabelWin
); 
2982     // ------------ Left double click 
2984     else if (event
.LeftDClick() ) 
2986         if ( YToEdgeOfRow(y
) < 0 ) 
2989             SendEvent( wxEVT_GRID_LABEL_LEFT_DCLICK
, row
, -1, event 
); 
2994     // ------------ Left button released 
2996     else if ( event
.LeftUp() ) 
2998         if ( m_cursorMode 
== WXGRID_CURSOR_RESIZE_ROW 
) 
3000             DoEndDragResizeRow(); 
3002             // Note: we are ending the event *after* doing 
3003             // default processing in this case 
3005             SendEvent( wxEVT_GRID_ROW_SIZE
, m_dragRowOrCol
, -1, event 
); 
3008         ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
, m_rowLabelWin
); 
3013     // ------------ Right button down 
3015     else if ( event
.RightDown() ) 
3018         if ( !SendEvent( wxEVT_GRID_LABEL_RIGHT_CLICK
, row
, -1, event 
) ) 
3020             // no default action at the moment 
3025     // ------------ Right double click 
3027     else if ( event
.RightDClick() ) 
3030         if ( !SendEvent( wxEVT_GRID_LABEL_RIGHT_DCLICK
, row
, -1, event 
) ) 
3032             // no default action at the moment 
3037     // ------------ No buttons down and mouse moving 
3039     else if ( event
.Moving() ) 
3041         m_dragRowOrCol 
= YToEdgeOfRow( y 
); 
3042         if ( m_dragRowOrCol 
>= 0 ) 
3044             if ( m_cursorMode 
== WXGRID_CURSOR_SELECT_CELL 
) 
3046                 // don't capture the mouse yet 
3047                 ChangeCursorMode(WXGRID_CURSOR_RESIZE_ROW
, m_rowLabelWin
, FALSE
); 
3050         else if ( m_cursorMode 
!= WXGRID_CURSOR_SELECT_CELL 
) 
3052             ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
, m_rowLabelWin
, FALSE
); 
3058 void wxGrid::ProcessColLabelMouseEvent( wxMouseEvent
& event 
) 
3061     wxPoint 
pos( event
.GetPosition() ); 
3062     CalcUnscrolledPosition( pos
.x
, pos
.y
, &x
, &y 
); 
3064     if ( event
.Dragging() ) 
3066         m_isDragging 
= TRUE
; 
3068         if ( event
.LeftIsDown() ) 
3070             switch( m_cursorMode 
) 
3072                 case WXGRID_CURSOR_RESIZE_COL
: 
3074                     int cw
, ch
, dummy
, top
; 
3075                     m_gridWin
->GetClientSize( &cw
, &ch 
); 
3076                     CalcUnscrolledPosition( 0, 0, &dummy
, &top 
); 
3078                     wxClientDC 
dc( m_gridWin 
); 
3081                     x 
= wxMax( x
, GetColLeft(m_dragRowOrCol
) + 
3082                                   GetColMinimalWidth(m_dragRowOrCol
)); 
3083                     dc
.SetLogicalFunction(wxINVERT
); 
3084                     if ( m_dragLastPos 
>= 0 ) 
3086                         dc
.DrawLine( m_dragLastPos
, top
, m_dragLastPos
, top
+ch 
); 
3088                     dc
.DrawLine( x
, top
, x
, top
+ch 
); 
3093                 case WXGRID_CURSOR_SELECT_COL
: 
3094                     if ( (col 
= XToCol( x 
)) >= 0  && 
3095                          !IsInSelection( 0, col 
) ) 
3097                         SelectCol( col
, TRUE 
); 
3100                 // default label to suppress warnings about "enumeration value 
3101                 // 'xxx' not handled in switch 
3109     m_isDragging 
= FALSE
; 
3112     // ------------ Entering or leaving the window 
3114     if ( event
.Entering() || event
.Leaving() ) 
3116         ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
, m_colLabelWin
); 
3120     // ------------ Left button pressed 
3122     else if ( event
.LeftDown() ) 
3124         // don't send a label click event for a hit on the 
3125         // edge of the col label - this is probably the user 
3126         // wanting to resize the col 
3128         if ( XToEdgeOfCol(x
) < 0 ) 
3132                  !SendEvent( wxEVT_GRID_LABEL_LEFT_CLICK
, -1, col
, event 
) ) 
3134                 SelectCol( col
, event
.ShiftDown() ); 
3135                 ChangeCursorMode(WXGRID_CURSOR_SELECT_COL
, m_colLabelWin
); 
3140             // starting to drag-resize a col 
3142             ChangeCursorMode(WXGRID_CURSOR_RESIZE_COL
, m_colLabelWin
); 
3147     // ------------ Left double click 
3149     if ( event
.LeftDClick() ) 
3151         if ( XToEdgeOfCol(x
) < 0 ) 
3154             SendEvent( wxEVT_GRID_LABEL_LEFT_DCLICK
, -1, col
, event 
); 
3159     // ------------ Left button released 
3161     else if ( event
.LeftUp() ) 
3163         if ( m_cursorMode 
== WXGRID_CURSOR_RESIZE_COL 
) 
3165             DoEndDragResizeCol(); 
3167             // Note: we are ending the event *after* doing 
3168             // default processing in this case 
3170             SendEvent( wxEVT_GRID_COL_SIZE
, -1, m_dragRowOrCol
, event 
); 
3173         ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
, m_colLabelWin
); 
3178     // ------------ Right button down 
3180     else if ( event
.RightDown() ) 
3183         if ( !SendEvent( wxEVT_GRID_LABEL_RIGHT_CLICK
, -1, col
, event 
) ) 
3185             // no default action at the moment 
3190     // ------------ Right double click 
3192     else if ( event
.RightDClick() ) 
3195         if ( !SendEvent( wxEVT_GRID_LABEL_RIGHT_DCLICK
, -1, col
, event 
) ) 
3197             // no default action at the moment 
3202     // ------------ No buttons down and mouse moving 
3204     else if ( event
.Moving() ) 
3206         m_dragRowOrCol 
= XToEdgeOfCol( x 
); 
3207         if ( m_dragRowOrCol 
>= 0 ) 
3209             if ( m_cursorMode 
== WXGRID_CURSOR_SELECT_CELL 
) 
3211                 // don't capture the cursor yet 
3212                 ChangeCursorMode(WXGRID_CURSOR_RESIZE_COL
, m_colLabelWin
, FALSE
); 
3215         else if ( m_cursorMode 
!= WXGRID_CURSOR_SELECT_CELL 
) 
3217             ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
, m_colLabelWin
, FALSE
); 
3223 void wxGrid::ProcessCornerLabelMouseEvent( wxMouseEvent
& event 
) 
3225     if ( event
.LeftDown() ) 
3227         // indicate corner label by having both row and 
3230         if ( !SendEvent( wxEVT_GRID_LABEL_LEFT_CLICK
, -1, -1, event 
) ) 
3236     else if ( event
.LeftDClick() ) 
3238         SendEvent( wxEVT_GRID_LABEL_LEFT_DCLICK
, -1, -1, event 
); 
3241     else if ( event
.RightDown() ) 
3243         if ( !SendEvent( wxEVT_GRID_LABEL_RIGHT_CLICK
, -1, -1, event 
) ) 
3245             // no default action at the moment 
3249     else if ( event
.RightDClick() ) 
3251         if ( !SendEvent( wxEVT_GRID_LABEL_RIGHT_DCLICK
, -1, -1, event 
) ) 
3253             // no default action at the moment 
3258 void wxGrid::ChangeCursorMode(CursorMode mode
, 
3263     static const wxChar 
*cursorModes
[] = 
3272     wxLogTrace(_T("grid"), 
3273                _T("wxGrid cursor mode (mouse capture for %s): %s -> %s"), 
3274                win 
== m_colLabelWin 
? _T("colLabelWin") 
3275                                     : win 
? _T("rowLabelWin") 
3277                cursorModes
[m_cursorMode
], cursorModes
[mode
]); 
3278 #endif // __WXDEBUG__ 
3280     if ( mode 
== m_cursorMode 
) 
3285         // by default use the grid itself 
3291         m_winCapture
->ReleaseMouse(); 
3292         m_winCapture 
= (wxWindow 
*)NULL
; 
3295     m_cursorMode 
= mode
; 
3297     switch ( m_cursorMode 
) 
3299         case WXGRID_CURSOR_RESIZE_ROW
: 
3300             win
->SetCursor( m_rowResizeCursor 
); 
3303         case WXGRID_CURSOR_RESIZE_COL
: 
3304             win
->SetCursor( m_colResizeCursor 
); 
3308             win
->SetCursor( *wxSTANDARD_CURSOR 
); 
3311     // we need to capture mouse when resizing 
3312     bool resize 
= m_cursorMode 
== WXGRID_CURSOR_RESIZE_ROW 
|| 
3313                   m_cursorMode 
== WXGRID_CURSOR_RESIZE_COL
; 
3315     if ( captureMouse 
&& resize 
) 
3317         win
->CaptureMouse(); 
3322 void wxGrid::ProcessGridCellMouseEvent( wxMouseEvent
& event 
) 
3325     wxPoint 
pos( event
.GetPosition() ); 
3326     CalcUnscrolledPosition( pos
.x
, pos
.y
, &x
, &y 
); 
3328     wxGridCellCoords coords
; 
3329     XYToCell( x
, y
, coords 
); 
3331     if ( event
.Dragging() ) 
3333         //wxLogDebug("pos(%d, %d) coords(%d, %d)", pos.x, pos.y, coords.GetRow(), coords.GetCol()); 
3335         // Don't start doing anything until the mouse has been drug at 
3336         // least 3 pixels in any direction... 
3339             if (m_startDragPos 
== wxDefaultPosition
) 
3341                 m_startDragPos 
= pos
; 
3344             if (abs(m_startDragPos
.x 
- pos
.x
) < 4 && abs(m_startDragPos
.y 
- pos
.y
) < 4) 
3348         m_isDragging 
= TRUE
; 
3349         if ( m_cursorMode 
== WXGRID_CURSOR_SELECT_CELL 
) 
3351             // Hide the edit control, so it 
3352             // won't interfer with drag-shrinking. 
3353             if ( IsCellEditControlEnabled() ) 
3354                 HideCellEditControl(); 
3356             // Have we captured the mouse yet? 
3359                 m_winCapture 
= m_gridWin
; 
3360                 m_winCapture
->CaptureMouse(); 
3363             if ( coords 
!= wxGridNoCellCoords 
) 
3365                 if ( !IsSelection() ) 
3367                     SelectBlock( coords
, coords 
); 
3371                     SelectBlock( m_currentCellCoords
, coords 
); 
3374                 if (! IsVisible(coords
)) 
3376                     MakeCellVisible(coords
); 
3377                     // TODO: need to introduce a delay or something here.  The 
3378                     // scrolling is way to fast, at least on MSW. 
3382         else if ( m_cursorMode 
== WXGRID_CURSOR_RESIZE_ROW 
) 
3384             int cw
, ch
, left
, dummy
; 
3385             m_gridWin
->GetClientSize( &cw
, &ch 
); 
3386             CalcUnscrolledPosition( 0, 0, &left
, &dummy 
); 
3388             wxClientDC 
dc( m_gridWin 
); 
3390             y 
= wxMax( y
, GetRowTop(m_dragRowOrCol
) + WXGRID_MIN_ROW_HEIGHT 
); 
3391             dc
.SetLogicalFunction(wxINVERT
); 
3392             if ( m_dragLastPos 
>= 0 ) 
3394                 dc
.DrawLine( left
, m_dragLastPos
, left
+cw
, m_dragLastPos 
); 
3396             dc
.DrawLine( left
, y
, left
+cw
, y 
); 
3399         else if ( m_cursorMode 
== WXGRID_CURSOR_RESIZE_COL 
) 
3401             int cw
, ch
, dummy
, top
; 
3402             m_gridWin
->GetClientSize( &cw
, &ch 
); 
3403             CalcUnscrolledPosition( 0, 0, &dummy
, &top 
); 
3405             wxClientDC 
dc( m_gridWin 
); 
3407             x 
= wxMax( x
, GetColLeft(m_dragRowOrCol
) + 
3408                           GetColMinimalWidth(m_dragRowOrCol
) ); 
3409             dc
.SetLogicalFunction(wxINVERT
); 
3410             if ( m_dragLastPos 
>= 0 ) 
3412                 dc
.DrawLine( m_dragLastPos
, top
, m_dragLastPos
, top
+ch 
); 
3414             dc
.DrawLine( x
, top
, x
, top
+ch 
); 
3421     m_isDragging 
= FALSE
; 
3422     m_startDragPos 
= wxDefaultPosition
; 
3425     if ( coords 
!= wxGridNoCellCoords 
) 
3427         // VZ: if we do this, the mode is reset to WXGRID_CURSOR_SELECT_CELL 
3428         //     immediately after it becomes WXGRID_CURSOR_RESIZE_ROW/COL under 
3431         if ( event
.Entering() || event
.Leaving() ) 
3433             ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
); 
3434             m_gridWin
->SetCursor( *wxSTANDARD_CURSOR 
); 
3439         // ------------ Left button pressed 
3441         if ( event
.LeftDown() ) 
3443             DisableCellEditControl(); 
3444             if ( event
.ShiftDown() ) 
3446                 SelectBlock( m_currentCellCoords
, coords 
); 
3448             else if ( XToEdgeOfCol(x
) < 0  && 
3449                       YToEdgeOfRow(y
) < 0 ) 
3451                 if ( !SendEvent( wxEVT_GRID_CELL_LEFT_CLICK
, 
3456                     MakeCellVisible( coords 
); 
3458                     // if this is the second click on this cell then start 
3460                     if ( m_waitForSlowClick 
&& 
3461                          (coords 
== m_currentCellCoords
) && 
3462                          CanEnableCellControl()) 
3464                         EnableCellEditControl(); 
3466                         wxGridCellAttr
* attr 
= GetCellAttr(m_currentCellCoords
); 
3467                         attr
->GetEditor(GetDefaultEditorForCell(coords
.GetRow(), coords
.GetCol()))->StartingClick(); 
3470                         m_waitForSlowClick 
= FALSE
; 
3474                         SetCurrentCell( coords 
); 
3475                         m_waitForSlowClick 
= TRUE
; 
3482         // ------------ Left double click 
3484         else if ( event
.LeftDClick() ) 
3486             DisableCellEditControl(); 
3487             if ( XToEdgeOfCol(x
) < 0  &&  YToEdgeOfRow(y
) < 0 ) 
3489                 SendEvent( wxEVT_GRID_CELL_LEFT_DCLICK
, 
3497         // ------------ Left button released 
3499         else if ( event
.LeftUp() ) 
3501             if ( m_cursorMode 
== WXGRID_CURSOR_SELECT_CELL 
) 
3503                 if ( IsSelection() ) 
3507                         m_winCapture
->ReleaseMouse(); 
3508                         m_winCapture 
= NULL
; 
3510                     SendEvent( wxEVT_GRID_RANGE_SELECT
, -1, -1, event 
); 
3513                 // Show the edit control, if it has been hidden for 
3515                 ShowCellEditControl(); 
3517             else if ( m_cursorMode 
== WXGRID_CURSOR_RESIZE_ROW 
) 
3519                 ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
); 
3520                 DoEndDragResizeRow(); 
3522                 // Note: we are ending the event *after* doing 
3523                 // default processing in this case 
3525                 SendEvent( wxEVT_GRID_ROW_SIZE
, m_dragRowOrCol
, -1, event 
); 
3527             else if ( m_cursorMode 
== WXGRID_CURSOR_RESIZE_COL 
) 
3529                 ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
); 
3530                 DoEndDragResizeCol(); 
3532                 // Note: we are ending the event *after* doing 
3533                 // default processing in this case 
3535                 SendEvent( wxEVT_GRID_COL_SIZE
, -1, m_dragRowOrCol
, event 
); 
3542         // ------------ Right button down 
3544         else if ( event
.RightDown() ) 
3546             DisableCellEditControl(); 
3547             if ( !SendEvent( wxEVT_GRID_CELL_RIGHT_CLICK
, 
3552                 // no default action at the moment 
3557         // ------------ Right double click 
3559         else if ( event
.RightDClick() ) 
3561             DisableCellEditControl(); 
3562             if ( !SendEvent( wxEVT_GRID_CELL_RIGHT_DCLICK
, 
3567                 // no default action at the moment 
3571         // ------------ Moving and no button action 
3573         else if ( event
.Moving() && !event
.IsButton() ) 
3575             int dragRow 
= YToEdgeOfRow( y 
); 
3576             int dragCol 
= XToEdgeOfCol( x 
); 
3578             // Dragging on the corner of a cell to resize in both 
3579             // directions is not implemented yet... 
3581             if ( dragRow 
>= 0  &&  dragCol 
>= 0 ) 
3583                 ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
); 
3589                 m_dragRowOrCol 
= dragRow
; 
3591                 if ( m_cursorMode 
== WXGRID_CURSOR_SELECT_CELL 
) 
3593                     ChangeCursorMode(WXGRID_CURSOR_RESIZE_ROW
); 
3601                 m_dragRowOrCol 
= dragCol
; 
3603                 if ( m_cursorMode 
== WXGRID_CURSOR_SELECT_CELL 
) 
3605                     ChangeCursorMode(WXGRID_CURSOR_RESIZE_COL
); 
3611             // Neither on a row or col edge 
3613             if ( m_cursorMode 
!= WXGRID_CURSOR_SELECT_CELL 
) 
3615                 ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
); 
3622 void wxGrid::DoEndDragResizeRow() 
3624     if ( m_dragLastPos 
>= 0 ) 
3626         // erase the last line and resize the row 
3628         int cw
, ch
, left
, dummy
; 
3629         m_gridWin
->GetClientSize( &cw
, &ch 
); 
3630         CalcUnscrolledPosition( 0, 0, &left
, &dummy 
); 
3632         wxClientDC 
dc( m_gridWin 
); 
3634         dc
.SetLogicalFunction( wxINVERT 
); 
3635         dc
.DrawLine( left
, m_dragLastPos
, left
+cw
, m_dragLastPos 
); 
3636         HideCellEditControl(); 
3638         int rowTop 
= GetRowTop(m_dragRowOrCol
); 
3639         SetRowSize( m_dragRowOrCol
, 
3640                     wxMax( m_dragLastPos 
- rowTop
, WXGRID_MIN_ROW_HEIGHT 
) ); 
3642         if ( !GetBatchCount() ) 
3644             // Only needed to get the correct rect.y: 
3645             wxRect 
rect ( CellToRect( m_dragRowOrCol
, 0 ) ); 
3647             CalcScrolledPosition(0, rect
.y
, &dummy
, &rect
.y
); 
3648             rect
.width 
= m_rowLabelWidth
; 
3649             rect
.height 
= ch 
- rect
.y
; 
3650             m_rowLabelWin
->Refresh( TRUE
, &rect 
); 
3652             m_gridWin
->Refresh( FALSE
, &rect 
); 
3655         ShowCellEditControl(); 
3660 void wxGrid::DoEndDragResizeCol() 
3662     if ( m_dragLastPos 
>= 0 ) 
3664         // erase the last line and resize the col 
3666         int cw
, ch
, dummy
, top
; 
3667         m_gridWin
->GetClientSize( &cw
, &ch 
); 
3668         CalcUnscrolledPosition( 0, 0, &dummy
, &top 
); 
3670         wxClientDC 
dc( m_gridWin 
); 
3672         dc
.SetLogicalFunction( wxINVERT 
); 
3673         dc
.DrawLine( m_dragLastPos
, top
, m_dragLastPos
, top
+ch 
); 
3674         HideCellEditControl(); 
3676         int colLeft 
= GetColLeft(m_dragRowOrCol
); 
3677         SetColSize( m_dragRowOrCol
, 
3678                     wxMax( m_dragLastPos 
- colLeft
, 
3679                            GetColMinimalWidth(m_dragRowOrCol
) ) ); 
3681         if ( !GetBatchCount() ) 
3683             // Only needed to get the correct rect.x: 
3684             wxRect 
rect ( CellToRect( 0, m_dragRowOrCol 
) ); 
3686             CalcScrolledPosition(rect
.x
, 0, &rect
.x
, &dummy
); 
3687             rect
.width 
= cw 
- rect
.x
; 
3688             rect
.height 
= m_colLabelHeight
; 
3689             m_colLabelWin
->Refresh( TRUE
, &rect 
); 
3691             m_gridWin
->Refresh( FALSE
, &rect 
); 
3694         ShowCellEditControl(); 
3701 // ------ interaction with data model 
3703 bool wxGrid::ProcessTableMessage( wxGridTableMessage
& msg 
) 
3705     switch ( msg
.GetId() ) 
3707         case wxGRIDTABLE_REQUEST_VIEW_GET_VALUES
: 
3708             return GetModelValues(); 
3710         case wxGRIDTABLE_REQUEST_VIEW_SEND_VALUES
: 
3711             return SetModelValues(); 
3713         case wxGRIDTABLE_NOTIFY_ROWS_INSERTED
: 
3714         case wxGRIDTABLE_NOTIFY_ROWS_APPENDED
: 
3715         case wxGRIDTABLE_NOTIFY_ROWS_DELETED
: 
3716         case wxGRIDTABLE_NOTIFY_COLS_INSERTED
: 
3717         case wxGRIDTABLE_NOTIFY_COLS_APPENDED
: 
3718         case wxGRIDTABLE_NOTIFY_COLS_DELETED
: 
3719             return Redimension( msg 
); 
3728 // The behaviour of this function depends on the grid table class 
3729 // Clear() function.  For the default wxGridStringTable class the 
3730 // behavious is to replace all cell contents with wxEmptyString but 
3731 // not to change the number of rows or cols. 
3733 void wxGrid::ClearGrid() 
3738         SetEditControlValue(); 
3739         if ( !GetBatchCount() ) m_gridWin
->Refresh(); 
3744 bool wxGrid::InsertRows( int pos
, int numRows
, bool WXUNUSED(updateLabels
) ) 
3746     // TODO: something with updateLabels flag 
3750         wxFAIL_MSG( wxT("Called wxGrid::InsertRows() before calling CreateGrid()") ); 
3756         if (IsCellEditControlEnabled()) 
3757             DisableCellEditControl(); 
3759         bool ok 
= m_table
->InsertRows( pos
, numRows 
); 
3761         // the table will have sent the results of the insert row 
3762         // operation to this view object as a grid table message 
3766             if ( m_numCols 
== 0 ) 
3768                 m_table
->AppendCols( WXGRID_DEFAULT_NUMBER_COLS 
); 
3770                 // TODO: perhaps instead of appending the default number of cols 
3771                 // we should remember what the last non-zero number of cols was ? 
3775             if ( m_currentCellCoords 
== wxGridNoCellCoords 
) 
3777                 // if we have just inserted cols into an empty grid the current 
3778                 // cell will be undefined... 
3780                 SetCurrentCell( 0, 0 ); 
3784             if ( !GetBatchCount() ) Refresh(); 
3787         SetEditControlValue(); 
3797 bool wxGrid::AppendRows( int numRows
, bool WXUNUSED(updateLabels
) ) 
3799     // TODO: something with updateLabels flag 
3803         wxFAIL_MSG( wxT("Called wxGrid::AppendRows() before calling CreateGrid()") ); 
3807     if ( m_table 
&& m_table
->AppendRows( numRows 
) ) 
3809         if ( m_currentCellCoords 
== wxGridNoCellCoords 
) 
3811             // if we have just inserted cols into an empty grid the current 
3812             // cell will be undefined... 
3814             SetCurrentCell( 0, 0 ); 
3817         // the table will have sent the results of the append row 
3818         // operation to this view object as a grid table message 
3821         if ( !GetBatchCount() ) Refresh(); 
3831 bool wxGrid::DeleteRows( int pos
, int numRows
, bool WXUNUSED(updateLabels
) ) 
3833     // TODO: something with updateLabels flag 
3837         wxFAIL_MSG( wxT("Called wxGrid::DeleteRows() before calling CreateGrid()") ); 
3843         if (IsCellEditControlEnabled()) 
3844             DisableCellEditControl(); 
3846         if (m_table
->DeleteRows( pos
, numRows 
)) 
3849             // the table will have sent the results of the delete row 
3850             // operation to this view object as a grid table message 
3853             if ( !GetBatchCount() ) Refresh(); 
3861 bool wxGrid::InsertCols( int pos
, int numCols
, bool WXUNUSED(updateLabels
) ) 
3863     // TODO: something with updateLabels flag 
3867         wxFAIL_MSG( wxT("Called wxGrid::InsertCols() before calling CreateGrid()") ); 
3873         if (IsCellEditControlEnabled()) 
3874             DisableCellEditControl(); 
3876         bool ok 
= m_table
->InsertCols( pos
, numCols 
); 
3878         // the table will have sent the results of the insert col 
3879         // operation to this view object as a grid table message 
3883             if ( m_currentCellCoords 
== wxGridNoCellCoords 
) 
3885                 // if we have just inserted cols into an empty grid the current 
3886                 // cell will be undefined... 
3888                 SetCurrentCell( 0, 0 ); 
3892             if ( !GetBatchCount() ) Refresh(); 
3895         SetEditControlValue(); 
3905 bool wxGrid::AppendCols( int numCols
, bool WXUNUSED(updateLabels
) ) 
3907     // TODO: something with updateLabels flag 
3911         wxFAIL_MSG( wxT("Called wxGrid::AppendCols() before calling CreateGrid()") ); 
3915     if ( m_table 
&& m_table
->AppendCols( numCols 
) ) 
3917         // the table will have sent the results of the append col 
3918         // operation to this view object as a grid table message 
3920         if ( m_currentCellCoords 
== wxGridNoCellCoords 
) 
3922             // if we have just inserted cols into an empty grid the current 
3923             // cell will be undefined... 
3925             SetCurrentCell( 0, 0 ); 
3929         if ( !GetBatchCount() ) Refresh(); 
3939 bool wxGrid::DeleteCols( int pos
, int numCols
, bool WXUNUSED(updateLabels
) ) 
3941     // TODO: something with updateLabels flag 
3945         wxFAIL_MSG( wxT("Called wxGrid::DeleteCols() before calling CreateGrid()") ); 
3951         if (IsCellEditControlEnabled()) 
3952             DisableCellEditControl(); 
3954         if ( m_table
->DeleteCols( pos
, numCols 
) ) 
3956             // the table will have sent the results of the delete col 
3957             // operation to this view object as a grid table message 
3960             if ( !GetBatchCount() ) Refresh(); 
3970 // ----- event handlers 
3973 // Generate a grid event based on a mouse event and 
3974 // return the result of ProcessEvent() 
3976 bool wxGrid::SendEvent( const wxEventType type
, 
3978                         wxMouseEvent
& mouseEv 
) 
3980     if ( type 
== wxEVT_GRID_ROW_SIZE 
|| type 
== wxEVT_GRID_COL_SIZE 
) 
3982         int rowOrCol 
= (row 
== -1 ? col 
: row
); 
3984         wxGridSizeEvent 
gridEvt( GetId(), 
3988                                  mouseEv
.GetX(), mouseEv
.GetY(), 
3989                                  mouseEv
.ControlDown(), 
3990                                  mouseEv
.ShiftDown(), 
3992                                  mouseEv
.MetaDown() ); 
3994         return GetEventHandler()->ProcessEvent(gridEvt
); 
3996     else if ( type 
== wxEVT_GRID_RANGE_SELECT 
) 
3998         wxGridRangeSelectEvent 
gridEvt( GetId(), 
4002                                         m_selectedBottomRight
, 
4003                                         mouseEv
.ControlDown(), 
4004                                         mouseEv
.ShiftDown(), 
4006                                         mouseEv
.MetaDown() ); 
4008         return GetEventHandler()->ProcessEvent(gridEvt
); 
4012         wxGridEvent 
gridEvt( GetId(), 
4016                              mouseEv
.GetX(), mouseEv
.GetY(), 
4017                              mouseEv
.ControlDown(), 
4018                              mouseEv
.ShiftDown(), 
4020                              mouseEv
.MetaDown() ); 
4022         return GetEventHandler()->ProcessEvent(gridEvt
); 
4027 // Generate a grid event of specified type and return the result 
4028 // of ProcessEvent(). 
4030 bool wxGrid::SendEvent( const wxEventType type
, 
4033     if ( type 
== wxEVT_GRID_ROW_SIZE 
|| type 
== wxEVT_GRID_COL_SIZE 
) 
4035         int rowOrCol 
= (row 
== -1 ? col 
: row
); 
4037         wxGridSizeEvent 
gridEvt( GetId(), 
4042         return GetEventHandler()->ProcessEvent(gridEvt
); 
4046         wxGridEvent 
gridEvt( GetId(), 
4051         return GetEventHandler()->ProcessEvent(gridEvt
); 
4056 void wxGrid::OnPaint( wxPaintEvent
& WXUNUSED(event
) ) 
4058     wxPaintDC 
dc( this ); 
4060     if ( m_currentCellCoords 
== wxGridNoCellCoords  
&& 
4061          m_numRows 
&& m_numCols 
) 
4063         m_currentCellCoords
.Set(0, 0); 
4064         SetEditControlValue(); 
4065         ShowCellEditControl(); 
4072 // This is just here to make sure that CalcDimensions gets called when 
4073 // the grid view is resized... then the size event is skipped to allow 
4074 // the box sizers to handle everything 
4076 void wxGrid::OnSize( wxSizeEvent
& event 
) 
4083 void wxGrid::OnKeyDown( wxKeyEvent
& event 
) 
4085     if ( m_inOnKeyDown 
) 
4087         // shouldn't be here - we are going round in circles... 
4089         wxFAIL_MSG( wxT("wxGrid::OnKeyDown called while already active") ); 
4092     m_inOnKeyDown 
= TRUE
; 
4094     // propagate the event up and see if it gets processed 
4096     wxWindow 
*parent 
= GetParent(); 
4097     wxKeyEvent 
keyEvt( event 
); 
4098     keyEvt
.SetEventObject( parent 
); 
4100     if ( !parent
->GetEventHandler()->ProcessEvent( keyEvt 
) ) 
4103         // TODO:  Should also support Shift-cursor keys for 
4104         //        extending the selection.  Maybe add a flag to 
4105         //        MoveCursorXXX() and MoveCursorXXXBlock() and 
4106         //        just send event.ShiftDown(). 
4108         // try local handlers 
4110         switch ( event
.KeyCode() ) 
4113                 if ( event
.ControlDown() ) 
4115                     MoveCursorUpBlock(); 
4124                 if ( event
.ControlDown() ) 
4126                     MoveCursorDownBlock(); 
4135                 if ( event
.ControlDown() ) 
4137                     MoveCursorLeftBlock(); 
4146                 if ( event
.ControlDown() ) 
4148                     MoveCursorRightBlock(); 
4157                 if ( event
.ControlDown() ) 
4159                     event
.Skip();  // to let the edit control have the return 
4168                 if (event
.ShiftDown()) 
4175                 if ( event
.ControlDown() ) 
4177                     MakeCellVisible( 0, 0 ); 
4178                     SetCurrentCell( 0, 0 ); 
4187                 if ( event
.ControlDown() ) 
4189                     MakeCellVisible( m_numRows
-1, m_numCols
-1 ); 
4190                     SetCurrentCell( m_numRows
-1, m_numCols
-1 ); 
4206             // We don't want these keys to trigger the edit control, any others? 
4215                 if ( !IsEditable() ) 
4220                 // Otherwise fall through to default 
4223                 // now try the cell edit control 
4225                 if ( !IsCellEditControlEnabled() && CanEnableCellControl() ) 
4227                     EnableCellEditControl(); 
4228                     int row 
= m_currentCellCoords
.GetRow(); 
4229                     int col 
= m_currentCellCoords
.GetCol(); 
4230                     wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
4231                     attr
->GetEditor(GetDefaultEditorForCell(row
, col
))->StartingKey(event
); 
4236                     // let others process char events for readonly cells 
4243     m_inOnKeyDown 
= FALSE
; 
4247 void wxGrid::OnEraseBackground(wxEraseEvent
&) 
4251 void wxGrid::SetCurrentCell( const wxGridCellCoords
& coords 
) 
4253     if ( SendEvent( wxEVT_GRID_SELECT_CELL
, coords
.GetRow(), coords
.GetCol() ) ) 
4255         // the event has been intercepted - do nothing 
4260          m_currentCellCoords 
!= wxGridNoCellCoords 
) 
4262         HideCellEditControl(); 
4263         SaveEditControlValue(); 
4264         DisableCellEditControl(); 
4266         // Clear the old current cell highlight 
4267         wxRect r 
= BlockToDeviceRect(m_currentCellCoords
, m_currentCellCoords
); 
4269         // Otherwise refresh redraws the highlight! 
4270         m_currentCellCoords 
= coords
; 
4272         m_gridWin
->Refresh( FALSE
, &r 
); 
4275     m_currentCellCoords 
= coords
; 
4277     SetEditControlValue(); 
4281         wxClientDC 
dc(m_gridWin
); 
4284         wxGridCellAttr
* attr 
= GetCellAttr(coords
); 
4285         DrawCellHighlight(dc
, attr
); 
4288         if ( IsSelection() ) 
4290             wxRect 
r( SelectionToDeviceRect() ); 
4292             if ( !GetBatchCount() ) m_gridWin
->Refresh( FALSE
, &r 
); 
4299 // ------ functions to get/send data (see also public functions) 
4302 bool wxGrid::GetModelValues() 
4306         // all we need to do is repaint the grid 
4308         m_gridWin
->Refresh(); 
4316 bool wxGrid::SetModelValues() 
4322         for ( row 
= 0;  row 
< m_numRows
;  row
++ ) 
4324             for ( col 
= 0;  col 
< m_numCols
;  col
++ ) 
4326                 m_table
->SetValue( row
, col
, GetCellValue(row
, col
) ); 
4338 // Note - this function only draws cells that are in the list of 
4339 // exposed cells (usually set from the update region by 
4340 // CalcExposedCells) 
4342 void wxGrid::DrawGridCellArea( wxDC
& dc 
) 
4344     if ( !m_numRows 
|| !m_numCols 
) return; 
4347     size_t numCells 
= m_cellsExposed
.GetCount(); 
4349     for ( i 
= 0;  i 
< numCells
;  i
++ ) 
4351         DrawCell( dc
, m_cellsExposed
[i
] ); 
4356 void wxGrid::DrawCell( wxDC
& dc
, const wxGridCellCoords
& coords 
) 
4358     int row 
= coords
.GetRow(); 
4359     int col 
= coords
.GetCol(); 
4361     if ( GetColWidth(col
) <= 0 || GetRowHeight(row
) <= 0 ) 
4364     // we draw the cell border ourselves 
4365 #if !WXGRID_DRAW_LINES 
4366     if ( m_gridLinesEnabled 
) 
4367         DrawCellBorder( dc
, coords 
); 
4370     wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
4372     bool isCurrent 
= coords 
== m_currentCellCoords
; 
4375     rect
.x 
= GetColLeft(col
); 
4376     rect
.y 
= GetRowTop(row
); 
4377     rect
.width 
= GetColWidth(col
) - 1; 
4378     rect
.height 
= GetRowHeight(row
) - 1; 
4380     // if the editor is shown, we should use it and not the renderer 
4381     if ( isCurrent 
&& IsCellEditControlEnabled() ) 
4383         attr
->GetEditor(GetDefaultEditorForCell(row
, col
))-> 
4384             PaintBackground(rect
, attr
); 
4388         // but all the rest is drawn by the cell renderer and hence may be 
4390         attr
->GetRenderer(GetDefaultRendererForCell(row
,col
))-> 
4391             Draw(*this, *attr
, dc
, rect
, row
, col
, IsInSelection(coords
)); 
4398 void wxGrid::DrawCellHighlight( wxDC
& dc
, const wxGridCellAttr 
*attr 
) 
4400     int row 
= m_currentCellCoords
.GetRow(); 
4401     int col 
= m_currentCellCoords
.GetCol(); 
4403     if ( GetColWidth(col
) <= 0 || GetRowHeight(row
) <= 0 ) 
4407     rect
.x 
= GetColLeft(col
); 
4408     rect
.y 
= GetRowTop(row
); 
4409     rect
.width 
= GetColWidth(col
) - 1; 
4410     rect
.height 
= GetRowHeight(row
) - 1; 
4412     // hmmm... what could we do here to show that the cell is disabled? 
4413     // for now, I just draw a thinner border than for the other ones, but 
4414     // it doesn't look really good 
4415     dc
.SetPen(wxPen(m_gridLineColour
, attr
->IsReadOnly() ? 1 : 3, wxSOLID
)); 
4416     dc
.SetBrush(*wxTRANSPARENT_BRUSH
); 
4418     dc
.DrawRectangle(rect
); 
4421         // VZ: my experiments with 3d borders... 
4423         // how to properly set colours for arbitrary bg? 
4424         wxCoord x1 
= rect
.x
, 
4426                 x2 
= rect
.x 
+ rect
.width 
-1, 
4427                 y2 
= rect
.y 
+ rect
.height 
-1; 
4429         dc
.SetPen(*wxWHITE_PEN
); 
4430         dc
.DrawLine(x1
, y1
, x2
, y1
); 
4431         dc
.DrawLine(x1
, y1
, x1
, y2
); 
4433         dc
.DrawLine(x1 
+ 1, y2 
- 1, x2 
- 1, y2 
- 1); 
4434         dc
.DrawLine(x2 
- 1, y1 
+ 1, x2 
- 1, y2 
); 
4436         dc
.SetPen(*wxBLACK_PEN
); 
4437         dc
.DrawLine(x1
, y2
, x2
, y2
); 
4438         dc
.DrawLine(x2
, y1
, x2
, y2
+1); 
4443 void wxGrid::DrawCellBorder( wxDC
& dc
, const wxGridCellCoords
& coords 
) 
4445     int row 
= coords
.GetRow(); 
4446     int col 
= coords
.GetCol(); 
4447     if ( GetColWidth(col
) <= 0 || GetRowHeight(row
) <= 0 ) 
4450     dc
.SetPen( wxPen(GetGridLineColour(), 1, wxSOLID
) ); 
4452     // right hand border 
4454     dc
.DrawLine( GetColRight(col
), GetRowTop(row
), 
4455                  GetColRight(col
), GetRowBottom(row
) ); 
4459     dc
.DrawLine( GetColLeft(col
), GetRowBottom(row
), 
4460                  GetColRight(col
), GetRowBottom(row
) ); 
4463 void wxGrid::DrawHighlight(wxDC
& dc
) 
4465     // if the active cell was repainted, repaint its highlight too because it 
4466     // might have been damaged by the grid lines 
4467     size_t count 
= m_cellsExposed
.GetCount(); 
4468     for ( size_t n 
= 0; n 
< count
; n
++ ) 
4470         if ( m_cellsExposed
[n
] == m_currentCellCoords 
) 
4472             wxGridCellAttr
* attr 
= GetCellAttr(m_currentCellCoords
); 
4473             DrawCellHighlight(dc
, attr
); 
4481 // TODO: remove this ??? 
4482 // This is used to redraw all grid lines e.g. when the grid line colour 
4485 void wxGrid::DrawAllGridLines( wxDC
& dc
, const wxRegion 
& reg 
) 
4487     if ( !m_gridLinesEnabled 
|| 
4489          !m_numCols 
) return; 
4491     int top
, bottom
, left
, right
; 
4496       m_gridWin
->GetClientSize(&cw
, &ch
); 
4498       // virtual coords of visible area 
4500       CalcUnscrolledPosition( 0, 0, &left
, &top 
); 
4501       CalcUnscrolledPosition( cw
, ch
, &right
, &bottom 
); 
4506       reg
.GetBox(x
, y
, w
, h
); 
4507       CalcUnscrolledPosition( x
, y
, &left
, &top 
); 
4508       CalcUnscrolledPosition( x 
+ w
, y 
+ h
, &right
, &bottom 
); 
4511     // avoid drawing grid lines past the last row and col 
4513     right 
= wxMin( right
, GetColRight(m_numCols 
- 1) ); 
4514     bottom 
= wxMin( bottom
, GetRowBottom(m_numRows 
- 1) ); 
4516     dc
.SetPen( wxPen(GetGridLineColour(), 1, wxSOLID
) ); 
4518     // horizontal grid lines 
4521     for ( i 
= 0; i 
< m_numRows
; i
++ ) 
4523         int bot 
= GetRowBottom(i
) - 1; 
4532             dc
.DrawLine( left
, bot
, right
, bot 
); 
4537     // vertical grid lines 
4539     for ( i 
= 0; i 
< m_numCols
; i
++ ) 
4541         int colRight 
= GetColRight(i
) - 1; 
4542         if ( colRight 
> right 
) 
4547         if ( colRight 
>= left 
) 
4549             dc
.DrawLine( colRight
, top
, colRight
, bottom 
); 
4555 void wxGrid::DrawRowLabels( wxDC
& dc 
) 
4557     if ( !m_numRows 
|| !m_numCols 
) return; 
4560     size_t numLabels 
= m_rowLabelsExposed
.GetCount(); 
4562     for ( i 
= 0;  i 
< numLabels
;  i
++ ) 
4564         DrawRowLabel( dc
, m_rowLabelsExposed
[i
] ); 
4569 void wxGrid::DrawRowLabel( wxDC
& dc
, int row 
) 
4571     if ( GetRowHeight(row
) <= 0 ) 
4574     int rowTop 
= GetRowTop(row
), 
4575         rowBottom 
= GetRowBottom(row
) - 1; 
4577     dc
.SetPen( *wxBLACK_PEN 
); 
4578     dc
.DrawLine( m_rowLabelWidth
-1, rowTop
, 
4579                  m_rowLabelWidth
-1, rowBottom 
); 
4581     dc
.DrawLine( 0, rowBottom
, m_rowLabelWidth
-1, rowBottom 
); 
4583     dc
.SetPen( *wxWHITE_PEN 
); 
4584     dc
.DrawLine( 0, rowTop
, 0, rowBottom 
); 
4585     dc
.DrawLine( 0, rowTop
, m_rowLabelWidth
-1, rowTop 
); 
4587     dc
.SetBackgroundMode( wxTRANSPARENT 
); 
4588     dc
.SetTextForeground( GetLabelTextColour() ); 
4589     dc
.SetFont( GetLabelFont() ); 
4592     GetRowLabelAlignment( &hAlign
, &vAlign 
); 
4596     rect
.SetY( GetRowTop(row
) + 2 ); 
4597     rect
.SetWidth( m_rowLabelWidth 
- 4 ); 
4598     rect
.SetHeight( GetRowHeight(row
) - 4 ); 
4599     DrawTextRectangle( dc
, GetRowLabelValue( row 
), rect
, hAlign
, vAlign 
); 
4603 void wxGrid::DrawColLabels( wxDC
& dc 
) 
4605     if ( !m_numRows 
|| !m_numCols 
) return; 
4608     size_t numLabels 
= m_colLabelsExposed
.GetCount(); 
4610     for ( i 
= 0;  i 
< numLabels
;  i
++ ) 
4612         DrawColLabel( dc
, m_colLabelsExposed
[i
] ); 
4617 void wxGrid::DrawColLabel( wxDC
& dc
, int col 
) 
4619     if ( GetColWidth(col
) <= 0 ) 
4622     int colLeft 
= GetColLeft(col
), 
4623         colRight 
= GetColRight(col
) - 1; 
4625     dc
.SetPen( *wxBLACK_PEN 
); 
4626     dc
.DrawLine( colRight
, 0, 
4627                  colRight
, m_colLabelHeight
-1 ); 
4629     dc
.DrawLine( colLeft
, m_colLabelHeight
-1, 
4630                  colRight
, m_colLabelHeight
-1 ); 
4632     dc
.SetPen( *wxWHITE_PEN 
); 
4633     dc
.DrawLine( colLeft
, 0, colLeft
, m_colLabelHeight
-1 ); 
4634     dc
.DrawLine( colLeft
, 0, colRight
, 0 ); 
4636     dc
.SetBackgroundMode( wxTRANSPARENT 
); 
4637     dc
.SetTextForeground( GetLabelTextColour() ); 
4638     dc
.SetFont( GetLabelFont() ); 
4640     dc
.SetBackgroundMode( wxTRANSPARENT 
); 
4641     dc
.SetTextForeground( GetLabelTextColour() ); 
4642     dc
.SetFont( GetLabelFont() ); 
4645     GetColLabelAlignment( &hAlign
, &vAlign 
); 
4648     rect
.SetX( colLeft 
+ 2 ); 
4650     rect
.SetWidth( GetColWidth(col
) - 4 ); 
4651     rect
.SetHeight( m_colLabelHeight 
- 4 ); 
4652     DrawTextRectangle( dc
, GetColLabelValue( col 
), rect
, hAlign
, vAlign 
); 
4656 void wxGrid::DrawTextRectangle( wxDC
& dc
, 
4657                                 const wxString
& value
, 
4662     long textWidth
, textHeight
; 
4663     long lineWidth
, lineHeight
; 
4664     wxArrayString lines
; 
4666     dc
.SetClippingRegion( rect 
); 
4667     StringToLines( value
, lines 
); 
4668     if ( lines
.GetCount() ) 
4670         GetTextBoxSize( dc
, lines
, &textWidth
, &textHeight 
); 
4671         dc
.GetTextExtent( lines
[0], &lineWidth
, &lineHeight 
); 
4674         switch ( horizAlign 
) 
4677                 x 
= rect
.x 
+ (rect
.width 
- textWidth 
- 1); 
4681                 x 
= rect
.x 
+ ((rect
.width 
- textWidth
)/2); 
4690         switch ( vertAlign 
) 
4693                 y 
= rect
.y 
+ (rect
.height 
- textHeight 
- 1); 
4697                 y 
= rect
.y 
+ ((rect
.height 
- textHeight
)/2); 
4706         for ( size_t i 
= 0;  i 
< lines
.GetCount();  i
++ ) 
4708             dc
.DrawText( lines
[i
], (long)x
, (long)y 
); 
4713     dc
.DestroyClippingRegion(); 
4717 // Split multi line text up into an array of strings.  Any existing 
4718 // contents of the string array are preserved. 
4720 void wxGrid::StringToLines( const wxString
& value
, wxArrayString
& lines 
) 
4724     wxString eol 
= wxTextFile::GetEOL( wxTextFileType_Unix 
); 
4725     wxString tVal 
= wxTextFile::Translate( value
, wxTextFileType_Unix 
); 
4727     while ( startPos 
< (int)tVal
.Length() ) 
4729         pos 
= tVal
.Mid(startPos
).Find( eol 
); 
4734         else if ( pos 
== 0 ) 
4736             lines
.Add( wxEmptyString 
); 
4740             lines
.Add( value
.Mid(startPos
, pos
) ); 
4744     if ( startPos 
< (int)value
.Length() ) 
4746         lines
.Add( value
.Mid( startPos 
) ); 
4751 void wxGrid::GetTextBoxSize( wxDC
& dc
, 
4752                              wxArrayString
& lines
, 
4753                              long *width
, long *height 
) 
4760     for ( i 
= 0;  i 
< lines
.GetCount();  i
++ ) 
4762         dc
.GetTextExtent( lines
[i
], &lineW
, &lineH 
); 
4763         w 
= wxMax( w
, lineW 
); 
4773 // ------ Edit control functions 
4777 void wxGrid::EnableEditing( bool edit 
) 
4779     // TODO: improve this ? 
4781     if ( edit 
!= m_editable 
) 
4785         // FIXME IMHO this won't disable the edit control if edit == FALSE 
4786         //       because of the check in the beginning of 
4787         //       EnableCellEditControl() just below (VZ) 
4788         EnableCellEditControl(m_editable
); 
4793 void wxGrid::EnableCellEditControl( bool enable 
) 
4798     if ( m_currentCellCoords 
== wxGridNoCellCoords 
) 
4799         SetCurrentCell( 0, 0 ); 
4801     if ( enable 
!= m_cellEditCtrlEnabled 
) 
4803         // TODO allow the app to Veto() this event? 
4804         SendEvent(enable 
? wxEVT_GRID_EDITOR_SHOWN 
: wxEVT_GRID_EDITOR_HIDDEN
); 
4808             // this should be checked by the caller! 
4809             wxASSERT_MSG( CanEnableCellControl(), 
4810                           _T("can't enable editing for this cell!") ); 
4812             // do it before ShowCellEditControl() 
4813             m_cellEditCtrlEnabled 
= enable
; 
4815             SetEditControlValue(); 
4816             ShowCellEditControl(); 
4820             HideCellEditControl(); 
4821             SaveEditControlValue(); 
4823             // do it after HideCellEditControl() 
4824             m_cellEditCtrlEnabled 
= enable
; 
4829 bool wxGrid::IsCurrentCellReadOnly() const 
4832     wxGridCellAttr
* attr 
= ((wxGrid 
*)this)->GetCellAttr(m_currentCellCoords
); 
4833     bool readonly 
= attr
->IsReadOnly(); 
4839 bool wxGrid::CanEnableCellControl() const 
4841     return m_editable 
&& !IsCurrentCellReadOnly(); 
4844 bool wxGrid::IsCellEditControlEnabled() const 
4846     // the cell edit control might be disable for all cells or just for the 
4847     // current one if it's read only 
4848     return m_cellEditCtrlEnabled 
? !IsCurrentCellReadOnly() : FALSE
; 
4851 wxWindow 
*wxGrid::GetGridWindow() const 
4856 void wxGrid::ShowCellEditControl() 
4858     if ( IsCellEditControlEnabled() ) 
4860         if ( !IsVisible( m_currentCellCoords 
) ) 
4866             wxRect rect 
= CellToRect( m_currentCellCoords 
); 
4867             int row 
= m_currentCellCoords
.GetRow(); 
4868             int col 
= m_currentCellCoords
.GetCol(); 
4870             // convert to scrolled coords 
4872             int left
, top
, right
, bottom
; 
4873             CalcScrolledPosition( rect
.GetLeft(), rect
.GetTop(), &left
, &top 
); 
4874             CalcScrolledPosition( rect
.GetRight(), rect
.GetBottom(), &right
, &bottom 
); 
4876             // cell is shifted by one pixel 
4882             // Make the edit control large enough to allow for internal 
4885             // TODO: remove this if the text ctrl sizing is improved esp. for 
4889 #if defined(__WXMOTIF__) 
4890             if ( row 
== 0  || col 
== 0 ) 
4899             if ( row 
== 0  || col 
== 0 ) 
4909 #if defined(__WXGTK__) 
4912             if (left 
!= 0) left_diff
++; 
4913             if (top 
!= 0) top_diff
++; 
4914             rect
.SetLeft( left 
+ left_diff 
); 
4915             rect
.SetTop( top 
+ top_diff 
); 
4916             rect
.SetRight( rect
.GetRight() - left_diff 
); 
4917             rect
.SetBottom( rect
.GetBottom() - top_diff 
); 
4919             rect
.SetLeft( wxMax(0, left 
- extra
) ); 
4920             rect
.SetTop( wxMax(0, top 
- extra
) ); 
4921             rect
.SetRight( rect
.GetRight() + 2*extra 
); 
4922             rect
.SetBottom( rect
.GetBottom() + 2*extra 
); 
4925             wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
4926             wxGridCellEditor
* editor 
= attr
->GetEditor(GetDefaultEditorForCell(row
, col
)); 
4927             if ( !editor
->IsCreated() ) 
4929                 editor
->Create(m_gridWin
, -1, 
4930                                new wxGridCellEditorEvtHandler(this, editor
)); 
4933             editor
->SetSize( rect 
); 
4934             editor
->Show( TRUE
, attr 
); 
4935             editor
->BeginEdit(row
, col
, this); 
4942 void wxGrid::HideCellEditControl() 
4944     if ( IsCellEditControlEnabled() ) 
4946         int row 
= m_currentCellCoords
.GetRow(); 
4947         int col 
= m_currentCellCoords
.GetCol(); 
4949         wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
4950         attr
->GetEditor(GetDefaultEditorForCell(row
, col
))->Show( FALSE 
); 
4952         m_gridWin
->SetFocus(); 
4957 void wxGrid::SetEditControlValue( const wxString
& value 
) 
4959     // RD: The new Editors get the value from the table themselves now.  This 
4960     // method can probably be removed... 
4964 void wxGrid::SaveEditControlValue() 
4966     if ( IsCellEditControlEnabled() ) 
4968         int row 
= m_currentCellCoords
.GetRow(); 
4969         int col 
= m_currentCellCoords
.GetCol(); 
4971         wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
4972         wxGridCellEditor
* editor 
= attr
->GetEditor(GetDefaultEditorForCell(row
, col
)); 
4973         bool changed 
= editor
->EndEdit(row
, col
, TRUE
, this); 
4979             SendEvent( wxEVT_GRID_CELL_CHANGE
, 
4980                        m_currentCellCoords
.GetRow(), 
4981                        m_currentCellCoords
.GetCol() ); 
4988 // ------ Grid location functions 
4989 //  Note that all of these functions work with the logical coordinates of 
4990 //  grid cells and labels so you will need to convert from device 
4991 //  coordinates for mouse events etc. 
4994 void wxGrid::XYToCell( int x
, int y
, wxGridCellCoords
& coords 
) 
4996     int row 
= YToRow(y
); 
4997     int col 
= XToCol(x
); 
4999     if ( row 
== -1  ||  col 
== -1 ) 
5001         coords 
= wxGridNoCellCoords
; 
5005         coords
.Set( row
, col 
); 
5010 int wxGrid::YToRow( int y 
) 
5014     for ( i 
= 0;  i 
< m_numRows
;  i
++ ) 
5016         if ( y 
< GetRowBottom(i
) ) 
5020     return m_numRows
; //-1; 
5024 int wxGrid::XToCol( int x 
) 
5028     for ( i 
= 0;  i 
< m_numCols
;  i
++ ) 
5030         if ( x 
< GetColRight(i
) ) 
5034     return m_numCols
; //-1; 
5038 // return the row number that that the y coord is near the edge of, or 
5039 // -1 if not near an edge 
5041 int wxGrid::YToEdgeOfRow( int y 
) 
5045     for ( i 
= 0;  i 
< m_numRows
;  i
++ ) 
5047         if ( GetRowHeight(i
) > WXGRID_LABEL_EDGE_ZONE 
) 
5049             d 
= abs( y 
- GetRowBottom(i
) ); 
5050             if ( d 
< WXGRID_LABEL_EDGE_ZONE 
) 
5059 // return the col number that that the x coord is near the edge of, or 
5060 // -1 if not near an edge 
5062 int wxGrid::XToEdgeOfCol( int x 
) 
5066     for ( i 
= 0;  i 
< m_numCols
;  i
++ ) 
5068         if ( GetColWidth(i
) > WXGRID_LABEL_EDGE_ZONE 
) 
5070             d 
= abs( x 
- GetColRight(i
) ); 
5071             if ( d 
< WXGRID_LABEL_EDGE_ZONE 
) 
5080 wxRect 
wxGrid::CellToRect( int row
, int col 
) 
5082     wxRect 
rect( -1, -1, -1, -1 ); 
5084     if ( row 
>= 0  &&  row 
< m_numRows  
&& 
5085          col 
>= 0  &&  col 
< m_numCols 
) 
5087         rect
.x 
= GetColLeft(col
); 
5088         rect
.y 
= GetRowTop(row
); 
5089         rect
.width 
= GetColWidth(col
); 
5090         rect
.height 
= GetRowHeight(row
); 
5097 bool wxGrid::IsVisible( int row
, int col
, bool wholeCellVisible 
) 
5099     // get the cell rectangle in logical coords 
5101     wxRect 
r( CellToRect( row
, col 
) ); 
5103     // convert to device coords 
5105     int left
, top
, right
, bottom
; 
5106     CalcScrolledPosition( r
.GetLeft(), r
.GetTop(), &left
, &top 
); 
5107     CalcScrolledPosition( r
.GetRight(), r
.GetBottom(), &right
, &bottom 
); 
5109     // check against the client area of the grid window 
5112     m_gridWin
->GetClientSize( &cw
, &ch 
); 
5114     if ( wholeCellVisible 
) 
5116         // is the cell wholly visible ? 
5118         return ( left 
>= 0  &&  right 
<= cw  
&& 
5119                  top 
>= 0  &&  bottom 
<= ch 
); 
5123         // is the cell partly visible ? 
5125         return ( ((left 
>=0 && left 
< cw
) || (right 
> 0 && right 
<= cw
))  && 
5126                  ((top 
>=0 && top 
< ch
) || (bottom 
> 0 && bottom 
<= ch
)) ); 
5131 // make the specified cell location visible by doing a minimal amount 
5134 void wxGrid::MakeCellVisible( int row
, int col 
) 
5137     int xpos 
= -1, ypos 
= -1; 
5139     if ( row 
>= 0  &&  row 
< m_numRows  
&& 
5140          col 
>= 0  &&  col 
< m_numCols 
) 
5142         // get the cell rectangle in logical coords 
5144         wxRect 
r( CellToRect( row
, col 
) ); 
5146         // convert to device coords 
5148         int left
, top
, right
, bottom
; 
5149         CalcScrolledPosition( r
.GetLeft(), r
.GetTop(), &left
, &top 
); 
5150         CalcScrolledPosition( r
.GetRight(), r
.GetBottom(), &right
, &bottom 
); 
5153         m_gridWin
->GetClientSize( &cw
, &ch 
); 
5159         else if ( bottom 
> ch 
) 
5161             int h 
= r
.GetHeight(); 
5163             for ( i 
= row
-1;  i 
>= 0;  i
-- ) 
5165                 int rowHeight 
= GetRowHeight(i
); 
5166                 if ( h 
+ rowHeight 
> ch 
) 
5173             // we divide it later by GRID_SCROLL_LINE, make sure that we don't 
5174             // have rounding errors (this is important, because if we do, we 
5175             // might not scroll at all and some cells won't be redrawn) 
5176             ypos 
+= GRID_SCROLL_LINE 
/ 2; 
5183         else if ( right 
> cw 
) 
5185             int w 
= r
.GetWidth(); 
5187             for ( i 
= col
-1;  i 
>= 0;  i
-- ) 
5189                 int colWidth 
= GetColWidth(i
); 
5190                 if ( w 
+ colWidth 
> cw 
) 
5197             // see comment for ypos above 
5198             xpos 
+= GRID_SCROLL_LINE 
/ 2; 
5201         if ( xpos 
!= -1  ||  ypos 
!= -1 ) 
5203             if ( xpos 
!= -1 ) xpos 
/= GRID_SCROLL_LINE
; 
5204             if ( ypos 
!= -1 ) ypos 
/= GRID_SCROLL_LINE
; 
5205             Scroll( xpos
, ypos 
); 
5213 // ------ Grid cursor movement functions 
5216 bool wxGrid::MoveCursorUp() 
5218     if ( m_currentCellCoords 
!= wxGridNoCellCoords  
&& 
5219          m_currentCellCoords
.GetRow() > 0 ) 
5221         MakeCellVisible( m_currentCellCoords
.GetRow() - 1, 
5222                         m_currentCellCoords
.GetCol() ); 
5224         SetCurrentCell( m_currentCellCoords
.GetRow() - 1, 
5225                         m_currentCellCoords
.GetCol() ); 
5234 bool wxGrid::MoveCursorDown() 
5236     // TODO: allow for scrolling 
5238     if ( m_currentCellCoords 
!= wxGridNoCellCoords  
&& 
5239          m_currentCellCoords
.GetRow() < m_numRows
-1 ) 
5241         MakeCellVisible( m_currentCellCoords
.GetRow() + 1, 
5242                         m_currentCellCoords
.GetCol() ); 
5244         SetCurrentCell( m_currentCellCoords
.GetRow() + 1, 
5245                         m_currentCellCoords
.GetCol() ); 
5254 bool wxGrid::MoveCursorLeft() 
5256     if ( m_currentCellCoords 
!= wxGridNoCellCoords  
&& 
5257          m_currentCellCoords
.GetCol() > 0 ) 
5259         MakeCellVisible( m_currentCellCoords
.GetRow(), 
5260                         m_currentCellCoords
.GetCol() - 1 ); 
5262         SetCurrentCell( m_currentCellCoords
.GetRow(), 
5263                         m_currentCellCoords
.GetCol() - 1 ); 
5272 bool wxGrid::MoveCursorRight() 
5274     if ( m_currentCellCoords 
!= wxGridNoCellCoords  
&& 
5275          m_currentCellCoords
.GetCol() < m_numCols 
- 1 ) 
5277         MakeCellVisible( m_currentCellCoords
.GetRow(), 
5278                         m_currentCellCoords
.GetCol() + 1 ); 
5280         SetCurrentCell( m_currentCellCoords
.GetRow(), 
5281                         m_currentCellCoords
.GetCol() + 1 ); 
5290 bool wxGrid::MovePageUp() 
5292     if ( m_currentCellCoords 
== wxGridNoCellCoords 
) return FALSE
; 
5294     int row 
= m_currentCellCoords
.GetRow(); 
5298         m_gridWin
->GetClientSize( &cw
, &ch 
); 
5300         int y 
= GetRowTop(row
); 
5301         int newRow 
= YToRow( y 
- ch 
+ 1 ); 
5306         else if ( newRow 
== row 
) 
5311         MakeCellVisible( newRow
, m_currentCellCoords
.GetCol() ); 
5312         SetCurrentCell( newRow
, m_currentCellCoords
.GetCol() ); 
5320 bool wxGrid::MovePageDown() 
5322     if ( m_currentCellCoords 
== wxGridNoCellCoords 
) return FALSE
; 
5324     int row 
= m_currentCellCoords
.GetRow(); 
5325     if ( row 
< m_numRows 
) 
5328         m_gridWin
->GetClientSize( &cw
, &ch 
); 
5330         int y 
= GetRowTop(row
); 
5331         int newRow 
= YToRow( y 
+ ch 
); 
5334             newRow 
= m_numRows 
- 1; 
5336         else if ( newRow 
== row 
) 
5341         MakeCellVisible( newRow
, m_currentCellCoords
.GetCol() ); 
5342         SetCurrentCell( newRow
, m_currentCellCoords
.GetCol() ); 
5350 bool wxGrid::MoveCursorUpBlock() 
5353          m_currentCellCoords 
!= wxGridNoCellCoords  
&& 
5354          m_currentCellCoords
.GetRow() > 0 ) 
5356         int row 
= m_currentCellCoords
.GetRow(); 
5357         int col 
= m_currentCellCoords
.GetCol(); 
5359         if ( m_table
->IsEmptyCell(row
, col
) ) 
5361             // starting in an empty cell: find the next block of 
5367                 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break; 
5370         else if ( m_table
->IsEmptyCell(row
-1, col
) ) 
5372             // starting at the top of a block: find the next block 
5378                 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break; 
5383             // starting within a block: find the top of the block 
5388                 if ( m_table
->IsEmptyCell(row
, col
) ) 
5396         MakeCellVisible( row
, col 
); 
5397         SetCurrentCell( row
, col 
); 
5405 bool wxGrid::MoveCursorDownBlock() 
5408          m_currentCellCoords 
!= wxGridNoCellCoords  
&& 
5409          m_currentCellCoords
.GetRow() < m_numRows
-1 ) 
5411         int row 
= m_currentCellCoords
.GetRow(); 
5412         int col 
= m_currentCellCoords
.GetCol(); 
5414         if ( m_table
->IsEmptyCell(row
, col
) ) 
5416             // starting in an empty cell: find the next block of 
5419             while ( row 
< m_numRows
-1 ) 
5422                 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break; 
5425         else if ( m_table
->IsEmptyCell(row
+1, col
) ) 
5427             // starting at the bottom of a block: find the next block 
5430             while ( row 
< m_numRows
-1 ) 
5433                 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break; 
5438             // starting within a block: find the bottom of the block 
5440             while ( row 
< m_numRows
-1 ) 
5443                 if ( m_table
->IsEmptyCell(row
, col
) ) 
5451         MakeCellVisible( row
, col 
); 
5452         SetCurrentCell( row
, col 
); 
5460 bool wxGrid::MoveCursorLeftBlock() 
5463          m_currentCellCoords 
!= wxGridNoCellCoords  
&& 
5464          m_currentCellCoords
.GetCol() > 0 ) 
5466         int row 
= m_currentCellCoords
.GetRow(); 
5467         int col 
= m_currentCellCoords
.GetCol(); 
5469         if ( m_table
->IsEmptyCell(row
, col
) ) 
5471             // starting in an empty cell: find the next block of 
5477                 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break; 
5480         else if ( m_table
->IsEmptyCell(row
, col
-1) ) 
5482             // starting at the left of a block: find the next block 
5488                 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break; 
5493             // starting within a block: find the left of the block 
5498                 if ( m_table
->IsEmptyCell(row
, col
) ) 
5506         MakeCellVisible( row
, col 
); 
5507         SetCurrentCell( row
, col 
); 
5515 bool wxGrid::MoveCursorRightBlock() 
5518          m_currentCellCoords 
!= wxGridNoCellCoords  
&& 
5519          m_currentCellCoords
.GetCol() < m_numCols
-1 ) 
5521         int row 
= m_currentCellCoords
.GetRow(); 
5522         int col 
= m_currentCellCoords
.GetCol(); 
5524         if ( m_table
->IsEmptyCell(row
, col
) ) 
5526             // starting in an empty cell: find the next block of 
5529             while ( col 
< m_numCols
-1 ) 
5532                 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break; 
5535         else if ( m_table
->IsEmptyCell(row
, col
+1) ) 
5537             // starting at the right of a block: find the next block 
5540             while ( col 
< m_numCols
-1 ) 
5543                 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break; 
5548             // starting within a block: find the right of the block 
5550             while ( col 
< m_numCols
-1 ) 
5553                 if ( m_table
->IsEmptyCell(row
, col
) ) 
5561         MakeCellVisible( row
, col 
); 
5562         SetCurrentCell( row
, col 
); 
5573 // ------ Label values and formatting 
5576 void wxGrid::GetRowLabelAlignment( int *horiz
, int *vert 
) 
5578     *horiz 
= m_rowLabelHorizAlign
; 
5579     *vert  
= m_rowLabelVertAlign
; 
5582 void wxGrid::GetColLabelAlignment( int *horiz
, int *vert 
) 
5584     *horiz 
= m_colLabelHorizAlign
; 
5585     *vert  
= m_colLabelVertAlign
; 
5588 wxString 
wxGrid::GetRowLabelValue( int row 
) 
5592         return m_table
->GetRowLabelValue( row 
); 
5602 wxString 
wxGrid::GetColLabelValue( int col 
) 
5606         return m_table
->GetColLabelValue( col 
); 
5617 void wxGrid::SetRowLabelSize( int width 
) 
5619     width 
= wxMax( width
, 0 ); 
5620     if ( width 
!= m_rowLabelWidth 
) 
5624             m_rowLabelWin
->Show( FALSE 
); 
5625             m_cornerLabelWin
->Show( FALSE 
); 
5627         else if ( m_rowLabelWidth 
== 0 ) 
5629             m_rowLabelWin
->Show( TRUE 
); 
5630             if ( m_colLabelHeight 
> 0 ) m_cornerLabelWin
->Show( TRUE 
); 
5633         m_rowLabelWidth 
= width
; 
5640 void wxGrid::SetColLabelSize( int height 
) 
5642     height 
= wxMax( height
, 0 ); 
5643     if ( height 
!= m_colLabelHeight 
) 
5647             m_colLabelWin
->Show( FALSE 
); 
5648             m_cornerLabelWin
->Show( FALSE 
); 
5650         else if ( m_colLabelHeight 
== 0 ) 
5652             m_colLabelWin
->Show( TRUE 
); 
5653             if ( m_rowLabelWidth 
> 0 ) m_cornerLabelWin
->Show( TRUE 
); 
5656         m_colLabelHeight 
= height
; 
5663 void wxGrid::SetLabelBackgroundColour( const wxColour
& colour 
) 
5665     if ( m_labelBackgroundColour 
!= colour 
) 
5667         m_labelBackgroundColour 
= colour
; 
5668         m_rowLabelWin
->SetBackgroundColour( colour 
); 
5669         m_colLabelWin
->SetBackgroundColour( colour 
); 
5670         m_cornerLabelWin
->SetBackgroundColour( colour 
); 
5672         if ( !GetBatchCount() ) 
5674             m_rowLabelWin
->Refresh(); 
5675             m_colLabelWin
->Refresh(); 
5676             m_cornerLabelWin
->Refresh(); 
5681 void wxGrid::SetLabelTextColour( const wxColour
& colour 
) 
5683     if ( m_labelTextColour 
!= colour 
) 
5685         m_labelTextColour 
= colour
; 
5686         if ( !GetBatchCount() ) 
5688             m_rowLabelWin
->Refresh(); 
5689             m_colLabelWin
->Refresh(); 
5694 void wxGrid::SetLabelFont( const wxFont
& font 
) 
5697     if ( !GetBatchCount() ) 
5699         m_rowLabelWin
->Refresh(); 
5700         m_colLabelWin
->Refresh(); 
5704 void wxGrid::SetRowLabelAlignment( int horiz
, int vert 
) 
5706     if ( horiz 
== wxLEFT 
|| horiz 
== wxCENTRE 
|| horiz 
== wxRIGHT 
) 
5708         m_rowLabelHorizAlign 
= horiz
; 
5711     if ( vert 
== wxTOP 
|| vert 
== wxCENTRE 
|| vert 
== wxBOTTOM 
) 
5713         m_rowLabelVertAlign 
= vert
; 
5716     if ( !GetBatchCount() ) 
5718         m_rowLabelWin
->Refresh(); 
5722 void wxGrid::SetColLabelAlignment( int horiz
, int vert 
) 
5724     if ( horiz 
== wxLEFT 
|| horiz 
== wxCENTRE 
|| horiz 
== wxRIGHT 
) 
5726         m_colLabelHorizAlign 
= horiz
; 
5729     if ( vert 
== wxTOP 
|| vert 
== wxCENTRE 
|| vert 
== wxBOTTOM 
) 
5731         m_colLabelVertAlign 
= vert
; 
5734     if ( !GetBatchCount() ) 
5736         m_colLabelWin
->Refresh(); 
5740 void wxGrid::SetRowLabelValue( int row
, const wxString
& s 
) 
5744         m_table
->SetRowLabelValue( row
, s 
); 
5745         if ( !GetBatchCount() ) 
5747             wxRect rect 
= CellToRect( row
, 0); 
5748             if ( rect
.height 
> 0 ) 
5750                 CalcScrolledPosition(0, rect
.y
, &rect
.x
, &rect
.y
); 
5752                 rect
.width 
= m_rowLabelWidth
; 
5753                 m_rowLabelWin
->Refresh( TRUE
, &rect 
); 
5759 void wxGrid::SetColLabelValue( int col
, const wxString
& s 
) 
5763         m_table
->SetColLabelValue( col
, s 
); 
5764         if ( !GetBatchCount() ) 
5766             wxRect rect 
= CellToRect( 0, col 
); 
5767             if ( rect
.width 
> 0 ) 
5769                 CalcScrolledPosition(rect
.x
, 0, &rect
.x
, &rect
.y
); 
5771                 rect
.height 
= m_colLabelHeight
; 
5772                 m_colLabelWin
->Refresh( TRUE
, &rect 
); 
5778 void wxGrid::SetGridLineColour( const wxColour
& colour 
) 
5780     if ( m_gridLineColour 
!= colour 
) 
5782         m_gridLineColour 
= colour
; 
5784         wxClientDC 
dc( m_gridWin 
); 
5786         DrawAllGridLines( dc
, wxRegion() ); 
5790 void wxGrid::EnableGridLines( bool enable 
) 
5792     if ( enable 
!= m_gridLinesEnabled 
) 
5794         m_gridLinesEnabled 
= enable
; 
5796         if ( !GetBatchCount() ) 
5800                 wxClientDC 
dc( m_gridWin 
); 
5802                 DrawAllGridLines( dc
, wxRegion() ); 
5806                 m_gridWin
->Refresh(); 
5813 int wxGrid::GetDefaultRowSize() 
5815     return m_defaultRowHeight
; 
5818 int wxGrid::GetRowSize( int row 
) 
5820     wxCHECK_MSG( row 
>= 0 && row 
< m_numRows
, 0, _T("invalid row index") ); 
5822     return GetRowHeight(row
); 
5825 int wxGrid::GetDefaultColSize() 
5827     return m_defaultColWidth
; 
5830 int wxGrid::GetColSize( int col 
) 
5832     wxCHECK_MSG( col 
>= 0 && col 
< m_numCols
, 0, _T("invalid column index") ); 
5834     return GetColWidth(col
); 
5837 // ============================================================================ 
5838 // access to the grid attributes: each of them has a default value in the grid 
5839 // itself and may be overidden on a per-cell basis 
5840 // ============================================================================ 
5842 // ---------------------------------------------------------------------------- 
5843 // setting default attributes 
5844 // ---------------------------------------------------------------------------- 
5846 void wxGrid::SetDefaultCellBackgroundColour( const wxColour
& col 
) 
5848     m_defaultCellAttr
->SetBackgroundColour(col
); 
5850     m_gridWin
->SetBackgroundColour(col
); 
5854 void wxGrid::SetDefaultCellTextColour( const wxColour
& col 
) 
5856     m_defaultCellAttr
->SetTextColour(col
); 
5859 void wxGrid::SetDefaultCellAlignment( int horiz
, int vert 
) 
5861     m_defaultCellAttr
->SetAlignment(horiz
, vert
); 
5864 void wxGrid::SetDefaultCellFont( const wxFont
& font 
) 
5866     m_defaultCellAttr
->SetFont(font
); 
5869 //  void wxGrid::SetDefaultRenderer(wxGridCellRenderer *renderer) 
5871 //      m_defaultCellAttr->SetRenderer(renderer); 
5874 //  void wxGrid::SetDefaultEditor(wxGridCellEditor *editor) 
5876 //      m_defaultCellAttr->SetEditor(editor); 
5879 // ---------------------------------------------------------------------------- 
5880 // access to the default attrbiutes 
5881 // ---------------------------------------------------------------------------- 
5883 wxColour 
wxGrid::GetDefaultCellBackgroundColour() 
5885     return m_defaultCellAttr
->GetBackgroundColour(); 
5888 wxColour 
wxGrid::GetDefaultCellTextColour() 
5890     return m_defaultCellAttr
->GetTextColour(); 
5893 wxFont 
wxGrid::GetDefaultCellFont() 
5895     return m_defaultCellAttr
->GetFont(); 
5898 void wxGrid::GetDefaultCellAlignment( int *horiz
, int *vert 
) 
5900     m_defaultCellAttr
->GetAlignment(horiz
, vert
); 
5903 //  wxGridCellRenderer *wxGrid::GetDefaultRenderer() const 
5905 //      return m_defaultCellAttr->GetRenderer(); 
5908 //  wxGridCellEditor *wxGrid::GetDefaultEditor() const 
5910 //      return m_defaultCellAttr->GetEditor(); 
5913 // ---------------------------------------------------------------------------- 
5914 // access to cell attributes 
5915 // ---------------------------------------------------------------------------- 
5917 wxColour 
wxGrid::GetCellBackgroundColour(int row
, int col
) 
5919     wxGridCellAttr 
*attr 
= GetCellAttr(row
, col
); 
5920     wxColour colour 
= attr
->GetBackgroundColour(); 
5925 wxColour 
wxGrid::GetCellTextColour( int row
, int col 
) 
5927     wxGridCellAttr 
*attr 
= GetCellAttr(row
, col
); 
5928     wxColour colour 
= attr
->GetTextColour(); 
5933 wxFont 
wxGrid::GetCellFont( int row
, int col 
) 
5935     wxGridCellAttr 
*attr 
= GetCellAttr(row
, col
); 
5936     wxFont font 
= attr
->GetFont(); 
5941 void wxGrid::GetCellAlignment( int row
, int col
, int *horiz
, int *vert 
) 
5943     wxGridCellAttr 
*attr 
= GetCellAttr(row
, col
); 
5944     attr
->GetAlignment(horiz
, vert
); 
5948 wxGridCellRenderer
* wxGrid::GetCellRenderer(int row
, int col
) 
5950     wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
5951     wxGridCellRenderer
* renderer 
= attr
->GetRenderer(GetDefaultRendererForCell(row
,col
)); 
5956 wxGridCellEditor
* wxGrid::GetCellEditor(int row
, int col
) 
5958     wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
5959     wxGridCellEditor
* editor 
= attr
->GetEditor(GetDefaultEditorForCell(row
, col
)); 
5964 bool wxGrid::IsReadOnly(int row
, int col
) const 
5966     wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
5967     bool isReadOnly 
= attr
->IsReadOnly(); 
5972 // ---------------------------------------------------------------------------- 
5973 // attribute support: cache, automatic provider creation, ... 
5974 // ---------------------------------------------------------------------------- 
5976 bool wxGrid::CanHaveAttributes() 
5983     return m_table
->CanHaveAttributes(); 
5986 void wxGrid::ClearAttrCache() 
5988     if ( m_attrCache
.row 
!= -1 ) 
5990         m_attrCache
.attr
->SafeDecRef(); 
5991         m_attrCache
.row 
= -1; 
5995 void wxGrid::CacheAttr(int row
, int col
, wxGridCellAttr 
*attr
) const 
5997     wxGrid 
*self 
= (wxGrid 
*)this;  // const_cast 
5999     self
->ClearAttrCache(); 
6000     self
->m_attrCache
.row 
= row
; 
6001     self
->m_attrCache
.col 
= col
; 
6002     self
->m_attrCache
.attr 
= attr
; 
6006 bool wxGrid::LookupAttr(int row
, int col
, wxGridCellAttr 
**attr
) const 
6008     if ( row 
== m_attrCache
.row 
&& col 
== m_attrCache
.col 
) 
6010         *attr 
= m_attrCache
.attr
; 
6011         (*attr
)->SafeIncRef(); 
6013 #ifdef DEBUG_ATTR_CACHE 
6014         gs_nAttrCacheHits
++; 
6021 #ifdef DEBUG_ATTR_CACHE 
6022         gs_nAttrCacheMisses
++; 
6028 wxGridCellAttr 
*wxGrid::GetCellAttr(int row
, int col
) const 
6030     wxGridCellAttr 
*attr
; 
6031     if ( !LookupAttr(row
, col
, &attr
) ) 
6033         attr 
= m_table 
? m_table
->GetAttr(row
, col
) : (wxGridCellAttr 
*)NULL
; 
6034         CacheAttr(row
, col
, attr
); 
6038         attr
->SetDefAttr(m_defaultCellAttr
); 
6042         attr 
= m_defaultCellAttr
; 
6049 wxGridCellAttr 
*wxGrid::GetOrCreateCellAttr(int row
, int col
) const 
6051     wxGridCellAttr 
*attr
; 
6052     if ( !LookupAttr(row
, col
, &attr
) || !attr 
) 
6054         wxASSERT_MSG( m_table
, 
6055                       _T("we may only be called if CanHaveAttributes() " 
6056                          "returned TRUE and then m_table should be !NULL") ); 
6058         attr 
= m_table
->GetAttr(row
, col
); 
6061             attr 
= new wxGridCellAttr
; 
6063             // artificially inc the ref count to match DecRef() in caller 
6066             m_table
->SetAttr(attr
, row
, col
); 
6069         CacheAttr(row
, col
, attr
); 
6071     attr
->SetDefAttr(m_defaultCellAttr
); 
6075 // ---------------------------------------------------------------------------- 
6076 // setting cell attributes: this is forwarded to the table 
6077 // ---------------------------------------------------------------------------- 
6079 void wxGrid::SetRowAttr(int row
, wxGridCellAttr 
*attr
) 
6081     if ( CanHaveAttributes() ) 
6083         m_table
->SetRowAttr(attr
, row
); 
6091 void wxGrid::SetColAttr(int col
, wxGridCellAttr 
*attr
) 
6093     if ( CanHaveAttributes() ) 
6095         m_table
->SetColAttr(attr
, col
); 
6103 void wxGrid::SetCellBackgroundColour( int row
, int col
, const wxColour
& colour 
) 
6105     if ( CanHaveAttributes() ) 
6107         wxGridCellAttr 
*attr 
= GetOrCreateCellAttr(row
, col
); 
6108         attr
->SetBackgroundColour(colour
); 
6113 void wxGrid::SetCellTextColour( int row
, int col
, const wxColour
& colour 
) 
6115     if ( CanHaveAttributes() ) 
6117         wxGridCellAttr 
*attr 
= GetOrCreateCellAttr(row
, col
); 
6118         attr
->SetTextColour(colour
); 
6123 void wxGrid::SetCellFont( int row
, int col
, const wxFont
& font 
) 
6125     if ( CanHaveAttributes() ) 
6127         wxGridCellAttr 
*attr 
= GetOrCreateCellAttr(row
, col
); 
6128         attr
->SetFont(font
); 
6133 void wxGrid::SetCellAlignment( int row
, int col
, int horiz
, int vert 
) 
6135     if ( CanHaveAttributes() ) 
6137         wxGridCellAttr 
*attr 
= GetOrCreateCellAttr(row
, col
); 
6138         attr
->SetAlignment(horiz
, vert
); 
6143 void wxGrid::SetCellRenderer(int row
, int col
, wxGridCellRenderer 
*renderer
) 
6145     if ( CanHaveAttributes() ) 
6147         wxGridCellAttr 
*attr 
= GetOrCreateCellAttr(row
, col
); 
6148         attr
->SetRenderer(renderer
); 
6153 void wxGrid::SetCellEditor(int row
, int col
, wxGridCellEditor
* editor
) 
6155     if ( CanHaveAttributes() ) 
6157         wxGridCellAttr 
*attr 
= GetOrCreateCellAttr(row
, col
); 
6158         attr
->SetEditor(editor
); 
6163 void wxGrid::SetReadOnly(int row
, int col
, bool isReadOnly
) 
6165     if ( CanHaveAttributes() ) 
6167         wxGridCellAttr 
*attr 
= GetOrCreateCellAttr(row
, col
); 
6168         attr
->SetReadOnly(isReadOnly
); 
6173 // ---------------------------------------------------------------------------- 
6174 // Data type registration 
6175 // ---------------------------------------------------------------------------- 
6177 void wxGrid::RegisterDataType(const wxString
& typeName
, 
6178                               wxGridCellRenderer
* renderer
, 
6179                               wxGridCellEditor
* editor
) 
6181     m_typeRegistry
->RegisterDataType(typeName
, renderer
, editor
); 
6185 wxGridCellEditor
* wxGrid::GetDefaultEditorForCell(int row
, int col
) 
6187     wxString typeName 
= m_table
->GetTypeName(row
, col
); 
6188     return GetDefaultEditorForType(typeName
); 
6191 wxGridCellRenderer
* wxGrid::GetDefaultRendererForCell(int row
, int col
) 
6193     wxString typeName 
= m_table
->GetTypeName(row
, col
); 
6194     return GetDefaultRendererForType(typeName
); 
6197 wxGridCellEditor
* wxGrid::GetDefaultEditorForType(const wxString
& typeName
) 
6199     int index 
= m_typeRegistry
->FindDataType(typeName
); 
6201         // Should we force the failure here or let it fallback to string handling??? 
6202         // wxFAIL_MSG(wxT("Unknown data type name")); 
6205     return m_typeRegistry
->GetEditor(index
); 
6208 wxGridCellRenderer
* wxGrid::GetDefaultRendererForType(const wxString
& typeName
) 
6210     int index 
= m_typeRegistry
->FindDataType(typeName
); 
6212         // Should we force the failure here or let it fallback to string handling??? 
6213         // wxFAIL_MSG(wxT("Unknown data type name")); 
6216     return m_typeRegistry
->GetRenderer(index
); 
6220 // ---------------------------------------------------------------------------- 
6222 // ---------------------------------------------------------------------------- 
6224 void wxGrid::SetDefaultRowSize( int height
, bool resizeExistingRows 
) 
6226     m_defaultRowHeight 
= wxMax( height
, WXGRID_MIN_ROW_HEIGHT 
); 
6228     if ( resizeExistingRows 
) 
6236 void wxGrid::SetRowSize( int row
, int height 
) 
6238     wxCHECK_RET( row 
>= 0 && row 
< m_numRows
, _T("invalid row index") ); 
6240     if ( m_rowHeights
.IsEmpty() ) 
6242         // need to really create the array 
6246     int h 
= wxMax( 0, height 
); 
6247     int diff 
= h 
- m_rowHeights
[row
]; 
6249     m_rowHeights
[row
] = h
; 
6251     for ( i 
= row
;  i 
< m_numRows
;  i
++ ) 
6253         m_rowBottoms
[i
] += diff
; 
6258 void wxGrid::SetDefaultColSize( int width
, bool resizeExistingCols 
) 
6260     m_defaultColWidth 
= wxMax( width
, WXGRID_MIN_COL_WIDTH 
); 
6262     if ( resizeExistingCols 
) 
6270 void wxGrid::SetColSize( int col
, int width 
) 
6272     wxCHECK_RET( col 
>= 0 && col 
< m_numCols
, _T("invalid column index") ); 
6274     // should we check that it's bigger than GetColMinimalWidth(col) here? 
6276     if ( m_colWidths
.IsEmpty() ) 
6278         // need to really create the array 
6282     int w 
= wxMax( 0, width 
); 
6283     int diff 
= w 
- m_colWidths
[col
]; 
6284     m_colWidths
[col
] = w
; 
6287     for ( i 
= col
;  i 
< m_numCols
;  i
++ ) 
6289         m_colRights
[i
] += diff
; 
6295 void wxGrid::SetColMinimalWidth( int col
, int width 
) 
6297     m_colMinWidths
.Put(col
, (wxObject 
*)width
); 
6300 int wxGrid::GetColMinimalWidth(int col
) const 
6302     wxObject 
*obj 
= m_colMinWidths
.Get(m_dragRowOrCol
); 
6303     return obj 
? (int)obj 
: WXGRID_MIN_COL_WIDTH
; 
6307 // ------ cell value accessor functions 
6310 void wxGrid::SetCellValue( int row
, int col
, const wxString
& s 
) 
6314         m_table
->SetValue( row
, col
, s
.c_str() ); 
6315         if ( !GetBatchCount() ) 
6317             wxClientDC 
dc( m_gridWin 
); 
6319             DrawCell( dc
, wxGridCellCoords(row
, col
) ); 
6322 #if 0  // TODO: edit in place 
6324         if ( m_currentCellCoords
.GetRow() == row 
&& 
6325              m_currentCellCoords
.GetCol() == col 
) 
6327             SetEditControlValue( s 
); 
6336 // ------ Block, row and col selection 
6339 void wxGrid::SelectRow( int row
, bool addToSelected 
) 
6343     if ( IsSelection() && addToSelected 
) 
6346         bool    need_refresh
[4]; 
6350         need_refresh
[3] = FALSE
; 
6354         wxCoord oldLeft   
= m_selectedTopLeft
.GetCol(); 
6355         wxCoord oldTop    
= m_selectedTopLeft
.GetRow(); 
6356         wxCoord oldRight  
= m_selectedBottomRight
.GetCol(); 
6357         wxCoord oldBottom 
= m_selectedBottomRight
.GetRow(); 
6361             need_refresh
[0] = TRUE
; 
6362             rect
[0] = BlockToDeviceRect( wxGridCellCoords ( row
, 0 ), 
6363                                          wxGridCellCoords ( oldTop 
- 1, 
6365             m_selectedTopLeft
.SetRow( row 
); 
6370             need_refresh
[1] = TRUE
; 
6371             rect
[1] = BlockToDeviceRect( wxGridCellCoords ( oldTop
, 0 ), 
6372                                          wxGridCellCoords ( oldBottom
, 
6375             m_selectedTopLeft
.SetCol( 0 ); 
6378         if ( oldBottom 
< row 
) 
6380             need_refresh
[2] = TRUE
; 
6381             rect
[2] = BlockToDeviceRect( wxGridCellCoords ( oldBottom 
+ 1, 0 ), 
6382                                          wxGridCellCoords ( row
, 
6384             m_selectedBottomRight
.SetRow( row 
); 
6387         if ( oldRight 
< m_numCols 
- 1 ) 
6389             need_refresh
[3] = TRUE
; 
6390             rect
[3] = BlockToDeviceRect( wxGridCellCoords ( oldTop 
, 
6392                                          wxGridCellCoords ( oldBottom
, 
6394             m_selectedBottomRight
.SetCol( m_numCols 
- 1 ); 
6397         for (i 
= 0; i 
< 4; i
++ ) 
6398             if ( need_refresh
[i
] && rect
[i
] != wxGridNoCellRect 
) 
6399                 m_gridWin
->Refresh( FALSE
, &(rect
[i
]) ); 
6403         r 
= SelectionToDeviceRect(); 
6405         if ( r 
!= wxGridNoCellRect 
) m_gridWin
->Refresh( FALSE
, &r 
); 
6407         m_selectedTopLeft
.Set( row
, 0 ); 
6408         m_selectedBottomRight
.Set( row
, m_numCols
-1 ); 
6409         r 
= SelectionToDeviceRect(); 
6410         m_gridWin
->Refresh( FALSE
, &r 
); 
6413     wxGridRangeSelectEvent 
gridEvt( GetId(), 
6414                                     wxEVT_GRID_RANGE_SELECT
, 
6417                                     m_selectedBottomRight 
); 
6419     GetEventHandler()->ProcessEvent(gridEvt
); 
6423 void wxGrid::SelectCol( int col
, bool addToSelected 
) 
6425     if ( IsSelection() && addToSelected 
) 
6428         bool    need_refresh
[4]; 
6432         need_refresh
[3] = FALSE
; 
6435         wxCoord oldLeft   
= m_selectedTopLeft
.GetCol(); 
6436         wxCoord oldTop    
= m_selectedTopLeft
.GetRow(); 
6437         wxCoord oldRight  
= m_selectedBottomRight
.GetCol(); 
6438         wxCoord oldBottom 
= m_selectedBottomRight
.GetRow(); 
6440         if ( oldLeft 
> col 
) 
6442             need_refresh
[0] = TRUE
; 
6443             rect
[0] = BlockToDeviceRect( wxGridCellCoords ( 0, col 
), 
6444                                          wxGridCellCoords ( m_numRows 
- 1, 
6446             m_selectedTopLeft
.SetCol( col 
); 
6451             need_refresh
[1] = TRUE
; 
6452             rect
[1] = BlockToDeviceRect( wxGridCellCoords ( 0, oldLeft 
), 
6453                                          wxGridCellCoords ( oldTop 
- 1, 
6455             m_selectedTopLeft
.SetRow( 0 ); 
6458         if ( oldRight 
< col 
) 
6460             need_refresh
[2] = TRUE
; 
6461             rect
[2] = BlockToDeviceRect( wxGridCellCoords ( 0, oldRight 
+ 1 ), 
6462                                          wxGridCellCoords ( m_numRows 
- 1, 
6464             m_selectedBottomRight
.SetCol( col 
); 
6467         if ( oldBottom 
< m_numRows 
- 1 ) 
6469             need_refresh
[3] = TRUE
; 
6470             rect
[3] = BlockToDeviceRect( wxGridCellCoords ( oldBottom 
+ 1, 
6472                                          wxGridCellCoords ( m_numRows 
- 1, 
6474             m_selectedBottomRight
.SetRow( m_numRows 
- 1 ); 
6477         for (i 
= 0; i 
< 4; i
++ ) 
6478             if ( need_refresh
[i
] && rect
[i
] != wxGridNoCellRect 
) 
6479                 m_gridWin
->Refresh( FALSE
, &(rect
[i
]) ); 
6485         r 
= SelectionToDeviceRect(); 
6487         if ( r 
!= wxGridNoCellRect 
) m_gridWin
->Refresh( FALSE
, &r 
); 
6489         m_selectedTopLeft
.Set( 0, col 
); 
6490         m_selectedBottomRight
.Set( m_numRows
-1, col 
); 
6491         r 
= SelectionToDeviceRect(); 
6492         m_gridWin
->Refresh( FALSE
, &r 
); 
6495     wxGridRangeSelectEvent 
gridEvt( GetId(), 
6496                                     wxEVT_GRID_RANGE_SELECT
, 
6499                                     m_selectedBottomRight 
); 
6501     GetEventHandler()->ProcessEvent(gridEvt
); 
6505 void wxGrid::SelectBlock( int topRow
, int leftCol
, int bottomRow
, int rightCol 
) 
6508     wxGridCellCoords updateTopLeft
, updateBottomRight
; 
6510     if ( topRow 
> bottomRow 
) 
6517     if ( leftCol 
> rightCol 
) 
6524     updateTopLeft 
= wxGridCellCoords( topRow
, leftCol 
); 
6525     updateBottomRight 
= wxGridCellCoords( bottomRow
, rightCol 
); 
6527     if ( m_selectedTopLeft 
!= updateTopLeft 
|| 
6528          m_selectedBottomRight 
!= updateBottomRight 
) 
6530         // Compute two optimal update rectangles: 
6531         // Either one rectangle is a real subset of the 
6532         // other, or they are (almost) disjoint! 
6534         bool    need_refresh
[4]; 
6538         need_refresh
[3] = FALSE
; 
6541         // Store intermediate values 
6542         wxCoord oldLeft   
= m_selectedTopLeft
.GetCol(); 
6543         wxCoord oldTop    
= m_selectedTopLeft
.GetRow(); 
6544         wxCoord oldRight  
= m_selectedBottomRight
.GetCol(); 
6545         wxCoord oldBottom 
= m_selectedBottomRight
.GetRow(); 
6547         // Determine the outer/inner coordinates. 
6548         if (oldLeft 
> leftCol
) 
6554         if (oldTop 
> topRow 
) 
6560         if (oldRight 
< rightCol 
) 
6563             oldRight 
= rightCol
; 
6566         if (oldBottom 
< bottomRow
) 
6569             oldBottom 
= bottomRow
; 
6573         // Now, either the stuff marked old is the outer 
6574         // rectangle or we don't have a situation where one 
6575         // is contained in the other. 
6577         if ( oldLeft 
< leftCol 
) 
6579             need_refresh
[0] = TRUE
; 
6580             rect
[0] = BlockToDeviceRect( wxGridCellCoords ( oldTop
, 
6582                                          wxGridCellCoords ( oldBottom
, 
6586         if ( oldTop  
< topRow 
) 
6588             need_refresh
[1] = TRUE
; 
6589             rect
[1] = BlockToDeviceRect( wxGridCellCoords ( oldTop
, 
6591                                          wxGridCellCoords ( topRow 
- 1, 
6595         if ( oldRight 
> rightCol 
) 
6597             need_refresh
[2] = TRUE
; 
6598             rect
[2] = BlockToDeviceRect( wxGridCellCoords ( oldTop
, 
6600                                          wxGridCellCoords ( oldBottom
, 
6604         if ( oldBottom 
> bottomRow 
) 
6606             need_refresh
[3] = TRUE
; 
6607             rect
[3] = BlockToDeviceRect( wxGridCellCoords ( bottomRow 
+ 1, 
6609                                          wxGridCellCoords ( oldBottom
, 
6615         m_selectedTopLeft 
= updateTopLeft
; 
6616         m_selectedBottomRight 
= updateBottomRight
; 
6618         // various Refresh() calls 
6619         for (i 
= 0; i 
< 4; i
++ ) 
6620             if ( need_refresh
[i
] && rect
[i
] != wxGridNoCellRect 
) 
6621                 m_gridWin
->Refresh( FALSE
, &(rect
[i
]) ); 
6624     // only generate an event if the block is not being selected by 
6625     // dragging the mouse (in which case the event will be generated in 
6626     // the mouse event handler) 
6627     if ( !m_isDragging 
) 
6629         wxGridRangeSelectEvent 
gridEvt( GetId(), 
6630                                         wxEVT_GRID_RANGE_SELECT
, 
6633                                         m_selectedBottomRight 
); 
6635         GetEventHandler()->ProcessEvent(gridEvt
); 
6639 void wxGrid::SelectAll() 
6641     m_selectedTopLeft
.Set( 0, 0 ); 
6642     m_selectedBottomRight
.Set( m_numRows
-1, m_numCols
-1 ); 
6644     m_gridWin
->Refresh(); 
6648 void wxGrid::ClearSelection() 
6650     m_selectedTopLeft 
= wxGridNoCellCoords
; 
6651     m_selectedBottomRight 
= wxGridNoCellCoords
; 
6655 // This function returns the rectangle that encloses the given block 
6656 // in device coords clipped to the client size of the grid window. 
6658 wxRect 
wxGrid::BlockToDeviceRect( const wxGridCellCoords 
&topLeft
, 
6659                                   const wxGridCellCoords 
&bottomRight 
) 
6661     wxRect 
rect( wxGridNoCellRect 
); 
6664     cellRect 
= CellToRect( topLeft 
); 
6665     if ( cellRect 
!= wxGridNoCellRect 
) 
6671         rect 
= wxRect( 0, 0, 0, 0 ); 
6674     cellRect 
= CellToRect( bottomRight 
); 
6675     if ( cellRect 
!= wxGridNoCellRect 
) 
6681         return wxGridNoCellRect
; 
6684     // convert to scrolled coords 
6686     int left
, top
, right
, bottom
; 
6687     CalcScrolledPosition( rect
.GetLeft(), rect
.GetTop(), &left
, &top 
); 
6688     CalcScrolledPosition( rect
.GetRight(), rect
.GetBottom(), &right
, &bottom 
); 
6691     m_gridWin
->GetClientSize( &cw
, &ch 
); 
6693     rect
.SetLeft( wxMax(0, left
) ); 
6694     rect
.SetTop( wxMax(0, top
) ); 
6695     rect
.SetRight( wxMin(cw
, right
) ); 
6696     rect
.SetBottom( wxMin(ch
, bottom
) ); 
6704 // ------ Grid event classes 
6707 IMPLEMENT_DYNAMIC_CLASS( wxGridEvent
, wxEvent 
) 
6709 wxGridEvent::wxGridEvent( int id
, wxEventType type
, wxObject
* obj
, 
6710                           int row
, int col
, int x
, int y
, 
6711                           bool control
, bool shift
, bool alt
, bool meta 
) 
6712         : wxNotifyEvent( type
, id 
) 
6718     m_control 
= control
; 
6723     SetEventObject(obj
); 
6727 IMPLEMENT_DYNAMIC_CLASS( wxGridSizeEvent
, wxEvent 
) 
6729 wxGridSizeEvent::wxGridSizeEvent( int id
, wxEventType type
, wxObject
* obj
, 
6730                                   int rowOrCol
, int x
, int y
, 
6731                                   bool control
, bool shift
, bool alt
, bool meta 
) 
6732         : wxNotifyEvent( type
, id 
) 
6734     m_rowOrCol 
= rowOrCol
; 
6737     m_control 
= control
; 
6742     SetEventObject(obj
); 
6746 IMPLEMENT_DYNAMIC_CLASS( wxGridRangeSelectEvent
, wxEvent 
) 
6748 wxGridRangeSelectEvent::wxGridRangeSelectEvent(int id
, wxEventType type
, wxObject
* obj
, 
6749                                                const wxGridCellCoords
& topLeft
, 
6750                                                const wxGridCellCoords
& bottomRight
, 
6751                                                bool control
, bool shift
, bool alt
, bool meta 
) 
6752         : wxNotifyEvent( type
, id 
) 
6754     m_topLeft     
= topLeft
; 
6755     m_bottomRight 
= bottomRight
; 
6756     m_control     
= control
; 
6761     SetEventObject(obj
); 
6765 #endif // ifndef wxUSE_NEW_GRID