1 /////////////////////////////////////////////////////////////////////////// 
   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" 
  52 // ---------------------------------------------------------------------------- 
  54 // ---------------------------------------------------------------------------- 
  56 WX_DEFINE_ARRAY(wxGridCellAttr 
*, wxArrayAttrs
); 
  58 struct wxGridCellWithAttr
 
  60     wxGridCellWithAttr(int row
, int col
, wxGridCellAttr 
*attr_
) 
  61         : coords(row
, col
), attr(attr_
) 
  70     wxGridCellCoords coords
; 
  74 WX_DECLARE_OBJARRAY(wxGridCellWithAttr
, wxGridCellWithAttrArray
); 
  76 #include "wx/arrimpl.cpp" 
  78 WX_DEFINE_OBJARRAY(wxGridCellCoordsArray
) 
  79 WX_DEFINE_OBJARRAY(wxGridCellWithAttrArray
) 
  81 // ---------------------------------------------------------------------------- 
  83 // ---------------------------------------------------------------------------- 
  85 class WXDLLEXPORT wxGridRowLabelWindow 
: public wxWindow
 
  88     wxGridRowLabelWindow() { m_owner 
= (wxGrid 
*)NULL
; } 
  89     wxGridRowLabelWindow( wxGrid 
*parent
, wxWindowID id
, 
  90                           const wxPoint 
&pos
, const wxSize 
&size 
); 
  95     void OnPaint( wxPaintEvent
& event 
); 
  96     void OnMouseEvent( wxMouseEvent
& event 
); 
  97     void OnKeyDown( wxKeyEvent
& event 
); 
  99     DECLARE_DYNAMIC_CLASS(wxGridRowLabelWindow
) 
 100     DECLARE_EVENT_TABLE() 
 104 class WXDLLEXPORT wxGridColLabelWindow 
: public wxWindow
 
 107     wxGridColLabelWindow() { m_owner 
= (wxGrid 
*)NULL
; } 
 108     wxGridColLabelWindow( wxGrid 
*parent
, wxWindowID id
, 
 109                           const wxPoint 
&pos
, const wxSize 
&size 
); 
 114     void OnPaint( wxPaintEvent 
&event 
); 
 115     void OnMouseEvent( wxMouseEvent
& event 
); 
 116     void OnKeyDown( wxKeyEvent
& event 
); 
 118     DECLARE_DYNAMIC_CLASS(wxGridColLabelWindow
) 
 119     DECLARE_EVENT_TABLE() 
 123 class WXDLLEXPORT wxGridCornerLabelWindow 
: public wxWindow
 
 126     wxGridCornerLabelWindow() { m_owner 
= (wxGrid 
*)NULL
; } 
 127     wxGridCornerLabelWindow( wxGrid 
*parent
, wxWindowID id
, 
 128                              const wxPoint 
&pos
, const wxSize 
&size 
); 
 133     void OnMouseEvent( wxMouseEvent
& event 
); 
 134     void OnKeyDown( wxKeyEvent
& event 
); 
 135     void OnPaint( wxPaintEvent
& event 
); 
 137     DECLARE_DYNAMIC_CLASS(wxGridCornerLabelWindow
) 
 138     DECLARE_EVENT_TABLE() 
 141 class WXDLLEXPORT wxGridWindow 
: public wxPanel
 
 146         m_owner 
= (wxGrid 
*)NULL
; 
 147         m_rowLabelWin 
= (wxGridRowLabelWindow 
*)NULL
; 
 148         m_colLabelWin 
= (wxGridColLabelWindow 
*)NULL
; 
 151     wxGridWindow( wxGrid 
*parent
, 
 152                   wxGridRowLabelWindow 
*rowLblWin
, 
 153                   wxGridColLabelWindow 
*colLblWin
, 
 154                   wxWindowID id
, const wxPoint 
&pos
, const wxSize 
&size 
); 
 157     void ScrollWindow( int dx
, int dy
, const wxRect 
*rect 
); 
 161     wxGridRowLabelWindow     
*m_rowLabelWin
; 
 162     wxGridColLabelWindow     
*m_colLabelWin
; 
 164     void OnPaint( wxPaintEvent 
&event 
); 
 165     void OnMouseEvent( wxMouseEvent
& event 
); 
 166     void OnKeyDown( wxKeyEvent
& ); 
 167     void OnEraseBackground( wxEraseEvent
& ); 
 170     DECLARE_DYNAMIC_CLASS(wxGridWindow
) 
 171     DECLARE_EVENT_TABLE() 
 176 class wxGridCellEditorEvtHandler 
: public wxEvtHandler
 
 179     wxGridCellEditorEvtHandler() 
 180         : m_grid(0), m_editor(0) 
 182     wxGridCellEditorEvtHandler(wxGrid
* grid
, wxGridCellEditor
* editor
) 
 183         : m_grid(grid
), m_editor(editor
) 
 186     void OnKeyDown(wxKeyEvent
& event
); 
 187     void OnChar(wxKeyEvent
& event
); 
 191     wxGridCellEditor
*   m_editor
; 
 192     DECLARE_DYNAMIC_CLASS(wxGridCellEditorEvtHandler
) 
 193     DECLARE_EVENT_TABLE() 
 197 IMPLEMENT_DYNAMIC_CLASS( wxGridCellEditorEvtHandler
, wxEvtHandler 
) 
 198 BEGIN_EVENT_TABLE( wxGridCellEditorEvtHandler
, wxEvtHandler 
) 
 199     EVT_KEY_DOWN( wxGridCellEditorEvtHandler::OnKeyDown 
) 
 200     EVT_CHAR( wxGridCellEditorEvtHandler::OnChar 
) 
 205 // ---------------------------------------------------------------------------- 
 206 // the internal data representation used by wxGridCellAttrProvider 
 207 // ---------------------------------------------------------------------------- 
 209 // this class stores attributes set for cells 
 210 class WXDLLEXPORT wxGridCellAttrData
 
 213     void SetAttr(wxGridCellAttr 
*attr
, int row
, int col
); 
 214     wxGridCellAttr 
*GetAttr(int row
, int col
) const; 
 215     void UpdateAttrRows( size_t pos
, int numRows 
); 
 216     void UpdateAttrCols( size_t pos
, int numCols 
); 
 219     // searches for the attr for given cell, returns wxNOT_FOUND if not found 
 220     int FindIndex(int row
, int col
) const; 
 222     wxGridCellWithAttrArray m_attrs
; 
 225 // this class stores attributes set for rows or columns 
 226 class WXDLLEXPORT wxGridRowOrColAttrData
 
 229     // empty ctor to suppress warnings 
 230     wxGridRowOrColAttrData() { } 
 231     ~wxGridRowOrColAttrData(); 
 233     void SetAttr(wxGridCellAttr 
*attr
, int rowOrCol
); 
 234     wxGridCellAttr 
*GetAttr(int rowOrCol
) const; 
 235     void UpdateAttrRowsOrCols( size_t pos
, int numRowsOrCols 
); 
 238     wxArrayInt m_rowsOrCols
; 
 239     wxArrayAttrs m_attrs
; 
 242 // NB: this is just a wrapper around 3 objects: one which stores cell 
 243 //     attributes, and 2 others for row/col ones 
 244 class WXDLLEXPORT wxGridCellAttrProviderData
 
 247     wxGridCellAttrData m_cellAttrs
; 
 248     wxGridRowOrColAttrData m_rowAttrs
, 
 252 // ---------------------------------------------------------------------------- 
 253 // conditional compilation 
 254 // ---------------------------------------------------------------------------- 
 256 #ifndef WXGRID_DRAW_LINES 
 257 #define WXGRID_DRAW_LINES 1 
 260 // ---------------------------------------------------------------------------- 
 262 // ---------------------------------------------------------------------------- 
 264 //#define DEBUG_ATTR_CACHE 
 265 #ifdef DEBUG_ATTR_CACHE 
 266     static size_t gs_nAttrCacheHits 
= 0; 
 267     static size_t gs_nAttrCacheMisses 
= 0; 
 268 #endif // DEBUG_ATTR_CACHE 
 270 wxGridCellCoords 
wxGridNoCellCoords( -1, -1 ); 
 271 wxRect           
wxGridNoCellRect( -1, -1, -1, -1 ); 
 274 // TODO: fixed so far - make configurable later (and also different for x/y) 
 275 static const size_t GRID_SCROLL_LINE 
= 10; 
 277 // ============================================================================ 
 279 // ============================================================================ 
 281 // ---------------------------------------------------------------------------- 
 283 // ---------------------------------------------------------------------------- 
 285 wxGridCellEditor::wxGridCellEditor() 
 291 wxGridCellEditor::~wxGridCellEditor() 
 296 void wxGridCellEditor::Create(wxWindow
* WXUNUSED(parent
), 
 297                               wxWindowID 
WXUNUSED(id
), 
 298                               wxEvtHandler
* evtHandler
) 
 301         m_control
->PushEventHandler(evtHandler
); 
 304 void wxGridCellEditor::PaintBackground(const wxRect
& rectCell
, 
 305                                        wxGridCellAttr 
*attr
) 
 307     // erase the background because we might not fill the cell 
 308     wxClientDC 
dc(m_control
->GetParent()); 
 309     dc
.SetPen(*wxTRANSPARENT_PEN
); 
 310     dc
.SetBrush(wxBrush(attr
->GetBackgroundColour(), wxSOLID
)); 
 311     dc
.DrawRectangle(rectCell
); 
 313     // redraw the control we just painted over 
 314     m_control
->Refresh(); 
 317 void wxGridCellEditor::Destroy() 
 321         m_control
->Destroy(); 
 326 void wxGridCellEditor::Show(bool show
, wxGridCellAttr 
*attr
) 
 328     wxASSERT_MSG(m_control
, 
 329                  wxT("The wxGridCellEditor must be Created first!")); 
 330     m_control
->Show(show
); 
 334         // set the colours/fonts if we have any 
 337             if ( attr
->HasTextColour() ) 
 339                 m_colFgOld 
= m_control
->GetForegroundColour(); 
 340                 m_control
->SetForegroundColour(attr
->GetTextColour()); 
 343             if ( attr
->HasBackgroundColour() ) 
 345                 m_colBgOld 
= m_control
->GetBackgroundColour(); 
 346                 m_control
->SetBackgroundColour(attr
->GetBackgroundColour()); 
 349             if ( attr
->HasFont() ) 
 351                 m_fontOld 
= m_control
->GetFont(); 
 352                 m_control
->SetFont(attr
->GetFont()); 
 355             // can't do anything more in the base class version, the other 
 356             // attributes may only be used by the derived classes 
 361         // restore the standard colours fonts 
 362         if ( m_colFgOld
.Ok() ) 
 364             m_control
->SetForegroundColour(m_colFgOld
); 
 365             m_colFgOld 
= wxNullColour
; 
 368         if ( m_colBgOld
.Ok() ) 
 370             m_control
->SetBackgroundColour(m_colBgOld
); 
 371             m_colBgOld 
= wxNullColour
; 
 374         if ( m_fontOld
.Ok() ) 
 376             m_control
->SetFont(m_fontOld
); 
 377             m_fontOld 
= wxNullFont
; 
 382 void wxGridCellEditor::SetSize(const wxRect
& rect
) 
 384     wxASSERT_MSG(m_control
, 
 385                  wxT("The wxGridCellEditor must be Created first!")); 
 386     m_control
->SetSize(rect
); 
 389 void wxGridCellEditor::HandleReturn(wxKeyEvent
& event
) 
 395 void wxGridCellEditor::StartingKey(wxKeyEvent
& event
) 
 400 void wxGridCellEditor::StartingClick() 
 404 // ---------------------------------------------------------------------------- 
 405 // wxGridCellTextEditor 
 406 // ---------------------------------------------------------------------------- 
 408 wxGridCellTextEditor::wxGridCellTextEditor() 
 412 void wxGridCellTextEditor::Create(wxWindow
* parent
, 
 414                                   wxEvtHandler
* evtHandler
) 
 416     m_control 
= new wxTextCtrl(parent
, id
, wxEmptyString
, 
 417                                wxDefaultPosition
, wxDefaultSize
 
 418 #if defined(__WXMSW__) 
 419                                , wxTE_MULTILINE 
| wxTE_NO_VSCROLL 
// necessary ??? 
 423     wxGridCellEditor::Create(parent
, id
, evtHandler
); 
 426 void wxGridCellTextEditor::PaintBackground(const wxRect
& WXUNUSED(rectCell
), 
 427                                            wxGridCellAttr 
* WXUNUSED(attr
)) 
 429     // as we fill the entire client area, don't do anything here to minimize 
 433 void wxGridCellTextEditor::BeginEdit(int row
, int col
, wxGrid
* grid
) 
 435     wxASSERT_MSG(m_control
, 
 436                  wxT("The wxGridCellEditor must be Created first!")); 
 438     m_startValue 
= grid
->GetTable()->GetValue(row
, col
); 
 439     Text()->SetValue(m_startValue
); 
 440     Text()->SetInsertionPointEnd(); 
 445 bool wxGridCellTextEditor::EndEdit(int row
, int col
, bool saveValue
, 
 448     wxASSERT_MSG(m_control
, 
 449                  wxT("The wxGridCellEditor must be Created first!")); 
 451     bool changed 
= FALSE
; 
 452     wxString value 
= Text()->GetValue(); 
 453     if (value 
!= m_startValue
) 
 457         grid
->GetTable()->SetValue(row
, col
, value
); 
 459     m_startValue 
= wxEmptyString
; 
 460     Text()->SetValue(m_startValue
); 
 466 void wxGridCellTextEditor::Reset() 
 468     wxASSERT_MSG(m_control
, 
 469                  wxT("The wxGridCellEditor must be Created first!")); 
 471     Text()->SetValue(m_startValue
); 
 472     Text()->SetInsertionPointEnd(); 
 475 void wxGridCellTextEditor::StartingKey(wxKeyEvent
& event
) 
 477     if ( !event
.AltDown() && !event
.MetaDown() && !event
.ControlDown() ) 
 479         // insert the key in the control 
 480         long keycode 
= event
.KeyCode(); 
 481         if ( isprint(keycode
) ) 
 483             // FIXME this is not going to work for non letters... 
 484             if ( !event
.ShiftDown() ) 
 486                 keycode 
= tolower(keycode
); 
 489             Text()->AppendText((wxChar
)keycode
); 
 499 void wxGridCellTextEditor::HandleReturn(wxKeyEvent
& event
) 
 501 #if defined(__WXMOTIF__) || defined(__WXGTK__) 
 502     // wxMotif needs a little extra help... 
 503     int pos 
= Text()->GetInsertionPoint(); 
 504     wxString 
s( Text()->GetValue() ); 
 505     s 
= s
.Left(pos
) + "\n" + s
.Mid(pos
); 
 507     Text()->SetInsertionPoint( pos 
); 
 509     // the other ports can handle a Return key press 
 515 // ---------------------------------------------------------------------------- 
 516 // wxGridCellBoolEditor 
 517 // ---------------------------------------------------------------------------- 
 519 void wxGridCellBoolEditor::Create(wxWindow
* parent
, 
 521                                   wxEvtHandler
* evtHandler
) 
 523     m_control 
= new wxCheckBox(parent
, id
, wxEmptyString
, 
 524                                wxDefaultPosition
, wxDefaultSize
, 
 527     wxGridCellEditor::Create(parent
, id
, evtHandler
); 
 530 void wxGridCellBoolEditor::SetSize(const wxRect
& r
) 
 532     // position it in the centre of the rectangle (TODO: support alignment?) 
 534     m_control
->GetSize(&w
, &h
); 
 536     // the checkbox without label still has some space to the right in wxGTK, 
 537     // so shift it to the right 
 542     m_control
->Move(r
.x 
+ r
.width
/2 - w
/2, r
.y 
+ r
.height
/2 - h
/2); 
 545 void wxGridCellBoolEditor::Show(bool show
, wxGridCellAttr 
*attr
) 
 547     wxGridCellEditor::Show(show
, attr
); 
 550         // VZ: normally base class already does it, but it doesn't work (FIXME) 
 551         wxColour colBg 
= attr 
? attr
->GetBackgroundColour() : *wxLIGHT_GREY
; 
 552         CBox()->SetBackgroundColour(colBg
); 
 556 void wxGridCellBoolEditor::BeginEdit(int row
, int col
, wxGrid
* grid
) 
 558     wxASSERT_MSG(m_control
, 
 559                  wxT("The wxGridCellEditor must be Created first!")); 
 561     m_startValue 
= !!grid
->GetTable()->GetValue(row
, col
); // FIXME-DATA 
 562     CBox()->SetValue(m_startValue
); 
 566 bool wxGridCellBoolEditor::EndEdit(int row
, int col
, 
 570     wxASSERT_MSG(m_control
, 
 571                  wxT("The wxGridCellEditor must be Created first!")); 
 573     bool changed 
= FALSE
; 
 574     bool value 
= CBox()->GetValue(); 
 575     if ( value 
!= m_startValue 
) 
 581         grid
->GetTable()->SetValue(row
, col
, value 
? _T("1") : wxEmptyString
); 
 587 void wxGridCellBoolEditor::Reset() 
 589     wxASSERT_MSG(m_control
, 
 590                  wxT("The wxGridCellEditor must be Created first!")); 
 592     CBox()->SetValue(m_startValue
); 
 595 void wxGridCellBoolEditor::StartingClick() 
 597     CBox()->SetValue(!CBox()->GetValue()); 
 600 // ---------------------------------------------------------------------------- 
 601 // wxGridCellEditorEvtHandler 
 602 // ---------------------------------------------------------------------------- 
 604 void wxGridCellEditorEvtHandler::OnKeyDown(wxKeyEvent
& event
) 
 606     switch ( event
.KeyCode() ) 
 610             m_grid
->DisableCellEditControl(); 
 614             event
.Skip( m_grid
->ProcessEvent( event 
) ); 
 618             if (!m_grid
->ProcessEvent(event
)) 
 619                 m_editor
->HandleReturn(event
); 
 628 void wxGridCellEditorEvtHandler::OnChar(wxKeyEvent
& event
) 
 630     switch ( event
.KeyCode() ) 
 642 // ============================================================================ 
 644 // ============================================================================ 
 646 // ---------------------------------------------------------------------------- 
 647 // wxGridCellRenderer 
 648 // ---------------------------------------------------------------------------- 
 650 void wxGridCellRenderer::Draw(wxGrid
& grid
, 
 651                               wxGridCellAttr
& attr
, 
 657     dc
.SetBackgroundMode( wxSOLID 
); 
 661         dc
.SetBrush( wxBrush(grid
.GetSelectionBackground(), wxSOLID
) ); 
 665         dc
.SetBrush( wxBrush(attr
.GetBackgroundColour(), wxSOLID
) ); 
 668     dc
.SetPen( *wxTRANSPARENT_PEN 
); 
 669     dc
.DrawRectangle(rect
); 
 672 // ---------------------------------------------------------------------------- 
 673 // wxGridCellStringRenderer 
 674 // ---------------------------------------------------------------------------- 
 676 void wxGridCellStringRenderer::Draw(wxGrid
& grid
, 
 677                                     wxGridCellAttr
& attr
, 
 679                                     const wxRect
& rectCell
, 
 683     wxGridCellRenderer::Draw(grid
, attr
, dc
, rectCell
, row
, col
, isSelected
); 
 685     // now we only have to draw the text 
 686     dc
.SetBackgroundMode( wxTRANSPARENT 
); 
 688     // TODO some special colours for attr.IsReadOnly() case? 
 692         dc
.SetTextBackground( grid
.GetSelectionBackground() ); 
 693         dc
.SetTextForeground( grid
.GetSelectionForeground() ); 
 697         dc
.SetTextBackground( attr
.GetBackgroundColour() ); 
 698         dc
.SetTextForeground( attr
.GetTextColour() ); 
 700     dc
.SetFont( attr
.GetFont() ); 
 703     attr
.GetAlignment(&hAlign
, &vAlign
); 
 705     wxRect rect 
= rectCell
; 
 711     grid
.DrawTextRectangle(dc
, grid
.GetCellValue(row
, col
), 
 712                            rect
, hAlign
, vAlign
); 
 715 // ---------------------------------------------------------------------------- 
 716 // wxGridCellBoolRenderer 
 717 // ---------------------------------------------------------------------------- 
 719 void wxGridCellBoolRenderer::Draw(wxGrid
& grid
, 
 720                                   wxGridCellAttr
& attr
, 
 726     wxGridCellRenderer::Draw(grid
, attr
, dc
, rect
, row
, col
, isSelected
); 
 728     // between checkmark and box 
 729     static const wxCoord margin 
= 4; 
 732     static wxCoord s_checkSize 
= 0; 
 733     if ( s_checkSize 
== 0 ) 
 735         // compute it only once (no locks for MT safeness in GUI thread...) 
 736         wxCheckBox 
*checkbox 
= new wxCheckBox(&grid
, -1, wxEmptyString
); 
 737         wxSize size 
= checkbox
->GetBestSize(); 
 738         s_checkSize 
= size
.y 
+ margin
; 
 740         // FIXME wxGTK::wxCheckBox::GetBestSize() is really weird... 
 742         s_checkSize 
-= size
.y 
/ 2; 
 748     // draw a check mark in the centre (ignoring alignment - TODO) 
 750     rectMark
.x 
= rect
.x 
+ rect
.width
/2 - s_checkSize
/2; 
 751     rectMark
.y 
= rect
.y 
+ rect
.height
/2 - s_checkSize
/2; 
 752     rectMark
.width 
= rectMark
.height 
= s_checkSize
; 
 754     dc
.SetBrush(*wxTRANSPARENT_BRUSH
); 
 755     dc
.SetPen(wxPen(attr
.GetTextColour(), 1, wxSOLID
)); 
 756     dc
.DrawRectangle(rectMark
); 
 758     rectMark
.Inflate(-margin
); 
 760     if ( !!grid
.GetTable()->GetValue(row
, col
) ) // FIXME-DATA 
 762         dc
.SetTextForeground(attr
.GetTextColour()); 
 763         dc
.DrawCheckMark(rectMark
); 
 767 // ---------------------------------------------------------------------------- 
 769 // ---------------------------------------------------------------------------- 
 771 const wxColour
& wxGridCellAttr::GetTextColour() const 
 777     else if (m_defGridAttr 
!= this) 
 779         return m_defGridAttr
->GetTextColour(); 
 783         wxFAIL_MSG(wxT("Missing default cell attribute")); 
 789 const wxColour
& wxGridCellAttr::GetBackgroundColour() const 
 791     if (HasBackgroundColour()) 
 793     else if (m_defGridAttr 
!= this) 
 794         return m_defGridAttr
->GetBackgroundColour(); 
 797         wxFAIL_MSG(wxT("Missing default cell attribute")); 
 803 const wxFont
& wxGridCellAttr::GetFont() const 
 807     else if (m_defGridAttr 
!= this) 
 808         return m_defGridAttr
->GetFont(); 
 811         wxFAIL_MSG(wxT("Missing default cell attribute")); 
 817 void wxGridCellAttr::GetAlignment(int *hAlign
, int *vAlign
) const 
 821         if ( hAlign 
) *hAlign 
= m_hAlign
; 
 822         if ( vAlign 
) *vAlign 
= m_vAlign
; 
 824     else if (m_defGridAttr 
!= this) 
 825         m_defGridAttr
->GetAlignment(hAlign
, vAlign
); 
 828         wxFAIL_MSG(wxT("Missing default cell attribute")); 
 833 wxGridCellRenderer
* wxGridCellAttr::GetRenderer() const 
 837     else if (m_defGridAttr 
!= this) 
 838         return m_defGridAttr
->GetRenderer(); 
 841         wxFAIL_MSG(wxT("Missing default cell attribute")); 
 846 wxGridCellEditor
* wxGridCellAttr::GetEditor() const 
 850     else if (m_defGridAttr 
!= this) 
 851         return m_defGridAttr
->GetEditor(); 
 854         wxFAIL_MSG(wxT("Missing default cell attribute")); 
 859 // ---------------------------------------------------------------------------- 
 860 // wxGridCellAttrData 
 861 // ---------------------------------------------------------------------------- 
 863 void wxGridCellAttrData::SetAttr(wxGridCellAttr 
*attr
, int row
, int col
) 
 865     int n 
= FindIndex(row
, col
); 
 866     if ( n 
== wxNOT_FOUND 
) 
 869         m_attrs
.Add(new wxGridCellWithAttr(row
, col
, attr
)); 
 875             // change the attribute 
 876             m_attrs
[(size_t)n
].attr 
= attr
; 
 880             // remove this attribute 
 881             m_attrs
.RemoveAt((size_t)n
); 
 886 wxGridCellAttr 
*wxGridCellAttrData::GetAttr(int row
, int col
) const 
 888     wxGridCellAttr 
*attr 
= (wxGridCellAttr 
*)NULL
; 
 890     int n 
= FindIndex(row
, col
); 
 891     if ( n 
!= wxNOT_FOUND 
) 
 893         attr 
= m_attrs
[(size_t)n
].attr
; 
 900 void wxGridCellAttrData::UpdateAttrRows( size_t pos
, int numRows 
) 
 902     size_t count 
= m_attrs
.GetCount(); 
 903     for ( size_t n 
= 0; n 
< count
; n
++ ) 
 905         wxGridCellCoords
& coords 
= m_attrs
[n
].coords
; 
 906         wxCoord row 
= coords
.GetRow(); 
 907         if ((size_t)row 
>= pos
) 
 911                 // If rows inserted, include row counter where necessary 
 912                 coords
.SetRow(row 
+ numRows
); 
 914             else if (numRows 
< 0) 
 916                 // If rows deleted ... 
 917                 if ((size_t)row 
>= pos 
- numRows
) 
 919                     // ...either decrement row counter (if row still exists)... 
 920                     coords
.SetRow(row 
+ numRows
); 
 924                     // ...or remove the attribute 
 925                     m_attrs
.RemoveAt((size_t)n
); 
 933 void wxGridCellAttrData::UpdateAttrCols( size_t pos
, int numCols 
) 
 935     size_t count 
= m_attrs
.GetCount(); 
 936     for ( size_t n 
= 0; n 
< count
; n
++ ) 
 938         wxGridCellCoords
& coords 
= m_attrs
[n
].coords
; 
 939         wxCoord col 
= coords
.GetCol(); 
 940         if ( (size_t)col 
>= pos 
) 
 944                 // If rows inserted, include row counter where necessary 
 945                 coords
.SetCol(col 
+ numCols
); 
 947             else if (numCols 
< 0) 
 949                 // If rows deleted ... 
 950                 if ((size_t)col 
>= pos 
- numCols
) 
 952                     // ...either decrement row counter (if row still exists)... 
 953                     coords
.SetCol(col 
+ numCols
); 
 957                     // ...or remove the attribute 
 958                     m_attrs
.RemoveAt((size_t)n
); 
 966 int wxGridCellAttrData::FindIndex(int row
, int col
) const 
 968     size_t count 
= m_attrs
.GetCount(); 
 969     for ( size_t n 
= 0; n 
< count
; n
++ ) 
 971         const wxGridCellCoords
& coords 
= m_attrs
[n
].coords
; 
 972         if ( (coords
.GetRow() == row
) && (coords
.GetCol() == col
) ) 
 981 // ---------------------------------------------------------------------------- 
 982 // wxGridRowOrColAttrData 
 983 // ---------------------------------------------------------------------------- 
 985 wxGridRowOrColAttrData::~wxGridRowOrColAttrData() 
 987     size_t count 
= m_attrs
.Count(); 
 988     for ( size_t n 
= 0; n 
< count
; n
++ ) 
 990         m_attrs
[n
]->DecRef(); 
 994 wxGridCellAttr 
*wxGridRowOrColAttrData::GetAttr(int rowOrCol
) const 
 996     wxGridCellAttr 
*attr 
= (wxGridCellAttr 
*)NULL
; 
 998     int n 
= m_rowsOrCols
.Index(rowOrCol
); 
 999     if ( n 
!= wxNOT_FOUND 
) 
1001         attr 
= m_attrs
[(size_t)n
]; 
1008 void wxGridRowOrColAttrData::SetAttr(wxGridCellAttr 
*attr
, int rowOrCol
) 
1010     int n 
= m_rowsOrCols
.Index(rowOrCol
); 
1011     if ( n 
== wxNOT_FOUND 
) 
1013         // add the attribute 
1014         m_rowsOrCols
.Add(rowOrCol
); 
1021             // change the attribute 
1022             m_attrs
[(size_t)n
] = attr
; 
1026             // remove this attribute 
1027             m_attrs
[(size_t)n
]->DecRef(); 
1028             m_rowsOrCols
.RemoveAt((size_t)n
); 
1029             m_attrs
.RemoveAt((size_t)n
); 
1034 void wxGridRowOrColAttrData::UpdateAttrRowsOrCols( size_t pos
, int numRowsOrCols 
) 
1036     size_t count 
= m_attrs
.GetCount(); 
1037     for ( size_t n 
= 0; n 
< count
; n
++ ) 
1039         int & rowOrCol 
= m_rowsOrCols
[n
]; 
1040         if ( (size_t)rowOrCol 
>= pos 
) 
1042             if ( numRowsOrCols 
> 0 ) 
1044                 // If rows inserted, include row counter where necessary 
1045                 rowOrCol 
+= numRowsOrCols
; 
1047             else if ( numRowsOrCols 
< 0) 
1049                 // If rows deleted, either decrement row counter (if row still exists) 
1050                 if ((size_t)rowOrCol 
>= pos 
- numRowsOrCols
) 
1051                     rowOrCol 
+= numRowsOrCols
; 
1054                     m_rowsOrCols
.RemoveAt((size_t)n
); 
1055                     m_attrs
.RemoveAt((size_t)n
); 
1063 // ---------------------------------------------------------------------------- 
1064 // wxGridCellAttrProvider 
1065 // ---------------------------------------------------------------------------- 
1067 wxGridCellAttrProvider::wxGridCellAttrProvider() 
1069     m_data 
= (wxGridCellAttrProviderData 
*)NULL
; 
1072 wxGridCellAttrProvider::~wxGridCellAttrProvider() 
1077 void wxGridCellAttrProvider::InitData() 
1079     m_data 
= new wxGridCellAttrProviderData
; 
1082 wxGridCellAttr 
*wxGridCellAttrProvider::GetAttr(int row
, int col
) const 
1084     wxGridCellAttr 
*attr 
= (wxGridCellAttr 
*)NULL
; 
1087         // first look for the attribute of this specific cell 
1088         attr 
= m_data
->m_cellAttrs
.GetAttr(row
, col
); 
1092             // then look for the col attr (col attributes are more common than 
1093             // the row ones, hence they have priority) 
1094             attr 
= m_data
->m_colAttrs
.GetAttr(col
); 
1099             // finally try the row attributes 
1100             attr 
= m_data
->m_rowAttrs
.GetAttr(row
); 
1107 void wxGridCellAttrProvider::SetAttr(wxGridCellAttr 
*attr
, 
1113     m_data
->m_cellAttrs
.SetAttr(attr
, row
, col
); 
1116 void wxGridCellAttrProvider::SetRowAttr(wxGridCellAttr 
*attr
, int row
) 
1121     m_data
->m_rowAttrs
.SetAttr(attr
, row
); 
1124 void wxGridCellAttrProvider::SetColAttr(wxGridCellAttr 
*attr
, int col
) 
1129     m_data
->m_colAttrs
.SetAttr(attr
, col
); 
1132 void wxGridCellAttrProvider::UpdateAttrRows( size_t pos
, int numRows 
) 
1136         m_data
->m_cellAttrs
.UpdateAttrRows( pos
, numRows 
); 
1138         m_data
->m_rowAttrs
.UpdateAttrRowsOrCols( pos
, numRows 
); 
1142 void wxGridCellAttrProvider::UpdateAttrCols( size_t pos
, int numCols 
) 
1146         m_data
->m_cellAttrs
.UpdateAttrCols( pos
, numCols 
); 
1148         m_data
->m_colAttrs
.UpdateAttrRowsOrCols( pos
, numCols 
); 
1152 // ---------------------------------------------------------------------------- 
1154 // ---------------------------------------------------------------------------- 
1156 ////////////////////////////////////////////////////////////////////// 
1158 // Abstract base class for grid data (the model) 
1160 IMPLEMENT_ABSTRACT_CLASS( wxGridTableBase
, wxObject 
) 
1163 wxGridTableBase::wxGridTableBase() 
1165     m_view 
= (wxGrid 
*) NULL
; 
1166     m_attrProvider 
= (wxGridCellAttrProvider 
*) NULL
; 
1169 wxGridTableBase::~wxGridTableBase() 
1171     delete m_attrProvider
; 
1174 void wxGridTableBase::SetAttrProvider(wxGridCellAttrProvider 
*attrProvider
) 
1176     delete m_attrProvider
; 
1177     m_attrProvider 
= attrProvider
; 
1180 wxGridCellAttr 
*wxGridTableBase::GetAttr(int row
, int col
) 
1182     if ( m_attrProvider 
) 
1183         return m_attrProvider
->GetAttr(row
, col
); 
1185         return (wxGridCellAttr 
*)NULL
; 
1188 void wxGridTableBase::SetAttr(wxGridCellAttr
* attr
, int row
, int col
) 
1190     if ( m_attrProvider 
) 
1192         m_attrProvider
->SetAttr(attr
, row
, col
); 
1196         // as we take ownership of the pointer and don't store it, we must 
1202 void wxGridTableBase::SetRowAttr(wxGridCellAttr 
*attr
, int row
) 
1204     if ( m_attrProvider 
) 
1206         m_attrProvider
->SetRowAttr(attr
, row
); 
1210         // as we take ownership of the pointer and don't store it, we must 
1216 void wxGridTableBase::SetColAttr(wxGridCellAttr 
*attr
, int col
) 
1218     if ( m_attrProvider 
) 
1220         m_attrProvider
->SetColAttr(attr
, col
); 
1224         // as we take ownership of the pointer and don't store it, we must 
1230 void wxGridTableBase::UpdateAttrRows( size_t pos
, int numRows 
) 
1232     if ( m_attrProvider 
) 
1234         m_attrProvider
->UpdateAttrRows( pos
, numRows 
); 
1238 void wxGridTableBase::UpdateAttrCols( size_t pos
, int numCols 
) 
1240     if ( m_attrProvider 
) 
1242         m_attrProvider
->UpdateAttrCols( pos
, numCols 
); 
1246 bool wxGridTableBase::InsertRows( size_t pos
, size_t numRows 
) 
1248     wxFAIL_MSG( wxT("Called grid table class function InsertRows\n" 
1249                     "but your derived table class does not override this function") ); 
1254 bool wxGridTableBase::AppendRows( size_t numRows 
) 
1256     wxFAIL_MSG( wxT("Called grid table class function AppendRows\n" 
1257                     "but your derived table class does not override this function")); 
1262 bool wxGridTableBase::DeleteRows( size_t pos
, size_t numRows 
) 
1264     wxFAIL_MSG( wxT("Called grid table class function DeleteRows\n" 
1265                     "but your derived table class does not override this function")); 
1270 bool wxGridTableBase::InsertCols( size_t pos
, size_t numCols 
) 
1272     wxFAIL_MSG( wxT("Called grid table class function InsertCols\n" 
1273                   "but your derived table class does not override this function")); 
1278 bool wxGridTableBase::AppendCols( size_t numCols 
) 
1280     wxFAIL_MSG(wxT("Called grid table class function AppendCols\n" 
1281                    "but your derived table class does not override this function")); 
1286 bool wxGridTableBase::DeleteCols( size_t pos
, size_t numCols 
) 
1288     wxFAIL_MSG( wxT("Called grid table class function DeleteCols\n" 
1289                     "but your derived table class does not override this function")); 
1295 wxString 
wxGridTableBase::GetRowLabelValue( int row 
) 
1302 wxString 
wxGridTableBase::GetColLabelValue( int col 
) 
1304     // default col labels are: 
1305     //   cols 0 to 25   : A-Z 
1306     //   cols 26 to 675 : AA-ZZ 
1311     for ( n 
= 1; ; n
++ ) 
1313         s 
+= (_T('A') + (wxChar
)( col%26 
)); 
1315         if ( col 
< 0 ) break; 
1318     // reverse the string... 
1320     for ( i 
= 0;  i 
< n
;  i
++ ) 
1330 ////////////////////////////////////////////////////////////////////// 
1332 // Message class for the grid table to send requests and notifications 
1336 wxGridTableMessage::wxGridTableMessage() 
1338     m_table 
= (wxGridTableBase 
*) NULL
; 
1344 wxGridTableMessage::wxGridTableMessage( wxGridTableBase 
*table
, int id
, 
1345                                         int commandInt1
, int commandInt2 
) 
1349     m_comInt1 
= commandInt1
; 
1350     m_comInt2 
= commandInt2
; 
1355 ////////////////////////////////////////////////////////////////////// 
1357 // A basic grid table for string data. An object of this class will 
1358 // created by wxGrid if you don't specify an alternative table class. 
1361 WX_DEFINE_OBJARRAY(wxGridStringArray
) 
1363 IMPLEMENT_DYNAMIC_CLASS( wxGridStringTable
, wxGridTableBase 
) 
1365 wxGridStringTable::wxGridStringTable() 
1370 wxGridStringTable::wxGridStringTable( int numRows
, int numCols 
) 
1375     m_data
.Alloc( numRows 
); 
1378     sa
.Alloc( numCols 
); 
1379     for ( col 
= 0;  col 
< numCols
;  col
++ ) 
1381         sa
.Add( wxEmptyString 
); 
1384     for ( row 
= 0;  row 
< numRows
;  row
++ ) 
1390 wxGridStringTable::~wxGridStringTable() 
1394 long wxGridStringTable::GetNumberRows() 
1396     return m_data
.GetCount(); 
1399 long wxGridStringTable::GetNumberCols() 
1401     if ( m_data
.GetCount() > 0 ) 
1402         return m_data
[0].GetCount(); 
1407 wxString 
wxGridStringTable::GetValue( int row
, int col 
) 
1409     // TODO: bounds checking 
1411     return m_data
[row
][col
]; 
1414 void wxGridStringTable::SetValue( int row
, int col
, const wxString
& s 
) 
1416     // TODO: bounds checking 
1418     m_data
[row
][col
] = s
; 
1421 bool wxGridStringTable::IsEmptyCell( int row
, int col 
) 
1423     // TODO: bounds checking 
1425     return (m_data
[row
][col
] == wxEmptyString
); 
1429 void wxGridStringTable::Clear() 
1432     int numRows
, numCols
; 
1434     numRows 
= m_data
.GetCount(); 
1437         numCols 
= m_data
[0].GetCount(); 
1439         for ( row 
= 0;  row 
< numRows
;  row
++ ) 
1441             for ( col 
= 0;  col 
< numCols
;  col
++ ) 
1443                 m_data
[row
][col
] = wxEmptyString
; 
1450 bool wxGridStringTable::InsertRows( size_t pos
, size_t numRows 
) 
1454     size_t curNumRows 
= m_data
.GetCount(); 
1455     size_t curNumCols 
= ( curNumRows 
> 0 ? m_data
[0].GetCount() : 0 ); 
1457     if ( pos 
>= curNumRows 
) 
1459         return AppendRows( numRows 
); 
1463     sa
.Alloc( curNumCols 
); 
1464     for ( col 
= 0;  col 
< curNumCols
;  col
++ ) 
1466         sa
.Add( wxEmptyString 
); 
1469     for ( row 
= pos
;  row 
< pos 
+ numRows
;  row
++ ) 
1471         m_data
.Insert( sa
, row 
); 
1473     UpdateAttrRows( pos
, numRows 
); 
1476         wxGridTableMessage 
msg( this, 
1477                                 wxGRIDTABLE_NOTIFY_ROWS_INSERTED
, 
1481         GetView()->ProcessTableMessage( msg 
); 
1487 bool wxGridStringTable::AppendRows( size_t numRows 
) 
1491     size_t curNumRows 
= m_data
.GetCount(); 
1492     size_t curNumCols 
= ( curNumRows 
> 0 ? m_data
[0].GetCount() : 0 ); 
1495     if ( curNumCols 
> 0 ) 
1497         sa
.Alloc( curNumCols 
); 
1498         for ( col 
= 0;  col 
< curNumCols
;  col
++ ) 
1500             sa
.Add( wxEmptyString 
); 
1504     for ( row 
= 0;  row 
< numRows
;  row
++ ) 
1511         wxGridTableMessage 
msg( this, 
1512                                 wxGRIDTABLE_NOTIFY_ROWS_APPENDED
, 
1515         GetView()->ProcessTableMessage( msg 
); 
1521 bool wxGridStringTable::DeleteRows( size_t pos
, size_t numRows 
) 
1525     size_t curNumRows 
= m_data
.GetCount(); 
1527     if ( pos 
>= curNumRows 
) 
1530         errmsg
.Printf("Called wxGridStringTable::DeleteRows(pos=%d, N=%d)\n" 
1531                       "Pos value is invalid for present table with %d rows", 
1532                       pos
, numRows
, curNumRows 
); 
1533         wxFAIL_MSG( wxT(errmsg
) ); 
1537     if ( numRows 
> curNumRows 
- pos 
) 
1539         numRows 
= curNumRows 
- pos
; 
1542     if ( numRows 
>= curNumRows 
) 
1544         m_data
.Empty();  // don't release memory just yet 
1548         for ( n 
= 0;  n 
< numRows
;  n
++ ) 
1550             m_data
.Remove( pos 
); 
1553     UpdateAttrRows( pos
, -((int)numRows
) ); 
1556         wxGridTableMessage 
msg( this, 
1557                                 wxGRIDTABLE_NOTIFY_ROWS_DELETED
, 
1561         GetView()->ProcessTableMessage( msg 
); 
1567 bool wxGridStringTable::InsertCols( size_t pos
, size_t numCols 
) 
1571     size_t curNumRows 
= m_data
.GetCount(); 
1572     size_t curNumCols 
= ( curNumRows 
> 0 ? m_data
[0].GetCount() : 0 ); 
1574     if ( pos 
>= curNumCols 
) 
1576         return AppendCols( numCols 
); 
1579     for ( row 
= 0;  row 
< curNumRows
;  row
++ ) 
1581         for ( col 
= pos
;  col 
< pos 
+ numCols
;  col
++ ) 
1583             m_data
[row
].Insert( wxEmptyString
, col 
); 
1586     UpdateAttrCols( pos
, numCols 
); 
1589         wxGridTableMessage 
msg( this, 
1590                                 wxGRIDTABLE_NOTIFY_COLS_INSERTED
, 
1594         GetView()->ProcessTableMessage( msg 
); 
1600 bool wxGridStringTable::AppendCols( size_t numCols 
) 
1604     size_t curNumRows 
= m_data
.GetCount(); 
1607         // TODO: something better than this ? 
1609         wxFAIL_MSG( wxT("Unable to append cols to a grid table with no rows.\n" 
1610                         "Call AppendRows() first") ); 
1614     for ( row 
= 0;  row 
< curNumRows
;  row
++ ) 
1616         for ( n 
= 0;  n 
< numCols
;  n
++ ) 
1618             m_data
[row
].Add( wxEmptyString 
); 
1624         wxGridTableMessage 
msg( this, 
1625                                 wxGRIDTABLE_NOTIFY_COLS_APPENDED
, 
1628         GetView()->ProcessTableMessage( msg 
); 
1634 bool wxGridStringTable::DeleteCols( size_t pos
, size_t numCols 
) 
1638     size_t curNumRows 
= m_data
.GetCount(); 
1639     size_t curNumCols 
= ( curNumRows 
> 0 ? m_data
[0].GetCount() : 0 ); 
1641     if ( pos 
>= curNumCols 
) 
1644         errmsg
.Printf( "Called wxGridStringTable::DeleteCols(pos=%d, N=%d)...\n" 
1645                         "Pos value is invalid for present table with %d cols", 
1646                         pos
, numCols
, curNumCols 
); 
1647         wxFAIL_MSG( wxT( errmsg 
) ); 
1651     if ( numCols 
> curNumCols 
- pos 
) 
1653         numCols 
= curNumCols 
- pos
; 
1656     for ( row 
= 0;  row 
< curNumRows
;  row
++ ) 
1658         if ( numCols 
>= curNumCols 
) 
1660             m_data
[row
].Clear(); 
1664             for ( n 
= 0;  n 
< numCols
;  n
++ ) 
1666                 m_data
[row
].Remove( pos 
); 
1670     UpdateAttrCols( pos
, -((int)numCols
) ); 
1673         wxGridTableMessage 
msg( this, 
1674                                 wxGRIDTABLE_NOTIFY_COLS_DELETED
, 
1678         GetView()->ProcessTableMessage( msg 
); 
1684 wxString 
wxGridStringTable::GetRowLabelValue( int row 
) 
1686     if ( row 
> (int)(m_rowLabels
.GetCount()) - 1 ) 
1688         // using default label 
1690         return wxGridTableBase::GetRowLabelValue( row 
); 
1694         return m_rowLabels
[ row 
]; 
1698 wxString 
wxGridStringTable::GetColLabelValue( int col 
) 
1700     if ( col 
> (int)(m_colLabels
.GetCount()) - 1 ) 
1702         // using default label 
1704         return wxGridTableBase::GetColLabelValue( col 
); 
1708         return m_colLabels
[ col 
]; 
1712 void wxGridStringTable::SetRowLabelValue( int row
, const wxString
& value 
) 
1714     if ( row 
> (int)(m_rowLabels
.GetCount()) - 1 ) 
1716         int n 
= m_rowLabels
.GetCount(); 
1718         for ( i 
= n
;  i 
<= row
;  i
++ ) 
1720             m_rowLabels
.Add( wxGridTableBase::GetRowLabelValue(i
) ); 
1724     m_rowLabels
[row
] = value
; 
1727 void wxGridStringTable::SetColLabelValue( int col
, const wxString
& value 
) 
1729     if ( col 
> (int)(m_colLabels
.GetCount()) - 1 ) 
1731         int n 
= m_colLabels
.GetCount(); 
1733         for ( i 
= n
;  i 
<= col
;  i
++ ) 
1735             m_colLabels
.Add( wxGridTableBase::GetColLabelValue(i
) ); 
1739     m_colLabels
[col
] = value
; 
1744 ////////////////////////////////////////////////////////////////////// 
1745 ////////////////////////////////////////////////////////////////////// 
1747 IMPLEMENT_DYNAMIC_CLASS( wxGridRowLabelWindow
, wxWindow 
) 
1749 BEGIN_EVENT_TABLE( wxGridRowLabelWindow
, wxWindow 
) 
1750     EVT_PAINT( wxGridRowLabelWindow::OnPaint 
) 
1751     EVT_MOUSE_EVENTS( wxGridRowLabelWindow::OnMouseEvent 
) 
1752     EVT_KEY_DOWN( wxGridRowLabelWindow::OnKeyDown 
) 
1755 wxGridRowLabelWindow::wxGridRowLabelWindow( wxGrid 
*parent
, 
1757                                             const wxPoint 
&pos
, const wxSize 
&size 
) 
1758   : wxWindow( parent
, id
, pos
, size 
) 
1763 void wxGridRowLabelWindow::OnPaint( wxPaintEvent 
&event 
) 
1767     // NO - don't do this because it will set both the x and y origin 
1768     // coords to match the parent scrolled window and we just want to 
1769     // set the y coord  - MB 
1771     // m_owner->PrepareDC( dc ); 
1774     m_owner
->CalcUnscrolledPosition( 0, 0, &x
, &y 
); 
1775     dc
.SetDeviceOrigin( 0, -y 
); 
1777     m_owner
->CalcRowLabelsExposed( GetUpdateRegion() ); 
1778     m_owner
->DrawRowLabels( dc 
); 
1782 void wxGridRowLabelWindow::OnMouseEvent( wxMouseEvent
& event 
) 
1784     m_owner
->ProcessRowLabelMouseEvent( event 
); 
1788 // This seems to be required for wxMotif otherwise the mouse 
1789 // cursor must be in the cell edit control to get key events 
1791 void wxGridRowLabelWindow::OnKeyDown( wxKeyEvent
& event 
) 
1793     if ( !m_owner
->ProcessEvent( event 
) ) event
.Skip(); 
1798 ////////////////////////////////////////////////////////////////////// 
1800 IMPLEMENT_DYNAMIC_CLASS( wxGridColLabelWindow
, wxWindow 
) 
1802 BEGIN_EVENT_TABLE( wxGridColLabelWindow
, wxWindow 
) 
1803     EVT_PAINT( wxGridColLabelWindow::OnPaint 
) 
1804     EVT_MOUSE_EVENTS( wxGridColLabelWindow::OnMouseEvent 
) 
1805     EVT_KEY_DOWN( wxGridColLabelWindow::OnKeyDown 
) 
1808 wxGridColLabelWindow::wxGridColLabelWindow( wxGrid 
*parent
, 
1810                                             const wxPoint 
&pos
, const wxSize 
&size 
) 
1811   : wxWindow( parent
, id
, pos
, size 
) 
1816 void wxGridColLabelWindow::OnPaint( wxPaintEvent 
&event 
) 
1820     // NO - don't do this because it will set both the x and y origin 
1821     // coords to match the parent scrolled window and we just want to 
1822     // set the x coord  - MB 
1824     // m_owner->PrepareDC( dc ); 
1827     m_owner
->CalcUnscrolledPosition( 0, 0, &x
, &y 
); 
1828     dc
.SetDeviceOrigin( -x
, 0 ); 
1830     m_owner
->CalcColLabelsExposed( GetUpdateRegion() ); 
1831     m_owner
->DrawColLabels( dc 
); 
1835 void wxGridColLabelWindow::OnMouseEvent( wxMouseEvent
& event 
) 
1837     m_owner
->ProcessColLabelMouseEvent( event 
); 
1841 // This seems to be required for wxMotif otherwise the mouse 
1842 // cursor must be in the cell edit control to get key events 
1844 void wxGridColLabelWindow::OnKeyDown( wxKeyEvent
& event 
) 
1846     if ( !m_owner
->ProcessEvent( event 
) ) event
.Skip(); 
1851 ////////////////////////////////////////////////////////////////////// 
1853 IMPLEMENT_DYNAMIC_CLASS( wxGridCornerLabelWindow
, wxWindow 
) 
1855 BEGIN_EVENT_TABLE( wxGridCornerLabelWindow
, wxWindow 
) 
1856     EVT_MOUSE_EVENTS( wxGridCornerLabelWindow::OnMouseEvent 
) 
1857     EVT_PAINT( wxGridCornerLabelWindow::OnPaint
) 
1858     EVT_KEY_DOWN( wxGridCornerLabelWindow::OnKeyDown 
) 
1861 wxGridCornerLabelWindow::wxGridCornerLabelWindow( wxGrid 
*parent
, 
1863                                                   const wxPoint 
&pos
, const wxSize 
&size 
) 
1864   : wxWindow( parent
, id
, pos
, size 
) 
1869 void wxGridCornerLabelWindow::OnPaint( wxPaintEvent
& WXUNUSED(event
) ) 
1873     int client_height 
= 0; 
1874     int client_width 
= 0; 
1875     GetClientSize( &client_width
, &client_height 
); 
1877     dc
.SetPen( *wxBLACK_PEN 
); 
1878     dc
.DrawLine( client_width
-1, client_height
-1, client_width
-1, 0 ); 
1879     dc
.DrawLine( client_width
-1, client_height
-1, 0, client_height
-1 ); 
1881     dc
.SetPen( *wxWHITE_PEN 
); 
1882     dc
.DrawLine( 0, 0, client_width
, 0 ); 
1883     dc
.DrawLine( 0, 0, 0, client_height 
); 
1887 void wxGridCornerLabelWindow::OnMouseEvent( wxMouseEvent
& event 
) 
1889     m_owner
->ProcessCornerLabelMouseEvent( event 
); 
1893 // This seems to be required for wxMotif otherwise the mouse 
1894 // cursor must be in the cell edit control to get key events 
1896 void wxGridCornerLabelWindow::OnKeyDown( wxKeyEvent
& event 
) 
1898     if ( !m_owner
->ProcessEvent( event 
) ) event
.Skip(); 
1903 ////////////////////////////////////////////////////////////////////// 
1905 IMPLEMENT_DYNAMIC_CLASS( wxGridWindow
, wxPanel 
) 
1907 BEGIN_EVENT_TABLE( wxGridWindow
, wxPanel 
) 
1908     EVT_PAINT( wxGridWindow::OnPaint 
) 
1909     EVT_MOUSE_EVENTS( wxGridWindow::OnMouseEvent 
) 
1910     EVT_KEY_DOWN( wxGridWindow::OnKeyDown 
) 
1911     EVT_ERASE_BACKGROUND( wxGridWindow::OnEraseBackground 
) 
1914 wxGridWindow::wxGridWindow( wxGrid 
*parent
, 
1915                             wxGridRowLabelWindow 
*rowLblWin
, 
1916                             wxGridColLabelWindow 
*colLblWin
, 
1917                             wxWindowID id
, const wxPoint 
&pos
, const wxSize 
&size 
) 
1918         : wxPanel( parent
, id
, pos
, size
, 0, "grid window" ) 
1921     m_rowLabelWin 
= rowLblWin
; 
1922     m_colLabelWin 
= colLblWin
; 
1923     SetBackgroundColour( "WHITE" ); 
1927 wxGridWindow::~wxGridWindow() 
1932 void wxGridWindow::OnPaint( wxPaintEvent 
&WXUNUSED(event
) ) 
1934     wxPaintDC 
dc( this ); 
1935     m_owner
->PrepareDC( dc 
); 
1936     wxRegion reg 
= GetUpdateRegion(); 
1937     m_owner
->CalcCellsExposed( reg 
); 
1938     m_owner
->DrawGridCellArea( dc 
); 
1939 #if WXGRID_DRAW_LINES 
1940     m_owner
->DrawAllGridLines( dc
, reg 
); 
1942     m_owner
->DrawHighlight( dc 
); 
1946 void wxGridWindow::ScrollWindow( int dx
, int dy
, const wxRect 
*rect 
) 
1948     wxPanel::ScrollWindow( dx
, dy
, rect 
); 
1949     m_rowLabelWin
->ScrollWindow( 0, dy
, rect 
); 
1950     m_colLabelWin
->ScrollWindow( dx
, 0, rect 
); 
1954 void wxGridWindow::OnMouseEvent( wxMouseEvent
& event 
) 
1956     m_owner
->ProcessGridCellMouseEvent( event 
); 
1960 // This seems to be required for wxMotif otherwise the mouse 
1961 // cursor must be in the cell edit control to get key events 
1963 void wxGridWindow::OnKeyDown( wxKeyEvent
& event 
) 
1965     if ( !m_owner
->ProcessEvent( event 
) ) event
.Skip(); 
1968 void wxGridWindow::OnEraseBackground(wxEraseEvent
&) 
1974 ////////////////////////////////////////////////////////////////////// 
1977 IMPLEMENT_DYNAMIC_CLASS( wxGrid
, wxScrolledWindow 
) 
1979 BEGIN_EVENT_TABLE( wxGrid
, wxScrolledWindow 
) 
1980     EVT_PAINT( wxGrid::OnPaint 
) 
1981     EVT_SIZE( wxGrid::OnSize 
) 
1982     EVT_KEY_DOWN( wxGrid::OnKeyDown 
) 
1983     EVT_ERASE_BACKGROUND( wxGrid::OnEraseBackground 
) 
1986 wxGrid::wxGrid( wxWindow 
*parent
, 
1991                  const wxString
& name 
) 
1992   : wxScrolledWindow( parent
, id
, pos
, size
, style
, name 
) 
2001     m_defaultCellAttr
->SafeDecRef(); 
2003 #ifdef DEBUG_ATTR_CACHE 
2004     size_t total 
= gs_nAttrCacheHits 
+ gs_nAttrCacheMisses
; 
2005     wxPrintf(_T("wxGrid attribute cache statistics: " 
2006                 "total: %u, hits: %u (%u%%)\n"), 
2007              total
, gs_nAttrCacheHits
, 
2008              total 
? (gs_nAttrCacheHits
*100) / total 
: 0); 
2017 // ----- internal init and update functions 
2020 void wxGrid::Create() 
2022     m_created 
= FALSE
;    // set to TRUE by CreateGrid 
2023     m_displayed 
= TRUE
; // FALSE;  // set to TRUE by OnPaint 
2025     m_table        
= (wxGridTableBase 
*) NULL
; 
2028     m_cellEditCtrlEnabled 
= FALSE
; 
2030     m_defaultCellAttr 
= new wxGridCellAttr
; 
2031     m_defaultCellAttr
->SetDefAttr(m_defaultCellAttr
); 
2032     // RD:  Should we fill the default attrs now or is waiting until Init() okay? 
2037     m_currentCellCoords 
= wxGridNoCellCoords
; 
2039     m_rowLabelWidth 
= WXGRID_DEFAULT_ROW_LABEL_WIDTH
; 
2040     m_colLabelHeight 
= WXGRID_DEFAULT_COL_LABEL_HEIGHT
; 
2042     m_cornerLabelWin 
= new wxGridCornerLabelWindow( this, 
2047     m_rowLabelWin 
= new wxGridRowLabelWindow( this, 
2052     m_colLabelWin 
= new wxGridColLabelWindow( this, 
2057     m_gridWin 
= new wxGridWindow( this, 
2064     SetTargetWindow( m_gridWin 
); 
2068 bool wxGrid::CreateGrid( int numRows
, int numCols 
) 
2072         wxFAIL_MSG( wxT("wxGrid::CreateGrid or wxGrid::SetTable called more than once") ); 
2077         m_numRows 
= numRows
; 
2078         m_numCols 
= numCols
; 
2080         m_table 
= new wxGridStringTable( m_numRows
, m_numCols 
); 
2081         m_table
->SetView( this ); 
2090 bool wxGrid::SetTable( wxGridTableBase 
*table
, bool takeOwnership 
) 
2094         // RD: Actually, this should probably be allowed.  I think it would be 
2095         // nice to be able to switch multiple Tables in and out of a single 
2096         // View at runtime.  Is there anything in the implmentation that would 
2099         wxFAIL_MSG( wxT("wxGrid::CreateGrid or wxGrid::SetTable called more than once") ); 
2104         m_numRows 
= table
->GetNumberRows(); 
2105         m_numCols 
= table
->GetNumberCols(); 
2108         m_table
->SetView( this ); 
2123     if ( m_numRows 
<= 0 ) 
2124         m_numRows 
= WXGRID_DEFAULT_NUMBER_ROWS
; 
2126     if ( m_numCols 
<= 0 ) 
2127         m_numCols 
= WXGRID_DEFAULT_NUMBER_COLS
; 
2129     m_rowLabelWidth  
= WXGRID_DEFAULT_ROW_LABEL_WIDTH
; 
2130     m_colLabelHeight 
= WXGRID_DEFAULT_COL_LABEL_HEIGHT
; 
2132     if ( m_rowLabelWin 
) 
2134         m_labelBackgroundColour 
= m_rowLabelWin
->GetBackgroundColour(); 
2138         m_labelBackgroundColour 
= wxColour( _T("WHITE") ); 
2141     m_labelTextColour 
= wxColour( _T("BLACK") ); 
2144     m_attrCache
.row 
= -1; 
2146     // TODO: something better than this ? 
2148     m_labelFont 
= this->GetFont(); 
2149     m_labelFont
.SetWeight( m_labelFont
.GetWeight() + 2 ); 
2151     m_rowLabelHorizAlign 
= wxLEFT
; 
2152     m_rowLabelVertAlign  
= wxCENTRE
; 
2154     m_colLabelHorizAlign 
= wxCENTRE
; 
2155     m_colLabelVertAlign  
= wxTOP
; 
2157     m_defaultColWidth  
= WXGRID_DEFAULT_COL_WIDTH
; 
2158     m_defaultRowHeight 
= m_gridWin
->GetCharHeight(); 
2160 #if defined(__WXMOTIF__) || defined(__WXGTK__)  // see also text ctrl sizing in ShowCellEditControl() 
2161     m_defaultRowHeight 
+= 8; 
2163     m_defaultRowHeight 
+= 4; 
2166     m_rowHeights
.Alloc( m_numRows 
); 
2167     m_rowBottoms
.Alloc( m_numRows 
); 
2169     for ( i 
= 0;  i 
< m_numRows
;  i
++ ) 
2171         m_rowHeights
.Add( m_defaultRowHeight 
); 
2172         rowBottom 
+= m_defaultRowHeight
; 
2173         m_rowBottoms
.Add( rowBottom 
); 
2176     m_colWidths
.Alloc( m_numCols 
); 
2177     m_colRights
.Alloc( m_numCols 
); 
2179     for ( i 
= 0;  i 
< m_numCols
;  i
++ ) 
2181         m_colWidths
.Add( m_defaultColWidth 
); 
2182         colRight 
+= m_defaultColWidth
; 
2183         m_colRights
.Add( colRight 
); 
2186     // Set default cell attributes 
2187     m_defaultCellAttr
->SetFont(GetFont()); 
2188     m_defaultCellAttr
->SetAlignment(wxLEFT
, wxTOP
); 
2189     m_defaultCellAttr
->SetRenderer(new wxGridCellStringRenderer
); 
2190     m_defaultCellAttr
->SetEditor(new wxGridCellTextEditor
); 
2191     m_defaultCellAttr
->SetTextColour( 
2192         wxSystemSettings::GetSystemColour(wxSYS_COLOUR_WINDOWTEXT
)); 
2193     m_defaultCellAttr
->SetBackgroundColour( 
2194         wxSystemSettings::GetSystemColour(wxSYS_COLOUR_WINDOW
)); 
2197     m_gridLineColour 
= wxColour( 128, 128, 255 ); 
2198     m_gridLinesEnabled 
= TRUE
; 
2200     m_cursorMode  
= WXGRID_CURSOR_SELECT_CELL
; 
2201     m_winCapture 
= (wxWindow 
*)NULL
; 
2203     m_dragRowOrCol 
= -1; 
2204     m_isDragging 
= FALSE
; 
2205     m_startDragPos 
= wxDefaultPosition
; 
2207     m_waitForSlowClick 
= FALSE
; 
2209     m_rowResizeCursor 
= wxCursor( wxCURSOR_SIZENS 
); 
2210     m_colResizeCursor 
= wxCursor( wxCURSOR_SIZEWE 
); 
2212     m_currentCellCoords 
= wxGridNoCellCoords
; 
2214     m_selectedTopLeft 
= wxGridNoCellCoords
; 
2215     m_selectedBottomRight 
= wxGridNoCellCoords
; 
2216     m_selectionBackground 
= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_HIGHLIGHT
); 
2217     m_selectionForeground 
= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_HIGHLIGHTTEXT
); 
2219     m_editable 
= TRUE
;  // default for whole grid 
2221     m_inOnKeyDown 
= FALSE
; 
2227 void wxGrid::CalcDimensions() 
2230     GetClientSize( &cw
, &ch 
); 
2232     if ( m_numRows 
> 0  &&  m_numCols 
> 0 ) 
2234         int right 
= m_colRights
[ m_numCols
-1 ] + 50; 
2235         int bottom 
= m_rowBottoms
[ m_numRows
-1 ] + 50; 
2237         // TODO: restore the scroll position that we had before sizing 
2240         GetViewStart( &x
, &y 
); 
2241         SetScrollbars( GRID_SCROLL_LINE
, GRID_SCROLL_LINE
, 
2242                        right
/GRID_SCROLL_LINE
, bottom
/GRID_SCROLL_LINE
, 
2248 void wxGrid::CalcWindowSizes() 
2251     GetClientSize( &cw
, &ch 
); 
2253     if ( m_cornerLabelWin
->IsShown() ) 
2254         m_cornerLabelWin
->SetSize( 0, 0, m_rowLabelWidth
, m_colLabelHeight 
); 
2256     if ( m_colLabelWin
->IsShown() ) 
2257         m_colLabelWin
->SetSize( m_rowLabelWidth
, 0, cw
-m_rowLabelWidth
, m_colLabelHeight
); 
2259     if ( m_rowLabelWin
->IsShown() ) 
2260         m_rowLabelWin
->SetSize( 0, m_colLabelHeight
, m_rowLabelWidth
, ch
-m_colLabelHeight
); 
2262     if ( m_gridWin
->IsShown() ) 
2263         m_gridWin
->SetSize( m_rowLabelWidth
, m_colLabelHeight
, cw
-m_rowLabelWidth
, ch
-m_colLabelHeight
); 
2267 // this is called when the grid table sends a message to say that it 
2268 // has been redimensioned 
2270 bool wxGrid::Redimension( wxGridTableMessage
& msg 
) 
2274     switch ( msg
.GetId() ) 
2276         case wxGRIDTABLE_NOTIFY_ROWS_INSERTED
: 
2278             size_t pos 
= msg
.GetCommandInt(); 
2279             int numRows 
= msg
.GetCommandInt2(); 
2280             for ( i 
= 0;  i 
< numRows
;  i
++ ) 
2282                 m_rowHeights
.Insert( m_defaultRowHeight
, pos 
); 
2283                 m_rowBottoms
.Insert( 0, pos 
); 
2285             m_numRows 
+= numRows
; 
2288             if ( pos 
> 0 ) bottom 
= m_rowBottoms
[pos
-1]; 
2290             for ( i 
= pos
;  i 
< m_numRows
;  i
++ ) 
2292                 bottom 
+= m_rowHeights
[i
]; 
2293                 m_rowBottoms
[i
] = bottom
; 
2299         case wxGRIDTABLE_NOTIFY_ROWS_APPENDED
: 
2301             int numRows 
= msg
.GetCommandInt(); 
2302             for ( i 
= 0;  i 
< numRows
;  i
++ ) 
2304                 m_rowHeights
.Add( m_defaultRowHeight 
); 
2305                 m_rowBottoms
.Add( 0 ); 
2308             int oldNumRows 
= m_numRows
; 
2309             m_numRows 
+= numRows
; 
2312             if ( oldNumRows 
> 0 ) bottom 
= m_rowBottoms
[oldNumRows
-1]; 
2314             for ( i 
= oldNumRows
;  i 
< m_numRows
;  i
++ ) 
2316                 bottom 
+= m_rowHeights
[i
]; 
2317                 m_rowBottoms
[i
] = bottom
; 
2323         case wxGRIDTABLE_NOTIFY_ROWS_DELETED
: 
2325             size_t pos 
= msg
.GetCommandInt(); 
2326             int numRows 
= msg
.GetCommandInt2(); 
2327             for ( i 
= 0;  i 
< numRows
;  i
++ ) 
2329                 m_rowHeights
.Remove( pos 
); 
2330                 m_rowBottoms
.Remove( pos 
); 
2332             m_numRows 
-= numRows
; 
2337                 m_colWidths
.Clear(); 
2338                 m_colRights
.Clear(); 
2339                 m_currentCellCoords 
= wxGridNoCellCoords
; 
2343                 if ( m_currentCellCoords
.GetRow() >= m_numRows 
) 
2344                     m_currentCellCoords
.Set( 0, 0 ); 
2347                 for ( i 
= 0;  i 
< m_numRows
;  i
++ ) 
2349                     h 
+= m_rowHeights
[i
]; 
2350                     m_rowBottoms
[i
] = h
; 
2358         case wxGRIDTABLE_NOTIFY_COLS_INSERTED
: 
2360             size_t pos 
= msg
.GetCommandInt(); 
2361             int numCols 
= msg
.GetCommandInt2(); 
2362             for ( i 
= 0;  i 
< numCols
;  i
++ ) 
2364                 m_colWidths
.Insert( m_defaultColWidth
, pos 
); 
2365                 m_colRights
.Insert( 0, pos 
); 
2367             m_numCols 
+= numCols
; 
2370             if ( pos 
> 0 ) right 
= m_colRights
[pos
-1]; 
2372             for ( i 
= pos
;  i 
< m_numCols
;  i
++ ) 
2374                 right 
+= m_colWidths
[i
]; 
2375                 m_colRights
[i
] = right
; 
2381         case wxGRIDTABLE_NOTIFY_COLS_APPENDED
: 
2383             int numCols 
= msg
.GetCommandInt(); 
2384             for ( i 
= 0;  i 
< numCols
;  i
++ ) 
2386                 m_colWidths
.Add( m_defaultColWidth 
); 
2387                 m_colRights
.Add( 0 ); 
2390             int oldNumCols 
= m_numCols
; 
2391             m_numCols 
+= numCols
; 
2394             if ( oldNumCols 
> 0 ) right 
= m_colRights
[oldNumCols
-1]; 
2396             for ( i 
= oldNumCols
;  i 
< m_numCols
;  i
++ ) 
2398                 right 
+= m_colWidths
[i
]; 
2399                 m_colRights
[i
] = right
; 
2405         case wxGRIDTABLE_NOTIFY_COLS_DELETED
: 
2407             size_t pos 
= msg
.GetCommandInt(); 
2408             int numCols 
= msg
.GetCommandInt2(); 
2409             for ( i 
= 0;  i 
< numCols
;  i
++ ) 
2411                 m_colWidths
.Remove( pos 
); 
2412                 m_colRights
.Remove( pos 
); 
2414             m_numCols 
-= numCols
; 
2418 #if 0  // leave the row alone here so that AppendCols will work subsequently 
2420                 m_rowHeights
.Clear(); 
2421                 m_rowBottoms
.Clear(); 
2423                 m_currentCellCoords 
= wxGridNoCellCoords
; 
2427                 if ( m_currentCellCoords
.GetCol() >= m_numCols 
) 
2428                     m_currentCellCoords
.Set( 0, 0 ); 
2431                 for ( i 
= 0;  i 
< m_numCols
;  i
++ ) 
2433                     w 
+= m_colWidths
[i
]; 
2446 void wxGrid::CalcRowLabelsExposed( wxRegion
& reg 
) 
2448     wxRegionIterator 
iter( reg 
); 
2451     m_rowLabelsExposed
.Empty(); 
2458         // TODO: remove this when we can... 
2459         // There is a bug in wxMotif that gives garbage update 
2460         // rectangles if you jump-scroll a long way by clicking the 
2461         // scrollbar with middle button.  This is a work-around 
2463 #if defined(__WXMOTIF__) 
2465         m_gridWin
->GetClientSize( &cw
, &ch 
); 
2466         if ( r
.GetTop() > ch 
) r
.SetTop( 0 ); 
2467         r
.SetBottom( wxMin( r
.GetBottom(), ch 
) ); 
2470         // logical bounds of update region 
2473         CalcUnscrolledPosition( 0, r
.GetTop(), &dummy
, &top 
); 
2474         CalcUnscrolledPosition( 0, r
.GetBottom(), &dummy
, &bottom 
); 
2476         // find the row labels within these bounds 
2480         for ( row 
= 0;  row 
< m_numRows
;  row
++ ) 
2482             if ( m_rowBottoms
[row
] < top 
) continue; 
2484             rowTop 
= m_rowBottoms
[row
] - m_rowHeights
[row
]; 
2485             if ( rowTop 
> bottom 
) break; 
2487             m_rowLabelsExposed
.Add( row 
); 
2495 void wxGrid::CalcColLabelsExposed( wxRegion
& reg 
) 
2497     wxRegionIterator 
iter( reg 
); 
2500     m_colLabelsExposed
.Empty(); 
2507         // TODO: remove this when we can... 
2508         // There is a bug in wxMotif that gives garbage update 
2509         // rectangles if you jump-scroll a long way by clicking the 
2510         // scrollbar with middle button.  This is a work-around 
2512 #if defined(__WXMOTIF__) 
2514         m_gridWin
->GetClientSize( &cw
, &ch 
); 
2515         if ( r
.GetLeft() > cw 
) r
.SetLeft( 0 ); 
2516         r
.SetRight( wxMin( r
.GetRight(), cw 
) ); 
2519         // logical bounds of update region 
2522         CalcUnscrolledPosition( r
.GetLeft(), 0, &left
, &dummy 
); 
2523         CalcUnscrolledPosition( r
.GetRight(), 0, &right
, &dummy 
); 
2525         // find the cells within these bounds 
2529         for ( col 
= 0;  col 
< m_numCols
;  col
++ ) 
2531             if ( m_colRights
[col
] < left 
) continue; 
2533             colLeft 
= m_colRights
[col
] - m_colWidths
[col
]; 
2534             if ( colLeft 
> right 
) break; 
2536             m_colLabelsExposed
.Add( col 
); 
2544 void wxGrid::CalcCellsExposed( wxRegion
& reg 
) 
2546     wxRegionIterator 
iter( reg 
); 
2549     m_cellsExposed
.Empty(); 
2550     m_rowsExposed
.Empty(); 
2551     m_colsExposed
.Empty(); 
2553     int left
, top
, right
, bottom
; 
2558         // TODO: remove this when we can... 
2559         // There is a bug in wxMotif that gives garbage update 
2560         // rectangles if you jump-scroll a long way by clicking the 
2561         // scrollbar with middle button.  This is a work-around 
2563 #if defined(__WXMOTIF__) 
2565         m_gridWin
->GetClientSize( &cw
, &ch 
); 
2566         if ( r
.GetTop() > ch 
) r
.SetTop( 0 ); 
2567         if ( r
.GetLeft() > cw 
) r
.SetLeft( 0 ); 
2568         r
.SetRight( wxMin( r
.GetRight(), cw 
) ); 
2569         r
.SetBottom( wxMin( r
.GetBottom(), ch 
) ); 
2572         // logical bounds of update region 
2574         CalcUnscrolledPosition( r
.GetLeft(), r
.GetTop(), &left
, &top 
); 
2575         CalcUnscrolledPosition( r
.GetRight(), r
.GetBottom(), &right
, &bottom 
); 
2577         // find the cells within these bounds 
2580         int colLeft
, rowTop
; 
2581         for ( row 
= 0;  row 
< m_numRows
;  row
++ ) 
2583             if ( m_rowBottoms
[row
] <= top 
) continue; 
2585             rowTop 
= m_rowBottoms
[row
] - m_rowHeights
[row
]; 
2586             if ( rowTop 
> bottom 
) break; 
2588             m_rowsExposed
.Add( row 
); 
2590             for ( col 
= 0;  col 
< m_numCols
;  col
++ ) 
2592                 if ( m_colRights
[col
] <= left 
) continue; 
2594                 colLeft 
= m_colRights
[col
] - m_colWidths
[col
]; 
2595                 if ( colLeft 
> right 
) break; 
2597                 if ( m_colsExposed
.Index( col 
) == wxNOT_FOUND 
) m_colsExposed
.Add( col 
); 
2598                 m_cellsExposed
.Add( wxGridCellCoords( row
, col 
) ); 
2607 void wxGrid::ProcessRowLabelMouseEvent( wxMouseEvent
& event 
) 
2610     wxPoint 
pos( event
.GetPosition() ); 
2611     CalcUnscrolledPosition( pos
.x
, pos
.y
, &x
, &y 
); 
2613     if ( event
.Dragging() ) 
2615         m_isDragging 
= TRUE
; 
2617         if ( event
.LeftIsDown() ) 
2619             switch( m_cursorMode 
) 
2621                 case WXGRID_CURSOR_RESIZE_ROW
: 
2623                     int cw
, ch
, left
, dummy
; 
2624                     m_gridWin
->GetClientSize( &cw
, &ch 
); 
2625                     CalcUnscrolledPosition( 0, 0, &left
, &dummy 
); 
2627                     wxClientDC 
dc( m_gridWin 
); 
2630                                m_rowBottoms
[m_dragRowOrCol
] - 
2631                                m_rowHeights
[m_dragRowOrCol
] + 
2632                                WXGRID_MIN_ROW_HEIGHT 
); 
2633                     dc
.SetLogicalFunction(wxINVERT
); 
2634                     if ( m_dragLastPos 
>= 0 ) 
2636                         dc
.DrawLine( left
, m_dragLastPos
, left
+cw
, m_dragLastPos 
); 
2638                     dc
.DrawLine( left
, y
, left
+cw
, y 
); 
2643                 case WXGRID_CURSOR_SELECT_ROW
: 
2644                     if ( (row 
= YToRow( y 
)) >= 0  && 
2645                          !IsInSelection( row
, 0 ) ) 
2647                         SelectRow( row
, TRUE 
); 
2650                 // default label to suppress warnings about "enumeration value 
2651                 // 'xxx' not handled in switch 
2659     m_isDragging 
= FALSE
; 
2662     // ------------ Entering or leaving the window 
2664     if ( event
.Entering() || event
.Leaving() ) 
2666         ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
, m_rowLabelWin
); 
2670     // ------------ Left button pressed 
2672     else if ( event
.LeftDown() ) 
2674         // don't send a label click event for a hit on the 
2675         // edge of the row label - this is probably the user 
2676         // wanting to resize the row 
2678         if ( YToEdgeOfRow(y
) < 0 ) 
2682                  !SendEvent( wxEVT_GRID_LABEL_LEFT_CLICK
, row
, -1, event 
) ) 
2684                 SelectRow( row
, event
.ShiftDown() ); 
2685                 ChangeCursorMode(WXGRID_CURSOR_SELECT_ROW
, m_rowLabelWin
); 
2690             // starting to drag-resize a row 
2692             ChangeCursorMode(WXGRID_CURSOR_RESIZE_ROW
, m_rowLabelWin
); 
2697     // ------------ Left double click 
2699     else if (event
.LeftDClick() ) 
2701         if ( YToEdgeOfRow(y
) < 0 ) 
2704             SendEvent( wxEVT_GRID_LABEL_LEFT_DCLICK
, row
, -1, event 
); 
2709     // ------------ Left button released 
2711     else if ( event
.LeftUp() ) 
2713         if ( m_cursorMode 
== WXGRID_CURSOR_RESIZE_ROW 
) 
2715             DoEndDragResizeRow(); 
2717             // Note: we are ending the event *after* doing 
2718             // default processing in this case 
2720             SendEvent( wxEVT_GRID_ROW_SIZE
, m_dragRowOrCol
, -1, event 
); 
2723         ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
, m_rowLabelWin
); 
2728     // ------------ Right button down 
2730     else if ( event
.RightDown() ) 
2733         if ( !SendEvent( wxEVT_GRID_LABEL_RIGHT_CLICK
, row
, -1, event 
) ) 
2735             // no default action at the moment 
2740     // ------------ Right double click 
2742     else if ( event
.RightDClick() ) 
2745         if ( !SendEvent( wxEVT_GRID_LABEL_RIGHT_DCLICK
, row
, -1, event 
) ) 
2747             // no default action at the moment 
2752     // ------------ No buttons down and mouse moving 
2754     else if ( event
.Moving() ) 
2756         m_dragRowOrCol 
= YToEdgeOfRow( y 
); 
2757         if ( m_dragRowOrCol 
>= 0 ) 
2759             if ( m_cursorMode 
== WXGRID_CURSOR_SELECT_CELL 
) 
2761                 // don't capture the mouse yet 
2762                 ChangeCursorMode(WXGRID_CURSOR_RESIZE_ROW
, m_rowLabelWin
, FALSE
); 
2765         else if ( m_cursorMode 
!= WXGRID_CURSOR_SELECT_CELL 
) 
2767             ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
, m_rowLabelWin
, FALSE
); 
2773 void wxGrid::ProcessColLabelMouseEvent( wxMouseEvent
& event 
) 
2776     wxPoint 
pos( event
.GetPosition() ); 
2777     CalcUnscrolledPosition( pos
.x
, pos
.y
, &x
, &y 
); 
2779     if ( event
.Dragging() ) 
2781         m_isDragging 
= TRUE
; 
2783         if ( event
.LeftIsDown() ) 
2785             switch( m_cursorMode 
) 
2787                 case WXGRID_CURSOR_RESIZE_COL
: 
2789                     int cw
, ch
, dummy
, top
; 
2790                     m_gridWin
->GetClientSize( &cw
, &ch 
); 
2791                     CalcUnscrolledPosition( 0, 0, &dummy
, &top 
); 
2793                     wxClientDC 
dc( m_gridWin 
); 
2796                                m_colRights
[m_dragRowOrCol
] - 
2797                                m_colWidths
[m_dragRowOrCol
] + 
2798                                WXGRID_MIN_COL_WIDTH 
); 
2799                     dc
.SetLogicalFunction(wxINVERT
); 
2800                     if ( m_dragLastPos 
>= 0 ) 
2802                         dc
.DrawLine( m_dragLastPos
, top
, m_dragLastPos
, top
+ch 
); 
2804                     dc
.DrawLine( x
, top
, x
, top
+ch 
); 
2809                 case WXGRID_CURSOR_SELECT_COL
: 
2810                     if ( (col 
= XToCol( x 
)) >= 0  && 
2811                          !IsInSelection( 0, col 
) ) 
2813                         SelectCol( col
, TRUE 
); 
2816                 // default label to suppress warnings about "enumeration value 
2817                 // 'xxx' not handled in switch 
2825     m_isDragging 
= FALSE
; 
2828     // ------------ Entering or leaving the window 
2830     if ( event
.Entering() || event
.Leaving() ) 
2832         ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
, m_colLabelWin
); 
2836     // ------------ Left button pressed 
2838     else if ( event
.LeftDown() ) 
2840         // don't send a label click event for a hit on the 
2841         // edge of the col label - this is probably the user 
2842         // wanting to resize the col 
2844         if ( XToEdgeOfCol(x
) < 0 ) 
2848                  !SendEvent( wxEVT_GRID_LABEL_LEFT_CLICK
, -1, col
, event 
) ) 
2850                 SelectCol( col
, event
.ShiftDown() ); 
2851                 ChangeCursorMode(WXGRID_CURSOR_SELECT_COL
, m_colLabelWin
); 
2856             // starting to drag-resize a col 
2858             ChangeCursorMode(WXGRID_CURSOR_RESIZE_COL
, m_colLabelWin
); 
2863     // ------------ Left double click 
2865     if ( event
.LeftDClick() ) 
2867         if ( XToEdgeOfCol(x
) < 0 ) 
2870             SendEvent( wxEVT_GRID_LABEL_LEFT_DCLICK
, -1, col
, event 
); 
2875     // ------------ Left button released 
2877     else if ( event
.LeftUp() ) 
2879         if ( m_cursorMode 
== WXGRID_CURSOR_RESIZE_COL 
) 
2881             DoEndDragResizeCol(); 
2883             // Note: we are ending the event *after* doing 
2884             // default processing in this case 
2886             SendEvent( wxEVT_GRID_COL_SIZE
, -1, m_dragRowOrCol
, event 
); 
2889         ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
, m_colLabelWin
); 
2894     // ------------ Right button down 
2896     else if ( event
.RightDown() ) 
2899         if ( !SendEvent( wxEVT_GRID_LABEL_RIGHT_CLICK
, -1, col
, event 
) ) 
2901             // no default action at the moment 
2906     // ------------ Right double click 
2908     else if ( event
.RightDClick() ) 
2911         if ( !SendEvent( wxEVT_GRID_LABEL_RIGHT_DCLICK
, -1, col
, event 
) ) 
2913             // no default action at the moment 
2918     // ------------ No buttons down and mouse moving 
2920     else if ( event
.Moving() ) 
2922         m_dragRowOrCol 
= XToEdgeOfCol( x 
); 
2923         if ( m_dragRowOrCol 
>= 0 ) 
2925             if ( m_cursorMode 
== WXGRID_CURSOR_SELECT_CELL 
) 
2927                 // don't capture the cursor yet 
2928                 ChangeCursorMode(WXGRID_CURSOR_RESIZE_COL
, m_colLabelWin
, FALSE
); 
2931         else if ( m_cursorMode 
!= WXGRID_CURSOR_SELECT_CELL 
) 
2933             ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
, m_colLabelWin
, FALSE
); 
2939 void wxGrid::ProcessCornerLabelMouseEvent( wxMouseEvent
& event 
) 
2941     if ( event
.LeftDown() ) 
2943         // indicate corner label by having both row and 
2946         if ( !SendEvent( wxEVT_GRID_LABEL_LEFT_CLICK
, -1, -1, event 
) ) 
2952     else if ( event
.LeftDClick() ) 
2954         SendEvent( wxEVT_GRID_LABEL_LEFT_DCLICK
, -1, -1, event 
); 
2957     else if ( event
.RightDown() ) 
2959         if ( !SendEvent( wxEVT_GRID_LABEL_RIGHT_CLICK
, -1, -1, event 
) ) 
2961             // no default action at the moment 
2965     else if ( event
.RightDClick() ) 
2967         if ( !SendEvent( wxEVT_GRID_LABEL_RIGHT_DCLICK
, -1, -1, event 
) ) 
2969             // no default action at the moment 
2974 void wxGrid::ChangeCursorMode(CursorMode mode
, 
2979     static const wxChar 
*cursorModes
[] = 
2988     wxLogTrace(_T("grid"), 
2989                _T("wxGrid cursor mode (mouse capture for %s): %s -> %s"), 
2990                win 
== m_colLabelWin 
? _T("colLabelWin") 
2991                                     : win 
? _T("rowLabelWin") 
2993                cursorModes
[m_cursorMode
], cursorModes
[mode
]); 
2994 #endif // __WXDEBUG__ 
2996     if ( mode 
== m_cursorMode 
) 
3001         // by default use the grid itself 
3007         m_winCapture
->ReleaseMouse(); 
3008         m_winCapture 
= (wxWindow 
*)NULL
; 
3011     m_cursorMode 
= mode
; 
3013     switch ( m_cursorMode 
) 
3015         case WXGRID_CURSOR_RESIZE_ROW
: 
3016             win
->SetCursor( m_rowResizeCursor 
); 
3019         case WXGRID_CURSOR_RESIZE_COL
: 
3020             win
->SetCursor( m_colResizeCursor 
); 
3024             win
->SetCursor( *wxSTANDARD_CURSOR 
); 
3027     // we need to capture mouse when resizing 
3028     bool resize 
= m_cursorMode 
== WXGRID_CURSOR_RESIZE_ROW 
|| 
3029                   m_cursorMode 
== WXGRID_CURSOR_RESIZE_COL
; 
3031     if ( captureMouse 
&& resize 
) 
3033         win
->CaptureMouse(); 
3038 void wxGrid::ProcessGridCellMouseEvent( wxMouseEvent
& event 
) 
3041     wxPoint 
pos( event
.GetPosition() ); 
3042     CalcUnscrolledPosition( pos
.x
, pos
.y
, &x
, &y 
); 
3044     wxGridCellCoords coords
; 
3045     XYToCell( x
, y
, coords 
); 
3047     if ( event
.Dragging() ) 
3049         //wxLogDebug("pos(%d, %d) coords(%d, %d)", pos.x, pos.y, coords.GetRow(), coords.GetCol()); 
3051         // Don't start doing anything until the mouse has been drug at 
3052         // least 3 pixels in any direction... 
3055             if (m_startDragPos 
== wxDefaultPosition
) 
3057                 m_startDragPos 
= pos
; 
3060             if (abs(m_startDragPos
.x 
- pos
.x
) < 4 && abs(m_startDragPos
.y 
- pos
.y
) < 4) 
3064         m_isDragging 
= TRUE
; 
3065         if ( m_cursorMode 
== WXGRID_CURSOR_SELECT_CELL 
) 
3067             // Hide the edit control, so it 
3068             // won't interfer with drag-shrinking. 
3069             if ( IsCellEditControlEnabled() ) 
3070                 HideCellEditControl(); 
3072             // Have we captured the mouse yet? 
3075                 m_winCapture 
= m_gridWin
; 
3076                 m_winCapture
->CaptureMouse(); 
3079             if ( coords 
!= wxGridNoCellCoords 
) 
3081                 if ( !IsSelection() ) 
3083                     SelectBlock( coords
, coords 
); 
3087                     SelectBlock( m_currentCellCoords
, coords 
); 
3090                 if (! IsVisible(coords
)) 
3092                     MakeCellVisible(coords
); 
3093                     // TODO: need to introduce a delay or something here.  The 
3094                     // scrolling is way to fast, at least on MSW. 
3098         else if ( m_cursorMode 
== WXGRID_CURSOR_RESIZE_ROW 
) 
3100             int cw
, ch
, left
, dummy
; 
3101             m_gridWin
->GetClientSize( &cw
, &ch 
); 
3102             CalcUnscrolledPosition( 0, 0, &left
, &dummy 
); 
3104             wxClientDC 
dc( m_gridWin 
); 
3107                     m_rowBottoms
[m_dragRowOrCol
] - 
3108                     m_rowHeights
[m_dragRowOrCol
] + 
3109                     WXGRID_MIN_ROW_HEIGHT 
); 
3110             dc
.SetLogicalFunction(wxINVERT
); 
3111             if ( m_dragLastPos 
>= 0 ) 
3113                 dc
.DrawLine( left
, m_dragLastPos
, left
+cw
, m_dragLastPos 
); 
3115             dc
.DrawLine( left
, y
, left
+cw
, y 
); 
3118         else if ( m_cursorMode 
== WXGRID_CURSOR_RESIZE_COL 
) 
3120             int cw
, ch
, dummy
, top
; 
3121             m_gridWin
->GetClientSize( &cw
, &ch 
); 
3122             CalcUnscrolledPosition( 0, 0, &dummy
, &top 
); 
3124             wxClientDC 
dc( m_gridWin 
); 
3127                     m_colRights
[m_dragRowOrCol
] - 
3128                     m_colWidths
[m_dragRowOrCol
] + WXGRID_MIN_COL_WIDTH 
); 
3129             dc
.SetLogicalFunction(wxINVERT
); 
3130             if ( m_dragLastPos 
>= 0 ) 
3132                 dc
.DrawLine( m_dragLastPos
, top
, m_dragLastPos
, top
+ch 
); 
3134             dc
.DrawLine( x
, top
, x
, top
+ch 
); 
3141     m_isDragging 
= FALSE
; 
3142     m_startDragPos 
= wxDefaultPosition
; 
3145     if ( coords 
!= wxGridNoCellCoords 
) 
3147         // VZ: if we do this, the mode is reset to WXGRID_CURSOR_SELECT_CELL 
3148         //     immediately after it becomes WXGRID_CURSOR_RESIZE_ROW/COL under 
3151         if ( event
.Entering() || event
.Leaving() ) 
3153             ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
); 
3154             m_gridWin
->SetCursor( *wxSTANDARD_CURSOR 
); 
3159         // ------------ Left button pressed 
3161         if ( event
.LeftDown() ) 
3163             DisableCellEditControl(); 
3164             if ( event
.ShiftDown() ) 
3166                 SelectBlock( m_currentCellCoords
, coords 
); 
3168             else if ( XToEdgeOfCol(x
) < 0  && 
3169                       YToEdgeOfRow(y
) < 0 ) 
3171                 if ( !SendEvent( wxEVT_GRID_CELL_LEFT_CLICK
, 
3176                     MakeCellVisible( coords 
); 
3178                     // if this is the second click on this cell then start 
3180                     if ( m_waitForSlowClick 
&& 
3181                          (coords 
== m_currentCellCoords
) && 
3182                          CanEnableCellControl()) 
3184                         EnableCellEditControl(); 
3186                         wxGridCellAttr
* attr 
= GetCellAttr(m_currentCellCoords
); 
3187                         attr
->GetEditor()->StartingClick(); 
3190                         m_waitForSlowClick 
= FALSE
; 
3194                         SetCurrentCell( coords 
); 
3195                         m_waitForSlowClick 
= TRUE
; 
3202         // ------------ Left double click 
3204         else if ( event
.LeftDClick() ) 
3206             DisableCellEditControl(); 
3207             if ( XToEdgeOfCol(x
) < 0  &&  YToEdgeOfRow(y
) < 0 ) 
3209                 SendEvent( wxEVT_GRID_CELL_LEFT_DCLICK
, 
3217         // ------------ Left button released 
3219         else if ( event
.LeftUp() ) 
3221             if ( m_cursorMode 
== WXGRID_CURSOR_SELECT_CELL 
) 
3223                 if ( IsSelection() ) 
3227                         m_winCapture
->ReleaseMouse(); 
3228                         m_winCapture 
= NULL
; 
3230                     SendEvent( wxEVT_GRID_RANGE_SELECT
, -1, -1, event 
); 
3233                 // Show the edit control, if it has been hidden for 
3235                 ShowCellEditControl(); 
3237             else if ( m_cursorMode 
== WXGRID_CURSOR_RESIZE_ROW 
) 
3239                 ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
); 
3240                 DoEndDragResizeRow(); 
3242                 // Note: we are ending the event *after* doing 
3243                 // default processing in this case 
3245                 SendEvent( wxEVT_GRID_ROW_SIZE
, m_dragRowOrCol
, -1, event 
); 
3247             else if ( m_cursorMode 
== WXGRID_CURSOR_RESIZE_COL 
) 
3249                 ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
); 
3250                 DoEndDragResizeCol(); 
3252                 // Note: we are ending the event *after* doing 
3253                 // default processing in this case 
3255                 SendEvent( wxEVT_GRID_COL_SIZE
, -1, m_dragRowOrCol
, event 
); 
3262         // ------------ Right button down 
3264         else if ( event
.RightDown() ) 
3266             DisableCellEditControl(); 
3267             if ( !SendEvent( wxEVT_GRID_CELL_RIGHT_CLICK
, 
3272                 // no default action at the moment 
3277         // ------------ Right double click 
3279         else if ( event
.RightDClick() ) 
3281             DisableCellEditControl(); 
3282             if ( !SendEvent( wxEVT_GRID_CELL_RIGHT_DCLICK
, 
3287                 // no default action at the moment 
3291         // ------------ Moving and no button action 
3293         else if ( event
.Moving() && !event
.IsButton() ) 
3295             int dragRow 
= YToEdgeOfRow( y 
); 
3296             int dragCol 
= XToEdgeOfCol( x 
); 
3298             // Dragging on the corner of a cell to resize in both 
3299             // directions is not implemented yet... 
3301             if ( dragRow 
>= 0  &&  dragCol 
>= 0 ) 
3303                 ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
); 
3309                 m_dragRowOrCol 
= dragRow
; 
3311                 if ( m_cursorMode 
== WXGRID_CURSOR_SELECT_CELL 
) 
3313                     ChangeCursorMode(WXGRID_CURSOR_RESIZE_ROW
); 
3321                 m_dragRowOrCol 
= dragCol
; 
3323                 if ( m_cursorMode 
== WXGRID_CURSOR_SELECT_CELL 
) 
3325                     ChangeCursorMode(WXGRID_CURSOR_RESIZE_COL
); 
3331             // Neither on a row or col edge 
3333             if ( m_cursorMode 
!= WXGRID_CURSOR_SELECT_CELL 
) 
3335                 ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
); 
3342 void wxGrid::DoEndDragResizeRow() 
3344     if ( m_dragLastPos 
>= 0 ) 
3346         // erase the last line and resize the row 
3348         int cw
, ch
, left
, dummy
; 
3349         m_gridWin
->GetClientSize( &cw
, &ch 
); 
3350         CalcUnscrolledPosition( 0, 0, &left
, &dummy 
); 
3352         wxClientDC 
dc( m_gridWin 
); 
3354         dc
.SetLogicalFunction( wxINVERT 
); 
3355         dc
.DrawLine( left
, m_dragLastPos
, left
+cw
, m_dragLastPos 
); 
3356         HideCellEditControl(); 
3358         int rowTop 
= m_rowBottoms
[m_dragRowOrCol
] - m_rowHeights
[m_dragRowOrCol
]; 
3359         SetRowSize( m_dragRowOrCol
, 
3360                     wxMax( m_dragLastPos 
- rowTop
, WXGRID_MIN_ROW_HEIGHT 
) ); 
3362         if ( !GetBatchCount() ) 
3364             // Only needed to get the correct rect.y: 
3365             wxRect 
rect ( CellToRect( m_dragRowOrCol
, 0 ) ); 
3367             CalcScrolledPosition(0, rect
.y
, &dummy
, &rect
.y
); 
3368             rect
.width 
= m_rowLabelWidth
; 
3369             rect
.height 
= ch 
- rect
.y
; 
3370             m_rowLabelWin
->Refresh( TRUE
, &rect 
); 
3372             m_gridWin
->Refresh( FALSE
, &rect 
); 
3375         ShowCellEditControl(); 
3380 void wxGrid::DoEndDragResizeCol() 
3382     if ( m_dragLastPos 
>= 0 ) 
3384         // erase the last line and resize the col 
3386         int cw
, ch
, dummy
, top
; 
3387         m_gridWin
->GetClientSize( &cw
, &ch 
); 
3388         CalcUnscrolledPosition( 0, 0, &dummy
, &top 
); 
3390         wxClientDC 
dc( m_gridWin 
); 
3392         dc
.SetLogicalFunction( wxINVERT 
); 
3393         dc
.DrawLine( m_dragLastPos
, top
, m_dragLastPos
, top
+ch 
); 
3394         HideCellEditControl(); 
3396         int colLeft 
= m_colRights
[m_dragRowOrCol
] - m_colWidths
[m_dragRowOrCol
]; 
3397         SetColSize( m_dragRowOrCol
, 
3398                     wxMax( m_dragLastPos 
- colLeft
, WXGRID_MIN_COL_WIDTH 
) ); 
3400         if ( !GetBatchCount() ) 
3402             // Only needed to get the correct rect.x: 
3403             wxRect 
rect ( CellToRect( 0, m_dragRowOrCol 
) ); 
3405             CalcScrolledPosition(rect
.x
, 0, &rect
.x
, &dummy
); 
3406             rect
.width 
= cw 
- rect
.x
; 
3407             rect
.height 
= m_colLabelHeight
; 
3408             m_colLabelWin
->Refresh( TRUE
, &rect 
); 
3410             m_gridWin
->Refresh( FALSE
, &rect 
); 
3413         ShowCellEditControl(); 
3420 // ------ interaction with data model 
3422 bool wxGrid::ProcessTableMessage( wxGridTableMessage
& msg 
) 
3424     switch ( msg
.GetId() ) 
3426         case wxGRIDTABLE_REQUEST_VIEW_GET_VALUES
: 
3427             return GetModelValues(); 
3429         case wxGRIDTABLE_REQUEST_VIEW_SEND_VALUES
: 
3430             return SetModelValues(); 
3432         case wxGRIDTABLE_NOTIFY_ROWS_INSERTED
: 
3433         case wxGRIDTABLE_NOTIFY_ROWS_APPENDED
: 
3434         case wxGRIDTABLE_NOTIFY_ROWS_DELETED
: 
3435         case wxGRIDTABLE_NOTIFY_COLS_INSERTED
: 
3436         case wxGRIDTABLE_NOTIFY_COLS_APPENDED
: 
3437         case wxGRIDTABLE_NOTIFY_COLS_DELETED
: 
3438             return Redimension( msg 
); 
3447 // The behaviour of this function depends on the grid table class 
3448 // Clear() function.  For the default wxGridStringTable class the 
3449 // behavious is to replace all cell contents with wxEmptyString but 
3450 // not to change the number of rows or cols. 
3452 void wxGrid::ClearGrid() 
3457         SetEditControlValue(); 
3458         if ( !GetBatchCount() ) m_gridWin
->Refresh(); 
3463 bool wxGrid::InsertRows( int pos
, int numRows
, bool WXUNUSED(updateLabels
) ) 
3465     // TODO: something with updateLabels flag 
3469         wxFAIL_MSG( wxT("Called wxGrid::InsertRows() before calling CreateGrid()") ); 
3475         if (IsCellEditControlEnabled()) 
3476             DisableCellEditControl(); 
3478         bool ok 
= m_table
->InsertRows( pos
, numRows 
); 
3480         // the table will have sent the results of the insert row 
3481         // operation to this view object as a grid table message 
3485             if ( m_numCols 
== 0 ) 
3487                 m_table
->AppendCols( WXGRID_DEFAULT_NUMBER_COLS 
); 
3489                 // TODO: perhaps instead of appending the default number of cols 
3490                 // we should remember what the last non-zero number of cols was ? 
3494             if ( m_currentCellCoords 
== wxGridNoCellCoords 
) 
3496                 // if we have just inserted cols into an empty grid the current 
3497                 // cell will be undefined... 
3499                 SetCurrentCell( 0, 0 ); 
3503             if ( !GetBatchCount() ) Refresh(); 
3506         SetEditControlValue(); 
3516 bool wxGrid::AppendRows( int numRows
, bool WXUNUSED(updateLabels
) ) 
3518     // TODO: something with updateLabels flag 
3522         wxFAIL_MSG( wxT("Called wxGrid::AppendRows() before calling CreateGrid()") ); 
3526     if ( m_table 
&& m_table
->AppendRows( numRows 
) ) 
3528         if ( m_currentCellCoords 
== wxGridNoCellCoords 
) 
3530             // if we have just inserted cols into an empty grid the current 
3531             // cell will be undefined... 
3533             SetCurrentCell( 0, 0 ); 
3536         // the table will have sent the results of the append row 
3537         // operation to this view object as a grid table message 
3540         if ( !GetBatchCount() ) Refresh(); 
3550 bool wxGrid::DeleteRows( int pos
, int numRows
, bool WXUNUSED(updateLabels
) ) 
3552     // TODO: something with updateLabels flag 
3556         wxFAIL_MSG( wxT("Called wxGrid::DeleteRows() before calling CreateGrid()") ); 
3562         if (IsCellEditControlEnabled()) 
3563             DisableCellEditControl(); 
3565         if (m_table
->DeleteRows( pos
, numRows 
)) 
3568             // the table will have sent the results of the delete row 
3569             // operation to this view object as a grid table message 
3572             if ( !GetBatchCount() ) Refresh(); 
3580 bool wxGrid::InsertCols( int pos
, int numCols
, bool WXUNUSED(updateLabels
) ) 
3582     // TODO: something with updateLabels flag 
3586         wxFAIL_MSG( wxT("Called wxGrid::InsertCols() before calling CreateGrid()") ); 
3592         if (IsCellEditControlEnabled()) 
3593             DisableCellEditControl(); 
3595         bool ok 
= m_table
->InsertCols( pos
, numCols 
); 
3597         // the table will have sent the results of the insert col 
3598         // operation to this view object as a grid table message 
3602             if ( m_currentCellCoords 
== wxGridNoCellCoords 
) 
3604                 // if we have just inserted cols into an empty grid the current 
3605                 // cell will be undefined... 
3607                 SetCurrentCell( 0, 0 ); 
3611             if ( !GetBatchCount() ) Refresh(); 
3614         SetEditControlValue(); 
3624 bool wxGrid::AppendCols( int numCols
, bool WXUNUSED(updateLabels
) ) 
3626     // TODO: something with updateLabels flag 
3630         wxFAIL_MSG( wxT("Called wxGrid::AppendCols() before calling CreateGrid()") ); 
3634     if ( m_table 
&& m_table
->AppendCols( numCols 
) ) 
3636         // the table will have sent the results of the append col 
3637         // operation to this view object as a grid table message 
3639         if ( m_currentCellCoords 
== wxGridNoCellCoords 
) 
3641             // if we have just inserted cols into an empty grid the current 
3642             // cell will be undefined... 
3644             SetCurrentCell( 0, 0 ); 
3648         if ( !GetBatchCount() ) Refresh(); 
3658 bool wxGrid::DeleteCols( int pos
, int numCols
, bool WXUNUSED(updateLabels
) ) 
3660     // TODO: something with updateLabels flag 
3664         wxFAIL_MSG( wxT("Called wxGrid::DeleteCols() before calling CreateGrid()") ); 
3670         if (IsCellEditControlEnabled()) 
3671             DisableCellEditControl(); 
3673         if ( m_table
->DeleteCols( pos
, numCols 
) ) 
3675             // the table will have sent the results of the delete col 
3676             // operation to this view object as a grid table message 
3679             if ( !GetBatchCount() ) Refresh(); 
3689 // ----- event handlers 
3692 // Generate a grid event based on a mouse event and 
3693 // return the result of ProcessEvent() 
3695 bool wxGrid::SendEvent( const wxEventType type
, 
3697                         wxMouseEvent
& mouseEv 
) 
3699     if ( type 
== wxEVT_GRID_ROW_SIZE 
|| type 
== wxEVT_GRID_COL_SIZE 
) 
3701         int rowOrCol 
= (row 
== -1 ? col 
: row
); 
3703         wxGridSizeEvent 
gridEvt( GetId(), 
3707                                  mouseEv
.GetX(), mouseEv
.GetY(), 
3708                                  mouseEv
.ControlDown(), 
3709                                  mouseEv
.ShiftDown(), 
3711                                  mouseEv
.MetaDown() ); 
3713         return GetEventHandler()->ProcessEvent(gridEvt
); 
3715     else if ( type 
== wxEVT_GRID_RANGE_SELECT 
) 
3717         wxGridRangeSelectEvent 
gridEvt( GetId(), 
3721                                         m_selectedBottomRight
, 
3722                                         mouseEv
.ControlDown(), 
3723                                         mouseEv
.ShiftDown(), 
3725                                         mouseEv
.MetaDown() ); 
3727         return GetEventHandler()->ProcessEvent(gridEvt
); 
3731         wxGridEvent 
gridEvt( GetId(), 
3735                              mouseEv
.GetX(), mouseEv
.GetY(), 
3736                              mouseEv
.ControlDown(), 
3737                              mouseEv
.ShiftDown(), 
3739                              mouseEv
.MetaDown() ); 
3741         return GetEventHandler()->ProcessEvent(gridEvt
); 
3746 // Generate a grid event of specified type and return the result 
3747 // of ProcessEvent(). 
3749 bool wxGrid::SendEvent( const wxEventType type
, 
3752     if ( type 
== wxEVT_GRID_ROW_SIZE 
|| type 
== wxEVT_GRID_COL_SIZE 
) 
3754         int rowOrCol 
= (row 
== -1 ? col 
: row
); 
3756         wxGridSizeEvent 
gridEvt( GetId(), 
3761         return GetEventHandler()->ProcessEvent(gridEvt
); 
3765         wxGridEvent 
gridEvt( GetId(), 
3770         return GetEventHandler()->ProcessEvent(gridEvt
); 
3775 void wxGrid::OnPaint( wxPaintEvent
& WXUNUSED(event
) ) 
3777     wxPaintDC 
dc( this ); 
3779     if ( m_currentCellCoords 
== wxGridNoCellCoords  
&& 
3780          m_numRows 
&& m_numCols 
) 
3782         m_currentCellCoords
.Set(0, 0); 
3783         SetEditControlValue(); 
3784         ShowCellEditControl(); 
3791 // This is just here to make sure that CalcDimensions gets called when 
3792 // the grid view is resized... then the size event is skipped to allow 
3793 // the box sizers to handle everything 
3795 void wxGrid::OnSize( wxSizeEvent
& event 
) 
3802 void wxGrid::OnKeyDown( wxKeyEvent
& event 
) 
3804     if ( m_inOnKeyDown 
) 
3806         // shouldn't be here - we are going round in circles... 
3808         wxFAIL_MSG( wxT("wxGrid::OnKeyDown called while already active") ); 
3811     m_inOnKeyDown 
= TRUE
; 
3813     // propagate the event up and see if it gets processed 
3815     wxWindow 
*parent 
= GetParent(); 
3816     wxKeyEvent 
keyEvt( event 
); 
3817     keyEvt
.SetEventObject( parent 
); 
3819     if ( !parent
->GetEventHandler()->ProcessEvent( keyEvt 
) ) 
3822         // TODO:  Should also support Shift-cursor keys for 
3823         //        extending the selection.  Maybe add a flag to 
3824         //        MoveCursorXXX() and MoveCursorXXXBlock() and 
3825         //        just send event.ShiftDown(). 
3827         // try local handlers 
3829         switch ( event
.KeyCode() ) 
3832                 if ( event
.ControlDown() ) 
3834                     MoveCursorUpBlock(); 
3843                 if ( event
.ControlDown() ) 
3845                     MoveCursorDownBlock(); 
3854                 if ( event
.ControlDown() ) 
3856                     MoveCursorLeftBlock(); 
3865                 if ( event
.ControlDown() ) 
3867                     MoveCursorRightBlock(); 
3876                 if ( event
.ControlDown() ) 
3878                     event
.Skip();  // to let the edit control have the return 
3887                 if (event
.ShiftDown()) 
3894                 if ( event
.ControlDown() ) 
3896                     MakeCellVisible( 0, 0 ); 
3897                     SetCurrentCell( 0, 0 ); 
3906                 if ( event
.ControlDown() ) 
3908                     MakeCellVisible( m_numRows
-1, m_numCols
-1 ); 
3909                     SetCurrentCell( m_numRows
-1, m_numCols
-1 ); 
3925             // We don't want these keys to trigger the edit control, any others? 
3934                 if ( !IsEditable() ) 
3939                 // Otherwise fall through to default 
3942                 // now try the cell edit control 
3944                 if ( !IsCellEditControlEnabled() && CanEnableCellControl() ) 
3946                     EnableCellEditControl(); 
3947                     wxGridCellAttr
* attr 
= GetCellAttr(m_currentCellCoords
); 
3948                     attr
->GetEditor()->StartingKey(event
); 
3953                     // let others process char events for readonly cells 
3960     m_inOnKeyDown 
= FALSE
; 
3964 void wxGrid::OnEraseBackground(wxEraseEvent
&) 
3968 void wxGrid::SetCurrentCell( const wxGridCellCoords
& coords 
) 
3970     if ( SendEvent( wxEVT_GRID_SELECT_CELL
, coords
.GetRow(), coords
.GetCol() ) ) 
3972         // the event has been intercepted - do nothing 
3977          m_currentCellCoords 
!= wxGridNoCellCoords 
) 
3979         HideCellEditControl(); 
3980         SaveEditControlValue(); 
3981         DisableCellEditControl(); 
3983         // Clear the old current cell highlight 
3984         wxRect r 
= BlockToDeviceRect(m_currentCellCoords
, m_currentCellCoords
); 
3986         // Otherwise refresh redraws the highlight! 
3987         m_currentCellCoords 
= coords
; 
3989         m_gridWin
->Refresh( FALSE
, &r 
); 
3992     m_currentCellCoords 
= coords
; 
3994     SetEditControlValue(); 
3998         wxClientDC 
dc(m_gridWin
); 
4001         wxGridCellAttr
* attr 
= GetCellAttr(coords
); 
4002         DrawCellHighlight(dc
, attr
); 
4005         if ( IsSelection() ) 
4007             wxRect 
r( SelectionToDeviceRect() ); 
4009             if ( !GetBatchCount() ) m_gridWin
->Refresh( FALSE
, &r 
); 
4016 // ------ functions to get/send data (see also public functions) 
4019 bool wxGrid::GetModelValues() 
4023         // all we need to do is repaint the grid 
4025         m_gridWin
->Refresh(); 
4033 bool wxGrid::SetModelValues() 
4039         for ( row 
= 0;  row 
< m_numRows
;  row
++ ) 
4041             for ( col 
= 0;  col 
< m_numCols
;  col
++ ) 
4043                 m_table
->SetValue( row
, col
, GetCellValue(row
, col
) ); 
4055 // Note - this function only draws cells that are in the list of 
4056 // exposed cells (usually set from the update region by 
4057 // CalcExposedCells) 
4059 void wxGrid::DrawGridCellArea( wxDC
& dc 
) 
4061     if ( !m_numRows 
|| !m_numCols 
) return; 
4064     size_t numCells 
= m_cellsExposed
.GetCount(); 
4066     for ( i 
= 0;  i 
< numCells
;  i
++ ) 
4068         DrawCell( dc
, m_cellsExposed
[i
] ); 
4073 void wxGrid::DrawCell( wxDC
& dc
, const wxGridCellCoords
& coords 
) 
4075     int row 
= coords
.GetRow(); 
4076     int col 
= coords
.GetCol(); 
4078     if ( m_colWidths
[col
] <= 0 || m_rowHeights
[row
] <= 0 ) 
4081     // we draw the cell border ourselves 
4082 #if !WXGRID_DRAW_LINES 
4083     if ( m_gridLinesEnabled 
) 
4084         DrawCellBorder( dc
, coords 
); 
4087     wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
4089     bool isCurrent 
= coords 
== m_currentCellCoords
; 
4092     rect
.x 
= m_colRights
[col
] - m_colWidths
[col
]; 
4093     rect
.y 
= m_rowBottoms
[row
] - m_rowHeights
[row
]; 
4094     rect
.width 
= m_colWidths
[col
] - 1; 
4095     rect
.height 
= m_rowHeights
[row
] - 1; 
4097     // if the editor is shown, we should use it and not the renderer 
4098     if ( isCurrent 
&& IsCellEditControlEnabled() ) 
4100         attr
->GetEditor()->PaintBackground(rect
, attr
); 
4104         // but all the rest is drawn by the cell renderer and hence may be 
4106         attr
->GetRenderer()->Draw(*this, *attr
, dc
, rect
, row
, col
, IsInSelection(coords
)); 
4112 void wxGrid::DrawCellHighlight( wxDC
& dc
, const wxGridCellAttr 
*attr 
) 
4114     int row 
= m_currentCellCoords
.GetRow(); 
4115     int col 
= m_currentCellCoords
.GetCol(); 
4117     if ( m_colWidths
[col
] <= 0 || m_rowHeights
[row
] <= 0 ) 
4121     rect
.x 
= m_colRights
[col
] - m_colWidths
[col
]; 
4122     rect
.y 
= m_rowBottoms
[row
] - m_rowHeights
[row
]; 
4123     rect
.width 
= m_colWidths
[col
] - 1; 
4124     rect
.height 
= m_rowHeights
[row
] - 1; 
4126     // hmmm... what could we do here to show that the cell is disabled? 
4127     // for now, I just draw a thinner border than for the other ones, but 
4128     // it doesn't look really good 
4129     dc
.SetPen(wxPen(m_gridLineColour
, attr
->IsReadOnly() ? 1 : 3, wxSOLID
)); 
4130     dc
.SetBrush(*wxTRANSPARENT_BRUSH
); 
4132     dc
.DrawRectangle(rect
); 
4135         // VZ: my experiments with 3d borders... 
4137         // how to properly set colours for arbitrary bg? 
4138         wxCoord x1 
= rect
.x
, 
4140                 x2 
= rect
.x 
+ rect
.width 
-1, 
4141                 y2 
= rect
.y 
+ rect
.height 
-1; 
4143         dc
.SetPen(*wxWHITE_PEN
); 
4144         dc
.DrawLine(x1
, y1
, x2
, y1
); 
4145         dc
.DrawLine(x1
, y1
, x1
, y2
); 
4147         dc
.DrawLine(x1 
+ 1, y2 
- 1, x2 
- 1, y2 
- 1); 
4148         dc
.DrawLine(x2 
- 1, y1 
+ 1, x2 
- 1, y2 
); 
4150         dc
.SetPen(*wxBLACK_PEN
); 
4151         dc
.DrawLine(x1
, y2
, x2
, y2
); 
4152         dc
.DrawLine(x2
, y1
, x2
, y2
+1); 
4156 void wxGrid::DrawCellBorder( wxDC
& dc
, const wxGridCellCoords
& coords 
) 
4158     if ( m_colWidths
[coords
.GetCol()] <=0  || 
4159          m_rowHeights
[coords
.GetRow()] <= 0 ) return; 
4161     dc
.SetPen( wxPen(GetGridLineColour(), 1, wxSOLID
) ); 
4162     int row 
= coords
.GetRow(); 
4163     int col 
= coords
.GetCol(); 
4165     // right hand border 
4167     dc
.DrawLine( m_colRights
[col
], m_rowBottoms
[row
] - m_rowHeights
[row
], 
4168                  m_colRights
[col
], m_rowBottoms
[row
] ); 
4172     dc
.DrawLine( m_colRights
[col
] - m_colWidths
[col
], m_rowBottoms
[row
], 
4173                  m_colRights
[col
], m_rowBottoms
[row
] ); 
4176 void wxGrid::DrawHighlight(wxDC
& dc
) 
4178     // if the active cell was repainted, repaint its highlight too because it 
4179     // might have been damaged by the grid lines 
4180     size_t count 
= m_cellsExposed
.GetCount(); 
4181     for ( size_t n 
= 0; n 
< count
; n
++ ) 
4183         if ( m_cellsExposed
[n
] == m_currentCellCoords 
) 
4185             wxGridCellAttr
* attr 
= GetCellAttr(m_currentCellCoords
); 
4186             DrawCellHighlight(dc
, attr
); 
4194 // TODO: remove this ??? 
4195 // This is used to redraw all grid lines e.g. when the grid line colour 
4198 void wxGrid::DrawAllGridLines( wxDC
& dc
, const wxRegion 
& reg 
) 
4200     if ( !m_gridLinesEnabled 
|| 
4202          !m_numCols 
) return; 
4204     int top
, bottom
, left
, right
; 
4209       m_gridWin
->GetClientSize(&cw
, &ch
); 
4211       // virtual coords of visible area 
4213       CalcUnscrolledPosition( 0, 0, &left
, &top 
); 
4214       CalcUnscrolledPosition( cw
, ch
, &right
, &bottom 
); 
4219       reg
.GetBox(x
, y
, w
, h
); 
4220       CalcUnscrolledPosition( x
, y
, &left
, &top 
); 
4221       CalcUnscrolledPosition( x 
+ w
, y 
+ h
, &right
, &bottom 
); 
4224     // avoid drawing grid lines past the last row and col 
4226     right 
= wxMin( right
, m_colRights
[m_numCols
-1] ); 
4227     bottom 
= wxMin( bottom
, m_rowBottoms
[m_numRows
-1] ); 
4229     dc
.SetPen( wxPen(GetGridLineColour(), 1, wxSOLID
) ); 
4231     // horizontal grid lines 
4234     for ( i 
= 0; i 
< m_numRows
; i
++ ) 
4236         if ( m_rowBottoms
[i
]-1 > bottom 
) 
4240         else if ( m_rowBottoms
[i
]-1 >= top 
) 
4242             dc
.DrawLine( left
, m_rowBottoms
[i
]-1, right
, m_rowBottoms
[i
]-1 ); 
4247     // vertical grid lines 
4249     for ( i 
= 0; i 
< m_numCols
; i
++ ) 
4251         if ( m_colRights
[i
]-1 > right 
) 
4255         else if ( m_colRights
[i
]-1 >= left 
) 
4257             dc
.DrawLine( m_colRights
[i
]-1, top
, m_colRights
[i
]-1, bottom 
); 
4263 void wxGrid::DrawRowLabels( wxDC
& dc 
) 
4265     if ( !m_numRows 
|| !m_numCols 
) return; 
4268     size_t numLabels 
= m_rowLabelsExposed
.GetCount(); 
4270     for ( i 
= 0;  i 
< numLabels
;  i
++ ) 
4272         DrawRowLabel( dc
, m_rowLabelsExposed
[i
] ); 
4277 void wxGrid::DrawRowLabel( wxDC
& dc
, int row 
) 
4279     if ( m_rowHeights
[row
] <= 0 ) return; 
4281     int rowTop 
= m_rowBottoms
[row
] - m_rowHeights
[row
]; 
4283     dc
.SetPen( *wxBLACK_PEN 
); 
4284     dc
.DrawLine( m_rowLabelWidth
-1, rowTop
, 
4285                  m_rowLabelWidth
-1, m_rowBottoms
[row
]-1 ); 
4287     dc
.DrawLine( 0, m_rowBottoms
[row
]-1, 
4288                  m_rowLabelWidth
-1, m_rowBottoms
[row
]-1 ); 
4290     dc
.SetPen( *wxWHITE_PEN 
); 
4291     dc
.DrawLine( 0, rowTop
, 0, m_rowBottoms
[row
]-1 ); 
4292     dc
.DrawLine( 0, rowTop
, m_rowLabelWidth
-1, rowTop 
); 
4294     dc
.SetBackgroundMode( wxTRANSPARENT 
); 
4295     dc
.SetTextForeground( GetLabelTextColour() ); 
4296     dc
.SetFont( GetLabelFont() ); 
4299     GetRowLabelAlignment( &hAlign
, &vAlign 
); 
4303     rect
.SetY( m_rowBottoms
[row
] - m_rowHeights
[row
] + 2 ); 
4304     rect
.SetWidth( m_rowLabelWidth 
- 4 ); 
4305     rect
.SetHeight( m_rowHeights
[row
] - 4 ); 
4306     DrawTextRectangle( dc
, GetRowLabelValue( row 
), rect
, hAlign
, vAlign 
); 
4310 void wxGrid::DrawColLabels( wxDC
& dc 
) 
4312     if ( !m_numRows 
|| !m_numCols 
) return; 
4315     size_t numLabels 
= m_colLabelsExposed
.GetCount(); 
4317     for ( i 
= 0;  i 
< numLabels
;  i
++ ) 
4319         DrawColLabel( dc
, m_colLabelsExposed
[i
] ); 
4324 void wxGrid::DrawColLabel( wxDC
& dc
, int col 
) 
4326     if ( m_colWidths
[col
] <= 0 ) return; 
4328     int colLeft 
= m_colRights
[col
] - m_colWidths
[col
]; 
4330     dc
.SetPen( *wxBLACK_PEN 
); 
4331     dc
.DrawLine( m_colRights
[col
]-1, 0, 
4332                  m_colRights
[col
]-1, m_colLabelHeight
-1 ); 
4334     dc
.DrawLine( colLeft
, m_colLabelHeight
-1, 
4335                  m_colRights
[col
]-1, m_colLabelHeight
-1 ); 
4337     dc
.SetPen( *wxWHITE_PEN 
); 
4338     dc
.DrawLine( colLeft
, 0, colLeft
, m_colLabelHeight
-1 ); 
4339     dc
.DrawLine( colLeft
, 0, m_colRights
[col
]-1, 0 ); 
4341     dc
.SetBackgroundMode( wxTRANSPARENT 
); 
4342     dc
.SetTextForeground( GetLabelTextColour() ); 
4343     dc
.SetFont( GetLabelFont() ); 
4345     dc
.SetBackgroundMode( wxTRANSPARENT 
); 
4346     dc
.SetTextForeground( GetLabelTextColour() ); 
4347     dc
.SetFont( GetLabelFont() ); 
4350     GetColLabelAlignment( &hAlign
, &vAlign 
); 
4353     rect
.SetX( m_colRights
[col
] - m_colWidths
[col
] + 2 ); 
4355     rect
.SetWidth( m_colWidths
[col
] - 4 ); 
4356     rect
.SetHeight( m_colLabelHeight 
- 4 ); 
4357     DrawTextRectangle( dc
, GetColLabelValue( col 
), rect
, hAlign
, vAlign 
); 
4361 void wxGrid::DrawTextRectangle( wxDC
& dc
, 
4362                                 const wxString
& value
, 
4367     long textWidth
, textHeight
; 
4368     long lineWidth
, lineHeight
; 
4369     wxArrayString lines
; 
4371     dc
.SetClippingRegion( rect 
); 
4372     StringToLines( value
, lines 
); 
4373     if ( lines
.GetCount() ) 
4375         GetTextBoxSize( dc
, lines
, &textWidth
, &textHeight 
); 
4376         dc
.GetTextExtent( lines
[0], &lineWidth
, &lineHeight 
); 
4379         switch ( horizAlign 
) 
4382                 x 
= rect
.x 
+ (rect
.width 
- textWidth 
- 1); 
4386                 x 
= rect
.x 
+ ((rect
.width 
- textWidth
)/2); 
4395         switch ( vertAlign 
) 
4398                 y 
= rect
.y 
+ (rect
.height 
- textHeight 
- 1); 
4402                 y 
= rect
.y 
+ ((rect
.height 
- textHeight
)/2); 
4411         for ( size_t i 
= 0;  i 
< lines
.GetCount();  i
++ ) 
4413             dc
.DrawText( lines
[i
], (long)x
, (long)y 
); 
4418     dc
.DestroyClippingRegion(); 
4422 // Split multi line text up into an array of strings.  Any existing 
4423 // contents of the string array are preserved. 
4425 void wxGrid::StringToLines( const wxString
& value
, wxArrayString
& lines 
) 
4429     wxString eol 
= wxTextFile::GetEOL( wxTextFileType_Unix 
); 
4430     wxString tVal 
= wxTextFile::Translate( value
, wxTextFileType_Unix 
); 
4432     while ( startPos 
< (int)tVal
.Length() ) 
4434         pos 
= tVal
.Mid(startPos
).Find( eol 
); 
4439         else if ( pos 
== 0 ) 
4441             lines
.Add( wxEmptyString 
); 
4445             lines
.Add( value
.Mid(startPos
, pos
) ); 
4449     if ( startPos 
< (int)value
.Length() ) 
4451         lines
.Add( value
.Mid( startPos 
) ); 
4456 void wxGrid::GetTextBoxSize( wxDC
& dc
, 
4457                              wxArrayString
& lines
, 
4458                              long *width
, long *height 
) 
4465     for ( i 
= 0;  i 
< lines
.GetCount();  i
++ ) 
4467         dc
.GetTextExtent( lines
[i
], &lineW
, &lineH 
); 
4468         w 
= wxMax( w
, lineW 
); 
4478 // ------ Edit control functions 
4482 void wxGrid::EnableEditing( bool edit 
) 
4484     // TODO: improve this ? 
4486     if ( edit 
!= m_editable 
) 
4490         // FIXME IMHO this won't disable the edit control if edit == FALSE 
4491         //       because of the check in the beginning of 
4492         //       EnableCellEditControl() just below (VZ) 
4493         EnableCellEditControl(m_editable
); 
4498 void wxGrid::EnableCellEditControl( bool enable 
) 
4503     if ( m_currentCellCoords 
== wxGridNoCellCoords 
) 
4504         SetCurrentCell( 0, 0 ); 
4506     if ( enable 
!= m_cellEditCtrlEnabled 
) 
4508         // TODO allow the app to Veto() this event? 
4509         SendEvent(enable 
? wxEVT_GRID_EDITOR_SHOWN 
: wxEVT_GRID_EDITOR_HIDDEN
); 
4513             // this should be checked by the caller! 
4514             wxASSERT_MSG( CanEnableCellControl(), 
4515                           _T("can't enable editing for this cell!") ); 
4517             // do it before ShowCellEditControl() 
4518             m_cellEditCtrlEnabled 
= enable
; 
4520             SetEditControlValue(); 
4521             ShowCellEditControl(); 
4525             HideCellEditControl(); 
4526             SaveEditControlValue(); 
4528             // do it after HideCellEditControl() 
4529             m_cellEditCtrlEnabled 
= enable
; 
4534 bool wxGrid::IsCurrentCellReadOnly() const 
4537     wxGridCellAttr
* attr 
= ((wxGrid 
*)this)->GetCellAttr(m_currentCellCoords
); 
4538     bool readonly 
= attr
->IsReadOnly(); 
4544 bool wxGrid::CanEnableCellControl() const 
4546     return m_editable 
&& !IsCurrentCellReadOnly(); 
4549 bool wxGrid::IsCellEditControlEnabled() const 
4551     // the cell edit control might be disable for all cells or just for the 
4552     // current one if it's read only 
4553     return m_cellEditCtrlEnabled 
? !IsCurrentCellReadOnly() : FALSE
; 
4556 wxWindow 
*wxGrid::GetGridWindow() const 
4561 void wxGrid::ShowCellEditControl() 
4563     if ( IsCellEditControlEnabled() ) 
4565         if ( !IsVisible( m_currentCellCoords 
) ) 
4571             wxRect rect 
= CellToRect( m_currentCellCoords 
); 
4572             int row 
= m_currentCellCoords
.GetRow(); 
4573             int col 
= m_currentCellCoords
.GetCol(); 
4575             // convert to scrolled coords 
4577             int left
, top
, right
, bottom
; 
4578             CalcScrolledPosition( rect
.GetLeft(), rect
.GetTop(), &left
, &top 
); 
4579             CalcScrolledPosition( rect
.GetRight(), rect
.GetBottom(), &right
, &bottom 
); 
4581             // cell is shifted by one pixel 
4587             // Make the edit control large enough to allow for internal 
4590             // TODO: remove this if the text ctrl sizing is improved esp. for 
4594 #if defined(__WXMOTIF__) 
4595             if ( row 
== 0  || col 
== 0 ) 
4604             if ( row 
== 0  || col 
== 0 ) 
4614 #if defined(__WXGTK__) 
4617             if (left 
!= 0) left_diff
++; 
4618             if (top 
!= 0) top_diff
++; 
4619             rect
.SetLeft( left 
+ left_diff 
); 
4620             rect
.SetTop( top 
+ top_diff 
); 
4621             rect
.SetRight( rect
.GetRight() - left_diff 
); 
4622             rect
.SetBottom( rect
.GetBottom() - top_diff 
); 
4624             rect
.SetLeft( wxMax(0, left 
- extra
) ); 
4625             rect
.SetTop( wxMax(0, top 
- extra
) ); 
4626             rect
.SetRight( rect
.GetRight() + 2*extra 
); 
4627             rect
.SetBottom( rect
.GetBottom() + 2*extra 
); 
4630             wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
4631             wxGridCellEditor
* editor 
= attr
->GetEditor(); 
4632             if ( !editor
->IsCreated() ) 
4634                 editor
->Create(m_gridWin
, -1, 
4635                                new wxGridCellEditorEvtHandler(this, editor
)); 
4638             editor
->SetSize( rect 
); 
4639             editor
->Show( TRUE
, attr 
); 
4640             editor
->BeginEdit(row
, col
, this); 
4647 void wxGrid::HideCellEditControl() 
4649     if ( IsCellEditControlEnabled() ) 
4651         int row 
= m_currentCellCoords
.GetRow(); 
4652         int col 
= m_currentCellCoords
.GetCol(); 
4654         wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
4655         attr
->GetEditor()->Show( FALSE 
); 
4657         m_gridWin
->SetFocus(); 
4662 void wxGrid::SetEditControlValue( const wxString
& value 
) 
4664     // RD: The new Editors get the value from the table themselves now.  This 
4665     // method can probably be removed... 
4669 void wxGrid::SaveEditControlValue() 
4671     if ( IsCellEditControlEnabled() ) 
4673         int row 
= m_currentCellCoords
.GetRow(); 
4674         int col 
= m_currentCellCoords
.GetCol(); 
4676         wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
4677         bool changed 
= attr
->GetEditor()->EndEdit(row
, col
, TRUE
, this); 
4683             SendEvent( wxEVT_GRID_CELL_CHANGE
, 
4684                        m_currentCellCoords
.GetRow(), 
4685                        m_currentCellCoords
.GetCol() ); 
4692 // ------ Grid location functions 
4693 //  Note that all of these functions work with the logical coordinates of 
4694 //  grid cells and labels so you will need to convert from device 
4695 //  coordinates for mouse events etc. 
4698 void wxGrid::XYToCell( int x
, int y
, wxGridCellCoords
& coords 
) 
4700     int row 
= YToRow(y
); 
4701     int col 
= XToCol(x
); 
4703     if ( row 
== -1  ||  col 
== -1 ) 
4705         coords 
= wxGridNoCellCoords
; 
4709         coords
.Set( row
, col 
); 
4714 int wxGrid::YToRow( int y 
) 
4718     for ( i 
= 0;  i 
< m_numRows
;  i
++ ) 
4720         if ( y 
< m_rowBottoms
[i
] ) return i
; 
4723     return m_numRows
; //-1; 
4727 int wxGrid::XToCol( int x 
) 
4731     for ( i 
= 0;  i 
< m_numCols
;  i
++ ) 
4733         if ( x 
< m_colRights
[i
] ) return i
; 
4736     return m_numCols
; //-1; 
4740 // return the row number that that the y coord is near the edge of, or 
4741 // -1 if not near an edge 
4743 int wxGrid::YToEdgeOfRow( int y 
) 
4747     for ( i 
= 0;  i 
< m_numRows
;  i
++ ) 
4749         if ( m_rowHeights
[i
] > WXGRID_LABEL_EDGE_ZONE 
) 
4751             d 
= abs( y 
- m_rowBottoms
[i
] ); 
4753                 if ( d 
< WXGRID_LABEL_EDGE_ZONE 
) return i
; 
4762 // return the col number that that the x coord is near the edge of, or 
4763 // -1 if not near an edge 
4765 int wxGrid::XToEdgeOfCol( int x 
) 
4769     for ( i 
= 0;  i 
< m_numCols
;  i
++ ) 
4771         if ( m_colWidths
[i
] > WXGRID_LABEL_EDGE_ZONE 
) 
4773             d 
= abs( x 
- m_colRights
[i
] ); 
4775                 if ( d 
< WXGRID_LABEL_EDGE_ZONE 
) return i
; 
4784 wxRect 
wxGrid::CellToRect( int row
, int col 
) 
4786     wxRect 
rect( -1, -1, -1, -1 ); 
4788     if ( row 
>= 0  &&  row 
< m_numRows  
&& 
4789          col 
>= 0  &&  col 
< m_numCols 
) 
4791         rect
.x 
= m_colRights
[col
] - m_colWidths
[col
]; 
4792         rect
.y 
= m_rowBottoms
[row
] - m_rowHeights
[row
]; 
4793         rect
.width 
= m_colWidths
[col
]; 
4794         rect
.height 
= m_rowHeights
[ row 
]; 
4801 bool wxGrid::IsVisible( int row
, int col
, bool wholeCellVisible 
) 
4803     // get the cell rectangle in logical coords 
4805     wxRect 
r( CellToRect( row
, col 
) ); 
4807     // convert to device coords 
4809     int left
, top
, right
, bottom
; 
4810     CalcScrolledPosition( r
.GetLeft(), r
.GetTop(), &left
, &top 
); 
4811     CalcScrolledPosition( r
.GetRight(), r
.GetBottom(), &right
, &bottom 
); 
4813     // check against the client area of the grid window 
4816     m_gridWin
->GetClientSize( &cw
, &ch 
); 
4818     if ( wholeCellVisible 
) 
4820         // is the cell wholly visible ? 
4822         return ( left 
>= 0  &&  right 
<= cw  
&& 
4823                  top 
>= 0  &&  bottom 
<= ch 
); 
4827         // is the cell partly visible ? 
4829         return ( ((left 
>=0 && left 
< cw
) || (right 
> 0 && right 
<= cw
))  && 
4830                  ((top 
>=0 && top 
< ch
) || (bottom 
> 0 && bottom 
<= ch
)) ); 
4835 // make the specified cell location visible by doing a minimal amount 
4838 void wxGrid::MakeCellVisible( int row
, int col 
) 
4841     int xpos 
= -1, ypos 
= -1; 
4843     if ( row 
>= 0  &&  row 
< m_numRows  
&& 
4844          col 
>= 0  &&  col 
< m_numCols 
) 
4846         // get the cell rectangle in logical coords 
4848         wxRect 
r( CellToRect( row
, col 
) ); 
4850         // convert to device coords 
4852         int left
, top
, right
, bottom
; 
4853         CalcScrolledPosition( r
.GetLeft(), r
.GetTop(), &left
, &top 
); 
4854         CalcScrolledPosition( r
.GetRight(), r
.GetBottom(), &right
, &bottom 
); 
4857         m_gridWin
->GetClientSize( &cw
, &ch 
); 
4863         else if ( bottom 
> ch 
) 
4865             int h 
= r
.GetHeight(); 
4867             for ( i 
= row
-1;  i 
>= 0;  i
-- ) 
4869                 if ( h 
+ m_rowHeights
[i
] > ch 
) break; 
4871                 h 
+= m_rowHeights
[i
]; 
4872                 ypos 
-= m_rowHeights
[i
]; 
4875             // we divide it later by GRID_SCROLL_LINE, make sure that we don't 
4876             // have rounding errors (this is important, because if we do, we 
4877             // might not scroll at all and some cells won't be redrawn) 
4878             ypos 
+= GRID_SCROLL_LINE 
/ 2; 
4885         else if ( right 
> cw 
) 
4887             int w 
= r
.GetWidth(); 
4889             for ( i 
= col
-1;  i 
>= 0;  i
-- ) 
4891                 if ( w 
+ m_colWidths
[i
] > cw 
) break; 
4893                 w 
+= m_colWidths
[i
]; 
4894                 xpos 
-= m_colWidths
[i
]; 
4897             // see comment for ypos above 
4898             xpos 
+= GRID_SCROLL_LINE 
/ 2; 
4901         if ( xpos 
!= -1  ||  ypos 
!= -1 ) 
4903             if ( xpos 
!= -1 ) xpos 
/= GRID_SCROLL_LINE
; 
4904             if ( ypos 
!= -1 ) ypos 
/= GRID_SCROLL_LINE
; 
4905             Scroll( xpos
, ypos 
); 
4913 // ------ Grid cursor movement functions 
4916 bool wxGrid::MoveCursorUp() 
4918     if ( m_currentCellCoords 
!= wxGridNoCellCoords  
&& 
4919          m_currentCellCoords
.GetRow() > 0 ) 
4921         MakeCellVisible( m_currentCellCoords
.GetRow() - 1, 
4922                         m_currentCellCoords
.GetCol() ); 
4924         SetCurrentCell( m_currentCellCoords
.GetRow() - 1, 
4925                         m_currentCellCoords
.GetCol() ); 
4934 bool wxGrid::MoveCursorDown() 
4936     // TODO: allow for scrolling 
4938     if ( m_currentCellCoords 
!= wxGridNoCellCoords  
&& 
4939          m_currentCellCoords
.GetRow() < m_numRows
-1 ) 
4941         MakeCellVisible( m_currentCellCoords
.GetRow() + 1, 
4942                         m_currentCellCoords
.GetCol() ); 
4944         SetCurrentCell( m_currentCellCoords
.GetRow() + 1, 
4945                         m_currentCellCoords
.GetCol() ); 
4954 bool wxGrid::MoveCursorLeft() 
4956     if ( m_currentCellCoords 
!= wxGridNoCellCoords  
&& 
4957          m_currentCellCoords
.GetCol() > 0 ) 
4959         MakeCellVisible( m_currentCellCoords
.GetRow(), 
4960                         m_currentCellCoords
.GetCol() - 1 ); 
4962         SetCurrentCell( m_currentCellCoords
.GetRow(), 
4963                         m_currentCellCoords
.GetCol() - 1 ); 
4972 bool wxGrid::MoveCursorRight() 
4974     if ( m_currentCellCoords 
!= wxGridNoCellCoords  
&& 
4975          m_currentCellCoords
.GetCol() < m_numCols 
- 1 ) 
4977         MakeCellVisible( m_currentCellCoords
.GetRow(), 
4978                         m_currentCellCoords
.GetCol() + 1 ); 
4980         SetCurrentCell( m_currentCellCoords
.GetRow(), 
4981                         m_currentCellCoords
.GetCol() + 1 ); 
4990 bool wxGrid::MovePageUp() 
4992     if ( m_currentCellCoords 
== wxGridNoCellCoords 
) return FALSE
; 
4994     int row 
= m_currentCellCoords
.GetRow(); 
4998         m_gridWin
->GetClientSize( &cw
, &ch 
); 
5000         int y 
= m_rowBottoms
[ row 
] - m_rowHeights
[ row 
]; 
5001         int newRow 
= YToRow( y 
- ch 
+ 1 ); 
5006         else if ( newRow 
== row 
) 
5011         MakeCellVisible( newRow
, m_currentCellCoords
.GetCol() ); 
5012         SetCurrentCell( newRow
, m_currentCellCoords
.GetCol() ); 
5020 bool wxGrid::MovePageDown() 
5022     if ( m_currentCellCoords 
== wxGridNoCellCoords 
) return FALSE
; 
5024     int row 
= m_currentCellCoords
.GetRow(); 
5025     if ( row 
< m_numRows 
) 
5028         m_gridWin
->GetClientSize( &cw
, &ch 
); 
5030         int y 
= m_rowBottoms
[ row 
] - m_rowHeights
[ row 
]; 
5031         int newRow 
= YToRow( y 
+ ch 
); 
5034             newRow 
= m_numRows 
- 1; 
5036         else if ( newRow 
== row 
) 
5041         MakeCellVisible( newRow
, m_currentCellCoords
.GetCol() ); 
5042         SetCurrentCell( newRow
, m_currentCellCoords
.GetCol() ); 
5050 bool wxGrid::MoveCursorUpBlock() 
5053          m_currentCellCoords 
!= wxGridNoCellCoords  
&& 
5054          m_currentCellCoords
.GetRow() > 0 ) 
5056         int row 
= m_currentCellCoords
.GetRow(); 
5057         int col 
= m_currentCellCoords
.GetCol(); 
5059         if ( m_table
->IsEmptyCell(row
, col
) ) 
5061             // starting in an empty cell: find the next block of 
5067                 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break; 
5070         else if ( m_table
->IsEmptyCell(row
-1, col
) ) 
5072             // starting at the top of a block: find the next block 
5078                 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break; 
5083             // starting within a block: find the top of the block 
5088                 if ( m_table
->IsEmptyCell(row
, col
) ) 
5096         MakeCellVisible( row
, col 
); 
5097         SetCurrentCell( row
, col 
); 
5105 bool wxGrid::MoveCursorDownBlock() 
5108          m_currentCellCoords 
!= wxGridNoCellCoords  
&& 
5109          m_currentCellCoords
.GetRow() < m_numRows
-1 ) 
5111         int row 
= m_currentCellCoords
.GetRow(); 
5112         int col 
= m_currentCellCoords
.GetCol(); 
5114         if ( m_table
->IsEmptyCell(row
, col
) ) 
5116             // starting in an empty cell: find the next block of 
5119             while ( row 
< m_numRows
-1 ) 
5122                 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break; 
5125         else if ( m_table
->IsEmptyCell(row
+1, col
) ) 
5127             // starting at the bottom of a block: find the next block 
5130             while ( row 
< m_numRows
-1 ) 
5133                 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break; 
5138             // starting within a block: find the bottom of the block 
5140             while ( row 
< m_numRows
-1 ) 
5143                 if ( m_table
->IsEmptyCell(row
, col
) ) 
5151         MakeCellVisible( row
, col 
); 
5152         SetCurrentCell( row
, col 
); 
5160 bool wxGrid::MoveCursorLeftBlock() 
5163          m_currentCellCoords 
!= wxGridNoCellCoords  
&& 
5164          m_currentCellCoords
.GetCol() > 0 ) 
5166         int row 
= m_currentCellCoords
.GetRow(); 
5167         int col 
= m_currentCellCoords
.GetCol(); 
5169         if ( m_table
->IsEmptyCell(row
, col
) ) 
5171             // starting in an empty cell: find the next block of 
5177                 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break; 
5180         else if ( m_table
->IsEmptyCell(row
, col
-1) ) 
5182             // starting at the left of a block: find the next block 
5188                 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break; 
5193             // starting within a block: find the left of the block 
5198                 if ( m_table
->IsEmptyCell(row
, col
) ) 
5206         MakeCellVisible( row
, col 
); 
5207         SetCurrentCell( row
, col 
); 
5215 bool wxGrid::MoveCursorRightBlock() 
5218          m_currentCellCoords 
!= wxGridNoCellCoords  
&& 
5219          m_currentCellCoords
.GetCol() < m_numCols
-1 ) 
5221         int row 
= m_currentCellCoords
.GetRow(); 
5222         int col 
= m_currentCellCoords
.GetCol(); 
5224         if ( m_table
->IsEmptyCell(row
, col
) ) 
5226             // starting in an empty cell: find the next block of 
5229             while ( col 
< m_numCols
-1 ) 
5232                 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break; 
5235         else if ( m_table
->IsEmptyCell(row
, col
+1) ) 
5237             // starting at the right of a block: find the next block 
5240             while ( col 
< m_numCols
-1 ) 
5243                 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break; 
5248             // starting within a block: find the right of the block 
5250             while ( col 
< m_numCols
-1 ) 
5253                 if ( m_table
->IsEmptyCell(row
, col
) ) 
5261         MakeCellVisible( row
, col 
); 
5262         SetCurrentCell( row
, col 
); 
5273 // ------ Label values and formatting 
5276 void wxGrid::GetRowLabelAlignment( int *horiz
, int *vert 
) 
5278     *horiz 
= m_rowLabelHorizAlign
; 
5279     *vert  
= m_rowLabelVertAlign
; 
5282 void wxGrid::GetColLabelAlignment( int *horiz
, int *vert 
) 
5284     *horiz 
= m_colLabelHorizAlign
; 
5285     *vert  
= m_colLabelVertAlign
; 
5288 wxString 
wxGrid::GetRowLabelValue( int row 
) 
5292         return m_table
->GetRowLabelValue( row 
); 
5302 wxString 
wxGrid::GetColLabelValue( int col 
) 
5306         return m_table
->GetColLabelValue( col 
); 
5317 void wxGrid::SetRowLabelSize( int width 
) 
5319     width 
= wxMax( width
, 0 ); 
5320     if ( width 
!= m_rowLabelWidth 
) 
5324             m_rowLabelWin
->Show( FALSE 
); 
5325             m_cornerLabelWin
->Show( FALSE 
); 
5327         else if ( m_rowLabelWidth 
== 0 ) 
5329             m_rowLabelWin
->Show( TRUE 
); 
5330             if ( m_colLabelHeight 
> 0 ) m_cornerLabelWin
->Show( TRUE 
); 
5333         m_rowLabelWidth 
= width
; 
5340 void wxGrid::SetColLabelSize( int height 
) 
5342     height 
= wxMax( height
, 0 ); 
5343     if ( height 
!= m_colLabelHeight 
) 
5347             m_colLabelWin
->Show( FALSE 
); 
5348             m_cornerLabelWin
->Show( FALSE 
); 
5350         else if ( m_colLabelHeight 
== 0 ) 
5352             m_colLabelWin
->Show( TRUE 
); 
5353             if ( m_rowLabelWidth 
> 0 ) m_cornerLabelWin
->Show( TRUE 
); 
5356         m_colLabelHeight 
= height
; 
5363 void wxGrid::SetLabelBackgroundColour( const wxColour
& colour 
) 
5365     if ( m_labelBackgroundColour 
!= colour 
) 
5367         m_labelBackgroundColour 
= colour
; 
5368         m_rowLabelWin
->SetBackgroundColour( colour 
); 
5369         m_colLabelWin
->SetBackgroundColour( colour 
); 
5370         m_cornerLabelWin
->SetBackgroundColour( colour 
); 
5372         if ( !GetBatchCount() ) 
5374             m_rowLabelWin
->Refresh(); 
5375             m_colLabelWin
->Refresh(); 
5376             m_cornerLabelWin
->Refresh(); 
5381 void wxGrid::SetLabelTextColour( const wxColour
& colour 
) 
5383     if ( m_labelTextColour 
!= colour 
) 
5385         m_labelTextColour 
= colour
; 
5386         if ( !GetBatchCount() ) 
5388             m_rowLabelWin
->Refresh(); 
5389             m_colLabelWin
->Refresh(); 
5394 void wxGrid::SetLabelFont( const wxFont
& font 
) 
5397     if ( !GetBatchCount() ) 
5399         m_rowLabelWin
->Refresh(); 
5400         m_colLabelWin
->Refresh(); 
5404 void wxGrid::SetRowLabelAlignment( int horiz
, int vert 
) 
5406     if ( horiz 
== wxLEFT 
|| horiz 
== wxCENTRE 
|| horiz 
== wxRIGHT 
) 
5408         m_rowLabelHorizAlign 
= horiz
; 
5411     if ( vert 
== wxTOP 
|| vert 
== wxCENTRE 
|| vert 
== wxBOTTOM 
) 
5413         m_rowLabelVertAlign 
= vert
; 
5416     if ( !GetBatchCount() ) 
5418         m_rowLabelWin
->Refresh(); 
5422 void wxGrid::SetColLabelAlignment( int horiz
, int vert 
) 
5424     if ( horiz 
== wxLEFT 
|| horiz 
== wxCENTRE 
|| horiz 
== wxRIGHT 
) 
5426         m_colLabelHorizAlign 
= horiz
; 
5429     if ( vert 
== wxTOP 
|| vert 
== wxCENTRE 
|| vert 
== wxBOTTOM 
) 
5431         m_colLabelVertAlign 
= vert
; 
5434     if ( !GetBatchCount() ) 
5436         m_colLabelWin
->Refresh(); 
5440 void wxGrid::SetRowLabelValue( int row
, const wxString
& s 
) 
5444         m_table
->SetRowLabelValue( row
, s 
); 
5445         if ( !GetBatchCount() ) 
5447             wxRect rect 
= CellToRect( row
, 0); 
5448             if ( rect
.height 
> 0 ) 
5450                 CalcScrolledPosition(0, rect
.y
, &rect
.x
, &rect
.y
); 
5452                 rect
.width 
= m_rowLabelWidth
; 
5453                 m_rowLabelWin
->Refresh( TRUE
, &rect 
); 
5459 void wxGrid::SetColLabelValue( int col
, const wxString
& s 
) 
5463         m_table
->SetColLabelValue( col
, s 
); 
5464         if ( !GetBatchCount() ) 
5466             wxRect rect 
= CellToRect( 0, col 
); 
5467             if ( rect
.width 
> 0 ) 
5469                 CalcScrolledPosition(rect
.x
, 0, &rect
.x
, &rect
.y
); 
5471                 rect
.height 
= m_colLabelHeight
; 
5472                 m_colLabelWin
->Refresh( TRUE
, &rect 
); 
5478 void wxGrid::SetGridLineColour( const wxColour
& colour 
) 
5480     if ( m_gridLineColour 
!= colour 
) 
5482         m_gridLineColour 
= colour
; 
5484         wxClientDC 
dc( m_gridWin 
); 
5486         DrawAllGridLines( dc
, wxRegion() ); 
5490 void wxGrid::EnableGridLines( bool enable 
) 
5492     if ( enable 
!= m_gridLinesEnabled 
) 
5494         m_gridLinesEnabled 
= enable
; 
5496         if ( !GetBatchCount() ) 
5500                 wxClientDC 
dc( m_gridWin 
); 
5502                 DrawAllGridLines( dc
, wxRegion() ); 
5506                 m_gridWin
->Refresh(); 
5513 int wxGrid::GetDefaultRowSize() 
5515     return m_defaultRowHeight
; 
5518 int wxGrid::GetRowSize( int row 
) 
5520     wxCHECK_MSG( row 
>= 0 && row 
< m_numRows
, 0, _T("invalid row index") ); 
5522     return m_rowHeights
[row
]; 
5525 int wxGrid::GetDefaultColSize() 
5527     return m_defaultColWidth
; 
5530 int wxGrid::GetColSize( int col 
) 
5532     wxCHECK_MSG( col 
>= 0 && col 
< m_numCols
, 0, _T("invalid column index") ); 
5534     return m_colWidths
[col
]; 
5537 // ============================================================================ 
5538 // access to the grid attributes: each of them has a default value in the grid 
5539 // itself and may be overidden on a per-cell basis 
5540 // ============================================================================ 
5542 // ---------------------------------------------------------------------------- 
5543 // setting default attributes 
5544 // ---------------------------------------------------------------------------- 
5546 void wxGrid::SetDefaultCellBackgroundColour( const wxColour
& col 
) 
5548     m_defaultCellAttr
->SetBackgroundColour(col
); 
5550     m_gridWin
->SetBackgroundColour(col
); 
5554 void wxGrid::SetDefaultCellTextColour( const wxColour
& col 
) 
5556     m_defaultCellAttr
->SetTextColour(col
); 
5559 void wxGrid::SetDefaultCellAlignment( int horiz
, int vert 
) 
5561     m_defaultCellAttr
->SetAlignment(horiz
, vert
); 
5564 void wxGrid::SetDefaultCellFont( const wxFont
& font 
) 
5566     m_defaultCellAttr
->SetFont(font
); 
5569 void wxGrid::SetDefaultRenderer(wxGridCellRenderer 
*renderer
) 
5571     m_defaultCellAttr
->SetRenderer(renderer
); 
5574 void wxGrid::SetDefaultEditor(wxGridCellEditor 
*editor
) 
5576     m_defaultCellAttr
->SetEditor(editor
); 
5579 // ---------------------------------------------------------------------------- 
5580 // access to the default attrbiutes 
5581 // ---------------------------------------------------------------------------- 
5583 wxColour 
wxGrid::GetDefaultCellBackgroundColour() 
5585     return m_defaultCellAttr
->GetBackgroundColour(); 
5588 wxColour 
wxGrid::GetDefaultCellTextColour() 
5590     return m_defaultCellAttr
->GetTextColour(); 
5593 wxFont 
wxGrid::GetDefaultCellFont() 
5595     return m_defaultCellAttr
->GetFont(); 
5598 void wxGrid::GetDefaultCellAlignment( int *horiz
, int *vert 
) 
5600     m_defaultCellAttr
->GetAlignment(horiz
, vert
); 
5603 wxGridCellRenderer 
*wxGrid::GetDefaultRenderer() const 
5605     return m_defaultCellAttr
->GetRenderer(); 
5608 wxGridCellEditor 
*wxGrid::GetDefaultEditor() const 
5610     return m_defaultCellAttr
->GetEditor(); 
5613 // ---------------------------------------------------------------------------- 
5614 // access to cell attributes 
5615 // ---------------------------------------------------------------------------- 
5617 wxColour 
wxGrid::GetCellBackgroundColour(int row
, int col
) 
5619     wxGridCellAttr 
*attr 
= GetCellAttr(row
, col
); 
5620     wxColour colour 
= attr
->GetBackgroundColour(); 
5625 wxColour 
wxGrid::GetCellTextColour( int row
, int col 
) 
5627     wxGridCellAttr 
*attr 
= GetCellAttr(row
, col
); 
5628     wxColour colour 
= attr
->GetTextColour(); 
5633 wxFont 
wxGrid::GetCellFont( int row
, int col 
) 
5635     wxGridCellAttr 
*attr 
= GetCellAttr(row
, col
); 
5636     wxFont font 
= attr
->GetFont(); 
5641 void wxGrid::GetCellAlignment( int row
, int col
, int *horiz
, int *vert 
) 
5643     wxGridCellAttr 
*attr 
= GetCellAttr(row
, col
); 
5644     attr
->GetAlignment(horiz
, vert
); 
5648 wxGridCellRenderer
* wxGrid::GetCellRenderer(int row
, int col
) 
5650     wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
5651     wxGridCellRenderer
* renderer 
= attr
->GetRenderer(); 
5656 wxGridCellEditor
* wxGrid::GetCellEditor(int row
, int col
) 
5658     wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
5659     wxGridCellEditor
* editor 
= attr
->GetEditor(); 
5664 bool wxGrid::IsReadOnly(int row
, int col
) const 
5666     wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
5667     bool isReadOnly 
= attr
->IsReadOnly(); 
5672 // ---------------------------------------------------------------------------- 
5673 // attribute support: cache, automatic provider creation, ... 
5674 // ---------------------------------------------------------------------------- 
5676 bool wxGrid::CanHaveAttributes() 
5683     // RD:  Maybe m_table->CanHaveAttributes() would be better in case the 
5684     //      table is providing the attributes itself???  In which case 
5685     //      I don't think the grid should create a Provider object for the 
5686     //      table but the table should be smart enough to do that on its own. 
5687     if ( !m_table
->GetAttrProvider() ) 
5689         // use the default attr provider by default 
5690         // (another choice would be to just return FALSE thus forcing the user 
5692         m_table
->SetAttrProvider(new wxGridCellAttrProvider
); 
5698 void wxGrid::ClearAttrCache() 
5700     if ( m_attrCache
.row 
!= -1 ) 
5702         m_attrCache
.attr
->SafeDecRef(); 
5703         m_attrCache
.row 
= -1; 
5707 void wxGrid::CacheAttr(int row
, int col
, wxGridCellAttr 
*attr
) const 
5709     wxGrid 
*self 
= (wxGrid 
*)this;  // const_cast 
5711     self
->ClearAttrCache(); 
5712     self
->m_attrCache
.row 
= row
; 
5713     self
->m_attrCache
.col 
= col
; 
5714     self
->m_attrCache
.attr 
= attr
; 
5718 bool wxGrid::LookupAttr(int row
, int col
, wxGridCellAttr 
**attr
) const 
5720     if ( row 
== m_attrCache
.row 
&& col 
== m_attrCache
.col 
) 
5722         *attr 
= m_attrCache
.attr
; 
5723         (*attr
)->SafeIncRef(); 
5725 #ifdef DEBUG_ATTR_CACHE 
5726         gs_nAttrCacheHits
++; 
5733 #ifdef DEBUG_ATTR_CACHE 
5734         gs_nAttrCacheMisses
++; 
5740 wxGridCellAttr 
*wxGrid::GetCellAttr(int row
, int col
) const 
5742     wxGridCellAttr 
*attr
; 
5743     if ( !LookupAttr(row
, col
, &attr
) ) 
5745         attr 
= m_table 
? m_table
->GetAttr(row
, col
) : (wxGridCellAttr 
*)NULL
; 
5746         CacheAttr(row
, col
, attr
); 
5750         attr
->SetDefAttr(m_defaultCellAttr
); 
5754         attr 
= m_defaultCellAttr
; 
5761 wxGridCellAttr 
*wxGrid::GetOrCreateCellAttr(int row
, int col
) const 
5763     wxGridCellAttr 
*attr
; 
5764     if ( !LookupAttr(row
, col
, &attr
) || !attr 
) 
5766         wxASSERT_MSG( m_table
, 
5767                       _T("we may only be called if CanHaveAttributes() " 
5768                          "returned TRUE and then m_table should be !NULL") ); 
5770         attr 
= m_table
->GetAttr(row
, col
); 
5773             attr 
= new wxGridCellAttr
; 
5775             // artificially inc the ref count to match DecRef() in caller 
5778             m_table
->SetAttr(attr
, row
, col
); 
5781         CacheAttr(row
, col
, attr
); 
5783     attr
->SetDefAttr(m_defaultCellAttr
); 
5787 // ---------------------------------------------------------------------------- 
5788 // setting cell attributes: this is forwarded to the table 
5789 // ---------------------------------------------------------------------------- 
5791 void wxGrid::SetRowAttr(int row
, wxGridCellAttr 
*attr
) 
5793     if ( CanHaveAttributes() ) 
5795         m_table
->SetRowAttr(attr
, row
); 
5803 void wxGrid::SetColAttr(int col
, wxGridCellAttr 
*attr
) 
5805     if ( CanHaveAttributes() ) 
5807         m_table
->SetColAttr(attr
, col
); 
5815 void wxGrid::SetCellBackgroundColour( int row
, int col
, const wxColour
& colour 
) 
5817     if ( CanHaveAttributes() ) 
5819         wxGridCellAttr 
*attr 
= GetOrCreateCellAttr(row
, col
); 
5820         attr
->SetBackgroundColour(colour
); 
5825 void wxGrid::SetCellTextColour( int row
, int col
, const wxColour
& colour 
) 
5827     if ( CanHaveAttributes() ) 
5829         wxGridCellAttr 
*attr 
= GetOrCreateCellAttr(row
, col
); 
5830         attr
->SetTextColour(colour
); 
5835 void wxGrid::SetCellFont( int row
, int col
, const wxFont
& font 
) 
5837     if ( CanHaveAttributes() ) 
5839         wxGridCellAttr 
*attr 
= GetOrCreateCellAttr(row
, col
); 
5840         attr
->SetFont(font
); 
5845 void wxGrid::SetCellAlignment( int row
, int col
, int horiz
, int vert 
) 
5847     if ( CanHaveAttributes() ) 
5849         wxGridCellAttr 
*attr 
= GetOrCreateCellAttr(row
, col
); 
5850         attr
->SetAlignment(horiz
, vert
); 
5855 void wxGrid::SetCellRenderer(int row
, int col
, wxGridCellRenderer 
*renderer
) 
5857     if ( CanHaveAttributes() ) 
5859         wxGridCellAttr 
*attr 
= GetOrCreateCellAttr(row
, col
); 
5860         attr
->SetRenderer(renderer
); 
5865 void wxGrid::SetCellEditor(int row
, int col
, wxGridCellEditor
* editor
) 
5867     if ( CanHaveAttributes() ) 
5869         wxGridCellAttr 
*attr 
= GetOrCreateCellAttr(row
, col
); 
5870         attr
->SetEditor(editor
); 
5875 void wxGrid::SetReadOnly(int row
, int col
, bool isReadOnly
) 
5877     if ( CanHaveAttributes() ) 
5879         wxGridCellAttr 
*attr 
= GetOrCreateCellAttr(row
, col
); 
5880         attr
->SetReadOnly(isReadOnly
); 
5885 // ---------------------------------------------------------------------------- 
5887 // ---------------------------------------------------------------------------- 
5889 void wxGrid::SetDefaultRowSize( int height
, bool resizeExistingRows 
) 
5891     m_defaultRowHeight 
= wxMax( height
, WXGRID_MIN_ROW_HEIGHT 
); 
5893     if ( resizeExistingRows 
) 
5897         for ( row 
= 0;  row 
< m_numRows
;  row
++ ) 
5899             m_rowHeights
[row
] = m_defaultRowHeight
; 
5900             bottom 
+= m_defaultRowHeight
; 
5901             m_rowBottoms
[row
] = bottom
; 
5907 void wxGrid::SetRowSize( int row
, int height 
) 
5909     wxCHECK_RET( row 
>= 0 && row 
< m_numRows
, _T("invalid row index") ); 
5913     int h 
= wxMax( 0, height 
); 
5914     int diff 
= h 
- m_rowHeights
[row
]; 
5916     m_rowHeights
[row
] = h
; 
5917     for ( i 
= row
;  i 
< m_numRows
;  i
++ ) 
5919         m_rowBottoms
[i
] += diff
; 
5924 void wxGrid::SetDefaultColSize( int width
, bool resizeExistingCols 
) 
5926     m_defaultColWidth 
= wxMax( width
, WXGRID_MIN_COL_WIDTH 
); 
5928     if ( resizeExistingCols 
) 
5932         for ( col 
= 0;  col 
< m_numCols
;  col
++ ) 
5934             m_colWidths
[col
] = m_defaultColWidth
; 
5935             right 
+= m_defaultColWidth
; 
5936             m_colRights
[col
] = right
; 
5942 void wxGrid::SetColSize( int col
, int width 
) 
5944     wxCHECK_RET( col 
>= 0 && col 
< m_numCols
, _T("invalid column index") ); 
5948     int w 
= wxMax( 0, width 
); 
5949     int diff 
= w 
- m_colWidths
[col
]; 
5950     m_colWidths
[col
] = w
; 
5952     for ( i 
= col
;  i 
< m_numCols
;  i
++ ) 
5954         m_colRights
[i
] += diff
; 
5961 // ------ cell value accessor functions 
5964 void wxGrid::SetCellValue( int row
, int col
, const wxString
& s 
) 
5968         m_table
->SetValue( row
, col
, s
.c_str() ); 
5969         if ( !GetBatchCount() ) 
5971             wxClientDC 
dc( m_gridWin 
); 
5973             DrawCell( dc
, wxGridCellCoords(row
, col
) ); 
5976 #if 0  // TODO: edit in place 
5978         if ( m_currentCellCoords
.GetRow() == row 
&& 
5979              m_currentCellCoords
.GetCol() == col 
) 
5981             SetEditControlValue( s 
); 
5990 // ------ Block, row and col selection 
5993 void wxGrid::SelectRow( int row
, bool addToSelected 
) 
5997     if ( IsSelection() && addToSelected 
) 
6000         bool    need_refresh
[4]; 
6004         need_refresh
[3] = FALSE
; 
6008         wxCoord oldLeft   
= m_selectedTopLeft
.GetCol(); 
6009         wxCoord oldTop    
= m_selectedTopLeft
.GetRow(); 
6010         wxCoord oldRight  
= m_selectedBottomRight
.GetCol(); 
6011         wxCoord oldBottom 
= m_selectedBottomRight
.GetRow(); 
6015             need_refresh
[0] = TRUE
; 
6016             rect
[0] = BlockToDeviceRect( wxGridCellCoords ( row
, 0 ), 
6017                                          wxGridCellCoords ( oldTop 
- 1, 
6019             m_selectedTopLeft
.SetRow( row 
); 
6024             need_refresh
[1] = TRUE
; 
6025             rect
[1] = BlockToDeviceRect( wxGridCellCoords ( oldTop
, 0 ), 
6026                                          wxGridCellCoords ( oldBottom
, 
6029             m_selectedTopLeft
.SetCol( 0 ); 
6032         if ( oldBottom 
< row 
) 
6034             need_refresh
[2] = TRUE
; 
6035             rect
[2] = BlockToDeviceRect( wxGridCellCoords ( oldBottom 
+ 1, 0 ), 
6036                                          wxGridCellCoords ( row
, 
6038             m_selectedBottomRight
.SetRow( row 
); 
6041         if ( oldRight 
< m_numCols 
- 1 ) 
6043             need_refresh
[3] = TRUE
; 
6044             rect
[3] = BlockToDeviceRect( wxGridCellCoords ( oldTop 
, 
6046                                          wxGridCellCoords ( oldBottom
, 
6048             m_selectedBottomRight
.SetCol( m_numCols 
- 1 ); 
6051         for (i 
= 0; i 
< 4; i
++ ) 
6052             if ( need_refresh
[i
] && rect
[i
] != wxGridNoCellRect 
) 
6053                 m_gridWin
->Refresh( FALSE
, &(rect
[i
]) ); 
6057         r 
= SelectionToDeviceRect(); 
6059         if ( r 
!= wxGridNoCellRect 
) m_gridWin
->Refresh( FALSE
, &r 
); 
6061         m_selectedTopLeft
.Set( row
, 0 ); 
6062         m_selectedBottomRight
.Set( row
, m_numCols
-1 ); 
6063         r 
= SelectionToDeviceRect(); 
6064         m_gridWin
->Refresh( FALSE
, &r 
); 
6067     wxGridRangeSelectEvent 
gridEvt( GetId(), 
6068                                     wxEVT_GRID_RANGE_SELECT
, 
6071                                     m_selectedBottomRight 
); 
6073     GetEventHandler()->ProcessEvent(gridEvt
); 
6077 void wxGrid::SelectCol( int col
, bool addToSelected 
) 
6079     if ( IsSelection() && addToSelected 
) 
6082         bool    need_refresh
[4]; 
6086         need_refresh
[3] = FALSE
; 
6089         wxCoord oldLeft   
= m_selectedTopLeft
.GetCol(); 
6090         wxCoord oldTop    
= m_selectedTopLeft
.GetRow(); 
6091         wxCoord oldRight  
= m_selectedBottomRight
.GetCol(); 
6092         wxCoord oldBottom 
= m_selectedBottomRight
.GetRow(); 
6094         if ( oldLeft 
> col 
) 
6096             need_refresh
[0] = TRUE
; 
6097             rect
[0] = BlockToDeviceRect( wxGridCellCoords ( 0, col 
), 
6098                                          wxGridCellCoords ( m_numRows 
- 1, 
6100             m_selectedTopLeft
.SetCol( col 
); 
6105             need_refresh
[1] = TRUE
; 
6106             rect
[1] = BlockToDeviceRect( wxGridCellCoords ( 0, oldLeft 
), 
6107                                          wxGridCellCoords ( oldTop 
- 1, 
6109             m_selectedTopLeft
.SetRow( 0 ); 
6112         if ( oldRight 
< col 
) 
6114             need_refresh
[2] = TRUE
; 
6115             rect
[2] = BlockToDeviceRect( wxGridCellCoords ( 0, oldRight 
+ 1 ), 
6116                                          wxGridCellCoords ( m_numRows 
- 1, 
6118             m_selectedBottomRight
.SetCol( col 
); 
6121         if ( oldBottom 
< m_numRows 
- 1 ) 
6123             need_refresh
[3] = TRUE
; 
6124             rect
[3] = BlockToDeviceRect( wxGridCellCoords ( oldBottom 
+ 1, 
6126                                          wxGridCellCoords ( m_numRows 
- 1, 
6128             m_selectedBottomRight
.SetRow( m_numRows 
- 1 ); 
6131         for (i 
= 0; i 
< 4; i
++ ) 
6132             if ( need_refresh
[i
] && rect
[i
] != wxGridNoCellRect 
) 
6133                 m_gridWin
->Refresh( FALSE
, &(rect
[i
]) ); 
6139         r 
= SelectionToDeviceRect(); 
6141         if ( r 
!= wxGridNoCellRect 
) m_gridWin
->Refresh( FALSE
, &r 
); 
6143         m_selectedTopLeft
.Set( 0, col 
); 
6144         m_selectedBottomRight
.Set( m_numRows
-1, col 
); 
6145         r 
= SelectionToDeviceRect(); 
6146         m_gridWin
->Refresh( FALSE
, &r 
); 
6149     wxGridRangeSelectEvent 
gridEvt( GetId(), 
6150                                     wxEVT_GRID_RANGE_SELECT
, 
6153                                     m_selectedBottomRight 
); 
6155     GetEventHandler()->ProcessEvent(gridEvt
); 
6159 void wxGrid::SelectBlock( int topRow
, int leftCol
, int bottomRow
, int rightCol 
) 
6162     wxGridCellCoords updateTopLeft
, updateBottomRight
; 
6164     if ( topRow 
> bottomRow 
) 
6171     if ( leftCol 
> rightCol 
) 
6178     updateTopLeft 
= wxGridCellCoords( topRow
, leftCol 
); 
6179     updateBottomRight 
= wxGridCellCoords( bottomRow
, rightCol 
); 
6181     if ( m_selectedTopLeft 
!= updateTopLeft 
|| 
6182          m_selectedBottomRight 
!= updateBottomRight 
) 
6184         // Compute two optimal update rectangles: 
6185         // Either one rectangle is a real subset of the 
6186         // other, or they are (almost) disjoint! 
6188         bool    need_refresh
[4]; 
6192         need_refresh
[3] = FALSE
; 
6195         // Store intermediate values 
6196         wxCoord oldLeft   
= m_selectedTopLeft
.GetCol(); 
6197         wxCoord oldTop    
= m_selectedTopLeft
.GetRow(); 
6198         wxCoord oldRight  
= m_selectedBottomRight
.GetCol(); 
6199         wxCoord oldBottom 
= m_selectedBottomRight
.GetRow(); 
6201         // Determine the outer/inner coordinates. 
6202         if (oldLeft 
> leftCol
) 
6208         if (oldTop 
> topRow 
) 
6214         if (oldRight 
< rightCol 
) 
6217             oldRight 
= rightCol
; 
6220         if (oldBottom 
< bottomRow
) 
6223             oldBottom 
= bottomRow
; 
6227         // Now, either the stuff marked old is the outer 
6228         // rectangle or we don't have a situation where one 
6229         // is contained in the other. 
6231         if ( oldLeft 
< leftCol 
) 
6233             need_refresh
[0] = TRUE
; 
6234             rect
[0] = BlockToDeviceRect( wxGridCellCoords ( oldTop
, 
6236                                          wxGridCellCoords ( oldBottom
, 
6240         if ( oldTop  
< topRow 
) 
6242             need_refresh
[1] = TRUE
; 
6243             rect
[1] = BlockToDeviceRect( wxGridCellCoords ( oldTop
, 
6245                                          wxGridCellCoords ( topRow 
- 1, 
6249         if ( oldRight 
> rightCol 
) 
6251             need_refresh
[2] = TRUE
; 
6252             rect
[2] = BlockToDeviceRect( wxGridCellCoords ( oldTop
, 
6254                                          wxGridCellCoords ( oldBottom
, 
6258         if ( oldBottom 
> bottomRow 
) 
6260             need_refresh
[3] = TRUE
; 
6261             rect
[3] = BlockToDeviceRect( wxGridCellCoords ( bottomRow 
+ 1, 
6263                                          wxGridCellCoords ( oldBottom
, 
6269         m_selectedTopLeft 
= updateTopLeft
; 
6270         m_selectedBottomRight 
= updateBottomRight
; 
6272         // various Refresh() calls 
6273         for (i 
= 0; i 
< 4; i
++ ) 
6274             if ( need_refresh
[i
] && rect
[i
] != wxGridNoCellRect 
) 
6275                 m_gridWin
->Refresh( FALSE
, &(rect
[i
]) ); 
6278     // only generate an event if the block is not being selected by 
6279     // dragging the mouse (in which case the event will be generated in 
6280     // the mouse event handler) 
6281     if ( !m_isDragging 
) 
6283         wxGridRangeSelectEvent 
gridEvt( GetId(), 
6284                                         wxEVT_GRID_RANGE_SELECT
, 
6287                                         m_selectedBottomRight 
); 
6289         GetEventHandler()->ProcessEvent(gridEvt
); 
6293 void wxGrid::SelectAll() 
6295     m_selectedTopLeft
.Set( 0, 0 ); 
6296     m_selectedBottomRight
.Set( m_numRows
-1, m_numCols
-1 ); 
6298     m_gridWin
->Refresh(); 
6302 void wxGrid::ClearSelection() 
6304     m_selectedTopLeft 
= wxGridNoCellCoords
; 
6305     m_selectedBottomRight 
= wxGridNoCellCoords
; 
6309 // This function returns the rectangle that encloses the given block 
6310 // in device coords clipped to the client size of the grid window. 
6312 wxRect 
wxGrid::BlockToDeviceRect( const wxGridCellCoords 
&topLeft
, 
6313                                   const wxGridCellCoords 
&bottomRight 
) 
6315     wxRect 
rect( wxGridNoCellRect 
); 
6318     cellRect 
= CellToRect( topLeft 
); 
6319     if ( cellRect 
!= wxGridNoCellRect 
) 
6325         rect 
= wxRect( 0, 0, 0, 0 ); 
6328     cellRect 
= CellToRect( bottomRight 
); 
6329     if ( cellRect 
!= wxGridNoCellRect 
) 
6335         return wxGridNoCellRect
; 
6338     // convert to scrolled coords 
6340     int left
, top
, right
, bottom
; 
6341     CalcScrolledPosition( rect
.GetLeft(), rect
.GetTop(), &left
, &top 
); 
6342     CalcScrolledPosition( rect
.GetRight(), rect
.GetBottom(), &right
, &bottom 
); 
6345     m_gridWin
->GetClientSize( &cw
, &ch 
); 
6347     rect
.SetLeft( wxMax(0, left
) ); 
6348     rect
.SetTop( wxMax(0, top
) ); 
6349     rect
.SetRight( wxMin(cw
, right
) ); 
6350     rect
.SetBottom( wxMin(ch
, bottom
) ); 
6358 // ------ Grid event classes 
6361 IMPLEMENT_DYNAMIC_CLASS( wxGridEvent
, wxEvent 
) 
6363 wxGridEvent::wxGridEvent( int id
, wxEventType type
, wxObject
* obj
, 
6364                           int row
, int col
, int x
, int y
, 
6365                           bool control
, bool shift
, bool alt
, bool meta 
) 
6366         : wxNotifyEvent( type
, id 
) 
6372     m_control 
= control
; 
6377     SetEventObject(obj
); 
6381 IMPLEMENT_DYNAMIC_CLASS( wxGridSizeEvent
, wxEvent 
) 
6383 wxGridSizeEvent::wxGridSizeEvent( int id
, wxEventType type
, wxObject
* obj
, 
6384                                   int rowOrCol
, int x
, int y
, 
6385                                   bool control
, bool shift
, bool alt
, bool meta 
) 
6386         : wxNotifyEvent( type
, id 
) 
6388     m_rowOrCol 
= rowOrCol
; 
6391     m_control 
= control
; 
6396     SetEventObject(obj
); 
6400 IMPLEMENT_DYNAMIC_CLASS( wxGridRangeSelectEvent
, wxEvent 
) 
6402 wxGridRangeSelectEvent::wxGridRangeSelectEvent(int id
, wxEventType type
, wxObject
* obj
, 
6403                                                const wxGridCellCoords
& topLeft
, 
6404                                                const wxGridCellCoords
& bottomRight
, 
6405                                                bool control
, bool shift
, bool alt
, bool meta 
) 
6406         : wxNotifyEvent( type
, id 
) 
6408     m_topLeft     
= topLeft
; 
6409     m_bottomRight 
= bottomRight
; 
6410     m_control     
= control
; 
6415     SetEventObject(obj
); 
6419 #endif // ifndef wxUSE_NEW_GRID