1 /////////////////////////////////////////////////////////////////////////// 
   2 // Name:        generic/grid.cpp 
   3 // Purpose:     wxGrid and related classes 
   4 // Author:      Michael Bedward (based on code by Julian Smart, Robin Dunn) 
   8 // Copyright:   (c) Michael Bedward (mbedward@ozemail.com.au) 
   9 // Licence:     wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////////// 
  12 // ============================================================================ 
  14 // ============================================================================ 
  16 // ---------------------------------------------------------------------------- 
  18 // ---------------------------------------------------------------------------- 
  21     #pragma implementation "grid.h" 
  24 // For compilers that support precompilation, includes "wx/wx.h". 
  25 #include "wx/wxprec.h" 
  33 #if !defined(wxUSE_NEW_GRID) || !(wxUSE_NEW_GRID) 
  39     #include "wx/dcclient.h" 
  40     #include "wx/settings.h" 
  42     #include "wx/textctrl.h" 
  43     #include "wx/checkbox.h" 
  44     #include "wx/combobox.h" 
  45     #include "wx/valtext.h" 
  48 #include "wx/textfile.h" 
  49 #include "wx/spinctrl.h" 
  53 // ---------------------------------------------------------------------------- 
  55 // ---------------------------------------------------------------------------- 
  57 WX_DEFINE_ARRAY(wxGridCellAttr 
*, wxArrayAttrs
); 
  59 struct wxGridCellWithAttr
 
  61     wxGridCellWithAttr(int row
, int col
, wxGridCellAttr 
*attr_
) 
  62         : coords(row
, col
), attr(attr_
) 
  71     wxGridCellCoords coords
; 
  75 WX_DECLARE_OBJARRAY(wxGridCellWithAttr
, wxGridCellWithAttrArray
); 
  77 #include "wx/arrimpl.cpp" 
  79 WX_DEFINE_OBJARRAY(wxGridCellCoordsArray
) 
  80 WX_DEFINE_OBJARRAY(wxGridCellWithAttrArray
) 
  82 // ---------------------------------------------------------------------------- 
  84 // ---------------------------------------------------------------------------- 
  86 class WXDLLEXPORT wxGridRowLabelWindow 
: public wxWindow
 
  89     wxGridRowLabelWindow() { m_owner 
= (wxGrid 
*)NULL
; } 
  90     wxGridRowLabelWindow( wxGrid 
*parent
, wxWindowID id
, 
  91                           const wxPoint 
&pos
, const wxSize 
&size 
); 
  96     void OnPaint( wxPaintEvent
& event 
); 
  97     void OnMouseEvent( wxMouseEvent
& event 
); 
  98     void OnKeyDown( wxKeyEvent
& event 
); 
 100     DECLARE_DYNAMIC_CLASS(wxGridRowLabelWindow
) 
 101     DECLARE_EVENT_TABLE() 
 105 class WXDLLEXPORT wxGridColLabelWindow 
: public wxWindow
 
 108     wxGridColLabelWindow() { m_owner 
= (wxGrid 
*)NULL
; } 
 109     wxGridColLabelWindow( wxGrid 
*parent
, wxWindowID id
, 
 110                           const wxPoint 
&pos
, const wxSize 
&size 
); 
 115     void OnPaint( wxPaintEvent 
&event 
); 
 116     void OnMouseEvent( wxMouseEvent
& event 
); 
 117     void OnKeyDown( wxKeyEvent
& event 
); 
 119     DECLARE_DYNAMIC_CLASS(wxGridColLabelWindow
) 
 120     DECLARE_EVENT_TABLE() 
 124 class WXDLLEXPORT wxGridCornerLabelWindow 
: public wxWindow
 
 127     wxGridCornerLabelWindow() { m_owner 
= (wxGrid 
*)NULL
; } 
 128     wxGridCornerLabelWindow( wxGrid 
*parent
, wxWindowID id
, 
 129                              const wxPoint 
&pos
, const wxSize 
&size 
); 
 134     void OnMouseEvent( wxMouseEvent
& event 
); 
 135     void OnKeyDown( wxKeyEvent
& event 
); 
 136     void OnPaint( wxPaintEvent
& event 
); 
 138     DECLARE_DYNAMIC_CLASS(wxGridCornerLabelWindow
) 
 139     DECLARE_EVENT_TABLE() 
 142 class WXDLLEXPORT wxGridWindow 
: public wxPanel
 
 147         m_owner 
= (wxGrid 
*)NULL
; 
 148         m_rowLabelWin 
= (wxGridRowLabelWindow 
*)NULL
; 
 149         m_colLabelWin 
= (wxGridColLabelWindow 
*)NULL
; 
 152     wxGridWindow( wxGrid 
*parent
, 
 153                   wxGridRowLabelWindow 
*rowLblWin
, 
 154                   wxGridColLabelWindow 
*colLblWin
, 
 155                   wxWindowID id
, const wxPoint 
&pos
, const wxSize 
&size 
); 
 158     void ScrollWindow( int dx
, int dy
, const wxRect 
*rect 
); 
 162     wxGridRowLabelWindow     
*m_rowLabelWin
; 
 163     wxGridColLabelWindow     
*m_colLabelWin
; 
 165     void OnPaint( wxPaintEvent 
&event 
); 
 166     void OnMouseEvent( wxMouseEvent
& event 
); 
 167     void OnKeyDown( wxKeyEvent
& ); 
 168     void OnEraseBackground( wxEraseEvent
& ); 
 171     DECLARE_DYNAMIC_CLASS(wxGridWindow
) 
 172     DECLARE_EVENT_TABLE() 
 177 class wxGridCellEditorEvtHandler 
: public wxEvtHandler
 
 180     wxGridCellEditorEvtHandler() 
 181         : m_grid(0), m_editor(0) 
 183     wxGridCellEditorEvtHandler(wxGrid
* grid
, wxGridCellEditor
* editor
) 
 184         : m_grid(grid
), m_editor(editor
) 
 187     void OnKeyDown(wxKeyEvent
& event
); 
 188     void OnChar(wxKeyEvent
& event
); 
 192     wxGridCellEditor
*   m_editor
; 
 193     DECLARE_DYNAMIC_CLASS(wxGridCellEditorEvtHandler
) 
 194     DECLARE_EVENT_TABLE() 
 198 IMPLEMENT_DYNAMIC_CLASS( wxGridCellEditorEvtHandler
, wxEvtHandler 
) 
 199 BEGIN_EVENT_TABLE( wxGridCellEditorEvtHandler
, wxEvtHandler 
) 
 200     EVT_KEY_DOWN( wxGridCellEditorEvtHandler::OnKeyDown 
) 
 201     EVT_CHAR( wxGridCellEditorEvtHandler::OnChar 
) 
 206 // ---------------------------------------------------------------------------- 
 207 // the internal data representation used by wxGridCellAttrProvider 
 208 // ---------------------------------------------------------------------------- 
 210 // this class stores attributes set for cells 
 211 class WXDLLEXPORT wxGridCellAttrData
 
 214     void SetAttr(wxGridCellAttr 
*attr
, int row
, int col
); 
 215     wxGridCellAttr 
*GetAttr(int row
, int col
) const; 
 216     void UpdateAttrRows( size_t pos
, int numRows 
); 
 217     void UpdateAttrCols( size_t pos
, int numCols 
); 
 220     // searches for the attr for given cell, returns wxNOT_FOUND if not found 
 221     int FindIndex(int row
, int col
) const; 
 223     wxGridCellWithAttrArray m_attrs
; 
 226 // this class stores attributes set for rows or columns 
 227 class WXDLLEXPORT wxGridRowOrColAttrData
 
 230     // empty ctor to suppress warnings 
 231     wxGridRowOrColAttrData() { } 
 232     ~wxGridRowOrColAttrData(); 
 234     void SetAttr(wxGridCellAttr 
*attr
, int rowOrCol
); 
 235     wxGridCellAttr 
*GetAttr(int rowOrCol
) const; 
 236     void UpdateAttrRowsOrCols( size_t pos
, int numRowsOrCols 
); 
 239     wxArrayInt m_rowsOrCols
; 
 240     wxArrayAttrs m_attrs
; 
 243 // NB: this is just a wrapper around 3 objects: one which stores cell 
 244 //     attributes, and 2 others for row/col ones 
 245 class WXDLLEXPORT wxGridCellAttrProviderData
 
 248     wxGridCellAttrData m_cellAttrs
; 
 249     wxGridRowOrColAttrData m_rowAttrs
, 
 254 // ---------------------------------------------------------------------------- 
 255 // data structures used for the data type registry 
 256 // ---------------------------------------------------------------------------- 
 258 struct wxGridDataTypeInfo
 
 260     wxGridDataTypeInfo(const wxString
& typeName
, 
 261                        wxGridCellRenderer
* renderer
, 
 262                        wxGridCellEditor
* editor
) 
 263         : m_typeName(typeName
), m_renderer(renderer
), m_editor(editor
) 
 266     ~wxGridDataTypeInfo() 
 268         wxSafeDecRef(m_renderer
); 
 269         wxSafeDecRef(m_editor
); 
 273     wxGridCellRenderer
* m_renderer
; 
 274     wxGridCellEditor
*   m_editor
; 
 278 WX_DEFINE_ARRAY(wxGridDataTypeInfo
*, wxGridDataTypeInfoArray
); 
 281 class WXDLLEXPORT wxGridTypeRegistry
 
 284     ~wxGridTypeRegistry(); 
 286     void RegisterDataType(const wxString
& typeName
, 
 287                      wxGridCellRenderer
* renderer
, 
 288                      wxGridCellEditor
* editor
); 
 289     int FindDataType(const wxString
& typeName
); 
 290     wxGridCellRenderer
* GetRenderer(int index
); 
 291     wxGridCellEditor
*   GetEditor(int index
); 
 294     wxGridDataTypeInfoArray m_typeinfo
; 
 297 // ---------------------------------------------------------------------------- 
 298 // conditional compilation 
 299 // ---------------------------------------------------------------------------- 
 301 #ifndef WXGRID_DRAW_LINES 
 302 #define WXGRID_DRAW_LINES 1 
 305 // ---------------------------------------------------------------------------- 
 307 // ---------------------------------------------------------------------------- 
 309 //#define DEBUG_ATTR_CACHE 
 310 #ifdef DEBUG_ATTR_CACHE 
 311     static size_t gs_nAttrCacheHits 
= 0; 
 312     static size_t gs_nAttrCacheMisses 
= 0; 
 313 #endif // DEBUG_ATTR_CACHE 
 315 // ---------------------------------------------------------------------------- 
 317 // ---------------------------------------------------------------------------- 
 319 wxGridCellCoords 
wxGridNoCellCoords( -1, -1 ); 
 320 wxRect           
wxGridNoCellRect( -1, -1, -1, -1 ); 
 323 // TODO: fixed so far - make configurable later (and also different for x/y) 
 324 static const size_t GRID_SCROLL_LINE 
= 10; 
 326 // the size of hash tables used a bit everywhere (the max number of elements 
 327 // in these hash tables is the number of rows/columns) 
 328 static const int GRID_HASH_SIZE 
= 100; 
 330 // ============================================================================ 
 332 // ============================================================================ 
 334 // ---------------------------------------------------------------------------- 
 336 // ---------------------------------------------------------------------------- 
 338 wxGridCellEditor::wxGridCellEditor() 
 346 wxGridCellEditor::~wxGridCellEditor() 
 351 void wxGridCellEditor::Create(wxWindow
* WXUNUSED(parent
), 
 352                               wxWindowID 
WXUNUSED(id
), 
 353                               wxEvtHandler
* evtHandler
) 
 356         m_control
->PushEventHandler(evtHandler
); 
 359 void wxGridCellEditor::PaintBackground(const wxRect
& rectCell
, 
 360                                        wxGridCellAttr 
*attr
) 
 362     // erase the background because we might not fill the cell 
 363     wxClientDC 
dc(m_control
->GetParent()); 
 364     dc
.SetPen(*wxTRANSPARENT_PEN
); 
 365     dc
.SetBrush(wxBrush(attr
->GetBackgroundColour(), wxSOLID
)); 
 366     dc
.DrawRectangle(rectCell
); 
 368     // redraw the control we just painted over 
 369     m_control
->Refresh(); 
 372 void wxGridCellEditor::Destroy() 
 376         m_control
->PopEventHandler(TRUE 
/* delete it*/); 
 378         m_control
->Destroy(); 
 383 void wxGridCellEditor::Show(bool show
, wxGridCellAttr 
*attr
) 
 385     wxASSERT_MSG(m_control
, 
 386                  wxT("The wxGridCellEditor must be Created first!")); 
 387     m_control
->Show(show
); 
 391         // set the colours/fonts if we have any 
 394             m_colFgOld 
= m_control
->GetForegroundColour(); 
 395             m_control
->SetForegroundColour(attr
->GetTextColour()); 
 397             m_colBgOld 
= m_control
->GetBackgroundColour(); 
 398             m_control
->SetBackgroundColour(attr
->GetBackgroundColour()); 
 400             m_fontOld 
= m_control
->GetFont(); 
 401             m_control
->SetFont(attr
->GetFont()); 
 403             // can't do anything more in the base class version, the other 
 404             // attributes may only be used by the derived classes 
 409         // restore the standard colours fonts 
 410         if ( m_colFgOld
.Ok() ) 
 412             m_control
->SetForegroundColour(m_colFgOld
); 
 413             m_colFgOld 
= wxNullColour
; 
 416         if ( m_colBgOld
.Ok() ) 
 418             m_control
->SetBackgroundColour(m_colBgOld
); 
 419             m_colBgOld 
= wxNullColour
; 
 422         if ( m_fontOld
.Ok() ) 
 424             m_control
->SetFont(m_fontOld
); 
 425             m_fontOld 
= wxNullFont
; 
 430 void wxGridCellEditor::SetSize(const wxRect
& rect
) 
 432     wxASSERT_MSG(m_control
, 
 433                  wxT("The wxGridCellEditor must be Created first!")); 
 434     m_control
->SetSize(rect
, wxSIZE_ALLOW_MINUS_ONE
); 
 437 void wxGridCellEditor::HandleReturn(wxKeyEvent
& event
) 
 443 void wxGridCellEditor::StartingKey(wxKeyEvent
& event
) 
 448 void wxGridCellEditor::StartingClick() 
 452 // ---------------------------------------------------------------------------- 
 453 // wxGridCellTextEditor 
 454 // ---------------------------------------------------------------------------- 
 456 wxGridCellTextEditor::wxGridCellTextEditor() 
 460 void wxGridCellTextEditor::Create(wxWindow
* parent
, 
 462                                   wxEvtHandler
* evtHandler
) 
 464     m_control 
= new wxTextCtrl(parent
, id
, wxEmptyString
, 
 465                                wxDefaultPosition
, wxDefaultSize
 
 466 #if defined(__WXMSW__) 
 467                                , wxTE_MULTILINE 
| wxTE_NO_VSCROLL 
// necessary ??? 
 471     wxGridCellEditor::Create(parent
, id
, evtHandler
); 
 474 void wxGridCellTextEditor::PaintBackground(const wxRect
& WXUNUSED(rectCell
), 
 475                                            wxGridCellAttr 
* WXUNUSED(attr
)) 
 477     // as we fill the entire client area, don't do anything here to minimize 
 481 void wxGridCellTextEditor::SetSize(const wxRect
& rectOrig
) 
 483     wxRect 
rect(rectOrig
); 
 485     // Make the edit control large enough to allow for internal 
 488     // TODO: remove this if the text ctrl sizing is improved esp. for 
 491 #if defined(__WXGTK__) 
 500     int extra_x 
= ( rect
.x 
> 2 )? 2 : 1; 
 501     int extra_y 
= ( rect
.y 
> 2 )? 2 : 1; 
 502 #if defined(__WXMOTIF__) 
 506     rect
.SetLeft( wxMax(0, rect
.x 
- extra_x
) ); 
 507     rect
.SetTop( wxMax(0, rect
.y 
- extra_y
) ); 
 508     rect
.SetRight( rect
.GetRight() + 2*extra_x 
); 
 509     rect
.SetBottom( rect
.GetBottom() + 2*extra_y 
); 
 512     wxGridCellEditor::SetSize(rect
); 
 515 void wxGridCellTextEditor::BeginEdit(int row
, int col
, wxGrid
* grid
) 
 517     wxASSERT_MSG(m_control
, 
 518                  wxT("The wxGridCellEditor must be Created first!")); 
 520     m_startValue 
= grid
->GetTable()->GetValue(row
, col
); 
 522     DoBeginEdit(m_startValue
); 
 525 void wxGridCellTextEditor::DoBeginEdit(const wxString
& startValue
) 
 527     Text()->SetValue(startValue
); 
 528     Text()->SetInsertionPointEnd(); 
 532 bool wxGridCellTextEditor::EndEdit(int row
, int col
, 
 535     wxASSERT_MSG(m_control
, 
 536                  wxT("The wxGridCellEditor must be Created first!")); 
 538     bool changed 
= FALSE
; 
 539     wxString value 
= Text()->GetValue(); 
 540     if (value 
!= m_startValue
) 
 544         grid
->GetTable()->SetValue(row
, col
, value
); 
 546     m_startValue 
= wxEmptyString
; 
 547     Text()->SetValue(m_startValue
); 
 553 void wxGridCellTextEditor::Reset() 
 555     wxASSERT_MSG(m_control
, 
 556                  wxT("The wxGridCellEditor must be Created first!")); 
 558     DoReset(m_startValue
); 
 561 void wxGridCellTextEditor::DoReset(const wxString
& startValue
) 
 563     Text()->SetValue(startValue
); 
 564     Text()->SetInsertionPointEnd(); 
 567 void wxGridCellTextEditor::StartingKey(wxKeyEvent
& event
) 
 569     if ( !event
.AltDown() && !event
.MetaDown() && !event
.ControlDown() ) 
 571         // insert the key in the control 
 572         long keycode 
= event
.KeyCode(); 
 573         if ( isprint(keycode
) ) 
 575             // FIXME this is not going to work for non letters... 
 576             if ( !event
.ShiftDown() ) 
 578                 keycode 
= tolower(keycode
); 
 581             Text()->AppendText((wxChar
)keycode
); 
 591 void wxGridCellTextEditor::HandleReturn(wxKeyEvent
& event
) 
 593 #if defined(__WXMOTIF__) || defined(__WXGTK__) 
 594     // wxMotif needs a little extra help... 
 595     int pos 
= Text()->GetInsertionPoint(); 
 596     wxString 
s( Text()->GetValue() ); 
 597     s 
= s
.Left(pos
) + "\n" + s
.Mid(pos
); 
 599     Text()->SetInsertionPoint( pos 
); 
 601     // the other ports can handle a Return key press 
 607 // ---------------------------------------------------------------------------- 
 608 // wxGridCellNumberEditor 
 609 // ---------------------------------------------------------------------------- 
 611 wxGridCellNumberEditor::wxGridCellNumberEditor(int min
, int max
) 
 617 void wxGridCellNumberEditor::Create(wxWindow
* parent
, 
 619                                     wxEvtHandler
* evtHandler
) 
 623         // create a spin ctrl 
 624         m_control 
= new wxSpinCtrl(parent
, -1, wxEmptyString
, 
 625                                    wxDefaultPosition
, wxDefaultSize
, 
 629         wxGridCellEditor::Create(parent
, id
, evtHandler
); 
 633         // just a text control 
 634         wxGridCellTextEditor::Create(parent
, id
, evtHandler
); 
 637         Text()->SetValidator(wxTextValidator(wxFILTER_NUMERIC
)); 
 638 #endif // wxUSE_VALIDATORS 
 642 void wxGridCellNumberEditor::BeginEdit(int row
, int col
, wxGrid
* grid
) 
 644     // first get the value 
 645     wxGridTableBase 
*table 
= grid
->GetTable(); 
 646     if ( table
->CanGetValueAs(row
, col
, wxGRID_VALUE_NUMBER
) ) 
 648         m_valueOld 
= table
->GetValueAsLong(row
, col
); 
 652         wxString sValue 
= table
->GetValue(row
, col
); 
 653         if (! sValue
.ToLong(&m_valueOld
)) 
 655             wxFAIL_MSG( _T("this cell doesn't have numeric value") ); 
 662         Spin()->SetValue(m_valueOld
); 
 666         DoBeginEdit(GetString()); 
 670 bool wxGridCellNumberEditor::EndEdit(int row
, int col
, 
 678         value 
= Spin()->GetValue(); 
 679         changed 
= value 
!= m_valueOld
; 
 683         changed 
= Text()->GetValue().ToLong(&value
) && (value 
!= m_valueOld
); 
 688         if (grid
->GetTable()->CanSetValueAs(row
, col
, wxGRID_VALUE_NUMBER
)) 
 689             grid
->GetTable()->SetValueAsLong(row
, col
, value
); 
 691             grid
->GetTable()->SetValue(row
, col
, wxString::Format("%ld", value
)); 
 697 void wxGridCellNumberEditor::Reset() 
 701         Spin()->SetValue(m_valueOld
); 
 705         DoReset(GetString()); 
 709 void wxGridCellNumberEditor::StartingKey(wxKeyEvent
& event
) 
 713         long keycode 
= event
.KeyCode(); 
 714         if ( isdigit(keycode
) || keycode 
== '+' || keycode 
== '-' ) 
 716             wxGridCellTextEditor::StartingKey(event
); 
 726 // ---------------------------------------------------------------------------- 
 727 // wxGridCellFloatEditor 
 728 // ---------------------------------------------------------------------------- 
 730 void wxGridCellFloatEditor::Create(wxWindow
* parent
, 
 732                                    wxEvtHandler
* evtHandler
) 
 734     wxGridCellTextEditor::Create(parent
, id
, evtHandler
); 
 737     Text()->SetValidator(wxTextValidator(wxFILTER_NUMERIC
)); 
 738 #endif // wxUSE_VALIDATORS 
 741 void wxGridCellFloatEditor::BeginEdit(int row
, int col
, wxGrid
* grid
) 
 743     // first get the value 
 744     wxGridTableBase 
*table 
= grid
->GetTable(); 
 745     if ( table
->CanGetValueAs(row
, col
, wxGRID_VALUE_FLOAT
) ) 
 747         m_valueOld 
= table
->GetValueAsDouble(row
, col
); 
 751         wxString sValue 
= table
->GetValue(row
, col
); 
 752         if (! sValue
.ToDouble(&m_valueOld
)) 
 754             wxFAIL_MSG( _T("this cell doesn't have float value") ); 
 759     DoBeginEdit(GetString()); 
 762 bool wxGridCellFloatEditor::EndEdit(int row
, int col
, 
 766     if ( Text()->GetValue().ToDouble(&value
) && (value 
!= m_valueOld
) ) 
 768         if (grid
->GetTable()->CanSetValueAs(row
, col
, wxGRID_VALUE_FLOAT
)) 
 769             grid
->GetTable()->SetValueAsDouble(row
, col
, value
); 
 771             grid
->GetTable()->SetValue(row
, col
, wxString::Format("%f", value
)); 
 781 void wxGridCellFloatEditor::Reset() 
 783     DoReset(GetString()); 
 786 void wxGridCellFloatEditor::StartingKey(wxKeyEvent
& event
) 
 788     long keycode 
= event
.KeyCode(); 
 789     if ( isdigit(keycode
) || 
 790          keycode 
== '+' || keycode 
== '-' || keycode 
== '.' ) 
 792         wxGridCellTextEditor::StartingKey(event
); 
 801 // ---------------------------------------------------------------------------- 
 802 // wxGridCellBoolEditor 
 803 // ---------------------------------------------------------------------------- 
 805 void wxGridCellBoolEditor::Create(wxWindow
* parent
, 
 807                                   wxEvtHandler
* evtHandler
) 
 809     m_control 
= new wxCheckBox(parent
, id
, wxEmptyString
, 
 810                                wxDefaultPosition
, wxDefaultSize
, 
 813     wxGridCellEditor::Create(parent
, id
, evtHandler
); 
 816 void wxGridCellBoolEditor::SetSize(const wxRect
& r
) 
 819     wxSize size 
= m_control
->GetSize(); 
 820     wxCoord minSize 
= wxMin(r
.width
, r
.height
); 
 822     // check if the checkbox is not too big/small for this cell 
 823     wxSize sizeBest 
= m_control
->GetBestSize(); 
 824     if ( !(size 
== sizeBest
) ) 
 826         // reset to default size if it had been made smaller 
 832     if ( size
.x 
>= minSize 
|| size
.y 
>= minSize 
) 
 834         // leave 1 pixel margin 
 835         size
.x 
= size
.y 
= minSize 
- 2; 
 842         m_control
->SetSize(size
); 
 845     // position it in the centre of the rectangle (TODO: support alignment?) 
 847 #if defined(__WXGTK__) || defined (__WXMOTIF__) 
 848     // the checkbox without label still has some space to the right in wxGTK, 
 849     // so shift it to the right 
 851 #elif defined(__WXMSW__) 
 857     m_control
->Move(r
.x 
+ r
.width
/2 - size
.x
/2, r
.y 
+ r
.height
/2 - size
.y
/2); 
 860 void wxGridCellBoolEditor::Show(bool show
, wxGridCellAttr 
*attr
) 
 862     m_control
->Show(show
); 
 866         wxColour colBg 
= attr 
? attr
->GetBackgroundColour() : *wxLIGHT_GREY
; 
 867         CBox()->SetBackgroundColour(colBg
); 
 871 void wxGridCellBoolEditor::BeginEdit(int row
, int col
, wxGrid
* grid
) 
 873     wxASSERT_MSG(m_control
, 
 874                  wxT("The wxGridCellEditor must be Created first!")); 
 876     if (grid
->GetTable()->CanGetValueAs(row
, col
, wxGRID_VALUE_BOOL
)) 
 877         m_startValue 
= grid
->GetTable()->GetValueAsBool(row
, col
); 
 879         m_startValue 
= !!grid
->GetTable()->GetValue(row
, col
); 
 880     CBox()->SetValue(m_startValue
); 
 884 bool wxGridCellBoolEditor::EndEdit(int row
, int col
, 
 887     wxASSERT_MSG(m_control
, 
 888                  wxT("The wxGridCellEditor must be Created first!")); 
 890     bool changed 
= FALSE
; 
 891     bool value 
= CBox()->GetValue(); 
 892     if ( value 
!= m_startValue 
) 
 897         if (grid
->GetTable()->CanGetValueAs(row
, col
, wxGRID_VALUE_BOOL
)) 
 898             grid
->GetTable()->SetValueAsBool(row
, col
, value
); 
 900             grid
->GetTable()->SetValue(row
, col
, value 
? _T("1") : wxEmptyString
); 
 906 void wxGridCellBoolEditor::Reset() 
 908     wxASSERT_MSG(m_control
, 
 909                  wxT("The wxGridCellEditor must be Created first!")); 
 911     CBox()->SetValue(m_startValue
); 
 914 void wxGridCellBoolEditor::StartingClick() 
 916     CBox()->SetValue(!CBox()->GetValue()); 
 919 // ---------------------------------------------------------------------------- 
 920 // wxGridCellChoiceEditor 
 921 // ---------------------------------------------------------------------------- 
 923 wxGridCellChoiceEditor::wxGridCellChoiceEditor(size_t count
, 
 924                                                const wxChar
* choices
[], 
 926                       : m_allowOthers(allowOthers
) 
 928     m_choices
.Alloc(count
); 
 929     for ( size_t n 
= 0; n 
< count
; n
++ ) 
 931         m_choices
.Add(choices
[n
]); 
 935 void wxGridCellChoiceEditor::Create(wxWindow
* parent
, 
 937                                     wxEvtHandler
* evtHandler
) 
 939     size_t count 
= m_choices
.GetCount(); 
 940     wxString 
*choices 
= new wxString
[count
]; 
 941     for ( size_t n 
= 0; n 
< count
; n
++ ) 
 943         choices
[n
] = m_choices
[n
]; 
 946     m_control 
= new wxComboBox(parent
, id
, wxEmptyString
, 
 947                                wxDefaultPosition
, wxDefaultSize
, 
 949                                m_allowOthers 
? 0 : wxCB_READONLY
); 
 953     wxGridCellEditor::Create(parent
, id
, evtHandler
); 
 956 void wxGridCellChoiceEditor::PaintBackground(const wxRect
& rectCell
, 
 957                                              wxGridCellAttr 
* attr
) 
 959     // as we fill the entire client area, don't do anything here to minimize 
 962     // TODO: It doesn't actually fill the client area since the height of a 
 963     // combo always defaults to the standard...  Until someone has time to 
 964     // figure out the right rectangle to paint, just do it the normal way... 
 965     wxGridCellEditor::PaintBackground(rectCell
, attr
); 
 968 void wxGridCellChoiceEditor::BeginEdit(int row
, int col
, wxGrid
* grid
) 
 970     wxASSERT_MSG(m_control
, 
 971                  wxT("The wxGridCellEditor must be Created first!")); 
 973     m_startValue 
= grid
->GetTable()->GetValue(row
, col
); 
 975     Combo()->SetValue(m_startValue
); 
 976     size_t count 
= m_choices
.GetCount(); 
 977     for (size_t i
=0; i
<count
; i
++) 
 979         if (m_startValue 
== m_choices
[i
]) 
 981             Combo()->SetSelection(i
); 
 985     Combo()->SetInsertionPointEnd(); 
 989 bool wxGridCellChoiceEditor::EndEdit(int row
, int col
, 
 992     wxString value 
= Combo()->GetValue(); 
 993     bool changed 
= value 
!= m_startValue
; 
 996         grid
->GetTable()->SetValue(row
, col
, value
); 
 998     m_startValue 
= wxEmptyString
; 
 999     Combo()->SetValue(m_startValue
); 
1004 void wxGridCellChoiceEditor::Reset() 
1006     Combo()->SetValue(m_startValue
); 
1007     Combo()->SetInsertionPointEnd(); 
1010 // ---------------------------------------------------------------------------- 
1011 // wxGridCellEditorEvtHandler 
1012 // ---------------------------------------------------------------------------- 
1014 void wxGridCellEditorEvtHandler::OnKeyDown(wxKeyEvent
& event
) 
1016     switch ( event
.KeyCode() ) 
1020             m_grid
->DisableCellEditControl(); 
1024             event
.Skip( m_grid
->ProcessEvent( event 
) ); 
1028             if (!m_grid
->ProcessEvent(event
)) 
1029                 m_editor
->HandleReturn(event
); 
1038 void wxGridCellEditorEvtHandler::OnChar(wxKeyEvent
& event
) 
1040     switch ( event
.KeyCode() ) 
1052 // ============================================================================ 
1054 // ============================================================================ 
1056 // ---------------------------------------------------------------------------- 
1057 // wxGridCellRenderer 
1058 // ---------------------------------------------------------------------------- 
1060 void wxGridCellRenderer::Draw(wxGrid
& grid
, 
1061                               wxGridCellAttr
& attr
, 
1067     dc
.SetBackgroundMode( wxSOLID 
); 
1071         dc
.SetBrush( wxBrush(grid
.GetSelectionBackground(), wxSOLID
) ); 
1075         dc
.SetBrush( wxBrush(attr
.GetBackgroundColour(), wxSOLID
) ); 
1078     dc
.SetPen( *wxTRANSPARENT_PEN 
); 
1079     dc
.DrawRectangle(rect
); 
1082 void wxGridCellRenderer::SetParameters(const wxString
& WXUNUSED(params
)) 
1087 wxGridCellRenderer::~wxGridCellRenderer() 
1091 // ---------------------------------------------------------------------------- 
1092 // wxGridCellStringRenderer 
1093 // ---------------------------------------------------------------------------- 
1095 void wxGridCellStringRenderer::SetTextColoursAndFont(wxGrid
& grid
, 
1096                                                      wxGridCellAttr
& attr
, 
1100     dc
.SetBackgroundMode( wxTRANSPARENT 
); 
1102     // TODO some special colours for attr.IsReadOnly() case? 
1106         dc
.SetTextBackground( grid
.GetSelectionBackground() ); 
1107         dc
.SetTextForeground( grid
.GetSelectionForeground() ); 
1111         dc
.SetTextBackground( attr
.GetBackgroundColour() ); 
1112         dc
.SetTextForeground( attr
.GetTextColour() ); 
1115     dc
.SetFont( attr
.GetFont() ); 
1118 wxSize 
wxGridCellStringRenderer::DoGetBestSize(wxGridCellAttr
& attr
, 
1120                                                const wxString
& text
) 
1123     dc
.SetFont(attr
.GetFont()); 
1124     dc
.GetTextExtent(text
, &x
, &y
); 
1126     return wxSize(x
, y
); 
1129 wxSize 
wxGridCellStringRenderer::GetBestSize(wxGrid
& grid
, 
1130                                              wxGridCellAttr
& attr
, 
1134     return DoGetBestSize(attr
, dc
, grid
.GetCellValue(row
, col
)); 
1137 void wxGridCellStringRenderer::Draw(wxGrid
& grid
, 
1138                                     wxGridCellAttr
& attr
, 
1140                                     const wxRect
& rectCell
, 
1144     wxGridCellRenderer::Draw(grid
, attr
, dc
, rectCell
, row
, col
, isSelected
); 
1146     // now we only have to draw the text 
1147     SetTextColoursAndFont(grid
, attr
, dc
, isSelected
); 
1150     attr
.GetAlignment(&hAlign
, &vAlign
); 
1152     wxRect rect 
= rectCell
; 
1155     grid
.DrawTextRectangle(dc
, grid
.GetCellValue(row
, col
), 
1156                            rect
, hAlign
, vAlign
); 
1159 // ---------------------------------------------------------------------------- 
1160 // wxGridCellNumberRenderer 
1161 // ---------------------------------------------------------------------------- 
1163 wxString 
wxGridCellNumberRenderer::GetString(wxGrid
& grid
, int row
, int col
) 
1165     wxGridTableBase 
*table 
= grid
.GetTable(); 
1167     if ( table
->CanGetValueAs(row
, col
, wxGRID_VALUE_NUMBER
) ) 
1169         text
.Printf(_T("%ld"), table
->GetValueAsLong(row
, col
)); 
1173         text 
= table
->GetValue(row
, col
); 
1179 void wxGridCellNumberRenderer::Draw(wxGrid
& grid
, 
1180                                     wxGridCellAttr
& attr
, 
1182                                     const wxRect
& rectCell
, 
1186     wxGridCellRenderer::Draw(grid
, attr
, dc
, rectCell
, row
, col
, isSelected
); 
1188     SetTextColoursAndFont(grid
, attr
, dc
, isSelected
); 
1190     // draw the text right aligned by default 
1192     attr
.GetAlignment(&hAlign
, &vAlign
); 
1195     wxRect rect 
= rectCell
; 
1198     grid
.DrawTextRectangle(dc
, GetString(grid
, row
, col
), rect
, hAlign
, vAlign
); 
1201 wxSize 
wxGridCellNumberRenderer::GetBestSize(wxGrid
& grid
, 
1202                                              wxGridCellAttr
& attr
, 
1206     return DoGetBestSize(attr
, dc
, GetString(grid
, row
, col
)); 
1209 // ---------------------------------------------------------------------------- 
1210 // wxGridCellFloatRenderer 
1211 // ---------------------------------------------------------------------------- 
1213 wxGridCellFloatRenderer::wxGridCellFloatRenderer(int width
, int precision
) 
1216     SetPrecision(precision
); 
1219 wxGridCellRenderer 
*wxGridCellFloatRenderer::Clone() const 
1221     wxGridCellFloatRenderer 
*renderer 
= new wxGridCellFloatRenderer
; 
1222     renderer
->m_width 
= m_width
; 
1223     renderer
->m_precision 
= m_precision
; 
1224     renderer
->m_format 
= m_format
; 
1229 wxString 
wxGridCellFloatRenderer::GetString(wxGrid
& grid
, int row
, int col
) 
1231     wxGridTableBase 
*table 
= grid
.GetTable(); 
1236     if ( table
->CanGetValueAs(row
, col
, wxGRID_VALUE_FLOAT
) ) 
1238         val 
= table
->GetValueAsDouble(row
, col
); 
1243         text 
= table
->GetValue(row
, col
); 
1244         hasDouble 
= text
.ToDouble(&val
); 
1251             if ( m_width 
== -1 ) 
1253                 // default width/precision 
1254                 m_format 
= _T("%f"); 
1256             else if ( m_precision 
== -1 ) 
1258                 // default precision 
1259                 m_format
.Printf(_T("%%%d.f"), m_width
); 
1263                 m_format
.Printf(_T("%%%d.%df"), m_width
, m_precision
); 
1267         text
.Printf(m_format
, val
); 
1269     //else: text already contains the string 
1274 void wxGridCellFloatRenderer::Draw(wxGrid
& grid
, 
1275                                    wxGridCellAttr
& attr
, 
1277                                    const wxRect
& rectCell
, 
1281     wxGridCellRenderer::Draw(grid
, attr
, dc
, rectCell
, row
, col
, isSelected
); 
1283     SetTextColoursAndFont(grid
, attr
, dc
, isSelected
); 
1285     // draw the text right aligned by default 
1287     attr
.GetAlignment(&hAlign
, &vAlign
); 
1290     wxRect rect 
= rectCell
; 
1293     grid
.DrawTextRectangle(dc
, GetString(grid
, row
, col
), rect
, hAlign
, vAlign
); 
1296 wxSize 
wxGridCellFloatRenderer::GetBestSize(wxGrid
& grid
, 
1297                                             wxGridCellAttr
& attr
, 
1301     return DoGetBestSize(attr
, dc
, GetString(grid
, row
, col
)); 
1304 void wxGridCellFloatRenderer::SetParameters(const wxString
& params
) 
1310         // reset to defaults 
1316         wxString tmp 
= params
.BeforeFirst(_T(',')); 
1320             if ( !tmp
.ToLong(&width
) ) 
1326                 SetWidth((int)width
); 
1328                 tmp 
= params
.AfterFirst(_T(',')); 
1332                     if ( !tmp
.ToLong(&precision
) ) 
1338                         SetPrecision((int)precision
); 
1346             wxLogDebug(_T("Invalid wxGridCellFloatRenderer parameter string " 
1347                           "'%s ignored"), params
.c_str()); 
1352 // ---------------------------------------------------------------------------- 
1353 // wxGridCellBoolRenderer 
1354 // ---------------------------------------------------------------------------- 
1356 wxSize 
wxGridCellBoolRenderer::ms_sizeCheckMark
; 
1358 // FIXME these checkbox size calculations are really ugly... 
1360 // between checkmark and box 
1362     static const wxCoord wxGRID_CHECKMARK_MARGIN 
= 4; 
1364     static const wxCoord wxGRID_CHECKMARK_MARGIN 
= 2; 
1367 wxSize 
wxGridCellBoolRenderer::GetBestSize(wxGrid
& grid
, 
1368                                            wxGridCellAttr
& WXUNUSED(attr
), 
1373     // compute it only once (no locks for MT safeness in GUI thread...) 
1374     if ( !ms_sizeCheckMark
.x 
) 
1376         // get checkbox size 
1377         wxCoord checkSize 
= 0; 
1378         wxCheckBox 
*checkbox 
= new wxCheckBox(&grid
, -1, wxEmptyString
); 
1379         wxSize size 
= checkbox
->GetBestSize(); 
1380         checkSize 
= size
.y 
+ wxGRID_CHECKMARK_MARGIN
; 
1382         // FIXME wxGTK::wxCheckBox::GetBestSize() gives "wrong" result 
1383 #if defined(__WXGTK__) || defined(__WXMOTIF__) 
1384         checkSize 
-= size
.y 
/ 2; 
1389         ms_sizeCheckMark
.x 
= ms_sizeCheckMark
.y 
= checkSize
; 
1392     return ms_sizeCheckMark
; 
1395 void wxGridCellBoolRenderer::Draw(wxGrid
& grid
, 
1396                                   wxGridCellAttr
& attr
, 
1402     wxGridCellRenderer::Draw(grid
, attr
, dc
, rect
, row
, col
, isSelected
); 
1404     // draw a check mark in the centre (ignoring alignment - TODO) 
1405     wxSize size 
= GetBestSize(grid
, attr
, dc
, row
, col
); 
1407     // don't draw outside the cell 
1408     wxCoord minSize 
= wxMin(rect
.width
, rect
.height
); 
1409     if ( size
.x 
>= minSize 
|| size
.y 
>= minSize 
) 
1411         // and even leave (at least) 1 pixel margin 
1412         size
.x 
= size
.y 
= minSize 
- 2; 
1415     // draw a border around checkmark 
1417     rectMark
.x 
= rect
.x 
+ rect
.width
/2 - size
.x
/2; 
1418     rectMark
.y 
= rect
.y 
+ rect
.height
/2 - size
.y
/2; 
1419     rectMark
.width 
= size
.x
; 
1420     rectMark
.height 
= size
.y
; 
1422     dc
.SetBrush(*wxTRANSPARENT_BRUSH
); 
1423     dc
.SetPen(wxPen(attr
.GetTextColour(), 1, wxSOLID
)); 
1424     dc
.DrawRectangle(rectMark
); 
1426     rectMark
.Inflate(-wxGRID_CHECKMARK_MARGIN
); 
1429     // looks nicer under MSW 
1434     if ( grid
.GetTable()->CanGetValueAs(row
, col
, wxGRID_VALUE_BOOL
) ) 
1435         value 
= grid
.GetTable()->GetValueAsBool(row
, col
); 
1437         value 
= !!grid
.GetTable()->GetValue(row
, col
); 
1441         dc
.SetTextForeground(attr
.GetTextColour()); 
1442         dc
.DrawCheckMark(rectMark
); 
1446 // ---------------------------------------------------------------------------- 
1448 // ---------------------------------------------------------------------------- 
1450 wxGridCellAttr 
*wxGridCellAttr::Clone() const 
1452     wxGridCellAttr 
*attr 
= new wxGridCellAttr
; 
1453     if ( HasTextColour() ) 
1454         attr
->SetTextColour(GetTextColour()); 
1455     if ( HasBackgroundColour() ) 
1456         attr
->SetBackgroundColour(GetBackgroundColour()); 
1458         attr
->SetFont(GetFont()); 
1459     if ( HasAlignment() ) 
1460         attr
->SetAlignment(m_hAlign
, m_vAlign
); 
1464         attr
->SetRenderer(m_renderer
); 
1465         m_renderer
->IncRef(); 
1469         attr
->SetEditor(m_editor
); 
1474         attr
->SetReadOnly(); 
1476     attr
->SetDefAttr(m_defGridAttr
); 
1481 const wxColour
& wxGridCellAttr::GetTextColour() const 
1483     if (HasTextColour()) 
1487     else if (m_defGridAttr 
!= this) 
1489         return m_defGridAttr
->GetTextColour(); 
1493         wxFAIL_MSG(wxT("Missing default cell attribute")); 
1494         return wxNullColour
; 
1499 const wxColour
& wxGridCellAttr::GetBackgroundColour() const 
1501     if (HasBackgroundColour()) 
1503     else if (m_defGridAttr 
!= this) 
1504         return m_defGridAttr
->GetBackgroundColour(); 
1507         wxFAIL_MSG(wxT("Missing default cell attribute")); 
1508         return wxNullColour
; 
1513 const wxFont
& wxGridCellAttr::GetFont() const 
1517     else if (m_defGridAttr 
!= this) 
1518         return m_defGridAttr
->GetFont(); 
1521         wxFAIL_MSG(wxT("Missing default cell attribute")); 
1527 void wxGridCellAttr::GetAlignment(int *hAlign
, int *vAlign
) const 
1531         if ( hAlign 
) *hAlign 
= m_hAlign
; 
1532         if ( vAlign 
) *vAlign 
= m_vAlign
; 
1534     else if (m_defGridAttr 
!= this) 
1535         m_defGridAttr
->GetAlignment(hAlign
, vAlign
); 
1538         wxFAIL_MSG(wxT("Missing default cell attribute")); 
1543 // GetRenderer and GetEditor use a slightly different decision path about 
1544 // which attribute to use.  If a non-default attr object has one then it is 
1545 // used, otherwise the default editor or renderer is fetched from the grid and 
1546 // used.  It should be the default for the data type of the cell.  If it is 
1547 // NULL (because the table has a type that the grid does not have in its 
1548 // registry,) then the grid's default editor or renderer is used. 
1550 wxGridCellRenderer
* wxGridCellAttr::GetRenderer(wxGrid
* grid
, int row
, int col
) const 
1552     wxGridCellRenderer
* renderer 
= NULL
; 
1554     if ( m_defGridAttr 
!= this || grid 
== NULL 
) 
1556         renderer 
= m_renderer
;      // use local attribute 
1561     if ( !renderer 
&& grid 
)        // get renderer for the data type 
1563         // GetDefaultRendererForCell() will do IncRef() for us 
1564         renderer 
= grid
->GetDefaultRendererForCell(row
, col
); 
1569         // if we still don't have one then use the grid default 
1570         // (no need for IncRef() here neither) 
1571         renderer 
= m_defGridAttr
->GetRenderer(NULL
,0,0); 
1576         wxFAIL_MSG(wxT("Missing default cell attribute")); 
1582 wxGridCellEditor
* wxGridCellAttr::GetEditor(wxGrid
* grid
, int row
, int col
) const 
1584     wxGridCellEditor
* editor 
= NULL
; 
1586     if ( m_defGridAttr 
!= this || grid 
== NULL 
) 
1588         editor 
= m_editor
;      // use local attribute 
1593     if ( grid 
)                   // get renderer for the data type 
1594         editor 
=  grid
->GetDefaultEditorForCell(row
, col
); 
1597         // if we still don't have one then use the grid default 
1598         editor 
= m_defGridAttr
->GetEditor(NULL
,0,0); 
1602         wxFAIL_MSG(wxT("Missing default cell attribute")); 
1608 // ---------------------------------------------------------------------------- 
1609 // wxGridCellAttrData 
1610 // ---------------------------------------------------------------------------- 
1612 void wxGridCellAttrData::SetAttr(wxGridCellAttr 
*attr
, int row
, int col
) 
1614     int n 
= FindIndex(row
, col
); 
1615     if ( n 
== wxNOT_FOUND 
) 
1617         // add the attribute 
1618         m_attrs
.Add(new wxGridCellWithAttr(row
, col
, attr
)); 
1624             // change the attribute 
1625             m_attrs
[(size_t)n
].attr 
= attr
; 
1629             // remove this attribute 
1630             m_attrs
.RemoveAt((size_t)n
); 
1635 wxGridCellAttr 
*wxGridCellAttrData::GetAttr(int row
, int col
) const 
1637     wxGridCellAttr 
*attr 
= (wxGridCellAttr 
*)NULL
; 
1639     int n 
= FindIndex(row
, col
); 
1640     if ( n 
!= wxNOT_FOUND 
) 
1642         attr 
= m_attrs
[(size_t)n
].attr
; 
1649 void wxGridCellAttrData::UpdateAttrRows( size_t pos
, int numRows 
) 
1651     size_t count 
= m_attrs
.GetCount(); 
1652     for ( size_t n 
= 0; n 
< count
; n
++ ) 
1654         wxGridCellCoords
& coords 
= m_attrs
[n
].coords
; 
1655         wxCoord row 
= coords
.GetRow(); 
1656         if ((size_t)row 
>= pos
) 
1660                 // If rows inserted, include row counter where necessary 
1661                 coords
.SetRow(row 
+ numRows
); 
1663             else if (numRows 
< 0) 
1665                 // If rows deleted ... 
1666                 if ((size_t)row 
>= pos 
- numRows
) 
1668                     // ...either decrement row counter (if row still exists)... 
1669                     coords
.SetRow(row 
+ numRows
); 
1673                     // ...or remove the attribute 
1674                     m_attrs
.RemoveAt((size_t)n
); 
1682 void wxGridCellAttrData::UpdateAttrCols( size_t pos
, int numCols 
) 
1684     size_t count 
= m_attrs
.GetCount(); 
1685     for ( size_t n 
= 0; n 
< count
; n
++ ) 
1687         wxGridCellCoords
& coords 
= m_attrs
[n
].coords
; 
1688         wxCoord col 
= coords
.GetCol(); 
1689         if ( (size_t)col 
>= pos 
) 
1693                 // If rows inserted, include row counter where necessary 
1694                 coords
.SetCol(col 
+ numCols
); 
1696             else if (numCols 
< 0) 
1698                 // If rows deleted ... 
1699                 if ((size_t)col 
>= pos 
- numCols
) 
1701                     // ...either decrement row counter (if row still exists)... 
1702                     coords
.SetCol(col 
+ numCols
); 
1706                     // ...or remove the attribute 
1707                     m_attrs
.RemoveAt((size_t)n
); 
1715 int wxGridCellAttrData::FindIndex(int row
, int col
) const 
1717     size_t count 
= m_attrs
.GetCount(); 
1718     for ( size_t n 
= 0; n 
< count
; n
++ ) 
1720         const wxGridCellCoords
& coords 
= m_attrs
[n
].coords
; 
1721         if ( (coords
.GetRow() == row
) && (coords
.GetCol() == col
) ) 
1730 // ---------------------------------------------------------------------------- 
1731 // wxGridRowOrColAttrData 
1732 // ---------------------------------------------------------------------------- 
1734 wxGridRowOrColAttrData::~wxGridRowOrColAttrData() 
1736     size_t count 
= m_attrs
.Count(); 
1737     for ( size_t n 
= 0; n 
< count
; n
++ ) 
1739         m_attrs
[n
]->DecRef(); 
1743 wxGridCellAttr 
*wxGridRowOrColAttrData::GetAttr(int rowOrCol
) const 
1745     wxGridCellAttr 
*attr 
= (wxGridCellAttr 
*)NULL
; 
1747     int n 
= m_rowsOrCols
.Index(rowOrCol
); 
1748     if ( n 
!= wxNOT_FOUND 
) 
1750         attr 
= m_attrs
[(size_t)n
]; 
1757 void wxGridRowOrColAttrData::SetAttr(wxGridCellAttr 
*attr
, int rowOrCol
) 
1759     int n 
= m_rowsOrCols
.Index(rowOrCol
); 
1760     if ( n 
== wxNOT_FOUND 
) 
1762         // add the attribute 
1763         m_rowsOrCols
.Add(rowOrCol
); 
1770             // change the attribute 
1771             m_attrs
[(size_t)n
] = attr
; 
1775             // remove this attribute 
1776             m_attrs
[(size_t)n
]->DecRef(); 
1777             m_rowsOrCols
.RemoveAt((size_t)n
); 
1778             m_attrs
.RemoveAt((size_t)n
); 
1783 void wxGridRowOrColAttrData::UpdateAttrRowsOrCols( size_t pos
, int numRowsOrCols 
) 
1785     size_t count 
= m_attrs
.GetCount(); 
1786     for ( size_t n 
= 0; n 
< count
; n
++ ) 
1788         int & rowOrCol 
= m_rowsOrCols
[n
]; 
1789         if ( (size_t)rowOrCol 
>= pos 
) 
1791             if ( numRowsOrCols 
> 0 ) 
1793                 // If rows inserted, include row counter where necessary 
1794                 rowOrCol 
+= numRowsOrCols
; 
1796             else if ( numRowsOrCols 
< 0) 
1798                 // If rows deleted, either decrement row counter (if row still exists) 
1799                 if ((size_t)rowOrCol 
>= pos 
- numRowsOrCols
) 
1800                     rowOrCol 
+= numRowsOrCols
; 
1803                     m_rowsOrCols
.RemoveAt((size_t)n
); 
1804                     m_attrs
.RemoveAt((size_t)n
); 
1812 // ---------------------------------------------------------------------------- 
1813 // wxGridCellAttrProvider 
1814 // ---------------------------------------------------------------------------- 
1816 wxGridCellAttrProvider::wxGridCellAttrProvider() 
1818     m_data 
= (wxGridCellAttrProviderData 
*)NULL
; 
1821 wxGridCellAttrProvider::~wxGridCellAttrProvider() 
1826 void wxGridCellAttrProvider::InitData() 
1828     m_data 
= new wxGridCellAttrProviderData
; 
1831 wxGridCellAttr 
*wxGridCellAttrProvider::GetAttr(int row
, int col
) const 
1833     wxGridCellAttr 
*attr 
= (wxGridCellAttr 
*)NULL
; 
1836         // first look for the attribute of this specific cell 
1837         attr 
= m_data
->m_cellAttrs
.GetAttr(row
, col
); 
1841             // then look for the col attr (col attributes are more common than 
1842             // the row ones, hence they have priority) 
1843             attr 
= m_data
->m_colAttrs
.GetAttr(col
); 
1848             // finally try the row attributes 
1849             attr 
= m_data
->m_rowAttrs
.GetAttr(row
); 
1856 void wxGridCellAttrProvider::SetAttr(wxGridCellAttr 
*attr
, 
1862     m_data
->m_cellAttrs
.SetAttr(attr
, row
, col
); 
1865 void wxGridCellAttrProvider::SetRowAttr(wxGridCellAttr 
*attr
, int row
) 
1870     m_data
->m_rowAttrs
.SetAttr(attr
, row
); 
1873 void wxGridCellAttrProvider::SetColAttr(wxGridCellAttr 
*attr
, int col
) 
1878     m_data
->m_colAttrs
.SetAttr(attr
, col
); 
1881 void wxGridCellAttrProvider::UpdateAttrRows( size_t pos
, int numRows 
) 
1885         m_data
->m_cellAttrs
.UpdateAttrRows( pos
, numRows 
); 
1887         m_data
->m_rowAttrs
.UpdateAttrRowsOrCols( pos
, numRows 
); 
1891 void wxGridCellAttrProvider::UpdateAttrCols( size_t pos
, int numCols 
) 
1895         m_data
->m_cellAttrs
.UpdateAttrCols( pos
, numCols 
); 
1897         m_data
->m_colAttrs
.UpdateAttrRowsOrCols( pos
, numCols 
); 
1901 // ---------------------------------------------------------------------------- 
1902 // wxGridTypeRegistry 
1903 // ---------------------------------------------------------------------------- 
1905 wxGridTypeRegistry::~wxGridTypeRegistry() 
1907     size_t count 
= m_typeinfo
.Count(); 
1908     for ( size_t i 
= 0; i 
< count
; i
++ ) 
1909         delete m_typeinfo
[i
]; 
1913 void wxGridTypeRegistry::RegisterDataType(const wxString
& typeName
, 
1914                                           wxGridCellRenderer
* renderer
, 
1915                                           wxGridCellEditor
* editor
) 
1917     wxGridDataTypeInfo
* info 
= new wxGridDataTypeInfo(typeName
, renderer
, editor
); 
1919     // is it already registered? 
1920     int loc 
= FindDataType(typeName
); 
1921     if ( loc 
!= wxNOT_FOUND 
) 
1923         delete m_typeinfo
[loc
]; 
1924         m_typeinfo
[loc
] = info
; 
1928         m_typeinfo
.Add(info
); 
1932 int wxGridTypeRegistry::FindDataType(const wxString
& typeName
) 
1936     for (size_t i
=0; i
<m_typeinfo
.Count(); i
++) { 
1937         if (typeName 
== m_typeinfo
[i
]->m_typeName
) { 
1946 wxGridCellRenderer
* wxGridTypeRegistry::GetRenderer(int index
) 
1948     wxGridCellRenderer
* renderer 
= m_typeinfo
[index
]->m_renderer
; 
1953 wxGridCellEditor
* wxGridTypeRegistry::GetEditor(int index
) 
1955     wxGridCellEditor
* editor 
= m_typeinfo
[index
]->m_editor
; 
1960 // ---------------------------------------------------------------------------- 
1962 // ---------------------------------------------------------------------------- 
1964 IMPLEMENT_ABSTRACT_CLASS( wxGridTableBase
, wxObject 
) 
1967 wxGridTableBase::wxGridTableBase() 
1969     m_view 
= (wxGrid 
*) NULL
; 
1970     m_attrProvider 
= (wxGridCellAttrProvider 
*) NULL
; 
1973 wxGridTableBase::~wxGridTableBase() 
1975     delete m_attrProvider
; 
1978 void wxGridTableBase::SetAttrProvider(wxGridCellAttrProvider 
*attrProvider
) 
1980     delete m_attrProvider
; 
1981     m_attrProvider 
= attrProvider
; 
1984 bool wxGridTableBase::CanHaveAttributes() 
1986     if ( ! GetAttrProvider() ) 
1988         // use the default attr provider by default 
1989         SetAttrProvider(new wxGridCellAttrProvider
); 
1994 wxGridCellAttr 
*wxGridTableBase::GetAttr(int row
, int col
) 
1996     if ( m_attrProvider 
) 
1997         return m_attrProvider
->GetAttr(row
, col
); 
1999         return (wxGridCellAttr 
*)NULL
; 
2002 void wxGridTableBase::SetAttr(wxGridCellAttr
* attr
, int row
, int col
) 
2004     if ( m_attrProvider 
) 
2006         m_attrProvider
->SetAttr(attr
, row
, col
); 
2010         // as we take ownership of the pointer and don't store it, we must 
2016 void wxGridTableBase::SetRowAttr(wxGridCellAttr 
*attr
, int row
) 
2018     if ( m_attrProvider 
) 
2020         m_attrProvider
->SetRowAttr(attr
, row
); 
2024         // as we take ownership of the pointer and don't store it, we must 
2030 void wxGridTableBase::SetColAttr(wxGridCellAttr 
*attr
, int col
) 
2032     if ( m_attrProvider 
) 
2034         m_attrProvider
->SetColAttr(attr
, col
); 
2038         // as we take ownership of the pointer and don't store it, we must 
2044 void wxGridTableBase::UpdateAttrRows( size_t pos
, int numRows 
) 
2046     if ( m_attrProvider 
) 
2048         m_attrProvider
->UpdateAttrRows( pos
, numRows 
); 
2052 void wxGridTableBase::UpdateAttrCols( size_t pos
, int numCols 
) 
2054     if ( m_attrProvider 
) 
2056         m_attrProvider
->UpdateAttrCols( pos
, numCols 
); 
2060 bool wxGridTableBase::InsertRows( size_t pos
, size_t numRows 
) 
2062     wxFAIL_MSG( wxT("Called grid table class function InsertRows\n" 
2063                     "but your derived table class does not override this function") ); 
2068 bool wxGridTableBase::AppendRows( size_t numRows 
) 
2070     wxFAIL_MSG( wxT("Called grid table class function AppendRows\n" 
2071                     "but your derived table class does not override this function")); 
2076 bool wxGridTableBase::DeleteRows( size_t pos
, size_t numRows 
) 
2078     wxFAIL_MSG( wxT("Called grid table class function DeleteRows\n" 
2079                     "but your derived table class does not override this function")); 
2084 bool wxGridTableBase::InsertCols( size_t pos
, size_t numCols 
) 
2086     wxFAIL_MSG( wxT("Called grid table class function InsertCols\n" 
2087                   "but your derived table class does not override this function")); 
2092 bool wxGridTableBase::AppendCols( size_t numCols 
) 
2094     wxFAIL_MSG(wxT("Called grid table class function AppendCols\n" 
2095                    "but your derived table class does not override this function")); 
2100 bool wxGridTableBase::DeleteCols( size_t pos
, size_t numCols 
) 
2102     wxFAIL_MSG( wxT("Called grid table class function DeleteCols\n" 
2103                     "but your derived table class does not override this function")); 
2109 wxString 
wxGridTableBase::GetRowLabelValue( int row 
) 
2112     s 
<< row 
+ 1; // RD: Starting the rows at zero confuses users, no matter 
2113                   //     how much it makes sense to us geeks. 
2117 wxString 
wxGridTableBase::GetColLabelValue( int col 
) 
2119     // default col labels are: 
2120     //   cols 0 to 25   : A-Z 
2121     //   cols 26 to 675 : AA-ZZ 
2126     for ( n 
= 1; ; n
++ ) 
2128         s 
+= (_T('A') + (wxChar
)( col%26 
)); 
2130         if ( col 
< 0 ) break; 
2133     // reverse the string... 
2135     for ( i 
= 0;  i 
< n
;  i
++ ) 
2144 wxString 
wxGridTableBase::GetTypeName( int WXUNUSED(row
), int WXUNUSED(col
) ) 
2146     return wxGRID_VALUE_STRING
; 
2149 bool wxGridTableBase::CanGetValueAs( int WXUNUSED(row
), int WXUNUSED(col
), 
2150                                      const wxString
& typeName 
) 
2152     return typeName 
== wxGRID_VALUE_STRING
; 
2155 bool wxGridTableBase::CanSetValueAs( int row
, int col
, const wxString
& typeName 
) 
2157     return CanGetValueAs(row
, col
, typeName
); 
2160 long wxGridTableBase::GetValueAsLong( int WXUNUSED(row
), int WXUNUSED(col
) ) 
2165 double wxGridTableBase::GetValueAsDouble( int WXUNUSED(row
), int WXUNUSED(col
) ) 
2170 bool wxGridTableBase::GetValueAsBool( int WXUNUSED(row
), int WXUNUSED(col
) ) 
2175 void wxGridTableBase::SetValueAsLong( int WXUNUSED(row
), int WXUNUSED(col
), 
2176                                       long WXUNUSED(value
) ) 
2180 void wxGridTableBase::SetValueAsDouble( int WXUNUSED(row
), int WXUNUSED(col
), 
2181                                         double WXUNUSED(value
) ) 
2185 void wxGridTableBase::SetValueAsBool( int WXUNUSED(row
), int WXUNUSED(col
), 
2186                                       bool WXUNUSED(value
) ) 
2191 void* wxGridTableBase::GetValueAsCustom( int WXUNUSED(row
), int WXUNUSED(col
), 
2192                                          const wxString
& WXUNUSED(typeName
) ) 
2197 void  wxGridTableBase::SetValueAsCustom( int WXUNUSED(row
), int WXUNUSED(col
), 
2198                                          const wxString
& WXUNUSED(typeName
), 
2199                                          void* WXUNUSED(value
) ) 
2203 ////////////////////////////////////////////////////////////////////// 
2205 // Message class for the grid table to send requests and notifications 
2209 wxGridTableMessage::wxGridTableMessage() 
2211     m_table 
= (wxGridTableBase 
*) NULL
; 
2217 wxGridTableMessage::wxGridTableMessage( wxGridTableBase 
*table
, int id
, 
2218                                         int commandInt1
, int commandInt2 
) 
2222     m_comInt1 
= commandInt1
; 
2223     m_comInt2 
= commandInt2
; 
2228 ////////////////////////////////////////////////////////////////////// 
2230 // A basic grid table for string data. An object of this class will 
2231 // created by wxGrid if you don't specify an alternative table class. 
2234 WX_DEFINE_OBJARRAY(wxGridStringArray
) 
2236 IMPLEMENT_DYNAMIC_CLASS( wxGridStringTable
, wxGridTableBase 
) 
2238 wxGridStringTable::wxGridStringTable() 
2243 wxGridStringTable::wxGridStringTable( int numRows
, int numCols 
) 
2248     m_data
.Alloc( numRows 
); 
2251     sa
.Alloc( numCols 
); 
2252     for ( col 
= 0;  col 
< numCols
;  col
++ ) 
2254         sa
.Add( wxEmptyString 
); 
2257     for ( row 
= 0;  row 
< numRows
;  row
++ ) 
2263 wxGridStringTable::~wxGridStringTable() 
2267 long wxGridStringTable::GetNumberRows() 
2269     return m_data
.GetCount(); 
2272 long wxGridStringTable::GetNumberCols() 
2274     if ( m_data
.GetCount() > 0 ) 
2275         return m_data
[0].GetCount(); 
2280 wxString 
wxGridStringTable::GetValue( int row
, int col 
) 
2282     wxASSERT_MSG( (row 
< GetNumberCols()) && (col 
< GetNumberCols()), 
2283                   _T("invalid row or column index in wxGridStringTable") ); 
2285     return m_data
[row
][col
]; 
2288 void wxGridStringTable::SetValue( int row
, int col
, const wxString
& value 
) 
2290     wxASSERT_MSG( (row 
< GetNumberCols()) && (col 
< GetNumberCols()), 
2291                   _T("invalid row or column index in wxGridStringTable") ); 
2293     m_data
[row
][col
] = value
; 
2296 bool wxGridStringTable::IsEmptyCell( int row
, int col 
) 
2298     wxASSERT_MSG( (row 
< GetNumberCols()) && (col 
< GetNumberCols()), 
2299                   _T("invalid row or column index in wxGridStringTable") ); 
2301     return (m_data
[row
][col
] == wxEmptyString
); 
2304 void wxGridStringTable::Clear() 
2307     int numRows
, numCols
; 
2309     numRows 
= m_data
.GetCount(); 
2312         numCols 
= m_data
[0].GetCount(); 
2314         for ( row 
= 0;  row 
< numRows
;  row
++ ) 
2316             for ( col 
= 0;  col 
< numCols
;  col
++ ) 
2318                 m_data
[row
][col
] = wxEmptyString
; 
2325 bool wxGridStringTable::InsertRows( size_t pos
, size_t numRows 
) 
2329     size_t curNumRows 
= m_data
.GetCount(); 
2330     size_t curNumCols 
= ( curNumRows 
> 0 ? m_data
[0].GetCount() : 0 ); 
2332     if ( pos 
>= curNumRows 
) 
2334         return AppendRows( numRows 
); 
2338     sa
.Alloc( curNumCols 
); 
2339     for ( col 
= 0;  col 
< curNumCols
;  col
++ ) 
2341         sa
.Add( wxEmptyString 
); 
2344     for ( row 
= pos
;  row 
< pos 
+ numRows
;  row
++ ) 
2346         m_data
.Insert( sa
, row 
); 
2348     UpdateAttrRows( pos
, numRows 
); 
2351         wxGridTableMessage 
msg( this, 
2352                                 wxGRIDTABLE_NOTIFY_ROWS_INSERTED
, 
2356         GetView()->ProcessTableMessage( msg 
); 
2362 bool wxGridStringTable::AppendRows( size_t numRows 
) 
2366     size_t curNumRows 
= m_data
.GetCount(); 
2367     size_t curNumCols 
= ( curNumRows 
> 0 ? m_data
[0].GetCount() : 0 ); 
2370     if ( curNumCols 
> 0 ) 
2372         sa
.Alloc( curNumCols 
); 
2373         for ( col 
= 0;  col 
< curNumCols
;  col
++ ) 
2375             sa
.Add( wxEmptyString 
); 
2379     for ( row 
= 0;  row 
< numRows
;  row
++ ) 
2386         wxGridTableMessage 
msg( this, 
2387                                 wxGRIDTABLE_NOTIFY_ROWS_APPENDED
, 
2390         GetView()->ProcessTableMessage( msg 
); 
2396 bool wxGridStringTable::DeleteRows( size_t pos
, size_t numRows 
) 
2400     size_t curNumRows 
= m_data
.GetCount(); 
2402     if ( pos 
>= curNumRows 
) 
2405         errmsg
.Printf("Called wxGridStringTable::DeleteRows(pos=%d, N=%d)\n" 
2406                       "Pos value is invalid for present table with %d rows", 
2407                       pos
, numRows
, curNumRows 
); 
2408         wxFAIL_MSG( wxT(errmsg
) ); 
2412     if ( numRows 
> curNumRows 
- pos 
) 
2414         numRows 
= curNumRows 
- pos
; 
2417     if ( numRows 
>= curNumRows 
) 
2419         m_data
.Empty();  // don't release memory just yet 
2423         for ( n 
= 0;  n 
< numRows
;  n
++ ) 
2425             m_data
.Remove( pos 
); 
2428     UpdateAttrRows( pos
, -((int)numRows
) ); 
2431         wxGridTableMessage 
msg( this, 
2432                                 wxGRIDTABLE_NOTIFY_ROWS_DELETED
, 
2436         GetView()->ProcessTableMessage( msg 
); 
2442 bool wxGridStringTable::InsertCols( size_t pos
, size_t numCols 
) 
2446     size_t curNumRows 
= m_data
.GetCount(); 
2447     size_t curNumCols 
= ( curNumRows 
> 0 ? m_data
[0].GetCount() : 0 ); 
2449     if ( pos 
>= curNumCols 
) 
2451         return AppendCols( numCols 
); 
2454     for ( row 
= 0;  row 
< curNumRows
;  row
++ ) 
2456         for ( col 
= pos
;  col 
< pos 
+ numCols
;  col
++ ) 
2458             m_data
[row
].Insert( wxEmptyString
, col 
); 
2461     UpdateAttrCols( pos
, numCols 
); 
2464         wxGridTableMessage 
msg( this, 
2465                                 wxGRIDTABLE_NOTIFY_COLS_INSERTED
, 
2469         GetView()->ProcessTableMessage( msg 
); 
2475 bool wxGridStringTable::AppendCols( size_t numCols 
) 
2479     size_t curNumRows 
= m_data
.GetCount(); 
2482         // TODO: something better than this ? 
2484         wxFAIL_MSG( wxT("Unable to append cols to a grid table with no rows.\n" 
2485                         "Call AppendRows() first") ); 
2489     for ( row 
= 0;  row 
< curNumRows
;  row
++ ) 
2491         for ( n 
= 0;  n 
< numCols
;  n
++ ) 
2493             m_data
[row
].Add( wxEmptyString 
); 
2499         wxGridTableMessage 
msg( this, 
2500                                 wxGRIDTABLE_NOTIFY_COLS_APPENDED
, 
2503         GetView()->ProcessTableMessage( msg 
); 
2509 bool wxGridStringTable::DeleteCols( size_t pos
, size_t numCols 
) 
2513     size_t curNumRows 
= m_data
.GetCount(); 
2514     size_t curNumCols 
= ( curNumRows 
> 0 ? m_data
[0].GetCount() : 0 ); 
2516     if ( pos 
>= curNumCols 
) 
2519         errmsg
.Printf( "Called wxGridStringTable::DeleteCols(pos=%d, N=%d)...\n" 
2520                         "Pos value is invalid for present table with %d cols", 
2521                         pos
, numCols
, curNumCols 
); 
2522         wxFAIL_MSG( wxT( errmsg 
) ); 
2526     if ( numCols 
> curNumCols 
- pos 
) 
2528         numCols 
= curNumCols 
- pos
; 
2531     for ( row 
= 0;  row 
< curNumRows
;  row
++ ) 
2533         if ( numCols 
>= curNumCols 
) 
2535             m_data
[row
].Clear(); 
2539             for ( n 
= 0;  n 
< numCols
;  n
++ ) 
2541                 m_data
[row
].Remove( pos 
); 
2545     UpdateAttrCols( pos
, -((int)numCols
) ); 
2548         wxGridTableMessage 
msg( this, 
2549                                 wxGRIDTABLE_NOTIFY_COLS_DELETED
, 
2553         GetView()->ProcessTableMessage( msg 
); 
2559 wxString 
wxGridStringTable::GetRowLabelValue( int row 
) 
2561     if ( row 
> (int)(m_rowLabels
.GetCount()) - 1 ) 
2563         // using default label 
2565         return wxGridTableBase::GetRowLabelValue( row 
); 
2569         return m_rowLabels
[ row 
]; 
2573 wxString 
wxGridStringTable::GetColLabelValue( int col 
) 
2575     if ( col 
> (int)(m_colLabels
.GetCount()) - 1 ) 
2577         // using default label 
2579         return wxGridTableBase::GetColLabelValue( col 
); 
2583         return m_colLabels
[ col 
]; 
2587 void wxGridStringTable::SetRowLabelValue( int row
, const wxString
& value 
) 
2589     if ( row 
> (int)(m_rowLabels
.GetCount()) - 1 ) 
2591         int n 
= m_rowLabels
.GetCount(); 
2593         for ( i 
= n
;  i 
<= row
;  i
++ ) 
2595             m_rowLabels
.Add( wxGridTableBase::GetRowLabelValue(i
) ); 
2599     m_rowLabels
[row
] = value
; 
2602 void wxGridStringTable::SetColLabelValue( int col
, const wxString
& value 
) 
2604     if ( col 
> (int)(m_colLabels
.GetCount()) - 1 ) 
2606         int n 
= m_colLabels
.GetCount(); 
2608         for ( i 
= n
;  i 
<= col
;  i
++ ) 
2610             m_colLabels
.Add( wxGridTableBase::GetColLabelValue(i
) ); 
2614     m_colLabels
[col
] = value
; 
2619 ////////////////////////////////////////////////////////////////////// 
2620 ////////////////////////////////////////////////////////////////////// 
2622 IMPLEMENT_DYNAMIC_CLASS( wxGridRowLabelWindow
, wxWindow 
) 
2624 BEGIN_EVENT_TABLE( wxGridRowLabelWindow
, wxWindow 
) 
2625     EVT_PAINT( wxGridRowLabelWindow::OnPaint 
) 
2626     EVT_MOUSE_EVENTS( wxGridRowLabelWindow::OnMouseEvent 
) 
2627     EVT_KEY_DOWN( wxGridRowLabelWindow::OnKeyDown 
) 
2630 wxGridRowLabelWindow::wxGridRowLabelWindow( wxGrid 
*parent
, 
2632                                             const wxPoint 
&pos
, const wxSize 
&size 
) 
2633   : wxWindow( parent
, id
, pos
, size
, wxWANTS_CHARS 
) 
2638 void wxGridRowLabelWindow::OnPaint( wxPaintEvent 
&event 
) 
2642     // NO - don't do this because it will set both the x and y origin 
2643     // coords to match the parent scrolled window and we just want to 
2644     // set the y coord  - MB 
2646     // m_owner->PrepareDC( dc ); 
2649     m_owner
->CalcUnscrolledPosition( 0, 0, &x
, &y 
); 
2650     dc
.SetDeviceOrigin( 0, -y 
); 
2652     m_owner
->CalcRowLabelsExposed( GetUpdateRegion() ); 
2653     m_owner
->DrawRowLabels( dc 
); 
2657 void wxGridRowLabelWindow::OnMouseEvent( wxMouseEvent
& event 
) 
2659     m_owner
->ProcessRowLabelMouseEvent( event 
); 
2663 // This seems to be required for wxMotif otherwise the mouse 
2664 // cursor must be in the cell edit control to get key events 
2666 void wxGridRowLabelWindow::OnKeyDown( wxKeyEvent
& event 
) 
2668     if ( !m_owner
->ProcessEvent( event 
) ) event
.Skip(); 
2673 ////////////////////////////////////////////////////////////////////// 
2675 IMPLEMENT_DYNAMIC_CLASS( wxGridColLabelWindow
, wxWindow 
) 
2677 BEGIN_EVENT_TABLE( wxGridColLabelWindow
, wxWindow 
) 
2678     EVT_PAINT( wxGridColLabelWindow::OnPaint 
) 
2679     EVT_MOUSE_EVENTS( wxGridColLabelWindow::OnMouseEvent 
) 
2680     EVT_KEY_DOWN( wxGridColLabelWindow::OnKeyDown 
) 
2683 wxGridColLabelWindow::wxGridColLabelWindow( wxGrid 
*parent
, 
2685                                             const wxPoint 
&pos
, const wxSize 
&size 
) 
2686   : wxWindow( parent
, id
, pos
, size
, wxWANTS_CHARS 
) 
2691 void wxGridColLabelWindow::OnPaint( wxPaintEvent 
&event 
) 
2695     // NO - don't do this because it will set both the x and y origin 
2696     // coords to match the parent scrolled window and we just want to 
2697     // set the x coord  - MB 
2699     // m_owner->PrepareDC( dc ); 
2702     m_owner
->CalcUnscrolledPosition( 0, 0, &x
, &y 
); 
2703     dc
.SetDeviceOrigin( -x
, 0 ); 
2705     m_owner
->CalcColLabelsExposed( GetUpdateRegion() ); 
2706     m_owner
->DrawColLabels( dc 
); 
2710 void wxGridColLabelWindow::OnMouseEvent( wxMouseEvent
& event 
) 
2712     m_owner
->ProcessColLabelMouseEvent( event 
); 
2716 // This seems to be required for wxMotif otherwise the mouse 
2717 // cursor must be in the cell edit control to get key events 
2719 void wxGridColLabelWindow::OnKeyDown( wxKeyEvent
& event 
) 
2721     if ( !m_owner
->ProcessEvent( event 
) ) event
.Skip(); 
2726 ////////////////////////////////////////////////////////////////////// 
2728 IMPLEMENT_DYNAMIC_CLASS( wxGridCornerLabelWindow
, wxWindow 
) 
2730 BEGIN_EVENT_TABLE( wxGridCornerLabelWindow
, wxWindow 
) 
2731     EVT_MOUSE_EVENTS( wxGridCornerLabelWindow::OnMouseEvent 
) 
2732     EVT_PAINT( wxGridCornerLabelWindow::OnPaint
) 
2733     EVT_KEY_DOWN( wxGridCornerLabelWindow::OnKeyDown 
) 
2736 wxGridCornerLabelWindow::wxGridCornerLabelWindow( wxGrid 
*parent
, 
2738                                                   const wxPoint 
&pos
, const wxSize 
&size 
) 
2739   : wxWindow( parent
, id
, pos
, size
, wxWANTS_CHARS 
) 
2744 void wxGridCornerLabelWindow::OnPaint( wxPaintEvent
& WXUNUSED(event
) ) 
2748     int client_height 
= 0; 
2749     int client_width 
= 0; 
2750     GetClientSize( &client_width
, &client_height 
); 
2752     dc
.SetPen( *wxBLACK_PEN 
); 
2753     dc
.DrawLine( client_width
-1, client_height
-1, client_width
-1, 0 ); 
2754     dc
.DrawLine( client_width
-1, client_height
-1, 0, client_height
-1 ); 
2756     dc
.SetPen( *wxWHITE_PEN 
); 
2757     dc
.DrawLine( 0, 0, client_width
, 0 ); 
2758     dc
.DrawLine( 0, 0, 0, client_height 
); 
2762 void wxGridCornerLabelWindow::OnMouseEvent( wxMouseEvent
& event 
) 
2764     m_owner
->ProcessCornerLabelMouseEvent( event 
); 
2768 // This seems to be required for wxMotif otherwise the mouse 
2769 // cursor must be in the cell edit control to get key events 
2771 void wxGridCornerLabelWindow::OnKeyDown( wxKeyEvent
& event 
) 
2773     if ( !m_owner
->ProcessEvent( event 
) ) event
.Skip(); 
2778 ////////////////////////////////////////////////////////////////////// 
2780 IMPLEMENT_DYNAMIC_CLASS( wxGridWindow
, wxPanel 
) 
2782 BEGIN_EVENT_TABLE( wxGridWindow
, wxPanel 
) 
2783     EVT_PAINT( wxGridWindow::OnPaint 
) 
2784     EVT_MOUSE_EVENTS( wxGridWindow::OnMouseEvent 
) 
2785     EVT_KEY_DOWN( wxGridWindow::OnKeyDown 
) 
2786     EVT_ERASE_BACKGROUND( wxGridWindow::OnEraseBackground 
) 
2789 wxGridWindow::wxGridWindow( wxGrid 
*parent
, 
2790                             wxGridRowLabelWindow 
*rowLblWin
, 
2791                             wxGridColLabelWindow 
*colLblWin
, 
2792                             wxWindowID id
, const wxPoint 
&pos
, const wxSize 
&size 
) 
2793         : wxPanel( parent
, id
, pos
, size
, wxWANTS_CHARS
, "grid window" ) 
2796     m_rowLabelWin 
= rowLblWin
; 
2797     m_colLabelWin 
= colLblWin
; 
2798     SetBackgroundColour( "WHITE" ); 
2802 wxGridWindow::~wxGridWindow() 
2807 void wxGridWindow::OnPaint( wxPaintEvent 
&WXUNUSED(event
) ) 
2809     wxPaintDC 
dc( this ); 
2810     m_owner
->PrepareDC( dc 
); 
2811     wxRegion reg 
= GetUpdateRegion(); 
2812     m_owner
->CalcCellsExposed( reg 
); 
2813     m_owner
->DrawGridCellArea( dc 
); 
2814 #if WXGRID_DRAW_LINES 
2815     m_owner
->DrawAllGridLines( dc
, reg 
); 
2817     m_owner
->DrawGridSpace( dc 
); 
2818     m_owner
->DrawHighlight( dc 
); 
2822 void wxGridWindow::ScrollWindow( int dx
, int dy
, const wxRect 
*rect 
) 
2824     wxPanel::ScrollWindow( dx
, dy
, rect 
); 
2825     m_rowLabelWin
->ScrollWindow( 0, dy
, rect 
); 
2826     m_colLabelWin
->ScrollWindow( dx
, 0, rect 
); 
2830 void wxGridWindow::OnMouseEvent( wxMouseEvent
& event 
) 
2832     m_owner
->ProcessGridCellMouseEvent( event 
); 
2836 // This seems to be required for wxMotif otherwise the mouse 
2837 // cursor must be in the cell edit control to get key events 
2839 void wxGridWindow::OnKeyDown( wxKeyEvent
& event 
) 
2841     if ( !m_owner
->ProcessEvent( event 
) ) event
.Skip(); 
2845 void wxGridWindow::OnEraseBackground(wxEraseEvent
& event
) 
2850 ////////////////////////////////////////////////////////////////////// 
2853 IMPLEMENT_DYNAMIC_CLASS( wxGrid
, wxScrolledWindow 
) 
2855 BEGIN_EVENT_TABLE( wxGrid
, wxScrolledWindow 
) 
2856     EVT_PAINT( wxGrid::OnPaint 
) 
2857     EVT_SIZE( wxGrid::OnSize 
) 
2858     EVT_KEY_DOWN( wxGrid::OnKeyDown 
) 
2859     EVT_ERASE_BACKGROUND( wxGrid::OnEraseBackground 
) 
2862 wxGrid::wxGrid( wxWindow 
*parent
, 
2867                  const wxString
& name 
) 
2868   : wxScrolledWindow( parent
, id
, pos
, size
, (style 
| wxWANTS_CHARS
), name 
), 
2869     m_colMinWidths(GRID_HASH_SIZE
), 
2870     m_rowMinHeights(GRID_HASH_SIZE
) 
2879     wxSafeDecRef(m_defaultCellAttr
); 
2881 #ifdef DEBUG_ATTR_CACHE 
2882     size_t total 
= gs_nAttrCacheHits 
+ gs_nAttrCacheMisses
; 
2883     wxPrintf(_T("wxGrid attribute cache statistics: " 
2884                 "total: %u, hits: %u (%u%%)\n"), 
2885              total
, gs_nAttrCacheHits
, 
2886              total 
? (gs_nAttrCacheHits
*100) / total 
: 0); 
2892     delete m_typeRegistry
; 
2897 // ----- internal init and update functions 
2900 void wxGrid::Create() 
2902     m_created 
= FALSE
;    // set to TRUE by CreateGrid 
2903     m_displayed 
= TRUE
; // FALSE;  // set to TRUE by OnPaint 
2905     m_table        
= (wxGridTableBase 
*) NULL
; 
2908     m_cellEditCtrlEnabled 
= FALSE
; 
2910     m_defaultCellAttr 
= new wxGridCellAttr
; 
2911     m_defaultCellAttr
->SetDefAttr(m_defaultCellAttr
); 
2913     // Set default cell attributes 
2914     m_defaultCellAttr
->SetFont(GetFont()); 
2915     m_defaultCellAttr
->SetAlignment(wxLEFT
, wxTOP
); 
2916     m_defaultCellAttr
->SetTextColour( 
2917         wxSystemSettings::GetSystemColour(wxSYS_COLOUR_WINDOWTEXT
)); 
2918     m_defaultCellAttr
->SetBackgroundColour( 
2919         wxSystemSettings::GetSystemColour(wxSYS_COLOUR_WINDOW
)); 
2920     m_defaultCellAttr
->SetRenderer(new wxGridCellStringRenderer
); 
2921     m_defaultCellAttr
->SetEditor(new wxGridCellTextEditor
); 
2926     m_currentCellCoords 
= wxGridNoCellCoords
; 
2928     m_rowLabelWidth 
= WXGRID_DEFAULT_ROW_LABEL_WIDTH
; 
2929     m_colLabelHeight 
= WXGRID_DEFAULT_COL_LABEL_HEIGHT
; 
2931     // data type registration: register all standard data types 
2932     // TODO: may be allow the app to selectively disable some of them? 
2933     m_typeRegistry 
= new wxGridTypeRegistry
; 
2934     RegisterDataType(wxGRID_VALUE_STRING
, 
2935                      new wxGridCellStringRenderer
, 
2936                      new wxGridCellTextEditor
); 
2937     RegisterDataType(wxGRID_VALUE_BOOL
, 
2938                      new wxGridCellBoolRenderer
, 
2939                      new wxGridCellBoolEditor
); 
2940     RegisterDataType(wxGRID_VALUE_NUMBER
, 
2941                      new wxGridCellNumberRenderer
, 
2942                      new wxGridCellNumberEditor
); 
2943     RegisterDataType(wxGRID_VALUE_FLOAT
, 
2944                      new wxGridCellFloatRenderer
, 
2945                      new wxGridCellFloatEditor
); 
2947     // subwindow components that make up the wxGrid 
2948     m_cornerLabelWin 
= new wxGridCornerLabelWindow( this, 
2953     m_rowLabelWin 
= new wxGridRowLabelWindow( this, 
2958     m_colLabelWin 
= new wxGridColLabelWindow( this, 
2963     m_gridWin 
= new wxGridWindow( this, 
2970     SetTargetWindow( m_gridWin 
); 
2974 bool wxGrid::CreateGrid( int numRows
, int numCols 
) 
2978         wxFAIL_MSG( wxT("wxGrid::CreateGrid or wxGrid::SetTable called more than once") ); 
2983         m_numRows 
= numRows
; 
2984         m_numCols 
= numCols
; 
2986         m_table 
= new wxGridStringTable( m_numRows
, m_numCols 
); 
2987         m_table
->SetView( this ); 
2996 bool wxGrid::SetTable( wxGridTableBase 
*table
, bool takeOwnership 
) 
3000         // RD: Actually, this should probably be allowed.  I think it would be 
3001         // nice to be able to switch multiple Tables in and out of a single 
3002         // View at runtime.  Is there anything in the implmentation that would 
3005         wxFAIL_MSG( wxT("wxGrid::CreateGrid or wxGrid::SetTable called more than once") ); 
3010         m_numRows 
= table
->GetNumberRows(); 
3011         m_numCols 
= table
->GetNumberCols(); 
3014         m_table
->SetView( this ); 
3027     if ( m_numRows 
<= 0 ) 
3028         m_numRows 
= WXGRID_DEFAULT_NUMBER_ROWS
; 
3030     if ( m_numCols 
<= 0 ) 
3031         m_numCols 
= WXGRID_DEFAULT_NUMBER_COLS
; 
3033     m_rowLabelWidth  
= WXGRID_DEFAULT_ROW_LABEL_WIDTH
; 
3034     m_colLabelHeight 
= WXGRID_DEFAULT_COL_LABEL_HEIGHT
; 
3036     if ( m_rowLabelWin 
) 
3038         m_labelBackgroundColour 
= m_rowLabelWin
->GetBackgroundColour(); 
3042         m_labelBackgroundColour 
= wxColour( _T("WHITE") ); 
3045     m_labelTextColour 
= wxColour( _T("BLACK") ); 
3048     m_attrCache
.row 
= -1; 
3050     // TODO: something better than this ? 
3052     m_labelFont 
= this->GetFont(); 
3053     m_labelFont
.SetWeight( m_labelFont
.GetWeight() + 2 ); 
3055     m_rowLabelHorizAlign 
= wxLEFT
; 
3056     m_rowLabelVertAlign  
= wxCENTRE
; 
3058     m_colLabelHorizAlign 
= wxCENTRE
; 
3059     m_colLabelVertAlign  
= wxTOP
; 
3061     m_defaultColWidth  
= WXGRID_DEFAULT_COL_WIDTH
; 
3062     m_defaultRowHeight 
= m_gridWin
->GetCharHeight(); 
3064 #if defined(__WXMOTIF__) || defined(__WXGTK__)  // see also text ctrl sizing in ShowCellEditControl() 
3065     m_defaultRowHeight 
+= 8; 
3067     m_defaultRowHeight 
+= 4; 
3070     m_gridLineColour 
= wxColour( 128, 128, 255 ); 
3071     m_gridLinesEnabled 
= TRUE
; 
3073     m_cursorMode  
= WXGRID_CURSOR_SELECT_CELL
; 
3074     m_winCapture 
= (wxWindow 
*)NULL
; 
3075     m_canDragRowSize 
= TRUE
; 
3076     m_canDragColSize 
= TRUE
; 
3077     m_canDragGridSize 
= TRUE
; 
3079     m_dragRowOrCol 
= -1; 
3080     m_isDragging 
= FALSE
; 
3081     m_startDragPos 
= wxDefaultPosition
; 
3083     m_waitForSlowClick 
= FALSE
; 
3085     m_rowResizeCursor 
= wxCursor( wxCURSOR_SIZENS 
); 
3086     m_colResizeCursor 
= wxCursor( wxCURSOR_SIZEWE 
); 
3088     m_currentCellCoords 
= wxGridNoCellCoords
; 
3090     m_selectedTopLeft 
= wxGridNoCellCoords
; 
3091     m_selectedBottomRight 
= wxGridNoCellCoords
; 
3092     m_selectionBackground 
= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_HIGHLIGHT
); 
3093     m_selectionForeground 
= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_HIGHLIGHTTEXT
); 
3095     m_editable 
= TRUE
;  // default for whole grid 
3097     m_inOnKeyDown 
= FALSE
; 
3106 // ---------------------------------------------------------------------------- 
3107 // the idea is to call these functions only when necessary because they create 
3108 // quite big arrays which eat memory mostly unnecessary - in particular, if 
3109 // default widths/heights are used for all rows/columns, we may not use these 
3112 // with some extra code, it should be possible to only store the 
3113 // widths/heights different from default ones but this will be done later... 
3114 // ---------------------------------------------------------------------------- 
3116 void wxGrid::InitRowHeights() 
3118     m_rowHeights
.Empty(); 
3119     m_rowBottoms
.Empty(); 
3121     m_rowHeights
.Alloc( m_numRows 
); 
3122     m_rowBottoms
.Alloc( m_numRows 
); 
3125     for ( int i 
= 0;  i 
< m_numRows
;  i
++ ) 
3127         m_rowHeights
.Add( m_defaultRowHeight 
); 
3128         rowBottom 
+= m_defaultRowHeight
; 
3129         m_rowBottoms
.Add( rowBottom 
); 
3133 void wxGrid::InitColWidths() 
3135     m_colWidths
.Empty(); 
3136     m_colRights
.Empty(); 
3138     m_colWidths
.Alloc( m_numCols 
); 
3139     m_colRights
.Alloc( m_numCols 
); 
3141     for ( int i 
= 0;  i 
< m_numCols
;  i
++ ) 
3143         m_colWidths
.Add( m_defaultColWidth 
); 
3144         colRight 
+= m_defaultColWidth
; 
3145         m_colRights
.Add( colRight 
); 
3149 int wxGrid::GetColWidth(int col
) const 
3151     return m_colWidths
.IsEmpty() ? m_defaultColWidth 
: m_colWidths
[col
]; 
3154 int wxGrid::GetColLeft(int col
) const 
3156     return m_colRights
.IsEmpty() ? col 
* m_defaultColWidth
 
3157                                  : m_colRights
[col
] - m_colWidths
[col
]; 
3160 int wxGrid::GetColRight(int col
) const 
3162     return m_colRights
.IsEmpty() ? (col 
+ 1) * m_defaultColWidth
 
3166 int wxGrid::GetRowHeight(int row
) const 
3168     return m_rowHeights
.IsEmpty() ? m_defaultRowHeight 
: m_rowHeights
[row
]; 
3171 int wxGrid::GetRowTop(int row
) const 
3173     return m_rowBottoms
.IsEmpty() ? row 
* m_defaultRowHeight
 
3174                                   : m_rowBottoms
[row
] - m_rowHeights
[row
]; 
3177 int wxGrid::GetRowBottom(int row
) const 
3179     return m_rowBottoms
.IsEmpty() ? (row 
+ 1) * m_defaultRowHeight
 
3180                                   : m_rowBottoms
[row
]; 
3183 void wxGrid::CalcDimensions() 
3186     GetClientSize( &cw
, &ch 
); 
3188     if ( m_numRows 
> 0  &&  m_numCols 
> 0 ) 
3190         int right 
= GetColRight( m_numCols
-1 ) + m_extraWidth
; 
3191         int bottom 
= GetRowBottom( m_numRows
-1 ) + m_extraHeight
; 
3193         // TODO: restore the scroll position that we had before sizing 
3196         GetViewStart( &x
, &y 
); 
3197         SetScrollbars( GRID_SCROLL_LINE
, GRID_SCROLL_LINE
, 
3198                        right
/GRID_SCROLL_LINE
, bottom
/GRID_SCROLL_LINE
, 
3204 void wxGrid::CalcWindowSizes() 
3207     GetClientSize( &cw
, &ch 
); 
3209     if ( m_cornerLabelWin
->IsShown() ) 
3210         m_cornerLabelWin
->SetSize( 0, 0, m_rowLabelWidth
, m_colLabelHeight 
); 
3212     if ( m_colLabelWin
->IsShown() ) 
3213         m_colLabelWin
->SetSize( m_rowLabelWidth
, 0, cw
-m_rowLabelWidth
, m_colLabelHeight
); 
3215     if ( m_rowLabelWin
->IsShown() ) 
3216         m_rowLabelWin
->SetSize( 0, m_colLabelHeight
, m_rowLabelWidth
, ch
-m_colLabelHeight
); 
3218     if ( m_gridWin
->IsShown() ) 
3219         m_gridWin
->SetSize( m_rowLabelWidth
, m_colLabelHeight
, cw
-m_rowLabelWidth
, ch
-m_colLabelHeight
); 
3223 // this is called when the grid table sends a message to say that it 
3224 // has been redimensioned 
3226 bool wxGrid::Redimension( wxGridTableMessage
& msg 
) 
3230     // if we were using the default widths/heights so far, we must change them 
3232     if ( m_colWidths
.IsEmpty() ) 
3237     if ( m_rowHeights
.IsEmpty() ) 
3242     switch ( msg
.GetId() ) 
3244         case wxGRIDTABLE_NOTIFY_ROWS_INSERTED
: 
3246             size_t pos 
= msg
.GetCommandInt(); 
3247             int numRows 
= msg
.GetCommandInt2(); 
3248             for ( i 
= 0;  i 
< numRows
;  i
++ ) 
3250                 m_rowHeights
.Insert( m_defaultRowHeight
, pos 
); 
3251                 m_rowBottoms
.Insert( 0, pos 
); 
3253             m_numRows 
+= numRows
; 
3256             if ( pos 
> 0 ) bottom 
= m_rowBottoms
[pos
-1]; 
3258             for ( i 
= pos
;  i 
< m_numRows
;  i
++ ) 
3260                 bottom 
+= m_rowHeights
[i
]; 
3261                 m_rowBottoms
[i
] = bottom
; 
3267         case wxGRIDTABLE_NOTIFY_ROWS_APPENDED
: 
3269             int numRows 
= msg
.GetCommandInt(); 
3270             for ( i 
= 0;  i 
< numRows
;  i
++ ) 
3272                 m_rowHeights
.Add( m_defaultRowHeight 
); 
3273                 m_rowBottoms
.Add( 0 ); 
3276             int oldNumRows 
= m_numRows
; 
3277             m_numRows 
+= numRows
; 
3280             if ( oldNumRows 
> 0 ) bottom 
= m_rowBottoms
[oldNumRows
-1]; 
3282             for ( i 
= oldNumRows
;  i 
< m_numRows
;  i
++ ) 
3284                 bottom 
+= m_rowHeights
[i
]; 
3285                 m_rowBottoms
[i
] = bottom
; 
3291         case wxGRIDTABLE_NOTIFY_ROWS_DELETED
: 
3293             size_t pos 
= msg
.GetCommandInt(); 
3294             int numRows 
= msg
.GetCommandInt2(); 
3295             for ( i 
= 0;  i 
< numRows
;  i
++ ) 
3297                 m_rowHeights
.Remove( pos 
); 
3298                 m_rowBottoms
.Remove( pos 
); 
3300             m_numRows 
-= numRows
; 
3305                 m_colWidths
.Clear(); 
3306                 m_colRights
.Clear(); 
3307                 m_currentCellCoords 
= wxGridNoCellCoords
; 
3311                 if ( m_currentCellCoords
.GetRow() >= m_numRows 
) 
3312                     m_currentCellCoords
.Set( 0, 0 ); 
3315                 for ( i 
= 0;  i 
< m_numRows
;  i
++ ) 
3317                     h 
+= m_rowHeights
[i
]; 
3318                     m_rowBottoms
[i
] = h
; 
3326         case wxGRIDTABLE_NOTIFY_COLS_INSERTED
: 
3328             size_t pos 
= msg
.GetCommandInt(); 
3329             int numCols 
= msg
.GetCommandInt2(); 
3330             for ( i 
= 0;  i 
< numCols
;  i
++ ) 
3332                 m_colWidths
.Insert( m_defaultColWidth
, pos 
); 
3333                 m_colRights
.Insert( 0, pos 
); 
3335             m_numCols 
+= numCols
; 
3338             if ( pos 
> 0 ) right 
= m_colRights
[pos
-1]; 
3340             for ( i 
= pos
;  i 
< m_numCols
;  i
++ ) 
3342                 right 
+= m_colWidths
[i
]; 
3343                 m_colRights
[i
] = right
; 
3349         case wxGRIDTABLE_NOTIFY_COLS_APPENDED
: 
3351             int numCols 
= msg
.GetCommandInt(); 
3352             for ( i 
= 0;  i 
< numCols
;  i
++ ) 
3354                 m_colWidths
.Add( m_defaultColWidth 
); 
3355                 m_colRights
.Add( 0 ); 
3358             int oldNumCols 
= m_numCols
; 
3359             m_numCols 
+= numCols
; 
3362             if ( oldNumCols 
> 0 ) right 
= m_colRights
[oldNumCols
-1]; 
3364             for ( i 
= oldNumCols
;  i 
< m_numCols
;  i
++ ) 
3366                 right 
+= m_colWidths
[i
]; 
3367                 m_colRights
[i
] = right
; 
3373         case wxGRIDTABLE_NOTIFY_COLS_DELETED
: 
3375             size_t pos 
= msg
.GetCommandInt(); 
3376             int numCols 
= msg
.GetCommandInt2(); 
3377             for ( i 
= 0;  i 
< numCols
;  i
++ ) 
3379                 m_colWidths
.Remove( pos 
); 
3380                 m_colRights
.Remove( pos 
); 
3382             m_numCols 
-= numCols
; 
3386 #if 0  // leave the row alone here so that AppendCols will work subsequently 
3388                 m_rowHeights
.Clear(); 
3389                 m_rowBottoms
.Clear(); 
3391                 m_currentCellCoords 
= wxGridNoCellCoords
; 
3395                 if ( m_currentCellCoords
.GetCol() >= m_numCols 
) 
3396                     m_currentCellCoords
.Set( 0, 0 ); 
3399                 for ( i 
= 0;  i 
< m_numCols
;  i
++ ) 
3401                     w 
+= m_colWidths
[i
]; 
3414 void wxGrid::CalcRowLabelsExposed( wxRegion
& reg 
) 
3416     wxRegionIterator 
iter( reg 
); 
3419     m_rowLabelsExposed
.Empty(); 
3426         // TODO: remove this when we can... 
3427         // There is a bug in wxMotif that gives garbage update 
3428         // rectangles if you jump-scroll a long way by clicking the 
3429         // scrollbar with middle button.  This is a work-around 
3431 #if defined(__WXMOTIF__) 
3433         m_gridWin
->GetClientSize( &cw
, &ch 
); 
3434         if ( r
.GetTop() > ch 
) r
.SetTop( 0 ); 
3435         r
.SetBottom( wxMin( r
.GetBottom(), ch 
) ); 
3438         // logical bounds of update region 
3441         CalcUnscrolledPosition( 0, r
.GetTop(), &dummy
, &top 
); 
3442         CalcUnscrolledPosition( 0, r
.GetBottom(), &dummy
, &bottom 
); 
3444         // find the row labels within these bounds 
3447         for ( row 
= 0;  row 
< m_numRows
;  row
++ ) 
3449             if ( GetRowBottom(row
) < top 
) 
3452             if ( GetRowTop(row
) > bottom 
) 
3455             m_rowLabelsExposed
.Add( row 
); 
3463 void wxGrid::CalcColLabelsExposed( wxRegion
& reg 
) 
3465     wxRegionIterator 
iter( reg 
); 
3468     m_colLabelsExposed
.Empty(); 
3475         // TODO: remove this when we can... 
3476         // There is a bug in wxMotif that gives garbage update 
3477         // rectangles if you jump-scroll a long way by clicking the 
3478         // scrollbar with middle button.  This is a work-around 
3480 #if defined(__WXMOTIF__) 
3482         m_gridWin
->GetClientSize( &cw
, &ch 
); 
3483         if ( r
.GetLeft() > cw 
) r
.SetLeft( 0 ); 
3484         r
.SetRight( wxMin( r
.GetRight(), cw 
) ); 
3487         // logical bounds of update region 
3490         CalcUnscrolledPosition( r
.GetLeft(), 0, &left
, &dummy 
); 
3491         CalcUnscrolledPosition( r
.GetRight(), 0, &right
, &dummy 
); 
3493         // find the cells within these bounds 
3496         for ( col 
= 0;  col 
< m_numCols
;  col
++ ) 
3498             if ( GetColRight(col
) < left 
) 
3501             if ( GetColLeft(col
) > right 
) 
3504             m_colLabelsExposed
.Add( col 
); 
3512 void wxGrid::CalcCellsExposed( wxRegion
& reg 
) 
3514     wxRegionIterator 
iter( reg 
); 
3517     m_cellsExposed
.Empty(); 
3518     m_rowsExposed
.Empty(); 
3519     m_colsExposed
.Empty(); 
3521     int left
, top
, right
, bottom
; 
3526         // TODO: remove this when we can... 
3527         // There is a bug in wxMotif that gives garbage update 
3528         // rectangles if you jump-scroll a long way by clicking the 
3529         // scrollbar with middle button.  This is a work-around 
3531 #if defined(__WXMOTIF__) 
3533         m_gridWin
->GetClientSize( &cw
, &ch 
); 
3534         if ( r
.GetTop() > ch 
) r
.SetTop( 0 ); 
3535         if ( r
.GetLeft() > cw 
) r
.SetLeft( 0 ); 
3536         r
.SetRight( wxMin( r
.GetRight(), cw 
) ); 
3537         r
.SetBottom( wxMin( r
.GetBottom(), ch 
) ); 
3540         // logical bounds of update region 
3542         CalcUnscrolledPosition( r
.GetLeft(), r
.GetTop(), &left
, &top 
); 
3543         CalcUnscrolledPosition( r
.GetRight(), r
.GetBottom(), &right
, &bottom 
); 
3545         // find the cells within these bounds 
3548         for ( row 
= 0;  row 
< m_numRows
;  row
++ ) 
3550             if ( GetRowBottom(row
) <= top 
) 
3553             if ( GetRowTop(row
) > bottom 
) 
3556             m_rowsExposed
.Add( row 
); 
3558             for ( col 
= 0;  col 
< m_numCols
;  col
++ ) 
3560                 if ( GetColRight(col
) <= left 
) 
3563                 if ( GetColLeft(col
) > right 
) 
3566                 if ( m_colsExposed
.Index( col 
) == wxNOT_FOUND 
) 
3567                     m_colsExposed
.Add( col 
); 
3568                 m_cellsExposed
.Add( wxGridCellCoords( row
, col 
) ); 
3577 void wxGrid::ProcessRowLabelMouseEvent( wxMouseEvent
& event 
) 
3580     wxPoint 
pos( event
.GetPosition() ); 
3581     CalcUnscrolledPosition( pos
.x
, pos
.y
, &x
, &y 
); 
3583     if ( event
.Dragging() ) 
3585         m_isDragging 
= TRUE
; 
3587         if ( event
.LeftIsDown() ) 
3589             switch( m_cursorMode 
) 
3591                 case WXGRID_CURSOR_RESIZE_ROW
: 
3593                     int cw
, ch
, left
, dummy
; 
3594                     m_gridWin
->GetClientSize( &cw
, &ch 
); 
3595                     CalcUnscrolledPosition( 0, 0, &left
, &dummy 
); 
3597                     wxClientDC 
dc( m_gridWin 
); 
3600                                GetRowTop(m_dragRowOrCol
) + 
3601                                GetRowMinimalHeight(m_dragRowOrCol
) ); 
3602                     dc
.SetLogicalFunction(wxINVERT
); 
3603                     if ( m_dragLastPos 
>= 0 ) 
3605                         dc
.DrawLine( left
, m_dragLastPos
, left
+cw
, m_dragLastPos 
); 
3607                     dc
.DrawLine( left
, y
, left
+cw
, y 
); 
3612                 case WXGRID_CURSOR_SELECT_ROW
: 
3613                     if ( (row 
= YToRow( y 
)) >= 0  && 
3614                          !IsInSelection( row
, 0 ) ) 
3616                         SelectRow( row
, TRUE 
); 
3619                 // default label to suppress warnings about "enumeration value 
3620                 // 'xxx' not handled in switch 
3628     m_isDragging 
= FALSE
; 
3631     // ------------ Entering or leaving the window 
3633     if ( event
.Entering() || event
.Leaving() ) 
3635         ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
, m_rowLabelWin
); 
3639     // ------------ Left button pressed 
3641     else if ( event
.LeftDown() ) 
3643         // don't send a label click event for a hit on the 
3644         // edge of the row label - this is probably the user 
3645         // wanting to resize the row 
3647         if ( YToEdgeOfRow(y
) < 0 ) 
3651                  !SendEvent( wxEVT_GRID_LABEL_LEFT_CLICK
, row
, -1, event 
) ) 
3653                 SelectRow( row
, event
.ShiftDown() ); 
3654                 ChangeCursorMode(WXGRID_CURSOR_SELECT_ROW
, m_rowLabelWin
); 
3659             // starting to drag-resize a row 
3661             if ( CanDragRowSize() ) 
3662                 ChangeCursorMode(WXGRID_CURSOR_RESIZE_ROW
, m_rowLabelWin
); 
3667     // ------------ Left double click 
3669     else if (event
.LeftDClick() ) 
3671         if ( YToEdgeOfRow(y
) < 0 ) 
3674             SendEvent( wxEVT_GRID_LABEL_LEFT_DCLICK
, row
, -1, event 
); 
3679     // ------------ Left button released 
3681     else if ( event
.LeftUp() ) 
3683         if ( m_cursorMode 
== WXGRID_CURSOR_RESIZE_ROW 
) 
3685             DoEndDragResizeRow(); 
3687             // Note: we are ending the event *after* doing 
3688             // default processing in this case 
3690             SendEvent( wxEVT_GRID_ROW_SIZE
, m_dragRowOrCol
, -1, event 
); 
3693         ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
, m_rowLabelWin
); 
3698     // ------------ Right button down 
3700     else if ( event
.RightDown() ) 
3703         if ( !SendEvent( wxEVT_GRID_LABEL_RIGHT_CLICK
, row
, -1, event 
) ) 
3705             // no default action at the moment 
3710     // ------------ Right double click 
3712     else if ( event
.RightDClick() ) 
3715         if ( !SendEvent( wxEVT_GRID_LABEL_RIGHT_DCLICK
, row
, -1, event 
) ) 
3717             // no default action at the moment 
3722     // ------------ No buttons down and mouse moving 
3724     else if ( event
.Moving() ) 
3726         m_dragRowOrCol 
= YToEdgeOfRow( y 
); 
3727         if ( m_dragRowOrCol 
>= 0 ) 
3729             if ( m_cursorMode 
== WXGRID_CURSOR_SELECT_CELL 
) 
3731                 // don't capture the mouse yet 
3732                 if ( CanDragRowSize() ) 
3733                     ChangeCursorMode(WXGRID_CURSOR_RESIZE_ROW
, m_rowLabelWin
, FALSE
); 
3736         else if ( m_cursorMode 
!= WXGRID_CURSOR_SELECT_CELL 
) 
3738             ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
, m_rowLabelWin
, FALSE
); 
3744 void wxGrid::ProcessColLabelMouseEvent( wxMouseEvent
& event 
) 
3747     wxPoint 
pos( event
.GetPosition() ); 
3748     CalcUnscrolledPosition( pos
.x
, pos
.y
, &x
, &y 
); 
3750     if ( event
.Dragging() ) 
3752         m_isDragging 
= TRUE
; 
3754         if ( event
.LeftIsDown() ) 
3756             switch( m_cursorMode 
) 
3758                 case WXGRID_CURSOR_RESIZE_COL
: 
3760                     int cw
, ch
, dummy
, top
; 
3761                     m_gridWin
->GetClientSize( &cw
, &ch 
); 
3762                     CalcUnscrolledPosition( 0, 0, &dummy
, &top 
); 
3764                     wxClientDC 
dc( m_gridWin 
); 
3767                     x 
= wxMax( x
, GetColLeft(m_dragRowOrCol
) + 
3768                                   GetColMinimalWidth(m_dragRowOrCol
)); 
3769                     dc
.SetLogicalFunction(wxINVERT
); 
3770                     if ( m_dragLastPos 
>= 0 ) 
3772                         dc
.DrawLine( m_dragLastPos
, top
, m_dragLastPos
, top
+ch 
); 
3774                     dc
.DrawLine( x
, top
, x
, top
+ch 
); 
3779                 case WXGRID_CURSOR_SELECT_COL
: 
3780                     if ( (col 
= XToCol( x 
)) >= 0  && 
3781                          !IsInSelection( 0, col 
) ) 
3783                         SelectCol( col
, TRUE 
); 
3786                 // default label to suppress warnings about "enumeration value 
3787                 // 'xxx' not handled in switch 
3795     m_isDragging 
= FALSE
; 
3798     // ------------ Entering or leaving the window 
3800     if ( event
.Entering() || event
.Leaving() ) 
3802         ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
, m_colLabelWin
); 
3806     // ------------ Left button pressed 
3808     else if ( event
.LeftDown() ) 
3810         // don't send a label click event for a hit on the 
3811         // edge of the col label - this is probably the user 
3812         // wanting to resize the col 
3814         if ( XToEdgeOfCol(x
) < 0 ) 
3818                  !SendEvent( wxEVT_GRID_LABEL_LEFT_CLICK
, -1, col
, event 
) ) 
3820                 SelectCol( col
, event
.ShiftDown() ); 
3821                 ChangeCursorMode(WXGRID_CURSOR_SELECT_COL
, m_colLabelWin
); 
3826             // starting to drag-resize a col 
3828             if ( CanDragColSize() ) 
3829                 ChangeCursorMode(WXGRID_CURSOR_RESIZE_COL
, m_colLabelWin
); 
3834     // ------------ Left double click 
3836     if ( event
.LeftDClick() ) 
3838         if ( XToEdgeOfCol(x
) < 0 ) 
3841             SendEvent( wxEVT_GRID_LABEL_LEFT_DCLICK
, -1, col
, event 
); 
3846     // ------------ Left button released 
3848     else if ( event
.LeftUp() ) 
3850         if ( m_cursorMode 
== WXGRID_CURSOR_RESIZE_COL 
) 
3852             DoEndDragResizeCol(); 
3854             // Note: we are ending the event *after* doing 
3855             // default processing in this case 
3857             SendEvent( wxEVT_GRID_COL_SIZE
, -1, m_dragRowOrCol
, event 
); 
3860         ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
, m_colLabelWin
); 
3865     // ------------ Right button down 
3867     else if ( event
.RightDown() ) 
3870         if ( !SendEvent( wxEVT_GRID_LABEL_RIGHT_CLICK
, -1, col
, event 
) ) 
3872             // no default action at the moment 
3877     // ------------ Right double click 
3879     else if ( event
.RightDClick() ) 
3882         if ( !SendEvent( wxEVT_GRID_LABEL_RIGHT_DCLICK
, -1, col
, event 
) ) 
3884             // no default action at the moment 
3889     // ------------ No buttons down and mouse moving 
3891     else if ( event
.Moving() ) 
3893         m_dragRowOrCol 
= XToEdgeOfCol( x 
); 
3894         if ( m_dragRowOrCol 
>= 0 ) 
3896             if ( m_cursorMode 
== WXGRID_CURSOR_SELECT_CELL 
) 
3898                 // don't capture the cursor yet 
3899                 if ( CanDragColSize() ) 
3900                     ChangeCursorMode(WXGRID_CURSOR_RESIZE_COL
, m_colLabelWin
, FALSE
); 
3903         else if ( m_cursorMode 
!= WXGRID_CURSOR_SELECT_CELL 
) 
3905             ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
, m_colLabelWin
, FALSE
); 
3911 void wxGrid::ProcessCornerLabelMouseEvent( wxMouseEvent
& event 
) 
3913     if ( event
.LeftDown() ) 
3915         // indicate corner label by having both row and 
3918         if ( !SendEvent( wxEVT_GRID_LABEL_LEFT_CLICK
, -1, -1, event 
) ) 
3924     else if ( event
.LeftDClick() ) 
3926         SendEvent( wxEVT_GRID_LABEL_LEFT_DCLICK
, -1, -1, event 
); 
3929     else if ( event
.RightDown() ) 
3931         if ( !SendEvent( wxEVT_GRID_LABEL_RIGHT_CLICK
, -1, -1, event 
) ) 
3933             // no default action at the moment 
3937     else if ( event
.RightDClick() ) 
3939         if ( !SendEvent( wxEVT_GRID_LABEL_RIGHT_DCLICK
, -1, -1, event 
) ) 
3941             // no default action at the moment 
3946 void wxGrid::ChangeCursorMode(CursorMode mode
, 
3951     static const wxChar 
*cursorModes
[] = 
3960     wxLogTrace(_T("grid"), 
3961                _T("wxGrid cursor mode (mouse capture for %s): %s -> %s"), 
3962                win 
== m_colLabelWin 
? _T("colLabelWin") 
3963                                     : win 
? _T("rowLabelWin") 
3965                cursorModes
[m_cursorMode
], cursorModes
[mode
]); 
3966 #endif // __WXDEBUG__ 
3968     if ( mode 
== m_cursorMode 
) 
3973         // by default use the grid itself 
3979         m_winCapture
->ReleaseMouse(); 
3980         m_winCapture 
= (wxWindow 
*)NULL
; 
3983     m_cursorMode 
= mode
; 
3985     switch ( m_cursorMode 
) 
3987         case WXGRID_CURSOR_RESIZE_ROW
: 
3988             win
->SetCursor( m_rowResizeCursor 
); 
3991         case WXGRID_CURSOR_RESIZE_COL
: 
3992             win
->SetCursor( m_colResizeCursor 
); 
3996             win
->SetCursor( *wxSTANDARD_CURSOR 
); 
3999     // we need to capture mouse when resizing 
4000     bool resize 
= m_cursorMode 
== WXGRID_CURSOR_RESIZE_ROW 
|| 
4001                   m_cursorMode 
== WXGRID_CURSOR_RESIZE_COL
; 
4003     if ( captureMouse 
&& resize 
) 
4005         win
->CaptureMouse(); 
4010 void wxGrid::ProcessGridCellMouseEvent( wxMouseEvent
& event 
) 
4013     wxPoint 
pos( event
.GetPosition() ); 
4014     CalcUnscrolledPosition( pos
.x
, pos
.y
, &x
, &y 
); 
4016     wxGridCellCoords coords
; 
4017     XYToCell( x
, y
, coords 
); 
4019     if ( event
.Dragging() ) 
4021         //wxLogDebug("pos(%d, %d) coords(%d, %d)", pos.x, pos.y, coords.GetRow(), coords.GetCol()); 
4023         // Don't start doing anything until the mouse has been drug at 
4024         // least 3 pixels in any direction... 
4027             if (m_startDragPos 
== wxDefaultPosition
) 
4029                 m_startDragPos 
= pos
; 
4032             if (abs(m_startDragPos
.x 
- pos
.x
) < 4 && abs(m_startDragPos
.y 
- pos
.y
) < 4) 
4036         m_isDragging 
= TRUE
; 
4037         if ( m_cursorMode 
== WXGRID_CURSOR_SELECT_CELL 
) 
4039             // Hide the edit control, so it 
4040             // won't interfer with drag-shrinking. 
4041             if ( IsCellEditControlEnabled() ) 
4043                 HideCellEditControl(); 
4044                 SaveEditControlValue(); 
4047             // Have we captured the mouse yet? 
4050                 m_winCapture 
= m_gridWin
; 
4051                 m_winCapture
->CaptureMouse(); 
4054             if ( coords 
!= wxGridNoCellCoords 
) 
4056                 if ( !IsSelection() ) 
4058                     SelectBlock( coords
, coords 
); 
4062                     SelectBlock( m_currentCellCoords
, coords 
); 
4065                 if (! IsVisible(coords
)) 
4067                     MakeCellVisible(coords
); 
4068                     // TODO: need to introduce a delay or something here.  The 
4069                     // scrolling is way to fast, at least on MSW. 
4073         else if ( m_cursorMode 
== WXGRID_CURSOR_RESIZE_ROW 
) 
4075             int cw
, ch
, left
, dummy
; 
4076             m_gridWin
->GetClientSize( &cw
, &ch 
); 
4077             CalcUnscrolledPosition( 0, 0, &left
, &dummy 
); 
4079             wxClientDC 
dc( m_gridWin 
); 
4081             y 
= wxMax( y
, GetRowTop(m_dragRowOrCol
) + WXGRID_MIN_ROW_HEIGHT 
); 
4082             dc
.SetLogicalFunction(wxINVERT
); 
4083             if ( m_dragLastPos 
>= 0 ) 
4085                 dc
.DrawLine( left
, m_dragLastPos
, left
+cw
, m_dragLastPos 
); 
4087             dc
.DrawLine( left
, y
, left
+cw
, y 
); 
4090         else if ( m_cursorMode 
== WXGRID_CURSOR_RESIZE_COL 
) 
4092             int cw
, ch
, dummy
, top
; 
4093             m_gridWin
->GetClientSize( &cw
, &ch 
); 
4094             CalcUnscrolledPosition( 0, 0, &dummy
, &top 
); 
4096             wxClientDC 
dc( m_gridWin 
); 
4098             x 
= wxMax( x
, GetColLeft(m_dragRowOrCol
) + 
4099                           GetColMinimalWidth(m_dragRowOrCol
) ); 
4100             dc
.SetLogicalFunction(wxINVERT
); 
4101             if ( m_dragLastPos 
>= 0 ) 
4103                 dc
.DrawLine( m_dragLastPos
, top
, m_dragLastPos
, top
+ch 
); 
4105             dc
.DrawLine( x
, top
, x
, top
+ch 
); 
4112     m_isDragging 
= FALSE
; 
4113     m_startDragPos 
= wxDefaultPosition
; 
4115     // VZ: if we do this, the mode is reset to WXGRID_CURSOR_SELECT_CELL 
4116     //     immediately after it becomes WXGRID_CURSOR_RESIZE_ROW/COL under 
4119     if ( event
.Entering() || event
.Leaving() ) 
4121         ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
); 
4122         m_gridWin
->SetCursor( *wxSTANDARD_CURSOR 
); 
4127     // ------------ Left button pressed 
4129     if ( event
.LeftDown() && coords 
!= wxGridNoCellCoords 
) 
4131         if ( event
.ShiftDown() ) 
4133             SelectBlock( m_currentCellCoords
, coords 
); 
4135         else if ( XToEdgeOfCol(x
) < 0  && 
4136                   YToEdgeOfRow(y
) < 0 ) 
4138             if ( !SendEvent( wxEVT_GRID_CELL_LEFT_CLICK
, 
4143                 DisableCellEditControl(); 
4144                 MakeCellVisible( coords 
); 
4146                 // if this is the second click on this cell then start 
4148                 if ( m_waitForSlowClick 
&& 
4149                      (coords 
== m_currentCellCoords
) && 
4150                      CanEnableCellControl()) 
4152                     EnableCellEditControl(); 
4154                     wxGridCellAttr
* attr 
= GetCellAttr(m_currentCellCoords
); 
4155                     wxGridCellEditor 
*editor 
= attr
->GetEditor(this, 
4158                     editor
->StartingClick(); 
4162                     m_waitForSlowClick 
= FALSE
; 
4166                     SetCurrentCell( coords 
); 
4167                     m_waitForSlowClick 
= TRUE
; 
4174     // ------------ Left double click 
4176     else if ( event
.LeftDClick() && coords 
!= wxGridNoCellCoords 
) 
4178         DisableCellEditControl(); 
4180         if ( XToEdgeOfCol(x
) < 0  &&  YToEdgeOfRow(y
) < 0 ) 
4182             SendEvent( wxEVT_GRID_CELL_LEFT_DCLICK
, 
4190     // ------------ Left button released 
4192     else if ( event
.LeftUp() ) 
4194         if ( m_cursorMode 
== WXGRID_CURSOR_SELECT_CELL 
) 
4196             if ( IsSelection() ) 
4200                     m_winCapture
->ReleaseMouse(); 
4201                     m_winCapture 
= NULL
; 
4203                 SendEvent( wxEVT_GRID_RANGE_SELECT
, -1, -1, event 
); 
4206             // Show the edit control, if it has been hidden for 
4208             ShowCellEditControl(); 
4210         else if ( m_cursorMode 
== WXGRID_CURSOR_RESIZE_ROW 
) 
4212             ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
); 
4213             DoEndDragResizeRow(); 
4215             // Note: we are ending the event *after* doing 
4216             // default processing in this case 
4218             SendEvent( wxEVT_GRID_ROW_SIZE
, m_dragRowOrCol
, -1, event 
); 
4220         else if ( m_cursorMode 
== WXGRID_CURSOR_RESIZE_COL 
) 
4222             ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
); 
4223             DoEndDragResizeCol(); 
4225             // Note: we are ending the event *after* doing 
4226             // default processing in this case 
4228             SendEvent( wxEVT_GRID_COL_SIZE
, -1, m_dragRowOrCol
, event 
); 
4235     // ------------ Right button down 
4237     else if ( event
.RightDown() && coords 
!= wxGridNoCellCoords 
) 
4239         DisableCellEditControl(); 
4240         if ( !SendEvent( wxEVT_GRID_CELL_RIGHT_CLICK
, 
4245             // no default action at the moment 
4250     // ------------ Right double click 
4252     else if ( event
.RightDClick() && coords 
!= wxGridNoCellCoords 
) 
4254         DisableCellEditControl(); 
4255         if ( !SendEvent( wxEVT_GRID_CELL_RIGHT_DCLICK
, 
4260             // no default action at the moment 
4264     // ------------ Moving and no button action 
4266     else if ( event
.Moving() && !event
.IsButton() ) 
4268         int dragRow 
= YToEdgeOfRow( y 
); 
4269         int dragCol 
= XToEdgeOfCol( x 
); 
4271         // Dragging on the corner of a cell to resize in both 
4272         // directions is not implemented yet... 
4274         if ( dragRow 
>= 0  &&  dragCol 
>= 0 ) 
4276             ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
); 
4282             m_dragRowOrCol 
= dragRow
; 
4284             if ( m_cursorMode 
== WXGRID_CURSOR_SELECT_CELL 
) 
4286                 if ( CanDragRowSize() && CanDragGridSize() ) 
4287                     ChangeCursorMode(WXGRID_CURSOR_RESIZE_ROW
); 
4292                 m_dragRowOrCol 
= dragCol
; 
4300             m_dragRowOrCol 
= dragCol
; 
4302             if ( m_cursorMode 
== WXGRID_CURSOR_SELECT_CELL 
) 
4304                 if ( CanDragColSize() && CanDragGridSize() ) 
4305                     ChangeCursorMode(WXGRID_CURSOR_RESIZE_COL
); 
4311         // Neither on a row or col edge 
4313         if ( m_cursorMode 
!= WXGRID_CURSOR_SELECT_CELL 
) 
4315             ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
); 
4321 void wxGrid::DoEndDragResizeRow() 
4323     if ( m_dragLastPos 
>= 0 ) 
4325         // erase the last line and resize the row 
4327         int cw
, ch
, left
, dummy
; 
4328         m_gridWin
->GetClientSize( &cw
, &ch 
); 
4329         CalcUnscrolledPosition( 0, 0, &left
, &dummy 
); 
4331         wxClientDC 
dc( m_gridWin 
); 
4333         dc
.SetLogicalFunction( wxINVERT 
); 
4334         dc
.DrawLine( left
, m_dragLastPos
, left
+cw
, m_dragLastPos 
); 
4335         HideCellEditControl(); 
4336         SaveEditControlValue(); 
4338         int rowTop 
= GetRowTop(m_dragRowOrCol
); 
4339         SetRowSize( m_dragRowOrCol
, 
4340                     wxMax( m_dragLastPos 
- rowTop
, WXGRID_MIN_ROW_HEIGHT 
) ); 
4342         if ( !GetBatchCount() ) 
4344             // Only needed to get the correct rect.y: 
4345             wxRect 
rect ( CellToRect( m_dragRowOrCol
, 0 ) ); 
4347             CalcScrolledPosition(0, rect
.y
, &dummy
, &rect
.y
); 
4348             rect
.width 
= m_rowLabelWidth
; 
4349             rect
.height 
= ch 
- rect
.y
; 
4350             m_rowLabelWin
->Refresh( TRUE
, &rect 
); 
4352             m_gridWin
->Refresh( FALSE
, &rect 
); 
4355         ShowCellEditControl(); 
4360 void wxGrid::DoEndDragResizeCol() 
4362     if ( m_dragLastPos 
>= 0 ) 
4364         // erase the last line and resize the col 
4366         int cw
, ch
, dummy
, top
; 
4367         m_gridWin
->GetClientSize( &cw
, &ch 
); 
4368         CalcUnscrolledPosition( 0, 0, &dummy
, &top 
); 
4370         wxClientDC 
dc( m_gridWin 
); 
4372         dc
.SetLogicalFunction( wxINVERT 
); 
4373         dc
.DrawLine( m_dragLastPos
, top
, m_dragLastPos
, top
+ch 
); 
4374         HideCellEditControl(); 
4375         SaveEditControlValue(); 
4377         int colLeft 
= GetColLeft(m_dragRowOrCol
); 
4378         SetColSize( m_dragRowOrCol
, 
4379                     wxMax( m_dragLastPos 
- colLeft
, 
4380                            GetColMinimalWidth(m_dragRowOrCol
) ) ); 
4382         if ( !GetBatchCount() ) 
4384             // Only needed to get the correct rect.x: 
4385             wxRect 
rect ( CellToRect( 0, m_dragRowOrCol 
) ); 
4387             CalcScrolledPosition(rect
.x
, 0, &rect
.x
, &dummy
); 
4388             rect
.width 
= cw 
- rect
.x
; 
4389             rect
.height 
= m_colLabelHeight
; 
4390             m_colLabelWin
->Refresh( TRUE
, &rect 
); 
4392             m_gridWin
->Refresh( FALSE
, &rect 
); 
4395         ShowCellEditControl(); 
4402 // ------ interaction with data model 
4404 bool wxGrid::ProcessTableMessage( wxGridTableMessage
& msg 
) 
4406     switch ( msg
.GetId() ) 
4408         case wxGRIDTABLE_REQUEST_VIEW_GET_VALUES
: 
4409             return GetModelValues(); 
4411         case wxGRIDTABLE_REQUEST_VIEW_SEND_VALUES
: 
4412             return SetModelValues(); 
4414         case wxGRIDTABLE_NOTIFY_ROWS_INSERTED
: 
4415         case wxGRIDTABLE_NOTIFY_ROWS_APPENDED
: 
4416         case wxGRIDTABLE_NOTIFY_ROWS_DELETED
: 
4417         case wxGRIDTABLE_NOTIFY_COLS_INSERTED
: 
4418         case wxGRIDTABLE_NOTIFY_COLS_APPENDED
: 
4419         case wxGRIDTABLE_NOTIFY_COLS_DELETED
: 
4420             return Redimension( msg 
); 
4429 // The behaviour of this function depends on the grid table class 
4430 // Clear() function.  For the default wxGridStringTable class the 
4431 // behavious is to replace all cell contents with wxEmptyString but 
4432 // not to change the number of rows or cols. 
4434 void wxGrid::ClearGrid() 
4438         if (IsCellEditControlEnabled()) 
4439             DisableCellEditControl(); 
4442         if ( !GetBatchCount() ) m_gridWin
->Refresh(); 
4447 bool wxGrid::InsertRows( int pos
, int numRows
, bool WXUNUSED(updateLabels
) ) 
4449     // TODO: something with updateLabels flag 
4453         wxFAIL_MSG( wxT("Called wxGrid::InsertRows() before calling CreateGrid()") ); 
4459         if (IsCellEditControlEnabled()) 
4460             DisableCellEditControl(); 
4462         bool ok 
= m_table
->InsertRows( pos
, numRows 
); 
4464         // the table will have sent the results of the insert row 
4465         // operation to this view object as a grid table message 
4469             if ( m_numCols 
== 0 ) 
4471                 m_table
->AppendCols( WXGRID_DEFAULT_NUMBER_COLS 
); 
4473                 // TODO: perhaps instead of appending the default number of cols 
4474                 // we should remember what the last non-zero number of cols was ? 
4478             if ( m_currentCellCoords 
== wxGridNoCellCoords 
) 
4480                 // if we have just inserted cols into an empty grid the current 
4481                 // cell will be undefined... 
4483                 SetCurrentCell( 0, 0 ); 
4487             if ( !GetBatchCount() ) Refresh(); 
4499 bool wxGrid::AppendRows( int numRows
, bool WXUNUSED(updateLabels
) ) 
4501     // TODO: something with updateLabels flag 
4505         wxFAIL_MSG( wxT("Called wxGrid::AppendRows() before calling CreateGrid()") ); 
4509     if ( m_table 
&& m_table
->AppendRows( numRows 
) ) 
4511         if ( m_currentCellCoords 
== wxGridNoCellCoords 
) 
4513             // if we have just inserted cols into an empty grid the current 
4514             // cell will be undefined... 
4516             SetCurrentCell( 0, 0 ); 
4519         // the table will have sent the results of the append row 
4520         // operation to this view object as a grid table message 
4523         if ( !GetBatchCount() ) Refresh(); 
4533 bool wxGrid::DeleteRows( int pos
, int numRows
, bool WXUNUSED(updateLabels
) ) 
4535     // TODO: something with updateLabels flag 
4539         wxFAIL_MSG( wxT("Called wxGrid::DeleteRows() before calling CreateGrid()") ); 
4545         if (IsCellEditControlEnabled()) 
4546             DisableCellEditControl(); 
4548         if (m_table
->DeleteRows( pos
, numRows 
)) 
4551             // the table will have sent the results of the delete row 
4552             // operation to this view object as a grid table message 
4555             if ( !GetBatchCount() ) Refresh(); 
4563 bool wxGrid::InsertCols( int pos
, int numCols
, bool WXUNUSED(updateLabels
) ) 
4565     // TODO: something with updateLabels flag 
4569         wxFAIL_MSG( wxT("Called wxGrid::InsertCols() before calling CreateGrid()") ); 
4575         if (IsCellEditControlEnabled()) 
4576             DisableCellEditControl(); 
4578         bool ok 
= m_table
->InsertCols( pos
, numCols 
); 
4580         // the table will have sent the results of the insert col 
4581         // operation to this view object as a grid table message 
4585             if ( m_currentCellCoords 
== wxGridNoCellCoords 
) 
4587                 // if we have just inserted cols into an empty grid the current 
4588                 // cell will be undefined... 
4590                 SetCurrentCell( 0, 0 ); 
4594             if ( !GetBatchCount() ) Refresh(); 
4606 bool wxGrid::AppendCols( int numCols
, bool WXUNUSED(updateLabels
) ) 
4608     // TODO: something with updateLabels flag 
4612         wxFAIL_MSG( wxT("Called wxGrid::AppendCols() before calling CreateGrid()") ); 
4616     if ( m_table 
&& m_table
->AppendCols( numCols 
) ) 
4618         // the table will have sent the results of the append col 
4619         // operation to this view object as a grid table message 
4621         if ( m_currentCellCoords 
== wxGridNoCellCoords 
) 
4623             // if we have just inserted cols into an empty grid the current 
4624             // cell will be undefined... 
4626             SetCurrentCell( 0, 0 ); 
4630         if ( !GetBatchCount() ) Refresh(); 
4640 bool wxGrid::DeleteCols( int pos
, int numCols
, bool WXUNUSED(updateLabels
) ) 
4642     // TODO: something with updateLabels flag 
4646         wxFAIL_MSG( wxT("Called wxGrid::DeleteCols() before calling CreateGrid()") ); 
4652         if (IsCellEditControlEnabled()) 
4653             DisableCellEditControl(); 
4655         if ( m_table
->DeleteCols( pos
, numCols 
) ) 
4657             // the table will have sent the results of the delete col 
4658             // operation to this view object as a grid table message 
4661             if ( !GetBatchCount() ) Refresh(); 
4671 // ----- event handlers 
4674 // Generate a grid event based on a mouse event and 
4675 // return the result of ProcessEvent() 
4677 bool wxGrid::SendEvent( const wxEventType type
, 
4679                         wxMouseEvent
& mouseEv 
) 
4681     if ( type 
== wxEVT_GRID_ROW_SIZE 
|| type 
== wxEVT_GRID_COL_SIZE 
) 
4683         int rowOrCol 
= (row 
== -1 ? col 
: row
); 
4685         wxGridSizeEvent 
gridEvt( GetId(), 
4689                                  mouseEv
.GetX(), mouseEv
.GetY(), 
4690                                  mouseEv
.ControlDown(), 
4691                                  mouseEv
.ShiftDown(), 
4693                                  mouseEv
.MetaDown() ); 
4695         return GetEventHandler()->ProcessEvent(gridEvt
); 
4697     else if ( type 
== wxEVT_GRID_RANGE_SELECT 
) 
4699         wxGridRangeSelectEvent 
gridEvt( GetId(), 
4703                                         m_selectedBottomRight
, 
4704                                         mouseEv
.ControlDown(), 
4705                                         mouseEv
.ShiftDown(), 
4707                                         mouseEv
.MetaDown() ); 
4709         return GetEventHandler()->ProcessEvent(gridEvt
); 
4713         wxGridEvent 
gridEvt( GetId(), 
4717                              mouseEv
.GetX(), mouseEv
.GetY(), 
4718                              mouseEv
.ControlDown(), 
4719                              mouseEv
.ShiftDown(), 
4721                              mouseEv
.MetaDown() ); 
4723         return GetEventHandler()->ProcessEvent(gridEvt
); 
4728 // Generate a grid event of specified type and return the result 
4729 // of ProcessEvent(). 
4731 bool wxGrid::SendEvent( const wxEventType type
, 
4734     if ( type 
== wxEVT_GRID_ROW_SIZE 
|| type 
== wxEVT_GRID_COL_SIZE 
) 
4736         int rowOrCol 
= (row 
== -1 ? col 
: row
); 
4738         wxGridSizeEvent 
gridEvt( GetId(), 
4743         return GetEventHandler()->ProcessEvent(gridEvt
); 
4747         wxGridEvent 
gridEvt( GetId(), 
4752         return GetEventHandler()->ProcessEvent(gridEvt
); 
4757 void wxGrid::OnPaint( wxPaintEvent
& WXUNUSED(event
) ) 
4759     wxPaintDC 
dc( this ); 
4761     if ( m_currentCellCoords 
== wxGridNoCellCoords  
&& 
4762          m_numRows 
&& m_numCols 
) 
4764         m_currentCellCoords
.Set(0, 0); 
4765         ShowCellEditControl(); 
4772 // This is just here to make sure that CalcDimensions gets called when 
4773 // the grid view is resized... then the size event is skipped to allow 
4774 // the box sizers to handle everything 
4776 void wxGrid::OnSize( wxSizeEvent
& event 
) 
4783 void wxGrid::OnKeyDown( wxKeyEvent
& event 
) 
4785     if ( m_inOnKeyDown 
) 
4787         // shouldn't be here - we are going round in circles... 
4789         wxFAIL_MSG( wxT("wxGrid::OnKeyDown called while already active") ); 
4792     m_inOnKeyDown 
= TRUE
; 
4794     // propagate the event up and see if it gets processed 
4796     wxWindow 
*parent 
= GetParent(); 
4797     wxKeyEvent 
keyEvt( event 
); 
4798     keyEvt
.SetEventObject( parent 
); 
4800     if ( !parent
->GetEventHandler()->ProcessEvent( keyEvt 
) ) 
4803         // TODO:  Should also support Shift-cursor keys for 
4804         //        extending the selection.  Maybe add a flag to 
4805         //        MoveCursorXXX() and MoveCursorXXXBlock() and 
4806         //        just send event.ShiftDown(). 
4808         // try local handlers 
4810         switch ( event
.KeyCode() ) 
4813                 if ( event
.ControlDown() ) 
4815                     MoveCursorUpBlock(); 
4824                 if ( event
.ControlDown() ) 
4826                     MoveCursorDownBlock(); 
4835                 if ( event
.ControlDown() ) 
4837                     MoveCursorLeftBlock(); 
4846                 if ( event
.ControlDown() ) 
4848                     MoveCursorRightBlock(); 
4857                 if ( event
.ControlDown() ) 
4859                     event
.Skip();  // to let the edit control have the return 
4868                 if (event
.ShiftDown()) 
4875                 if ( event
.ControlDown() ) 
4877                     MakeCellVisible( 0, 0 ); 
4878                     SetCurrentCell( 0, 0 ); 
4887                 if ( event
.ControlDown() ) 
4889                     MakeCellVisible( m_numRows
-1, m_numCols
-1 ); 
4890                     SetCurrentCell( m_numRows
-1, m_numCols
-1 ); 
4907                 if ( !IsEditable() ) 
4912                 // Otherwise fall through to default 
4915                 // alphanumeric keys or F2 (special key just for this) enable 
4916                 // the cell edit control 
4917                 if ( !(event
.AltDown() || 
4919                        event
.ControlDown()) && 
4920                      (isalnum(event
.KeyCode()) || event
.KeyCode() == WXK_F2
) && 
4921                      !IsCellEditControlEnabled() && 
4922                      CanEnableCellControl() ) 
4924                     EnableCellEditControl(); 
4925                     int row 
= m_currentCellCoords
.GetRow(); 
4926                     int col 
= m_currentCellCoords
.GetCol(); 
4927                     wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
4928                     wxGridCellEditor 
*editor 
= attr
->GetEditor(this, row
, col
); 
4929                     editor
->StartingKey(event
); 
4935                     // let others process char events with modifiers or all 
4936                     // char events for readonly cells 
4943     m_inOnKeyDown 
= FALSE
; 
4947 void wxGrid::OnEraseBackground(wxEraseEvent
&) 
4951 void wxGrid::SetCurrentCell( const wxGridCellCoords
& coords 
) 
4953     if ( SendEvent( wxEVT_GRID_SELECT_CELL
, coords
.GetRow(), coords
.GetCol() ) ) 
4955         // the event has been intercepted - do nothing 
4960          m_currentCellCoords 
!= wxGridNoCellCoords 
) 
4962         HideCellEditControl(); 
4963         DisableCellEditControl(); 
4965         // Clear the old current cell highlight 
4966         wxRect r 
= BlockToDeviceRect(m_currentCellCoords
, m_currentCellCoords
); 
4968         // Otherwise refresh redraws the highlight! 
4969         m_currentCellCoords 
= coords
; 
4971         m_gridWin
->Refresh( FALSE
, &r 
); 
4974     m_currentCellCoords 
= coords
; 
4978         wxClientDC 
dc(m_gridWin
); 
4981         wxGridCellAttr
* attr 
= GetCellAttr(coords
); 
4982         DrawCellHighlight(dc
, attr
); 
4985         if ( IsSelection() ) 
4987             wxRect 
r( SelectionToDeviceRect() ); 
4989             if ( !GetBatchCount() ) m_gridWin
->Refresh( FALSE
, &r 
); 
4996 // ------ functions to get/send data (see also public functions) 
4999 bool wxGrid::GetModelValues() 
5003         // all we need to do is repaint the grid 
5005         m_gridWin
->Refresh(); 
5013 bool wxGrid::SetModelValues() 
5019         for ( row 
= 0;  row 
< m_numRows
;  row
++ ) 
5021             for ( col 
= 0;  col 
< m_numCols
;  col
++ ) 
5023                 m_table
->SetValue( row
, col
, GetCellValue(row
, col
) ); 
5035 // Note - this function only draws cells that are in the list of 
5036 // exposed cells (usually set from the update region by 
5037 // CalcExposedCells) 
5039 void wxGrid::DrawGridCellArea( wxDC
& dc 
) 
5041     if ( !m_numRows 
|| !m_numCols 
) return; 
5044     size_t numCells 
= m_cellsExposed
.GetCount(); 
5046     for ( i 
= 0;  i 
< numCells
;  i
++ ) 
5048         DrawCell( dc
, m_cellsExposed
[i
] ); 
5053 void wxGrid::DrawGridSpace( wxDC
& dc 
) 
5055     if ( m_numRows  
&&  m_numCols 
) 
5058         m_gridWin
->GetClientSize( &cw
, &ch 
); 
5061         CalcUnscrolledPosition( cw
, ch
, &right
, &bottom 
); 
5063         if ( right 
> GetColRight(m_numCols
-1)  || 
5064              bottom 
> GetRowBottom(m_numRows
-1) ) 
5067             CalcUnscrolledPosition( 0, 0, &left
, &top 
); 
5069             dc
.SetBrush( wxBrush(GetDefaultCellBackgroundColour(), wxSOLID
) ); 
5070             dc
.SetPen( *wxTRANSPARENT_PEN 
); 
5072             if ( right 
> GetColRight(m_numCols
-1) ) 
5073                 dc
.DrawRectangle( GetColRight(m_numCols
-1), top
, 
5074                                   right 
- GetColRight(m_numCols
-1), ch 
); 
5076             if ( bottom 
> GetRowBottom(m_numRows
-1) ) 
5077                 dc
.DrawRectangle( left
, GetRowBottom(m_numRows
-1), 
5078                                   cw
, bottom 
- GetRowBottom(m_numRows
-1) ); 
5084 void wxGrid::DrawCell( wxDC
& dc
, const wxGridCellCoords
& coords 
) 
5086     int row 
= coords
.GetRow(); 
5087     int col 
= coords
.GetCol(); 
5089     if ( GetColWidth(col
) <= 0 || GetRowHeight(row
) <= 0 ) 
5092     // we draw the cell border ourselves 
5093 #if !WXGRID_DRAW_LINES 
5094     if ( m_gridLinesEnabled 
) 
5095         DrawCellBorder( dc
, coords 
); 
5098     wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
5100     bool isCurrent 
= coords 
== m_currentCellCoords
; 
5103     rect
.x 
= GetColLeft(col
); 
5104     rect
.y 
= GetRowTop(row
); 
5105     rect
.width 
= GetColWidth(col
) - 1; 
5106     rect
.height 
= GetRowHeight(row
) - 1; 
5108     // if the editor is shown, we should use it and not the renderer 
5109     if ( isCurrent 
&& IsCellEditControlEnabled() ) 
5111         wxGridCellEditor 
*editor 
= attr
->GetEditor(this, row
, col
); 
5112         editor
->PaintBackground(rect
, attr
); 
5117         // but all the rest is drawn by the cell renderer and hence may be 
5119         wxGridCellRenderer 
*renderer 
= attr
->GetRenderer(this, row
, col
); 
5120         renderer
->Draw(*this, *attr
, dc
, rect
, row
, col
, IsInSelection(coords
)); 
5127 void wxGrid::DrawCellHighlight( wxDC
& dc
, const wxGridCellAttr 
*attr 
) 
5129     int row 
= m_currentCellCoords
.GetRow(); 
5130     int col 
= m_currentCellCoords
.GetCol(); 
5132     if ( GetColWidth(col
) <= 0 || GetRowHeight(row
) <= 0 ) 
5136     rect
.x 
= GetColLeft(col
); 
5137     rect
.y 
= GetRowTop(row
); 
5138     rect
.width 
= GetColWidth(col
) - 1; 
5139     rect
.height 
= GetRowHeight(row
) - 1; 
5141     // hmmm... what could we do here to show that the cell is disabled? 
5142     // for now, I just draw a thinner border than for the other ones, but 
5143     // it doesn't look really good 
5144     dc
.SetPen(wxPen(m_gridLineColour
, attr
->IsReadOnly() ? 1 : 3, wxSOLID
)); 
5145     dc
.SetBrush(*wxTRANSPARENT_BRUSH
); 
5147     dc
.DrawRectangle(rect
); 
5150         // VZ: my experiments with 3d borders... 
5152         // how to properly set colours for arbitrary bg? 
5153         wxCoord x1 
= rect
.x
, 
5155                 x2 
= rect
.x 
+ rect
.width 
-1, 
5156                 y2 
= rect
.y 
+ rect
.height 
-1; 
5158         dc
.SetPen(*wxWHITE_PEN
); 
5159         dc
.DrawLine(x1
, y1
, x2
, y1
); 
5160         dc
.DrawLine(x1
, y1
, x1
, y2
); 
5162         dc
.DrawLine(x1 
+ 1, y2 
- 1, x2 
- 1, y2 
- 1); 
5163         dc
.DrawLine(x2 
- 1, y1 
+ 1, x2 
- 1, y2 
); 
5165         dc
.SetPen(*wxBLACK_PEN
); 
5166         dc
.DrawLine(x1
, y2
, x2
, y2
); 
5167         dc
.DrawLine(x2
, y1
, x2
, y2
+1); 
5172 void wxGrid::DrawCellBorder( wxDC
& dc
, const wxGridCellCoords
& coords 
) 
5174     int row 
= coords
.GetRow(); 
5175     int col 
= coords
.GetCol(); 
5176     if ( GetColWidth(col
) <= 0 || GetRowHeight(row
) <= 0 ) 
5179     dc
.SetPen( wxPen(GetGridLineColour(), 1, wxSOLID
) ); 
5181     // right hand border 
5183     dc
.DrawLine( GetColRight(col
), GetRowTop(row
), 
5184                  GetColRight(col
), GetRowBottom(row
) ); 
5188     dc
.DrawLine( GetColLeft(col
), GetRowBottom(row
), 
5189                  GetColRight(col
), GetRowBottom(row
) ); 
5192 void wxGrid::DrawHighlight(wxDC
& dc
) 
5194     if ( IsCellEditControlEnabled() ) 
5196         // don't show highlight when the edit control is shown 
5200     // if the active cell was repainted, repaint its highlight too because it 
5201     // might have been damaged by the grid lines 
5202     size_t count 
= m_cellsExposed
.GetCount(); 
5203     for ( size_t n 
= 0; n 
< count
; n
++ ) 
5205         if ( m_cellsExposed
[n
] == m_currentCellCoords 
) 
5207             wxGridCellAttr
* attr 
= GetCellAttr(m_currentCellCoords
); 
5208             DrawCellHighlight(dc
, attr
); 
5216 // TODO: remove this ??? 
5217 // This is used to redraw all grid lines e.g. when the grid line colour 
5220 void wxGrid::DrawAllGridLines( wxDC
& dc
, const wxRegion 
& reg 
) 
5222     if ( !m_gridLinesEnabled 
|| 
5224          !m_numCols 
) return; 
5226     int top
, bottom
, left
, right
; 
5232       m_gridWin
->GetClientSize(&cw
, &ch
); 
5234       // virtual coords of visible area 
5236       CalcUnscrolledPosition( 0, 0, &left
, &top 
); 
5237       CalcUnscrolledPosition( cw
, ch
, &right
, &bottom 
); 
5242       reg
.GetBox(x
, y
, w
, h
); 
5243       CalcUnscrolledPosition( x
, y
, &left
, &top 
); 
5244       CalcUnscrolledPosition( x 
+ w
, y 
+ h
, &right
, &bottom 
); 
5248       m_gridWin
->GetClientSize(&cw
, &ch
); 
5249       CalcUnscrolledPosition( 0, 0, &left
, &top 
); 
5250       CalcUnscrolledPosition( cw
, ch
, &right
, &bottom 
); 
5253     // avoid drawing grid lines past the last row and col 
5255     right 
= wxMin( right
, GetColRight(m_numCols 
- 1) ); 
5256     bottom 
= wxMin( bottom
, GetRowBottom(m_numRows 
- 1) ); 
5258     dc
.SetPen( wxPen(GetGridLineColour(), 1, wxSOLID
) ); 
5260     // horizontal grid lines 
5263     for ( i 
= 0; i 
< m_numRows
; i
++ ) 
5265         int bot 
= GetRowBottom(i
) - 1; 
5274             dc
.DrawLine( left
, bot
, right
, bot 
); 
5279     // vertical grid lines 
5281     for ( i 
= 0; i 
< m_numCols
; i
++ ) 
5283         int colRight 
= GetColRight(i
) - 1; 
5284         if ( colRight 
> right 
) 
5289         if ( colRight 
>= left 
) 
5291             dc
.DrawLine( colRight
, top
, colRight
, bottom 
); 
5297 void wxGrid::DrawRowLabels( wxDC
& dc 
) 
5299     if ( !m_numRows 
|| !m_numCols 
) return; 
5302     size_t numLabels 
= m_rowLabelsExposed
.GetCount(); 
5304     for ( i 
= 0;  i 
< numLabels
;  i
++ ) 
5306         DrawRowLabel( dc
, m_rowLabelsExposed
[i
] ); 
5311 void wxGrid::DrawRowLabel( wxDC
& dc
, int row 
) 
5313     if ( GetRowHeight(row
) <= 0 ) 
5316     int rowTop 
= GetRowTop(row
), 
5317         rowBottom 
= GetRowBottom(row
) - 1; 
5319     dc
.SetPen( *wxBLACK_PEN 
); 
5320     dc
.DrawLine( m_rowLabelWidth
-1, rowTop
, 
5321                  m_rowLabelWidth
-1, rowBottom 
); 
5323     dc
.DrawLine( 0, rowBottom
, m_rowLabelWidth
-1, rowBottom 
); 
5325     dc
.SetPen( *wxWHITE_PEN 
); 
5326     dc
.DrawLine( 0, rowTop
, 0, rowBottom 
); 
5327     dc
.DrawLine( 0, rowTop
, m_rowLabelWidth
-1, rowTop 
); 
5329     dc
.SetBackgroundMode( wxTRANSPARENT 
); 
5330     dc
.SetTextForeground( GetLabelTextColour() ); 
5331     dc
.SetFont( GetLabelFont() ); 
5334     GetRowLabelAlignment( &hAlign
, &vAlign 
); 
5338     rect
.SetY( GetRowTop(row
) + 2 ); 
5339     rect
.SetWidth( m_rowLabelWidth 
- 4 ); 
5340     rect
.SetHeight( GetRowHeight(row
) - 4 ); 
5341     DrawTextRectangle( dc
, GetRowLabelValue( row 
), rect
, hAlign
, vAlign 
); 
5345 void wxGrid::DrawColLabels( wxDC
& dc 
) 
5347     if ( !m_numRows 
|| !m_numCols 
) return; 
5350     size_t numLabels 
= m_colLabelsExposed
.GetCount(); 
5352     for ( i 
= 0;  i 
< numLabels
;  i
++ ) 
5354         DrawColLabel( dc
, m_colLabelsExposed
[i
] ); 
5359 void wxGrid::DrawColLabel( wxDC
& dc
, int col 
) 
5361     if ( GetColWidth(col
) <= 0 ) 
5364     int colLeft 
= GetColLeft(col
), 
5365         colRight 
= GetColRight(col
) - 1; 
5367     dc
.SetPen( *wxBLACK_PEN 
); 
5368     dc
.DrawLine( colRight
, 0, 
5369                  colRight
, m_colLabelHeight
-1 ); 
5371     dc
.DrawLine( colLeft
, m_colLabelHeight
-1, 
5372                  colRight
, m_colLabelHeight
-1 ); 
5374     dc
.SetPen( *wxWHITE_PEN 
); 
5375     dc
.DrawLine( colLeft
, 0, colLeft
, m_colLabelHeight
-1 ); 
5376     dc
.DrawLine( colLeft
, 0, colRight
, 0 ); 
5378     dc
.SetBackgroundMode( wxTRANSPARENT 
); 
5379     dc
.SetTextForeground( GetLabelTextColour() ); 
5380     dc
.SetFont( GetLabelFont() ); 
5382     dc
.SetBackgroundMode( wxTRANSPARENT 
); 
5383     dc
.SetTextForeground( GetLabelTextColour() ); 
5384     dc
.SetFont( GetLabelFont() ); 
5387     GetColLabelAlignment( &hAlign
, &vAlign 
); 
5390     rect
.SetX( colLeft 
+ 2 ); 
5392     rect
.SetWidth( GetColWidth(col
) - 4 ); 
5393     rect
.SetHeight( m_colLabelHeight 
- 4 ); 
5394     DrawTextRectangle( dc
, GetColLabelValue( col 
), rect
, hAlign
, vAlign 
); 
5398 void wxGrid::DrawTextRectangle( wxDC
& dc
, 
5399                                 const wxString
& value
, 
5404     long textWidth
, textHeight
; 
5405     long lineWidth
, lineHeight
; 
5406     wxArrayString lines
; 
5408     dc
.SetClippingRegion( rect 
); 
5409     StringToLines( value
, lines 
); 
5410     if ( lines
.GetCount() ) 
5412         GetTextBoxSize( dc
, lines
, &textWidth
, &textHeight 
); 
5413         dc
.GetTextExtent( lines
[0], &lineWidth
, &lineHeight 
); 
5416         switch ( horizAlign 
) 
5419                 x 
= rect
.x 
+ (rect
.width 
- textWidth 
- 1); 
5423                 x 
= rect
.x 
+ ((rect
.width 
- textWidth
)/2); 
5432         switch ( vertAlign 
) 
5435                 y 
= rect
.y 
+ (rect
.height 
- textHeight 
- 1); 
5439                 y 
= rect
.y 
+ ((rect
.height 
- textHeight
)/2); 
5448         for ( size_t i 
= 0;  i 
< lines
.GetCount();  i
++ ) 
5450             dc
.DrawText( lines
[i
], (long)x
, (long)y 
); 
5455     dc
.DestroyClippingRegion(); 
5459 // Split multi line text up into an array of strings.  Any existing 
5460 // contents of the string array are preserved. 
5462 void wxGrid::StringToLines( const wxString
& value
, wxArrayString
& lines 
) 
5466     wxString eol 
= wxTextFile::GetEOL( wxTextFileType_Unix 
); 
5467     wxString tVal 
= wxTextFile::Translate( value
, wxTextFileType_Unix 
); 
5469     while ( startPos 
< (int)tVal
.Length() ) 
5471         pos 
= tVal
.Mid(startPos
).Find( eol 
); 
5476         else if ( pos 
== 0 ) 
5478             lines
.Add( wxEmptyString 
); 
5482             lines
.Add( value
.Mid(startPos
, pos
) ); 
5486     if ( startPos 
< (int)value
.Length() ) 
5488         lines
.Add( value
.Mid( startPos 
) ); 
5493 void wxGrid::GetTextBoxSize( wxDC
& dc
, 
5494                              wxArrayString
& lines
, 
5495                              long *width
, long *height 
) 
5502     for ( i 
= 0;  i 
< lines
.GetCount();  i
++ ) 
5504         dc
.GetTextExtent( lines
[i
], &lineW
, &lineH 
); 
5505         w 
= wxMax( w
, lineW 
); 
5515 // ------ Edit control functions 
5519 void wxGrid::EnableEditing( bool edit 
) 
5521     // TODO: improve this ? 
5523     if ( edit 
!= m_editable 
) 
5527         // FIXME IMHO this won't disable the edit control if edit == FALSE 
5528         //       because of the check in the beginning of 
5529         //       EnableCellEditControl() just below (VZ) 
5530         EnableCellEditControl(m_editable
); 
5535 void wxGrid::EnableCellEditControl( bool enable 
) 
5540     if ( m_currentCellCoords 
== wxGridNoCellCoords 
) 
5541         SetCurrentCell( 0, 0 ); 
5543     if ( enable 
!= m_cellEditCtrlEnabled 
) 
5545         // TODO allow the app to Veto() this event? 
5546         SendEvent(enable 
? wxEVT_GRID_EDITOR_SHOWN 
: wxEVT_GRID_EDITOR_HIDDEN
); 
5550             // this should be checked by the caller! 
5551             wxASSERT_MSG( CanEnableCellControl(), 
5552                           _T("can't enable editing for this cell!") ); 
5554             // do it before ShowCellEditControl() 
5555             m_cellEditCtrlEnabled 
= enable
; 
5557             ShowCellEditControl(); 
5561             HideCellEditControl(); 
5562             SaveEditControlValue(); 
5564             // do it after HideCellEditControl() 
5565             m_cellEditCtrlEnabled 
= enable
; 
5570 bool wxGrid::IsCurrentCellReadOnly() const 
5573     wxGridCellAttr
* attr 
= ((wxGrid 
*)this)->GetCellAttr(m_currentCellCoords
); 
5574     bool readonly 
= attr
->IsReadOnly(); 
5580 bool wxGrid::CanEnableCellControl() const 
5582     return m_editable 
&& !IsCurrentCellReadOnly(); 
5585 bool wxGrid::IsCellEditControlEnabled() const 
5587     // the cell edit control might be disable for all cells or just for the 
5588     // current one if it's read only 
5589     return m_cellEditCtrlEnabled 
? !IsCurrentCellReadOnly() : FALSE
; 
5592 void wxGrid::ShowCellEditControl() 
5594     if ( IsCellEditControlEnabled() ) 
5596         if ( !IsVisible( m_currentCellCoords 
) ) 
5602             wxRect rect 
= CellToRect( m_currentCellCoords 
); 
5603             int row 
= m_currentCellCoords
.GetRow(); 
5604             int col 
= m_currentCellCoords
.GetCol(); 
5606             // convert to scrolled coords 
5608             CalcScrolledPosition( rect
.x
, rect
.y
, &rect
.x
, &rect
.y 
); 
5610             // done in PaintBackground() 
5612             // erase the highlight and the cell contents because the editor 
5613             // might not cover the entire cell 
5614             wxClientDC 
dc( m_gridWin 
); 
5616             dc
.SetBrush(*wxLIGHT_GREY_BRUSH
); //wxBrush(attr->GetBackgroundColour(), wxSOLID)); 
5617             dc
.SetPen(*wxTRANSPARENT_PEN
); 
5618             dc
.DrawRectangle(rect
); 
5621             // cell is shifted by one pixel 
5625             wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
5626             wxGridCellEditor
* editor 
= attr
->GetEditor(this, row
, col
); 
5627             if ( !editor
->IsCreated() ) 
5629                 editor
->Create(m_gridWin
, -1, 
5630                                new wxGridCellEditorEvtHandler(this, editor
)); 
5633             editor
->Show( TRUE
, attr 
); 
5635             editor
->SetSize( rect 
); 
5637             editor
->BeginEdit(row
, col
, this); 
5646 void wxGrid::HideCellEditControl() 
5648     if ( IsCellEditControlEnabled() ) 
5650         int row 
= m_currentCellCoords
.GetRow(); 
5651         int col 
= m_currentCellCoords
.GetCol(); 
5653         wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
5654         wxGridCellEditor 
*editor 
= attr
->GetEditor(this, row
, col
); 
5655         editor
->Show( FALSE 
); 
5658         m_gridWin
->SetFocus(); 
5663 void wxGrid::SaveEditControlValue() 
5665     if ( IsCellEditControlEnabled() ) 
5667         int row 
= m_currentCellCoords
.GetRow(); 
5668         int col 
= m_currentCellCoords
.GetCol(); 
5670         wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
5671         wxGridCellEditor
* editor 
= attr
->GetEditor(this, row
, col
); 
5672         bool changed 
= editor
->EndEdit(row
, col
, this); 
5679             SendEvent( wxEVT_GRID_CELL_CHANGE
, 
5680                        m_currentCellCoords
.GetRow(), 
5681                        m_currentCellCoords
.GetCol() ); 
5688 // ------ Grid location functions 
5689 //  Note that all of these functions work with the logical coordinates of 
5690 //  grid cells and labels so you will need to convert from device 
5691 //  coordinates for mouse events etc. 
5694 void wxGrid::XYToCell( int x
, int y
, wxGridCellCoords
& coords 
) 
5696     int row 
= YToRow(y
); 
5697     int col 
= XToCol(x
); 
5699     if ( row 
== -1  ||  col 
== -1 ) 
5701         coords 
= wxGridNoCellCoords
; 
5705         coords
.Set( row
, col 
); 
5710 int wxGrid::YToRow( int y 
) 
5714     for ( i 
= 0;  i 
< m_numRows
;  i
++ ) 
5716         if ( y 
< GetRowBottom(i
) ) 
5724 int wxGrid::XToCol( int x 
) 
5728     for ( i 
= 0;  i 
< m_numCols
;  i
++ ) 
5730         if ( x 
< GetColRight(i
) ) 
5738 // return the row number that that the y coord is near the edge of, or 
5739 // -1 if not near an edge 
5741 int wxGrid::YToEdgeOfRow( int y 
) 
5745     for ( i 
= 0;  i 
< m_numRows
;  i
++ ) 
5747         if ( GetRowHeight(i
) > WXGRID_LABEL_EDGE_ZONE 
) 
5749             d 
= abs( y 
- GetRowBottom(i
) ); 
5750             if ( d 
< WXGRID_LABEL_EDGE_ZONE 
) 
5759 // return the col number that that the x coord is near the edge of, or 
5760 // -1 if not near an edge 
5762 int wxGrid::XToEdgeOfCol( int x 
) 
5766     for ( i 
= 0;  i 
< m_numCols
;  i
++ ) 
5768         if ( GetColWidth(i
) > WXGRID_LABEL_EDGE_ZONE 
) 
5770             d 
= abs( x 
- GetColRight(i
) ); 
5771             if ( d 
< WXGRID_LABEL_EDGE_ZONE 
) 
5780 wxRect 
wxGrid::CellToRect( int row
, int col 
) 
5782     wxRect 
rect( -1, -1, -1, -1 ); 
5784     if ( row 
>= 0  &&  row 
< m_numRows  
&& 
5785          col 
>= 0  &&  col 
< m_numCols 
) 
5787         rect
.x 
= GetColLeft(col
); 
5788         rect
.y 
= GetRowTop(row
); 
5789         rect
.width 
= GetColWidth(col
); 
5790         rect
.height 
= GetRowHeight(row
); 
5797 bool wxGrid::IsVisible( int row
, int col
, bool wholeCellVisible 
) 
5799     // get the cell rectangle in logical coords 
5801     wxRect 
r( CellToRect( row
, col 
) ); 
5803     // convert to device coords 
5805     int left
, top
, right
, bottom
; 
5806     CalcScrolledPosition( r
.GetLeft(), r
.GetTop(), &left
, &top 
); 
5807     CalcScrolledPosition( r
.GetRight(), r
.GetBottom(), &right
, &bottom 
); 
5809     // check against the client area of the grid window 
5812     m_gridWin
->GetClientSize( &cw
, &ch 
); 
5814     if ( wholeCellVisible 
) 
5816         // is the cell wholly visible ? 
5818         return ( left 
>= 0  &&  right 
<= cw  
&& 
5819                  top 
>= 0  &&  bottom 
<= ch 
); 
5823         // is the cell partly visible ? 
5825         return ( ((left 
>=0 && left 
< cw
) || (right 
> 0 && right 
<= cw
))  && 
5826                  ((top 
>=0 && top 
< ch
) || (bottom 
> 0 && bottom 
<= ch
)) ); 
5831 // make the specified cell location visible by doing a minimal amount 
5834 void wxGrid::MakeCellVisible( int row
, int col 
) 
5837     int xpos 
= -1, ypos 
= -1; 
5839     if ( row 
>= 0  &&  row 
< m_numRows  
&& 
5840          col 
>= 0  &&  col 
< m_numCols 
) 
5842         // get the cell rectangle in logical coords 
5844         wxRect 
r( CellToRect( row
, col 
) ); 
5846         // convert to device coords 
5848         int left
, top
, right
, bottom
; 
5849         CalcScrolledPosition( r
.GetLeft(), r
.GetTop(), &left
, &top 
); 
5850         CalcScrolledPosition( r
.GetRight(), r
.GetBottom(), &right
, &bottom 
); 
5853         m_gridWin
->GetClientSize( &cw
, &ch 
); 
5859         else if ( bottom 
> ch 
) 
5861             int h 
= r
.GetHeight(); 
5863             for ( i 
= row
-1;  i 
>= 0;  i
-- ) 
5865                 int rowHeight 
= GetRowHeight(i
); 
5866                 if ( h 
+ rowHeight 
> ch 
) 
5873             // we divide it later by GRID_SCROLL_LINE, make sure that we don't 
5874             // have rounding errors (this is important, because if we do, we 
5875             // might not scroll at all and some cells won't be redrawn) 
5876             ypos 
+= GRID_SCROLL_LINE 
/ 2; 
5883         else if ( right 
> cw 
) 
5885             int w 
= r
.GetWidth(); 
5887             for ( i 
= col
-1;  i 
>= 0;  i
-- ) 
5889                 int colWidth 
= GetColWidth(i
); 
5890                 if ( w 
+ colWidth 
> cw 
) 
5897             // see comment for ypos above 
5898             xpos 
+= GRID_SCROLL_LINE 
/ 2; 
5901         if ( xpos 
!= -1  ||  ypos 
!= -1 ) 
5903             if ( xpos 
!= -1 ) xpos 
/= GRID_SCROLL_LINE
; 
5904             if ( ypos 
!= -1 ) ypos 
/= GRID_SCROLL_LINE
; 
5905             Scroll( xpos
, ypos 
); 
5913 // ------ Grid cursor movement functions 
5916 bool wxGrid::MoveCursorUp() 
5918     if ( m_currentCellCoords 
!= wxGridNoCellCoords  
&& 
5919          m_currentCellCoords
.GetRow() > 0 ) 
5921         MakeCellVisible( m_currentCellCoords
.GetRow() - 1, 
5922                         m_currentCellCoords
.GetCol() ); 
5924         SetCurrentCell( m_currentCellCoords
.GetRow() - 1, 
5925                         m_currentCellCoords
.GetCol() ); 
5934 bool wxGrid::MoveCursorDown() 
5936     // TODO: allow for scrolling 
5938     if ( m_currentCellCoords 
!= wxGridNoCellCoords  
&& 
5939          m_currentCellCoords
.GetRow() < m_numRows
-1 ) 
5941         MakeCellVisible( m_currentCellCoords
.GetRow() + 1, 
5942                         m_currentCellCoords
.GetCol() ); 
5944         SetCurrentCell( m_currentCellCoords
.GetRow() + 1, 
5945                         m_currentCellCoords
.GetCol() ); 
5954 bool wxGrid::MoveCursorLeft() 
5956     if ( m_currentCellCoords 
!= wxGridNoCellCoords  
&& 
5957          m_currentCellCoords
.GetCol() > 0 ) 
5959         MakeCellVisible( m_currentCellCoords
.GetRow(), 
5960                         m_currentCellCoords
.GetCol() - 1 ); 
5962         SetCurrentCell( m_currentCellCoords
.GetRow(), 
5963                         m_currentCellCoords
.GetCol() - 1 ); 
5972 bool wxGrid::MoveCursorRight() 
5974     if ( m_currentCellCoords 
!= wxGridNoCellCoords  
&& 
5975          m_currentCellCoords
.GetCol() < m_numCols 
- 1 ) 
5977         MakeCellVisible( m_currentCellCoords
.GetRow(), 
5978                         m_currentCellCoords
.GetCol() + 1 ); 
5980         SetCurrentCell( m_currentCellCoords
.GetRow(), 
5981                         m_currentCellCoords
.GetCol() + 1 ); 
5990 bool wxGrid::MovePageUp() 
5992     if ( m_currentCellCoords 
== wxGridNoCellCoords 
) return FALSE
; 
5994     int row 
= m_currentCellCoords
.GetRow(); 
5998         m_gridWin
->GetClientSize( &cw
, &ch 
); 
6000         int y 
= GetRowTop(row
); 
6001         int newRow 
= YToRow( y 
- ch 
+ 1 ); 
6006         else if ( newRow 
== row 
) 
6011         MakeCellVisible( newRow
, m_currentCellCoords
.GetCol() ); 
6012         SetCurrentCell( newRow
, m_currentCellCoords
.GetCol() ); 
6020 bool wxGrid::MovePageDown() 
6022     if ( m_currentCellCoords 
== wxGridNoCellCoords 
) return FALSE
; 
6024     int row 
= m_currentCellCoords
.GetRow(); 
6025     if ( row 
< m_numRows 
) 
6028         m_gridWin
->GetClientSize( &cw
, &ch 
); 
6030         int y 
= GetRowTop(row
); 
6031         int newRow 
= YToRow( y 
+ ch 
); 
6034             newRow 
= m_numRows 
- 1; 
6036         else if ( newRow 
== row 
) 
6041         MakeCellVisible( newRow
, m_currentCellCoords
.GetCol() ); 
6042         SetCurrentCell( newRow
, m_currentCellCoords
.GetCol() ); 
6050 bool wxGrid::MoveCursorUpBlock() 
6053          m_currentCellCoords 
!= wxGridNoCellCoords  
&& 
6054          m_currentCellCoords
.GetRow() > 0 ) 
6056         int row 
= m_currentCellCoords
.GetRow(); 
6057         int col 
= m_currentCellCoords
.GetCol(); 
6059         if ( m_table
->IsEmptyCell(row
, col
) ) 
6061             // starting in an empty cell: find the next block of 
6067                 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break; 
6070         else if ( m_table
->IsEmptyCell(row
-1, col
) ) 
6072             // starting at the top of a block: find the next block 
6078                 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break; 
6083             // starting within a block: find the top of the block 
6088                 if ( m_table
->IsEmptyCell(row
, col
) ) 
6096         MakeCellVisible( row
, col 
); 
6097         SetCurrentCell( row
, col 
); 
6105 bool wxGrid::MoveCursorDownBlock() 
6108          m_currentCellCoords 
!= wxGridNoCellCoords  
&& 
6109          m_currentCellCoords
.GetRow() < m_numRows
-1 ) 
6111         int row 
= m_currentCellCoords
.GetRow(); 
6112         int col 
= m_currentCellCoords
.GetCol(); 
6114         if ( m_table
->IsEmptyCell(row
, col
) ) 
6116             // starting in an empty cell: find the next block of 
6119             while ( row 
< m_numRows
-1 ) 
6122                 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break; 
6125         else if ( m_table
->IsEmptyCell(row
+1, col
) ) 
6127             // starting at the bottom of a block: find the next block 
6130             while ( row 
< m_numRows
-1 ) 
6133                 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break; 
6138             // starting within a block: find the bottom of the block 
6140             while ( row 
< m_numRows
-1 ) 
6143                 if ( m_table
->IsEmptyCell(row
, col
) ) 
6151         MakeCellVisible( row
, col 
); 
6152         SetCurrentCell( row
, col 
); 
6160 bool wxGrid::MoveCursorLeftBlock() 
6163          m_currentCellCoords 
!= wxGridNoCellCoords  
&& 
6164          m_currentCellCoords
.GetCol() > 0 ) 
6166         int row 
= m_currentCellCoords
.GetRow(); 
6167         int col 
= m_currentCellCoords
.GetCol(); 
6169         if ( m_table
->IsEmptyCell(row
, col
) ) 
6171             // starting in an empty cell: find the next block of 
6177                 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break; 
6180         else if ( m_table
->IsEmptyCell(row
, col
-1) ) 
6182             // starting at the left of a block: find the next block 
6188                 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break; 
6193             // starting within a block: find the left of the block 
6198                 if ( m_table
->IsEmptyCell(row
, col
) ) 
6206         MakeCellVisible( row
, col 
); 
6207         SetCurrentCell( row
, col 
); 
6215 bool wxGrid::MoveCursorRightBlock() 
6218          m_currentCellCoords 
!= wxGridNoCellCoords  
&& 
6219          m_currentCellCoords
.GetCol() < m_numCols
-1 ) 
6221         int row 
= m_currentCellCoords
.GetRow(); 
6222         int col 
= m_currentCellCoords
.GetCol(); 
6224         if ( m_table
->IsEmptyCell(row
, col
) ) 
6226             // starting in an empty cell: find the next block of 
6229             while ( col 
< m_numCols
-1 ) 
6232                 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break; 
6235         else if ( m_table
->IsEmptyCell(row
, col
+1) ) 
6237             // starting at the right of a block: find the next block 
6240             while ( col 
< m_numCols
-1 ) 
6243                 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break; 
6248             // starting within a block: find the right of the block 
6250             while ( col 
< m_numCols
-1 ) 
6253                 if ( m_table
->IsEmptyCell(row
, col
) ) 
6261         MakeCellVisible( row
, col 
); 
6262         SetCurrentCell( row
, col 
); 
6273 // ------ Label values and formatting 
6276 void wxGrid::GetRowLabelAlignment( int *horiz
, int *vert 
) 
6278     *horiz 
= m_rowLabelHorizAlign
; 
6279     *vert  
= m_rowLabelVertAlign
; 
6282 void wxGrid::GetColLabelAlignment( int *horiz
, int *vert 
) 
6284     *horiz 
= m_colLabelHorizAlign
; 
6285     *vert  
= m_colLabelVertAlign
; 
6288 wxString 
wxGrid::GetRowLabelValue( int row 
) 
6292         return m_table
->GetRowLabelValue( row 
); 
6302 wxString 
wxGrid::GetColLabelValue( int col 
) 
6306         return m_table
->GetColLabelValue( col 
); 
6317 void wxGrid::SetRowLabelSize( int width 
) 
6319     width 
= wxMax( width
, 0 ); 
6320     if ( width 
!= m_rowLabelWidth 
) 
6324             m_rowLabelWin
->Show( FALSE 
); 
6325             m_cornerLabelWin
->Show( FALSE 
); 
6327         else if ( m_rowLabelWidth 
== 0 ) 
6329             m_rowLabelWin
->Show( TRUE 
); 
6330             if ( m_colLabelHeight 
> 0 ) m_cornerLabelWin
->Show( TRUE 
); 
6333         m_rowLabelWidth 
= width
; 
6340 void wxGrid::SetColLabelSize( int height 
) 
6342     height 
= wxMax( height
, 0 ); 
6343     if ( height 
!= m_colLabelHeight 
) 
6347             m_colLabelWin
->Show( FALSE 
); 
6348             m_cornerLabelWin
->Show( FALSE 
); 
6350         else if ( m_colLabelHeight 
== 0 ) 
6352             m_colLabelWin
->Show( TRUE 
); 
6353             if ( m_rowLabelWidth 
> 0 ) m_cornerLabelWin
->Show( TRUE 
); 
6356         m_colLabelHeight 
= height
; 
6363 void wxGrid::SetLabelBackgroundColour( const wxColour
& colour 
) 
6365     if ( m_labelBackgroundColour 
!= colour 
) 
6367         m_labelBackgroundColour 
= colour
; 
6368         m_rowLabelWin
->SetBackgroundColour( colour 
); 
6369         m_colLabelWin
->SetBackgroundColour( colour 
); 
6370         m_cornerLabelWin
->SetBackgroundColour( colour 
); 
6372         if ( !GetBatchCount() ) 
6374             m_rowLabelWin
->Refresh(); 
6375             m_colLabelWin
->Refresh(); 
6376             m_cornerLabelWin
->Refresh(); 
6381 void wxGrid::SetLabelTextColour( const wxColour
& colour 
) 
6383     if ( m_labelTextColour 
!= colour 
) 
6385         m_labelTextColour 
= colour
; 
6386         if ( !GetBatchCount() ) 
6388             m_rowLabelWin
->Refresh(); 
6389             m_colLabelWin
->Refresh(); 
6394 void wxGrid::SetLabelFont( const wxFont
& font 
) 
6397     if ( !GetBatchCount() ) 
6399         m_rowLabelWin
->Refresh(); 
6400         m_colLabelWin
->Refresh(); 
6404 void wxGrid::SetRowLabelAlignment( int horiz
, int vert 
) 
6406     if ( horiz 
== wxLEFT 
|| horiz 
== wxCENTRE 
|| horiz 
== wxRIGHT 
) 
6408         m_rowLabelHorizAlign 
= horiz
; 
6411     if ( vert 
== wxTOP 
|| vert 
== wxCENTRE 
|| vert 
== wxBOTTOM 
) 
6413         m_rowLabelVertAlign 
= vert
; 
6416     if ( !GetBatchCount() ) 
6418         m_rowLabelWin
->Refresh(); 
6422 void wxGrid::SetColLabelAlignment( int horiz
, int vert 
) 
6424     if ( horiz 
== wxLEFT 
|| horiz 
== wxCENTRE 
|| horiz 
== wxRIGHT 
) 
6426         m_colLabelHorizAlign 
= horiz
; 
6429     if ( vert 
== wxTOP 
|| vert 
== wxCENTRE 
|| vert 
== wxBOTTOM 
) 
6431         m_colLabelVertAlign 
= vert
; 
6434     if ( !GetBatchCount() ) 
6436         m_colLabelWin
->Refresh(); 
6440 void wxGrid::SetRowLabelValue( int row
, const wxString
& s 
) 
6444         m_table
->SetRowLabelValue( row
, s 
); 
6445         if ( !GetBatchCount() ) 
6447             wxRect rect 
= CellToRect( row
, 0); 
6448             if ( rect
.height 
> 0 ) 
6450                 CalcScrolledPosition(0, rect
.y
, &rect
.x
, &rect
.y
); 
6452                 rect
.width 
= m_rowLabelWidth
; 
6453                 m_rowLabelWin
->Refresh( TRUE
, &rect 
); 
6459 void wxGrid::SetColLabelValue( int col
, const wxString
& s 
) 
6463         m_table
->SetColLabelValue( col
, s 
); 
6464         if ( !GetBatchCount() ) 
6466             wxRect rect 
= CellToRect( 0, col 
); 
6467             if ( rect
.width 
> 0 ) 
6469                 CalcScrolledPosition(rect
.x
, 0, &rect
.x
, &rect
.y
); 
6471                 rect
.height 
= m_colLabelHeight
; 
6472                 m_colLabelWin
->Refresh( TRUE
, &rect 
); 
6478 void wxGrid::SetGridLineColour( const wxColour
& colour 
) 
6480     if ( m_gridLineColour 
!= colour 
) 
6482         m_gridLineColour 
= colour
; 
6484         wxClientDC 
dc( m_gridWin 
); 
6486         DrawAllGridLines( dc
, wxRegion() ); 
6490 void wxGrid::EnableGridLines( bool enable 
) 
6492     if ( enable 
!= m_gridLinesEnabled 
) 
6494         m_gridLinesEnabled 
= enable
; 
6496         if ( !GetBatchCount() ) 
6500                 wxClientDC 
dc( m_gridWin 
); 
6502                 DrawAllGridLines( dc
, wxRegion() ); 
6506                 m_gridWin
->Refresh(); 
6513 int wxGrid::GetDefaultRowSize() 
6515     return m_defaultRowHeight
; 
6518 int wxGrid::GetRowSize( int row 
) 
6520     wxCHECK_MSG( row 
>= 0 && row 
< m_numRows
, 0, _T("invalid row index") ); 
6522     return GetRowHeight(row
); 
6525 int wxGrid::GetDefaultColSize() 
6527     return m_defaultColWidth
; 
6530 int wxGrid::GetColSize( int col 
) 
6532     wxCHECK_MSG( col 
>= 0 && col 
< m_numCols
, 0, _T("invalid column index") ); 
6534     return GetColWidth(col
); 
6537 // ============================================================================ 
6538 // access to the grid attributes: each of them has a default value in the grid 
6539 // itself and may be overidden on a per-cell basis 
6540 // ============================================================================ 
6542 // ---------------------------------------------------------------------------- 
6543 // setting default attributes 
6544 // ---------------------------------------------------------------------------- 
6546 void wxGrid::SetDefaultCellBackgroundColour( const wxColour
& col 
) 
6548     m_defaultCellAttr
->SetBackgroundColour(col
); 
6550     m_gridWin
->SetBackgroundColour(col
); 
6554 void wxGrid::SetDefaultCellTextColour( const wxColour
& col 
) 
6556     m_defaultCellAttr
->SetTextColour(col
); 
6559 void wxGrid::SetDefaultCellAlignment( int horiz
, int vert 
) 
6561     m_defaultCellAttr
->SetAlignment(horiz
, vert
); 
6564 void wxGrid::SetDefaultCellFont( const wxFont
& font 
) 
6566     m_defaultCellAttr
->SetFont(font
); 
6569 void wxGrid::SetDefaultRenderer(wxGridCellRenderer 
*renderer
) 
6571     m_defaultCellAttr
->SetRenderer(renderer
); 
6574 void wxGrid::SetDefaultEditor(wxGridCellEditor 
*editor
) 
6576     m_defaultCellAttr
->SetEditor(editor
); 
6579 // ---------------------------------------------------------------------------- 
6580 // access to the default attrbiutes 
6581 // ---------------------------------------------------------------------------- 
6583 wxColour 
wxGrid::GetDefaultCellBackgroundColour() 
6585     return m_defaultCellAttr
->GetBackgroundColour(); 
6588 wxColour 
wxGrid::GetDefaultCellTextColour() 
6590     return m_defaultCellAttr
->GetTextColour(); 
6593 wxFont 
wxGrid::GetDefaultCellFont() 
6595     return m_defaultCellAttr
->GetFont(); 
6598 void wxGrid::GetDefaultCellAlignment( int *horiz
, int *vert 
) 
6600     m_defaultCellAttr
->GetAlignment(horiz
, vert
); 
6603 wxGridCellRenderer 
*wxGrid::GetDefaultRenderer() const 
6605     return m_defaultCellAttr
->GetRenderer(NULL
, 0, 0); 
6608 wxGridCellEditor 
*wxGrid::GetDefaultEditor() const 
6610     return m_defaultCellAttr
->GetEditor(NULL
,0,0); 
6613 // ---------------------------------------------------------------------------- 
6614 // access to cell attributes 
6615 // ---------------------------------------------------------------------------- 
6617 wxColour 
wxGrid::GetCellBackgroundColour(int row
, int col
) 
6619     wxGridCellAttr 
*attr 
= GetCellAttr(row
, col
); 
6620     wxColour colour 
= attr
->GetBackgroundColour(); 
6625 wxColour 
wxGrid::GetCellTextColour( int row
, int col 
) 
6627     wxGridCellAttr 
*attr 
= GetCellAttr(row
, col
); 
6628     wxColour colour 
= attr
->GetTextColour(); 
6633 wxFont 
wxGrid::GetCellFont( int row
, int col 
) 
6635     wxGridCellAttr 
*attr 
= GetCellAttr(row
, col
); 
6636     wxFont font 
= attr
->GetFont(); 
6641 void wxGrid::GetCellAlignment( int row
, int col
, int *horiz
, int *vert 
) 
6643     wxGridCellAttr 
*attr 
= GetCellAttr(row
, col
); 
6644     attr
->GetAlignment(horiz
, vert
); 
6648 wxGridCellRenderer
* wxGrid::GetCellRenderer(int row
, int col
) 
6650     wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
6651     wxGridCellRenderer
* renderer 
= attr
->GetRenderer(this, row
, col
); 
6657 wxGridCellEditor
* wxGrid::GetCellEditor(int row
, int col
) 
6659     wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
6660     wxGridCellEditor
* editor 
= attr
->GetEditor(this, row
, col
); 
6666 bool wxGrid::IsReadOnly(int row
, int col
) const 
6668     wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
6669     bool isReadOnly 
= attr
->IsReadOnly(); 
6674 // ---------------------------------------------------------------------------- 
6675 // attribute support: cache, automatic provider creation, ... 
6676 // ---------------------------------------------------------------------------- 
6678 bool wxGrid::CanHaveAttributes() 
6685     return m_table
->CanHaveAttributes(); 
6688 void wxGrid::ClearAttrCache() 
6690     if ( m_attrCache
.row 
!= -1 ) 
6692         wxSafeDecRef(m_attrCache
.attr
); 
6693         m_attrCache
.row 
= -1; 
6697 void wxGrid::CacheAttr(int row
, int col
, wxGridCellAttr 
*attr
) const 
6699     wxGrid 
*self 
= (wxGrid 
*)this;  // const_cast 
6701     self
->ClearAttrCache(); 
6702     self
->m_attrCache
.row 
= row
; 
6703     self
->m_attrCache
.col 
= col
; 
6704     self
->m_attrCache
.attr 
= attr
; 
6708 bool wxGrid::LookupAttr(int row
, int col
, wxGridCellAttr 
**attr
) const 
6710     if ( row 
== m_attrCache
.row 
&& col 
== m_attrCache
.col 
) 
6712         *attr 
= m_attrCache
.attr
; 
6713         wxSafeIncRef(m_attrCache
.attr
); 
6715 #ifdef DEBUG_ATTR_CACHE 
6716         gs_nAttrCacheHits
++; 
6723 #ifdef DEBUG_ATTR_CACHE 
6724         gs_nAttrCacheMisses
++; 
6730 wxGridCellAttr 
*wxGrid::GetCellAttr(int row
, int col
) const 
6732     wxGridCellAttr 
*attr
; 
6733     if ( !LookupAttr(row
, col
, &attr
) ) 
6735         attr 
= m_table 
? m_table
->GetAttr(row
, col
) : (wxGridCellAttr 
*)NULL
; 
6736         CacheAttr(row
, col
, attr
); 
6740         attr
->SetDefAttr(m_defaultCellAttr
); 
6744         attr 
= m_defaultCellAttr
; 
6751 wxGridCellAttr 
*wxGrid::GetOrCreateCellAttr(int row
, int col
) const 
6753     wxGridCellAttr 
*attr
; 
6754     if ( !LookupAttr(row
, col
, &attr
) || !attr 
) 
6756         wxASSERT_MSG( m_table
, 
6757                       _T("we may only be called if CanHaveAttributes() " 
6758                          "returned TRUE and then m_table should be !NULL") ); 
6760         attr 
= m_table
->GetAttr(row
, col
); 
6763             attr 
= new wxGridCellAttr
; 
6765             // artificially inc the ref count to match DecRef() in caller 
6768             m_table
->SetAttr(attr
, row
, col
); 
6771         CacheAttr(row
, col
, attr
); 
6773     attr
->SetDefAttr(m_defaultCellAttr
); 
6777 // ---------------------------------------------------------------------------- 
6778 // setting column attributes (wrappers around SetColAttr) 
6779 // ---------------------------------------------------------------------------- 
6781 void wxGrid::SetColFormatBool(int col
) 
6783     SetColFormatCustom(col
, wxGRID_VALUE_BOOL
); 
6786 void wxGrid::SetColFormatNumber(int col
) 
6788     SetColFormatCustom(col
, wxGRID_VALUE_NUMBER
); 
6791 void wxGrid::SetColFormatFloat(int col
, int width
, int precision
) 
6793     wxString typeName 
= wxGRID_VALUE_FLOAT
; 
6794     if ( (width 
!= -1) || (precision 
!= -1) ) 
6796         typeName 
<< _T(':') << width 
<< _T(',') << precision
; 
6799     SetColFormatCustom(col
, typeName
); 
6802 void wxGrid::SetColFormatCustom(int col
, const wxString
& typeName
) 
6804     wxGridCellAttr 
*attr 
= new wxGridCellAttr
; 
6805     wxGridCellRenderer 
*renderer 
= GetDefaultRendererForType(typeName
); 
6806     attr
->SetRenderer(renderer
); 
6808     SetColAttr(col
, attr
); 
6811 // ---------------------------------------------------------------------------- 
6812 // setting cell attributes: this is forwarded to the table 
6813 // ---------------------------------------------------------------------------- 
6815 void wxGrid::SetRowAttr(int row
, wxGridCellAttr 
*attr
) 
6817     if ( CanHaveAttributes() ) 
6819         m_table
->SetRowAttr(attr
, row
); 
6827 void wxGrid::SetColAttr(int col
, wxGridCellAttr 
*attr
) 
6829     if ( CanHaveAttributes() ) 
6831         m_table
->SetColAttr(attr
, col
); 
6839 void wxGrid::SetCellBackgroundColour( int row
, int col
, const wxColour
& colour 
) 
6841     if ( CanHaveAttributes() ) 
6843         wxGridCellAttr 
*attr 
= GetOrCreateCellAttr(row
, col
); 
6844         attr
->SetBackgroundColour(colour
); 
6849 void wxGrid::SetCellTextColour( int row
, int col
, const wxColour
& colour 
) 
6851     if ( CanHaveAttributes() ) 
6853         wxGridCellAttr 
*attr 
= GetOrCreateCellAttr(row
, col
); 
6854         attr
->SetTextColour(colour
); 
6859 void wxGrid::SetCellFont( int row
, int col
, const wxFont
& font 
) 
6861     if ( CanHaveAttributes() ) 
6863         wxGridCellAttr 
*attr 
= GetOrCreateCellAttr(row
, col
); 
6864         attr
->SetFont(font
); 
6869 void wxGrid::SetCellAlignment( int row
, int col
, int horiz
, int vert 
) 
6871     if ( CanHaveAttributes() ) 
6873         wxGridCellAttr 
*attr 
= GetOrCreateCellAttr(row
, col
); 
6874         attr
->SetAlignment(horiz
, vert
); 
6879 void wxGrid::SetCellRenderer(int row
, int col
, wxGridCellRenderer 
*renderer
) 
6881     if ( CanHaveAttributes() ) 
6883         wxGridCellAttr 
*attr 
= GetOrCreateCellAttr(row
, col
); 
6884         attr
->SetRenderer(renderer
); 
6889 void wxGrid::SetCellEditor(int row
, int col
, wxGridCellEditor
* editor
) 
6891     if ( CanHaveAttributes() ) 
6893         wxGridCellAttr 
*attr 
= GetOrCreateCellAttr(row
, col
); 
6894         attr
->SetEditor(editor
); 
6899 void wxGrid::SetReadOnly(int row
, int col
, bool isReadOnly
) 
6901     if ( CanHaveAttributes() ) 
6903         wxGridCellAttr 
*attr 
= GetOrCreateCellAttr(row
, col
); 
6904         attr
->SetReadOnly(isReadOnly
); 
6909 // ---------------------------------------------------------------------------- 
6910 // Data type registration 
6911 // ---------------------------------------------------------------------------- 
6913 void wxGrid::RegisterDataType(const wxString
& typeName
, 
6914                               wxGridCellRenderer
* renderer
, 
6915                               wxGridCellEditor
* editor
) 
6917     m_typeRegistry
->RegisterDataType(typeName
, renderer
, editor
); 
6921 wxGridCellEditor
* wxGrid::GetDefaultEditorForCell(int row
, int col
) const 
6923     wxString typeName 
= m_table
->GetTypeName(row
, col
); 
6924     return GetDefaultEditorForType(typeName
); 
6927 wxGridCellRenderer
* wxGrid::GetDefaultRendererForCell(int row
, int col
) const 
6929     wxString typeName 
= m_table
->GetTypeName(row
, col
); 
6930     return GetDefaultRendererForType(typeName
); 
6934 wxGrid::GetDefaultEditorForType(const wxString
& typeName
) const 
6936     int index 
= m_typeRegistry
->FindDataType(typeName
); 
6937     if ( index 
== wxNOT_FOUND 
) 
6939         wxFAIL_MSG(wxT("Unknown data type name")); 
6944     return m_typeRegistry
->GetEditor(index
); 
6948 wxGrid::GetDefaultRendererForType(const wxString
& typeName
) const 
6950     // first try to find an exact match 
6951     wxGridCellRenderer 
*renderer
; 
6952     int index 
= m_typeRegistry
->FindDataType(typeName
); 
6953     if ( index 
== wxNOT_FOUND 
) 
6955         // then try to construct a renderer from the base name and parameters 
6958         // the first part of the typename is the "real" type, anything after ':' 
6959         // are the parameters for the renderer 
6960         index 
= m_typeRegistry
->FindDataType(typeName
.BeforeFirst(_T(':'))); 
6961         if ( index 
== wxNOT_FOUND 
) 
6963             wxFAIL_MSG(wxT("Unknown data type name")); 
6968         renderer 
= m_typeRegistry
->GetRenderer(index
); 
6969         wxGridCellRenderer 
*rendererOld 
= renderer
; 
6970         renderer 
= renderer
->Clone(); 
6971         rendererOld
->DecRef(); 
6973         // do it even if there are no parameters to reset them to defaults 
6974         renderer
->SetParameters(typeName
.AfterFirst(_T(':'))); 
6976         // register the new typename 
6977         m_typeRegistry
->RegisterDataType(typeName
, renderer
, NULL
); 
6981         renderer 
= m_typeRegistry
->GetRenderer(index
); 
6988 // ---------------------------------------------------------------------------- 
6990 // ---------------------------------------------------------------------------- 
6992 void wxGrid::EnableDragRowSize( bool enable 
) 
6994     m_canDragRowSize 
= enable
; 
6998 void wxGrid::EnableDragColSize( bool enable 
) 
7000     m_canDragColSize 
= enable
; 
7003 void wxGrid::EnableDragGridSize( bool enable 
) 
7005     m_canDragGridSize 
= enable
; 
7009 void wxGrid::SetDefaultRowSize( int height
, bool resizeExistingRows 
) 
7011     m_defaultRowHeight 
= wxMax( height
, WXGRID_MIN_ROW_HEIGHT 
); 
7013     if ( resizeExistingRows 
) 
7021 void wxGrid::SetRowSize( int row
, int height 
) 
7023     wxCHECK_RET( row 
>= 0 && row 
< m_numRows
, _T("invalid row index") ); 
7025     if ( m_rowHeights
.IsEmpty() ) 
7027         // need to really create the array 
7031     int h 
= wxMax( 0, height 
); 
7032     int diff 
= h 
- m_rowHeights
[row
]; 
7034     m_rowHeights
[row
] = h
; 
7036     for ( i 
= row
;  i 
< m_numRows
;  i
++ ) 
7038         m_rowBottoms
[i
] += diff
; 
7043 void wxGrid::SetDefaultColSize( int width
, bool resizeExistingCols 
) 
7045     m_defaultColWidth 
= wxMax( width
, WXGRID_MIN_COL_WIDTH 
); 
7047     if ( resizeExistingCols 
) 
7055 void wxGrid::SetColSize( int col
, int width 
) 
7057     wxCHECK_RET( col 
>= 0 && col 
< m_numCols
, _T("invalid column index") ); 
7059     // should we check that it's bigger than GetColMinimalWidth(col) here? 
7061     if ( m_colWidths
.IsEmpty() ) 
7063         // need to really create the array 
7067     int w 
= wxMax( 0, width 
); 
7068     int diff 
= w 
- m_colWidths
[col
]; 
7069     m_colWidths
[col
] = w
; 
7072     for ( i 
= col
;  i 
< m_numCols
;  i
++ ) 
7074         m_colRights
[i
] += diff
; 
7080 void wxGrid::SetColMinimalWidth( int col
, int width 
) 
7082     m_colMinWidths
.Put(col
, width
); 
7085 void wxGrid::SetRowMinimalHeight( int row
, int width 
) 
7087     m_rowMinHeights
.Put(row
, width
); 
7090 int wxGrid::GetColMinimalWidth(int col
) const 
7092     long value 
= m_colMinWidths
.Get(col
); 
7093     return value 
!= wxNOT_FOUND 
? (int)value 
: WXGRID_MIN_COL_WIDTH
; 
7096 int wxGrid::GetRowMinimalHeight(int row
) const 
7098     long value 
= m_rowMinHeights
.Get(row
); 
7099     return value 
!= wxNOT_FOUND 
? (int)value 
: WXGRID_MIN_ROW_HEIGHT
; 
7102 // ---------------------------------------------------------------------------- 
7104 // ---------------------------------------------------------------------------- 
7106 void wxGrid::AutoSizeColOrRow( int colOrRow
, bool setAsMin
, bool column 
) 
7108     wxClientDC 
dc(m_gridWin
); 
7116     wxCoord extent
, extentMax 
= 0; 
7117     int max 
= column 
? m_numRows 
: m_numCols
; 
7118     for ( int rowOrCol 
= 0; rowOrCol 
< max
; rowOrCol
++ ) 
7125         wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
7126         wxGridCellRenderer
* renderer 
= attr
->GetRenderer(this, row
, col
); 
7129             wxSize size 
= renderer
->GetBestSize(*this, *attr
, dc
, row
, col
); 
7130             extent 
= column 
? size
.x 
: size
.y
; 
7131             if ( extent 
> extentMax 
) 
7142     // now also compare with the column label extent 
7144     dc
.SetFont( GetLabelFont() ); 
7147         dc
.GetTextExtent( GetColLabelValue(col
), &w
, &h 
); 
7149         dc
.GetTextExtent( GetRowLabelValue(col
), &w
, &h 
); 
7151     extent 
= column 
? w 
: h
; 
7152     if ( extent 
> extentMax 
) 
7159         // empty column - give default extent (notice that if extentMax is less 
7160         // than default extent but != 0, it's ok) 
7161         extentMax 
= column 
? m_defaultColWidth 
: m_defaultRowHeight
; 
7165         // leave some space around text 
7170         SetColSize(col
, extentMax
); 
7172         SetRowSize(row
, extentMax
); 
7177             SetColMinimalWidth(col
, extentMax
); 
7179             SetRowMinimalHeight(row
, extentMax
); 
7183 int wxGrid::SetOrCalcColumnSizes(bool calcOnly
, bool setAsMin
) 
7185     int width 
= m_rowLabelWidth
; 
7187     for ( int col 
= 0; col 
< m_numCols
; col
++ ) 
7191             AutoSizeColumn(col
, setAsMin
); 
7194         width 
+= GetColWidth(col
); 
7200 int wxGrid::SetOrCalcRowSizes(bool calcOnly
, bool setAsMin
) 
7202     int height 
= m_colLabelHeight
; 
7204     for ( int row 
= 0; row 
< m_numRows
; row
++ ) 
7208             AutoSizeRow(row
, setAsMin
); 
7211         height 
+= GetRowHeight(row
); 
7217 void wxGrid::AutoSize() 
7220     SetSize(SetOrCalcColumnSizes(FALSE
), SetOrCalcRowSizes(FALSE
)); 
7223 wxSize 
wxGrid::DoGetBestSize() const 
7225     // don't set sizes, only calculate them 
7226     wxGrid 
*self 
= (wxGrid 
*)this;  // const_cast 
7228     return wxSize(self
->SetOrCalcColumnSizes(TRUE
), 
7229                   self
->SetOrCalcRowSizes(TRUE
)); 
7237 // ---------------------------------------------------------------------------- 
7238 // cell value accessor functions 
7239 // ---------------------------------------------------------------------------- 
7241 void wxGrid::SetCellValue( int row
, int col
, const wxString
& s 
) 
7245         m_table
->SetValue( row
, col
, s
.c_str() ); 
7246         if ( !GetBatchCount() ) 
7248             wxClientDC 
dc( m_gridWin 
); 
7250             DrawCell( dc
, wxGridCellCoords(row
, col
) ); 
7253         if ( m_currentCellCoords
.GetRow() == row 
&& 
7254              m_currentCellCoords
.GetCol() == col 
&& 
7255              IsCellEditControlEnabled()) 
7257             HideCellEditControl(); 
7258             ShowCellEditControl(); // will reread data from table 
7265 // ------ Block, row and col selection 
7268 void wxGrid::SelectRow( int row
, bool addToSelected 
) 
7272     if ( IsSelection() && addToSelected 
) 
7275         bool    need_refresh
[4]; 
7279         need_refresh
[3] = FALSE
; 
7283         wxCoord oldLeft   
= m_selectedTopLeft
.GetCol(); 
7284         wxCoord oldTop    
= m_selectedTopLeft
.GetRow(); 
7285         wxCoord oldRight  
= m_selectedBottomRight
.GetCol(); 
7286         wxCoord oldBottom 
= m_selectedBottomRight
.GetRow(); 
7290             need_refresh
[0] = TRUE
; 
7291             rect
[0] = BlockToDeviceRect( wxGridCellCoords ( row
, 0 ), 
7292                                          wxGridCellCoords ( oldTop 
- 1, 
7294             m_selectedTopLeft
.SetRow( row 
); 
7299             need_refresh
[1] = TRUE
; 
7300             rect
[1] = BlockToDeviceRect( wxGridCellCoords ( oldTop
, 0 ), 
7301                                          wxGridCellCoords ( oldBottom
, 
7304             m_selectedTopLeft
.SetCol( 0 ); 
7307         if ( oldBottom 
< row 
) 
7309             need_refresh
[2] = TRUE
; 
7310             rect
[2] = BlockToDeviceRect( wxGridCellCoords ( oldBottom 
+ 1, 0 ), 
7311                                          wxGridCellCoords ( row
, 
7313             m_selectedBottomRight
.SetRow( row 
); 
7316         if ( oldRight 
< m_numCols 
- 1 ) 
7318             need_refresh
[3] = TRUE
; 
7319             rect
[3] = BlockToDeviceRect( wxGridCellCoords ( oldTop 
, 
7321                                          wxGridCellCoords ( oldBottom
, 
7323             m_selectedBottomRight
.SetCol( m_numCols 
- 1 ); 
7326         for (i 
= 0; i 
< 4; i
++ ) 
7327             if ( need_refresh
[i
] && rect
[i
] != wxGridNoCellRect 
) 
7328                 m_gridWin
->Refresh( FALSE
, &(rect
[i
]) ); 
7332         r 
= SelectionToDeviceRect(); 
7334         if ( r 
!= wxGridNoCellRect 
) m_gridWin
->Refresh( FALSE
, &r 
); 
7336         m_selectedTopLeft
.Set( row
, 0 ); 
7337         m_selectedBottomRight
.Set( row
, m_numCols
-1 ); 
7338         r 
= SelectionToDeviceRect(); 
7339         m_gridWin
->Refresh( FALSE
, &r 
); 
7342     wxGridRangeSelectEvent 
gridEvt( GetId(), 
7343                                     wxEVT_GRID_RANGE_SELECT
, 
7346                                     m_selectedBottomRight 
); 
7348     GetEventHandler()->ProcessEvent(gridEvt
); 
7352 void wxGrid::SelectCol( int col
, bool addToSelected 
) 
7354     if ( IsSelection() && addToSelected 
) 
7357         bool    need_refresh
[4]; 
7361         need_refresh
[3] = FALSE
; 
7364         wxCoord oldLeft   
= m_selectedTopLeft
.GetCol(); 
7365         wxCoord oldTop    
= m_selectedTopLeft
.GetRow(); 
7366         wxCoord oldRight  
= m_selectedBottomRight
.GetCol(); 
7367         wxCoord oldBottom 
= m_selectedBottomRight
.GetRow(); 
7369         if ( oldLeft 
> col 
) 
7371             need_refresh
[0] = TRUE
; 
7372             rect
[0] = BlockToDeviceRect( wxGridCellCoords ( 0, col 
), 
7373                                          wxGridCellCoords ( m_numRows 
- 1, 
7375             m_selectedTopLeft
.SetCol( col 
); 
7380             need_refresh
[1] = TRUE
; 
7381             rect
[1] = BlockToDeviceRect( wxGridCellCoords ( 0, oldLeft 
), 
7382                                          wxGridCellCoords ( oldTop 
- 1, 
7384             m_selectedTopLeft
.SetRow( 0 ); 
7387         if ( oldRight 
< col 
) 
7389             need_refresh
[2] = TRUE
; 
7390             rect
[2] = BlockToDeviceRect( wxGridCellCoords ( 0, oldRight 
+ 1 ), 
7391                                          wxGridCellCoords ( m_numRows 
- 1, 
7393             m_selectedBottomRight
.SetCol( col 
); 
7396         if ( oldBottom 
< m_numRows 
- 1 ) 
7398             need_refresh
[3] = TRUE
; 
7399             rect
[3] = BlockToDeviceRect( wxGridCellCoords ( oldBottom 
+ 1, 
7401                                          wxGridCellCoords ( m_numRows 
- 1, 
7403             m_selectedBottomRight
.SetRow( m_numRows 
- 1 ); 
7406         for (i 
= 0; i 
< 4; i
++ ) 
7407             if ( need_refresh
[i
] && rect
[i
] != wxGridNoCellRect 
) 
7408                 m_gridWin
->Refresh( FALSE
, &(rect
[i
]) ); 
7414         r 
= SelectionToDeviceRect(); 
7416         if ( r 
!= wxGridNoCellRect 
) m_gridWin
->Refresh( FALSE
, &r 
); 
7418         m_selectedTopLeft
.Set( 0, col 
); 
7419         m_selectedBottomRight
.Set( m_numRows
-1, col 
); 
7420         r 
= SelectionToDeviceRect(); 
7421         m_gridWin
->Refresh( FALSE
, &r 
); 
7424     wxGridRangeSelectEvent 
gridEvt( GetId(), 
7425                                     wxEVT_GRID_RANGE_SELECT
, 
7428                                     m_selectedBottomRight 
); 
7430     GetEventHandler()->ProcessEvent(gridEvt
); 
7434 void wxGrid::SelectBlock( int topRow
, int leftCol
, int bottomRow
, int rightCol 
) 
7437     wxGridCellCoords updateTopLeft
, updateBottomRight
; 
7439     if ( topRow 
> bottomRow 
) 
7446     if ( leftCol 
> rightCol 
) 
7453     updateTopLeft 
= wxGridCellCoords( topRow
, leftCol 
); 
7454     updateBottomRight 
= wxGridCellCoords( bottomRow
, rightCol 
); 
7456     if ( m_selectedTopLeft 
!= updateTopLeft 
|| 
7457          m_selectedBottomRight 
!= updateBottomRight 
) 
7459         // Compute two optimal update rectangles: 
7460         // Either one rectangle is a real subset of the 
7461         // other, or they are (almost) disjoint! 
7463         bool    need_refresh
[4]; 
7467         need_refresh
[3] = FALSE
; 
7470         // Store intermediate values 
7471         wxCoord oldLeft   
= m_selectedTopLeft
.GetCol(); 
7472         wxCoord oldTop    
= m_selectedTopLeft
.GetRow(); 
7473         wxCoord oldRight  
= m_selectedBottomRight
.GetCol(); 
7474         wxCoord oldBottom 
= m_selectedBottomRight
.GetRow(); 
7476         // Determine the outer/inner coordinates. 
7477         if (oldLeft 
> leftCol
) 
7483         if (oldTop 
> topRow 
) 
7489         if (oldRight 
< rightCol 
) 
7492             oldRight 
= rightCol
; 
7495         if (oldBottom 
< bottomRow
) 
7498             oldBottom 
= bottomRow
; 
7502         // Now, either the stuff marked old is the outer 
7503         // rectangle or we don't have a situation where one 
7504         // is contained in the other. 
7506         if ( oldLeft 
< leftCol 
) 
7508             need_refresh
[0] = TRUE
; 
7509             rect
[0] = BlockToDeviceRect( wxGridCellCoords ( oldTop
, 
7511                                          wxGridCellCoords ( oldBottom
, 
7515         if ( oldTop  
< topRow 
) 
7517             need_refresh
[1] = TRUE
; 
7518             rect
[1] = BlockToDeviceRect( wxGridCellCoords ( oldTop
, 
7520                                          wxGridCellCoords ( topRow 
- 1, 
7524         if ( oldRight 
> rightCol 
) 
7526             need_refresh
[2] = TRUE
; 
7527             rect
[2] = BlockToDeviceRect( wxGridCellCoords ( oldTop
, 
7529                                          wxGridCellCoords ( oldBottom
, 
7533         if ( oldBottom 
> bottomRow 
) 
7535             need_refresh
[3] = TRUE
; 
7536             rect
[3] = BlockToDeviceRect( wxGridCellCoords ( bottomRow 
+ 1, 
7538                                          wxGridCellCoords ( oldBottom
, 
7544         m_selectedTopLeft 
= updateTopLeft
; 
7545         m_selectedBottomRight 
= updateBottomRight
; 
7547         // various Refresh() calls 
7548         for (i 
= 0; i 
< 4; i
++ ) 
7549             if ( need_refresh
[i
] && rect
[i
] != wxGridNoCellRect 
) 
7550                 m_gridWin
->Refresh( FALSE
, &(rect
[i
]) ); 
7553     // only generate an event if the block is not being selected by 
7554     // dragging the mouse (in which case the event will be generated in 
7555     // the mouse event handler) 
7556     if ( !m_isDragging 
) 
7558         wxGridRangeSelectEvent 
gridEvt( GetId(), 
7559                                         wxEVT_GRID_RANGE_SELECT
, 
7562                                         m_selectedBottomRight 
); 
7564         GetEventHandler()->ProcessEvent(gridEvt
); 
7568 void wxGrid::SelectAll() 
7570     m_selectedTopLeft
.Set( 0, 0 ); 
7571     m_selectedBottomRight
.Set( m_numRows
-1, m_numCols
-1 ); 
7573     m_gridWin
->Refresh(); 
7577 void wxGrid::ClearSelection() 
7579     m_selectedTopLeft 
= wxGridNoCellCoords
; 
7580     m_selectedBottomRight 
= wxGridNoCellCoords
; 
7584 // This function returns the rectangle that encloses the given block 
7585 // in device coords clipped to the client size of the grid window. 
7587 wxRect 
wxGrid::BlockToDeviceRect( const wxGridCellCoords 
&topLeft
, 
7588                                   const wxGridCellCoords 
&bottomRight 
) 
7590     wxRect 
rect( wxGridNoCellRect 
); 
7593     cellRect 
= CellToRect( topLeft 
); 
7594     if ( cellRect 
!= wxGridNoCellRect 
) 
7600         rect 
= wxRect( 0, 0, 0, 0 ); 
7603     cellRect 
= CellToRect( bottomRight 
); 
7604     if ( cellRect 
!= wxGridNoCellRect 
) 
7610         return wxGridNoCellRect
; 
7613     // convert to scrolled coords 
7615     int left
, top
, right
, bottom
; 
7616     CalcScrolledPosition( rect
.GetLeft(), rect
.GetTop(), &left
, &top 
); 
7617     CalcScrolledPosition( rect
.GetRight(), rect
.GetBottom(), &right
, &bottom 
); 
7620     m_gridWin
->GetClientSize( &cw
, &ch 
); 
7622     rect
.SetLeft( wxMax(0, left
) ); 
7623     rect
.SetTop( wxMax(0, top
) ); 
7624     rect
.SetRight( wxMin(cw
, right
) ); 
7625     rect
.SetBottom( wxMin(ch
, bottom
) ); 
7633 // ------ Grid event classes 
7636 IMPLEMENT_DYNAMIC_CLASS( wxGridEvent
, wxEvent 
) 
7638 wxGridEvent::wxGridEvent( int id
, wxEventType type
, wxObject
* obj
, 
7639                           int row
, int col
, int x
, int y
, 
7640                           bool control
, bool shift
, bool alt
, bool meta 
) 
7641         : wxNotifyEvent( type
, id 
) 
7647     m_control 
= control
; 
7652     SetEventObject(obj
); 
7656 IMPLEMENT_DYNAMIC_CLASS( wxGridSizeEvent
, wxEvent 
) 
7658 wxGridSizeEvent::wxGridSizeEvent( int id
, wxEventType type
, wxObject
* obj
, 
7659                                   int rowOrCol
, int x
, int y
, 
7660                                   bool control
, bool shift
, bool alt
, bool meta 
) 
7661         : wxNotifyEvent( type
, id 
) 
7663     m_rowOrCol 
= rowOrCol
; 
7666     m_control 
= control
; 
7671     SetEventObject(obj
); 
7675 IMPLEMENT_DYNAMIC_CLASS( wxGridRangeSelectEvent
, wxEvent 
) 
7677 wxGridRangeSelectEvent::wxGridRangeSelectEvent(int id
, wxEventType type
, wxObject
* obj
, 
7678                                                const wxGridCellCoords
& topLeft
, 
7679                                                const wxGridCellCoords
& bottomRight
, 
7680                                                bool control
, bool shift
, bool alt
, bool meta 
) 
7681         : wxNotifyEvent( type
, id 
) 
7683     m_topLeft     
= topLeft
; 
7684     m_bottomRight 
= bottomRight
; 
7685     m_control     
= control
; 
7690     SetEventObject(obj
); 
7694 #endif // ifndef wxUSE_NEW_GRID