1 /////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/generic/grid.cpp 
   3 // Purpose:     wxGrid and related classes 
   4 // Author:      Michael Bedward (based on code by Julian Smart, Robin Dunn) 
   5 // Modified by: Robin Dunn, Vadim Zeitlin 
   8 // Copyright:   (c) Michael Bedward (mbedward@ozemail.com.au) 
   9 // Licence:     wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////////// 
  12 // ============================================================================ 
  14 // ============================================================================ 
  16 // ---------------------------------------------------------------------------- 
  18 // ---------------------------------------------------------------------------- 
  20 // For compilers that support precompilatixon, includes "wx/wx.h". 
  21 #include "wx/wxprec.h" 
  33     #include "wx/dcclient.h" 
  34     #include "wx/settings.h" 
  36     #include "wx/textctrl.h" 
  37     #include "wx/checkbox.h" 
  38     #include "wx/combobox.h" 
  39     #include "wx/valtext.h" 
  44 #include "wx/textfile.h" 
  45 #include "wx/spinctrl.h" 
  46 #include "wx/tokenzr.h" 
  47 #include "wx/renderer.h" 
  50 #include "wx/generic/gridsel.h" 
  52 #if defined(__WXMOTIF__) 
  53     #define WXUNUSED_MOTIF(identifier)  WXUNUSED(identifier) 
  55     #define WXUNUSED_MOTIF(identifier)  identifier 
  58 #if defined(__WXGTK__) 
  59     #define WXUNUSED_GTK(identifier)    WXUNUSED(identifier) 
  61     #define WXUNUSED_GTK(identifier)    identifier 
  64 // Required for wxIs... functions 
  67 // ---------------------------------------------------------------------------- 
  69 // ---------------------------------------------------------------------------- 
  71 WX_DEFINE_ARRAY_WITH_DECL_PTR(wxGridCellAttr 
*, wxArrayAttrs
, 
  72                                  class WXDLLIMPEXP_ADV
); 
  74 struct wxGridCellWithAttr
 
  76     wxGridCellWithAttr(int row
, int col
, wxGridCellAttr 
*attr_
) 
  77         : coords(row
, col
), attr(attr_
) 
  86     wxGridCellCoords coords
; 
  90 //  DECLARE_NO_COPY_CLASS(wxGridCellWithAttr) 
  91 // without rewriting the macros, which require a public copy constructor. 
  94 WX_DECLARE_OBJARRAY_WITH_DECL(wxGridCellWithAttr
, wxGridCellWithAttrArray
, 
  95                               class WXDLLIMPEXP_ADV
); 
  97 #include "wx/arrimpl.cpp" 
  99 WX_DEFINE_OBJARRAY(wxGridCellCoordsArray
) 
 100 WX_DEFINE_OBJARRAY(wxGridCellWithAttrArray
) 
 102 // ---------------------------------------------------------------------------- 
 104 // ---------------------------------------------------------------------------- 
 106 DEFINE_EVENT_TYPE(wxEVT_GRID_CELL_LEFT_CLICK
) 
 107 DEFINE_EVENT_TYPE(wxEVT_GRID_CELL_RIGHT_CLICK
) 
 108 DEFINE_EVENT_TYPE(wxEVT_GRID_CELL_LEFT_DCLICK
) 
 109 DEFINE_EVENT_TYPE(wxEVT_GRID_CELL_RIGHT_DCLICK
) 
 110 DEFINE_EVENT_TYPE(wxEVT_GRID_CELL_BEGIN_DRAG
) 
 111 DEFINE_EVENT_TYPE(wxEVT_GRID_LABEL_LEFT_CLICK
) 
 112 DEFINE_EVENT_TYPE(wxEVT_GRID_LABEL_RIGHT_CLICK
) 
 113 DEFINE_EVENT_TYPE(wxEVT_GRID_LABEL_LEFT_DCLICK
) 
 114 DEFINE_EVENT_TYPE(wxEVT_GRID_LABEL_RIGHT_DCLICK
) 
 115 DEFINE_EVENT_TYPE(wxEVT_GRID_ROW_SIZE
) 
 116 DEFINE_EVENT_TYPE(wxEVT_GRID_COL_SIZE
) 
 117 DEFINE_EVENT_TYPE(wxEVT_GRID_RANGE_SELECT
) 
 118 DEFINE_EVENT_TYPE(wxEVT_GRID_CELL_CHANGE
) 
 119 DEFINE_EVENT_TYPE(wxEVT_GRID_SELECT_CELL
) 
 120 DEFINE_EVENT_TYPE(wxEVT_GRID_EDITOR_SHOWN
) 
 121 DEFINE_EVENT_TYPE(wxEVT_GRID_EDITOR_HIDDEN
) 
 122 DEFINE_EVENT_TYPE(wxEVT_GRID_EDITOR_CREATED
) 
 124 // ---------------------------------------------------------------------------- 
 126 // ---------------------------------------------------------------------------- 
 128 class WXDLLIMPEXP_ADV wxGridRowLabelWindow 
: public wxWindow
 
 131     wxGridRowLabelWindow() { m_owner 
= (wxGrid 
*)NULL
; } 
 132     wxGridRowLabelWindow( wxGrid 
*parent
, wxWindowID id
, 
 133                           const wxPoint 
&pos
, const wxSize 
&size 
); 
 138     void OnPaint( wxPaintEvent
& event 
); 
 139     void OnMouseEvent( wxMouseEvent
& event 
); 
 140     void OnMouseWheel( wxMouseEvent
& event 
); 
 141     void OnKeyDown( wxKeyEvent
& event 
); 
 142     void OnKeyUp( wxKeyEvent
& ); 
 143     void OnChar( wxKeyEvent
& ); 
 145     DECLARE_DYNAMIC_CLASS(wxGridRowLabelWindow
) 
 146     DECLARE_EVENT_TABLE() 
 147     DECLARE_NO_COPY_CLASS(wxGridRowLabelWindow
) 
 151 class WXDLLIMPEXP_ADV wxGridColLabelWindow 
: public wxWindow
 
 154     wxGridColLabelWindow() { m_owner 
= (wxGrid 
*)NULL
; } 
 155     wxGridColLabelWindow( wxGrid 
*parent
, wxWindowID id
, 
 156                           const wxPoint 
&pos
, const wxSize 
&size 
); 
 161     void OnPaint( wxPaintEvent 
&event 
); 
 162     void OnMouseEvent( wxMouseEvent
& event 
); 
 163     void OnMouseWheel( wxMouseEvent
& event 
); 
 164     void OnKeyDown( wxKeyEvent
& event 
); 
 165     void OnKeyUp( wxKeyEvent
& ); 
 166     void OnChar( wxKeyEvent
& ); 
 168     DECLARE_DYNAMIC_CLASS(wxGridColLabelWindow
) 
 169     DECLARE_EVENT_TABLE() 
 170     DECLARE_NO_COPY_CLASS(wxGridColLabelWindow
) 
 174 class WXDLLIMPEXP_ADV wxGridCornerLabelWindow 
: public wxWindow
 
 177     wxGridCornerLabelWindow() { m_owner 
= (wxGrid 
*)NULL
; } 
 178     wxGridCornerLabelWindow( wxGrid 
*parent
, wxWindowID id
, 
 179                              const wxPoint 
&pos
, const wxSize 
&size 
); 
 184     void OnMouseEvent( wxMouseEvent
& event 
); 
 185     void OnMouseWheel( wxMouseEvent
& event 
); 
 186     void OnKeyDown( wxKeyEvent
& event 
); 
 187     void OnKeyUp( wxKeyEvent
& ); 
 188     void OnChar( wxKeyEvent
& ); 
 189     void OnPaint( wxPaintEvent
& event 
); 
 191     DECLARE_DYNAMIC_CLASS(wxGridCornerLabelWindow
) 
 192     DECLARE_EVENT_TABLE() 
 193     DECLARE_NO_COPY_CLASS(wxGridCornerLabelWindow
) 
 196 class WXDLLIMPEXP_ADV wxGridWindow 
: public wxWindow
 
 201         m_owner 
= (wxGrid 
*)NULL
; 
 202         m_rowLabelWin 
= (wxGridRowLabelWindow 
*)NULL
; 
 203         m_colLabelWin 
= (wxGridColLabelWindow 
*)NULL
; 
 206     wxGridWindow( wxGrid 
*parent
, 
 207                   wxGridRowLabelWindow 
*rowLblWin
, 
 208                   wxGridColLabelWindow 
*colLblWin
, 
 209                   wxWindowID id
, const wxPoint 
&pos
, const wxSize 
&size 
); 
 212     void ScrollWindow( int dx
, int dy
, const wxRect 
*rect 
); 
 214     wxGrid
* GetOwner() { return m_owner
; } 
 218     wxGridRowLabelWindow     
*m_rowLabelWin
; 
 219     wxGridColLabelWindow     
*m_colLabelWin
; 
 221     void OnPaint( wxPaintEvent 
&event 
); 
 222     void OnMouseWheel( wxMouseEvent
& event 
); 
 223     void OnMouseEvent( wxMouseEvent
& event 
); 
 224     void OnKeyDown( wxKeyEvent
& ); 
 225     void OnKeyUp( wxKeyEvent
& ); 
 226     void OnChar( wxKeyEvent
& ); 
 227     void OnEraseBackground( wxEraseEvent
& ); 
 228     void OnFocus( wxFocusEvent
& ); 
 230     DECLARE_DYNAMIC_CLASS(wxGridWindow
) 
 231     DECLARE_EVENT_TABLE() 
 232     DECLARE_NO_COPY_CLASS(wxGridWindow
) 
 236 class wxGridCellEditorEvtHandler 
: public wxEvtHandler
 
 239     wxGridCellEditorEvtHandler(wxGrid
* grid
, wxGridCellEditor
* editor
) 
 246     void OnKillFocus(wxFocusEvent
& event
); 
 247     void OnKeyDown(wxKeyEvent
& event
); 
 248     void OnChar(wxKeyEvent
& event
); 
 250     void SetInSetFocus(bool inSetFocus
) { m_inSetFocus 
= inSetFocus
; } 
 254     wxGridCellEditor
*   m_editor
; 
 256     // Work around the fact that a focus kill event can be sent to 
 257     // a combobox within a set focus event. 
 260     DECLARE_EVENT_TABLE() 
 261     DECLARE_DYNAMIC_CLASS(wxGridCellEditorEvtHandler
) 
 262     DECLARE_NO_COPY_CLASS(wxGridCellEditorEvtHandler
) 
 266 IMPLEMENT_ABSTRACT_CLASS(wxGridCellEditorEvtHandler
, wxEvtHandler
) 
 268 BEGIN_EVENT_TABLE( wxGridCellEditorEvtHandler
, wxEvtHandler 
) 
 269     EVT_KILL_FOCUS( wxGridCellEditorEvtHandler::OnKillFocus 
) 
 270     EVT_KEY_DOWN( wxGridCellEditorEvtHandler::OnKeyDown 
) 
 271     EVT_CHAR( wxGridCellEditorEvtHandler::OnChar 
) 
 276 // ---------------------------------------------------------------------------- 
 277 // the internal data representation used by wxGridCellAttrProvider 
 278 // ---------------------------------------------------------------------------- 
 280 // this class stores attributes set for cells 
 281 class WXDLLIMPEXP_ADV wxGridCellAttrData
 
 284     void SetAttr(wxGridCellAttr 
*attr
, int row
, int col
); 
 285     wxGridCellAttr 
*GetAttr(int row
, int col
) const; 
 286     void UpdateAttrRows( size_t pos
, int numRows 
); 
 287     void UpdateAttrCols( size_t pos
, int numCols 
); 
 290     // searches for the attr for given cell, returns wxNOT_FOUND if not found 
 291     int FindIndex(int row
, int col
) const; 
 293     wxGridCellWithAttrArray m_attrs
; 
 296 // this class stores attributes set for rows or columns 
 297 class WXDLLIMPEXP_ADV wxGridRowOrColAttrData
 
 300     // empty ctor to suppress warnings 
 301     wxGridRowOrColAttrData() { } 
 302     ~wxGridRowOrColAttrData(); 
 304     void SetAttr(wxGridCellAttr 
*attr
, int rowOrCol
); 
 305     wxGridCellAttr 
*GetAttr(int rowOrCol
) const; 
 306     void UpdateAttrRowsOrCols( size_t pos
, int numRowsOrCols 
); 
 309     wxArrayInt m_rowsOrCols
; 
 310     wxArrayAttrs m_attrs
; 
 313 // NB: this is just a wrapper around 3 objects: one which stores cell 
 314 //     attributes, and 2 others for row/col ones 
 315 class WXDLLIMPEXP_ADV wxGridCellAttrProviderData
 
 318     wxGridCellAttrData m_cellAttrs
; 
 319     wxGridRowOrColAttrData m_rowAttrs
, 
 324 // ---------------------------------------------------------------------------- 
 325 // data structures used for the data type registry 
 326 // ---------------------------------------------------------------------------- 
 328 struct wxGridDataTypeInfo
 
 330     wxGridDataTypeInfo(const wxString
& typeName
, 
 331                        wxGridCellRenderer
* renderer
, 
 332                        wxGridCellEditor
* editor
) 
 333         : m_typeName(typeName
), m_renderer(renderer
), m_editor(editor
) 
 336     ~wxGridDataTypeInfo() 
 338         wxSafeDecRef(m_renderer
); 
 339         wxSafeDecRef(m_editor
); 
 343     wxGridCellRenderer
* m_renderer
; 
 344     wxGridCellEditor
*   m_editor
; 
 346     DECLARE_NO_COPY_CLASS(wxGridDataTypeInfo
) 
 350 WX_DEFINE_ARRAY_WITH_DECL_PTR(wxGridDataTypeInfo
*, wxGridDataTypeInfoArray
, 
 351                                  class WXDLLIMPEXP_ADV
); 
 354 class WXDLLIMPEXP_ADV wxGridTypeRegistry
 
 357   wxGridTypeRegistry() {} 
 358     ~wxGridTypeRegistry(); 
 360     void RegisterDataType(const wxString
& typeName
, 
 361                      wxGridCellRenderer
* renderer
, 
 362                      wxGridCellEditor
* editor
); 
 364     // find one of already registered data types 
 365     int FindRegisteredDataType(const wxString
& typeName
); 
 367     // try to FindRegisteredDataType(), if this fails and typeName is one of 
 368     // standard typenames, register it and return its index 
 369     int FindDataType(const wxString
& typeName
); 
 371     // try to FindDataType(), if it fails see if it is not one of already 
 372     // registered data types with some params in which case clone the 
 373     // registered data type and set params for it 
 374     int FindOrCloneDataType(const wxString
& typeName
); 
 376     wxGridCellRenderer
* GetRenderer(int index
); 
 377     wxGridCellEditor
*   GetEditor(int index
); 
 380     wxGridDataTypeInfoArray m_typeinfo
; 
 383 // ---------------------------------------------------------------------------- 
 384 // conditional compilation 
 385 // ---------------------------------------------------------------------------- 
 387 #ifndef WXGRID_DRAW_LINES 
 388 #define WXGRID_DRAW_LINES 1 
 391 // ---------------------------------------------------------------------------- 
 393 // ---------------------------------------------------------------------------- 
 395 //#define DEBUG_ATTR_CACHE 
 396 #ifdef DEBUG_ATTR_CACHE 
 397     static size_t gs_nAttrCacheHits 
= 0; 
 398     static size_t gs_nAttrCacheMisses 
= 0; 
 399 #endif // DEBUG_ATTR_CACHE 
 401 // ---------------------------------------------------------------------------- 
 403 // ---------------------------------------------------------------------------- 
 405 wxGridCellCoords 
wxGridNoCellCoords( -1, -1 ); 
 406 wxRect           
wxGridNoCellRect( -1, -1, -1, -1 ); 
 409 // TODO: this doesn't work at all, grid cells have different sizes and approx 
 410 //       calculations don't work as because of the size mismatch scrollbars 
 411 //       sometimes fail to be shown when they should be or vice versa 
 413 //       The scroll bars may be a little flakey once in a while, but that is 
 414 //       surely much less horrible than having scroll lines of only 1!!! 
 417 //       Well, it's still seriously broken so it might be better but needs 
 420 static const size_t GRID_SCROLL_LINE_X 
= 15;  // 1; 
 421 static const size_t GRID_SCROLL_LINE_Y 
= GRID_SCROLL_LINE_X
; 
 423 // the size of hash tables used a bit everywhere (the max number of elements 
 424 // in these hash tables is the number of rows/columns) 
 425 static const int GRID_HASH_SIZE 
= 100; 
 428 // ---------------------------------------------------------------------------- 
 430 // ---------------------------------------------------------------------------- 
 432 static inline int GetScrollX(int x
) 
 434     return (x 
+ GRID_SCROLL_LINE_X 
- 1) / GRID_SCROLL_LINE_X
; 
 437 static inline int GetScrollY(int y
) 
 439     return (y 
+ GRID_SCROLL_LINE_Y 
- 1) / GRID_SCROLL_LINE_Y
; 
 443 // ============================================================================ 
 445 // ============================================================================ 
 447 // ---------------------------------------------------------------------------- 
 449 // ---------------------------------------------------------------------------- 
 451 wxGridCellEditor::wxGridCellEditor() 
 458 wxGridCellEditor::~wxGridCellEditor() 
 463 void wxGridCellEditor::Create(wxWindow
* WXUNUSED(parent
), 
 464                               wxWindowID 
WXUNUSED(id
), 
 465                               wxEvtHandler
* evtHandler
) 
 468         m_control
->PushEventHandler(evtHandler
); 
 471 void wxGridCellEditor::PaintBackground(const wxRect
& rectCell
, 
 472                                        wxGridCellAttr 
*attr
) 
 474     // erase the background because we might not fill the cell 
 475     wxClientDC 
dc(m_control
->GetParent()); 
 476     wxGridWindow
* gridWindow 
= wxDynamicCast(m_control
->GetParent(), wxGridWindow
); 
 478         gridWindow
->GetOwner()->PrepareDC(dc
); 
 480     dc
.SetPen(*wxTRANSPARENT_PEN
); 
 481     dc
.SetBrush(wxBrush(attr
->GetBackgroundColour(), wxSOLID
)); 
 482     dc
.DrawRectangle(rectCell
); 
 484     // redraw the control we just painted over 
 485     m_control
->Refresh(); 
 488 void wxGridCellEditor::Destroy() 
 492         m_control
->PopEventHandler(true /* delete it*/); 
 494         m_control
->Destroy(); 
 499 void wxGridCellEditor::Show(bool show
, wxGridCellAttr 
*attr
) 
 501     wxASSERT_MSG(m_control
, 
 502                  wxT("The wxGridCellEditor must be Created first!")); 
 503     m_control
->Show(show
); 
 507         // set the colours/fonts if we have any 
 510             m_colFgOld 
= m_control
->GetForegroundColour(); 
 511             m_control
->SetForegroundColour(attr
->GetTextColour()); 
 513             m_colBgOld 
= m_control
->GetBackgroundColour(); 
 514             m_control
->SetBackgroundColour(attr
->GetBackgroundColour()); 
 516 // Workaround for GTK+1 font setting problem on some platforms 
 517 #if !defined(__WXGTK__) || defined(__WXGTK20__) 
 518             m_fontOld 
= m_control
->GetFont(); 
 519             m_control
->SetFont(attr
->GetFont()); 
 521             // can't do anything more in the base class version, the other 
 522             // attributes may only be used by the derived classes 
 527         // restore the standard colours fonts 
 528         if ( m_colFgOld
.Ok() ) 
 530             m_control
->SetForegroundColour(m_colFgOld
); 
 531             m_colFgOld 
= wxNullColour
; 
 534         if ( m_colBgOld
.Ok() ) 
 536             m_control
->SetBackgroundColour(m_colBgOld
); 
 537             m_colBgOld 
= wxNullColour
; 
 539 // Workaround for GTK+1 font setting problem on some platforms 
 540 #if !defined(__WXGTK__) || defined(__WXGTK20__) 
 541         if ( m_fontOld
.Ok() ) 
 543             m_control
->SetFont(m_fontOld
); 
 544             m_fontOld 
= wxNullFont
; 
 550 void wxGridCellEditor::SetSize(const wxRect
& rect
) 
 552     wxASSERT_MSG(m_control
, 
 553                  wxT("The wxGridCellEditor must be Created first!")); 
 554     m_control
->SetSize(rect
, wxSIZE_ALLOW_MINUS_ONE
); 
 557 void wxGridCellEditor::HandleReturn(wxKeyEvent
& event
) 
 562 bool wxGridCellEditor::IsAcceptedKey(wxKeyEvent
& event
) 
 564     bool ctrl 
= event
.ControlDown(); 
 565     bool alt  
= event
.AltDown(); 
 567     // On the Mac the Alt key is more like shift and is used for entry of 
 568     // valid characters, so check for Ctrl and Meta instead. 
 569     alt 
= event
.MetaDown(); 
 572     // Assume it's not a valid char if ctrl or alt is down, but if both are 
 573     // down then it may be because of an AltGr key combination, so let them 
 574     // through in that case. 
 575     if ((ctrl 
|| alt
) && !(ctrl 
&& alt
)) 
 579     int key 
= event
.GetUnicodeKey(); 
 582     // if the unicode key code is not really a unicode character (it may 
 583     // be a function key or etc., the platforms appear to always give us a 
 584     // small value in this case) then fallback to the ascii key code but 
 585     // don't do anything for function keys or etc. 
 588         key 
= event
.GetKeyCode(); 
 589         keyOk 
= (key 
<= 127); 
 592 #else // !wxUSE_UNICODE 
 593     int key 
= event
.GetKeyCode(); 
 597 #endif // wxUSE_UNICODE/!wxUSE_UNICODE 
 600 void wxGridCellEditor::StartingKey(wxKeyEvent
& event
) 
 605 void wxGridCellEditor::StartingClick() 
 611 // ---------------------------------------------------------------------------- 
 612 // wxGridCellTextEditor 
 613 // ---------------------------------------------------------------------------- 
 615 wxGridCellTextEditor::wxGridCellTextEditor() 
 620 void wxGridCellTextEditor::Create(wxWindow
* parent
, 
 622                                   wxEvtHandler
* evtHandler
) 
 624     m_control 
= new wxTextCtrl(parent
, id
, wxEmptyString
, 
 625                                wxDefaultPosition
, wxDefaultSize
 
 626 #if defined(__WXMSW__) 
 627                                , wxTE_PROCESS_TAB 
| wxTE_AUTO_SCROLL
 
 631     // set max length allowed in the textctrl, if the parameter was set 
 634         ((wxTextCtrl
*)m_control
)->SetMaxLength(m_maxChars
); 
 637     wxGridCellEditor::Create(parent
, id
, evtHandler
); 
 640 void wxGridCellTextEditor::PaintBackground(const wxRect
& WXUNUSED(rectCell
), 
 641                                            wxGridCellAttr 
* WXUNUSED(attr
)) 
 643     // as we fill the entire client area, don't do anything here to minimize 
 647 void wxGridCellTextEditor::SetSize(const wxRect
& rectOrig
) 
 649     wxRect 
rect(rectOrig
); 
 651     // Make the edit control large enough to allow for internal 
 654     // TODO: remove this if the text ctrl sizing is improved esp. for 
 657 #if defined(__WXGTK__) 
 666     int extra_x 
= ( rect
.x 
> 2 )? 2 : 1; 
 668 // MB: treat MSW separately here otherwise the caret doesn't show 
 669 // when the editor is in the first row. 
 670 #if defined(__WXMSW__) 
 673     int extra_y 
= ( rect
.y 
> 2 )? 2 : 1; 
 676 #if defined(__WXMOTIF__) 
 680     rect
.SetLeft( wxMax(0, rect
.x 
- extra_x
) ); 
 681     rect
.SetTop( wxMax(0, rect
.y 
- extra_y
) ); 
 682     rect
.SetRight( rect
.GetRight() + 2*extra_x 
); 
 683     rect
.SetBottom( rect
.GetBottom() + 2*extra_y 
); 
 686     wxGridCellEditor::SetSize(rect
); 
 689 void wxGridCellTextEditor::BeginEdit(int row
, int col
, wxGrid
* grid
) 
 691     wxASSERT_MSG(m_control
, 
 692                  wxT("The wxGridCellEditor must be Created first!")); 
 694     m_startValue 
= grid
->GetTable()->GetValue(row
, col
); 
 696     DoBeginEdit(m_startValue
); 
 699 void wxGridCellTextEditor::DoBeginEdit(const wxString
& startValue
) 
 701     Text()->SetValue(startValue
); 
 702     Text()->SetInsertionPointEnd(); 
 703     Text()->SetSelection(-1,-1); 
 707 bool wxGridCellTextEditor::EndEdit(int row
, int col
, 
 710     wxASSERT_MSG(m_control
, 
 711                  wxT("The wxGridCellEditor must be Created first!")); 
 713     bool changed 
= false; 
 714     wxString value 
= Text()->GetValue(); 
 715     if (value 
!= m_startValue
) 
 719         grid
->GetTable()->SetValue(row
, col
, value
); 
 721     m_startValue 
= wxEmptyString
; 
 722     // No point in setting the text of the hidden control 
 723     //Text()->SetValue(m_startValue); 
 729 void wxGridCellTextEditor::Reset() 
 731     wxASSERT_MSG(m_control
, 
 732                  wxT("The wxGridCellEditor must be Created first!")); 
 734     DoReset(m_startValue
); 
 737 void wxGridCellTextEditor::DoReset(const wxString
& startValue
) 
 739     Text()->SetValue(startValue
); 
 740     Text()->SetInsertionPointEnd(); 
 743 bool wxGridCellTextEditor::IsAcceptedKey(wxKeyEvent
& event
) 
 745     return wxGridCellEditor::IsAcceptedKey(event
); 
 748 void wxGridCellTextEditor::StartingKey(wxKeyEvent
& event
) 
 750     // Since this is now happening in the EVT_CHAR event EmulateKeyPress is no 
 751     // longer an appropriate way to get the character into the text control. 
 752     // Do it ourselves instead.  We know that if we get this far that we have 
 753     // a valid character, so not a whole lot of testing needs to be done. 
 755     wxTextCtrl
* tc 
= Text(); 
 760     ch 
= event
.GetUnicodeKey(); 
 762         ch 
= (wxChar
)event
.GetKeyCode(); 
 764     ch 
= (wxChar
)event
.GetKeyCode(); 
 769             // delete the character at the cursor 
 770             pos 
= tc
->GetInsertionPoint(); 
 771             if (pos 
< tc
->GetLastPosition()) 
 772                 tc
->Remove(pos
, pos
+1); 
 776             // delete the character before the cursor 
 777             pos 
= tc
->GetInsertionPoint(); 
 779                 tc
->Remove(pos
-1, pos
); 
 788 void wxGridCellTextEditor::HandleReturn( wxKeyEvent
& 
 789                                          WXUNUSED_GTK(WXUNUSED_MOTIF(event
)) ) 
 791 #if defined(__WXMOTIF__) || defined(__WXGTK__) 
 792     // wxMotif needs a little extra help... 
 793     size_t pos 
= (size_t)( Text()->GetInsertionPoint() ); 
 794     wxString 
s( Text()->GetValue() ); 
 795     s 
= s
.Left(pos
) + wxT("\n") + s
.Mid(pos
); 
 797     Text()->SetInsertionPoint( pos 
); 
 799     // the other ports can handle a Return key press 
 805 void wxGridCellTextEditor::SetParameters(const wxString
& params
) 
 815         if ( !params
.ToLong(&tmp
) ) 
 817             wxLogDebug(_T("Invalid wxGridCellTextEditor parameter string '%s' ignored"), params
.c_str()); 
 821             m_maxChars 
= (size_t)tmp
; 
 826 // return the value in the text control 
 827 wxString 
wxGridCellTextEditor::GetValue() const 
 829   return Text()->GetValue(); 
 832 // ---------------------------------------------------------------------------- 
 833 // wxGridCellNumberEditor 
 834 // ---------------------------------------------------------------------------- 
 836 wxGridCellNumberEditor::wxGridCellNumberEditor(int min
, int max
) 
 842 void wxGridCellNumberEditor::Create(wxWindow
* parent
, 
 844                                     wxEvtHandler
* evtHandler
) 
 849         // create a spin ctrl 
 850         m_control 
= new wxSpinCtrl(parent
, wxID_ANY
, wxEmptyString
, 
 851                                    wxDefaultPosition
, wxDefaultSize
, 
 855         wxGridCellEditor::Create(parent
, id
, evtHandler
); 
 860         // just a text control 
 861         wxGridCellTextEditor::Create(parent
, id
, evtHandler
); 
 864         Text()->SetValidator(wxTextValidator(wxFILTER_NUMERIC
)); 
 865 #endif // wxUSE_VALIDATORS 
 869 void wxGridCellNumberEditor::BeginEdit(int row
, int col
, wxGrid
* grid
) 
 871     // first get the value 
 872     wxGridTableBase 
*table 
= grid
->GetTable(); 
 873     if ( table
->CanGetValueAs(row
, col
, wxGRID_VALUE_NUMBER
) ) 
 875         m_valueOld 
= table
->GetValueAsLong(row
, col
); 
 880         wxString sValue 
= table
->GetValue(row
, col
); 
 881         if (! sValue
.ToLong(&m_valueOld
) && ! sValue
.empty()) 
 883             wxFAIL_MSG( _T("this cell doesn't have numeric value") ); 
 891         Spin()->SetValue((int)m_valueOld
); 
 897         DoBeginEdit(GetString()); 
 901 bool wxGridCellNumberEditor::EndEdit(int row
, int col
, 
 911         value 
= Spin()->GetValue(); 
 912         changed 
= value 
!= m_valueOld
; 
 914             text 
= wxString::Format(wxT("%ld"), value
); 
 919         text 
= Text()->GetValue(); 
 920         changed 
= (text
.empty() || text
.ToLong(&value
)) && (value 
!= m_valueOld
); 
 925         if (grid
->GetTable()->CanSetValueAs(row
, col
, wxGRID_VALUE_NUMBER
)) 
 926             grid
->GetTable()->SetValueAsLong(row
, col
, value
); 
 928             grid
->GetTable()->SetValue(row
, col
, text
); 
 934 void wxGridCellNumberEditor::Reset() 
 939         Spin()->SetValue((int)m_valueOld
); 
 944         DoReset(GetString()); 
 948 bool wxGridCellNumberEditor::IsAcceptedKey(wxKeyEvent
& event
) 
 950     if ( wxGridCellEditor::IsAcceptedKey(event
) ) 
 952         int keycode 
= event
.GetKeyCode(); 
 953         if ( (keycode 
< 128) && 
 954              (wxIsdigit(keycode
) || keycode 
== '+' || keycode 
== '-')) 
 963 void wxGridCellNumberEditor::StartingKey(wxKeyEvent
& event
) 
 965     int keycode 
= event
.GetKeyCode(); 
 968         if ( wxIsdigit(keycode
) || keycode 
== '+' || keycode 
== '-') 
 970             wxGridCellTextEditor::StartingKey(event
); 
 979         if ( wxIsdigit(keycode
) ) 
 981             wxSpinCtrl
* spin 
= (wxSpinCtrl
*)m_control
; 
 982             spin
->SetValue(keycode 
- '0'); 
 983             spin
->SetSelection(1,1); 
 991 void wxGridCellNumberEditor::SetParameters(const wxString
& params
) 
1002         if ( params
.BeforeFirst(_T(',')).ToLong(&tmp
) ) 
1006             if ( params
.AfterFirst(_T(',')).ToLong(&tmp
) ) 
1010                 // skip the error message below 
1015         wxLogDebug(_T("Invalid wxGridCellNumberEditor parameter string '%s' ignored"), params
.c_str()); 
1019 // return the value in the spin control if it is there (the text control otherwise) 
1020 wxString 
wxGridCellNumberEditor::GetValue() const 
1027         long value 
= Spin()->GetValue(); 
1028         s
.Printf(wxT("%ld"), value
); 
1033         s 
= Text()->GetValue(); 
1039 // ---------------------------------------------------------------------------- 
1040 // wxGridCellFloatEditor 
1041 // ---------------------------------------------------------------------------- 
1043 wxGridCellFloatEditor::wxGridCellFloatEditor(int width
, int precision
) 
1046     m_precision 
= precision
; 
1049 void wxGridCellFloatEditor::Create(wxWindow
* parent
, 
1051                                    wxEvtHandler
* evtHandler
) 
1053     wxGridCellTextEditor::Create(parent
, id
, evtHandler
); 
1055 #if wxUSE_VALIDATORS 
1056     Text()->SetValidator(wxTextValidator(wxFILTER_NUMERIC
)); 
1057 #endif // wxUSE_VALIDATORS 
1060 void wxGridCellFloatEditor::BeginEdit(int row
, int col
, wxGrid
* grid
) 
1062     // first get the value 
1063     wxGridTableBase 
*table 
= grid
->GetTable(); 
1064     if ( table
->CanGetValueAs(row
, col
, wxGRID_VALUE_FLOAT
) ) 
1066         m_valueOld 
= table
->GetValueAsDouble(row
, col
); 
1071         wxString sValue 
= table
->GetValue(row
, col
); 
1072         if (! sValue
.ToDouble(&m_valueOld
) && ! sValue
.empty()) 
1074             wxFAIL_MSG( _T("this cell doesn't have float value") ); 
1079     DoBeginEdit(GetString()); 
1082 bool wxGridCellFloatEditor::EndEdit(int row
, int col
, 
1086     wxString 
text(Text()->GetValue()); 
1088     if ( (text
.empty() || text
.ToDouble(&value
)) && 
1089             !wxIsSameDouble(value
, m_valueOld
) ) 
1091         if (grid
->GetTable()->CanSetValueAs(row
, col
, wxGRID_VALUE_FLOAT
)) 
1092             grid
->GetTable()->SetValueAsDouble(row
, col
, value
); 
1094             grid
->GetTable()->SetValue(row
, col
, text
); 
1101 void wxGridCellFloatEditor::Reset() 
1103     DoReset(GetString()); 
1106 void wxGridCellFloatEditor::StartingKey(wxKeyEvent
& event
) 
1108     int keycode 
= event
.GetKeyCode(); 
1110     tmpbuf
[0] = (char) keycode
; 
1112     wxString 
strbuf(tmpbuf
, *wxConvCurrent
); 
1114     bool is_decimal_point 
= ( strbuf 
== 
1115        wxLocale::GetInfo(wxLOCALE_DECIMAL_POINT
, wxLOCALE_CAT_NUMBER
) ); 
1117     bool is_decimal_point 
= ( strbuf 
== _T(".") ); 
1119     if ( wxIsdigit(keycode
) || keycode 
== '+' || keycode 
== '-' 
1120          || is_decimal_point 
) 
1122         wxGridCellTextEditor::StartingKey(event
); 
1124         // skip Skip() below 
1131 void wxGridCellFloatEditor::SetParameters(const wxString
& params
) 
1142         if ( params
.BeforeFirst(_T(',')).ToLong(&tmp
) ) 
1146             if ( params
.AfterFirst(_T(',')).ToLong(&tmp
) ) 
1148                 m_precision 
= (int)tmp
; 
1150                 // skip the error message below 
1155         wxLogDebug(_T("Invalid wxGridCellFloatEditor parameter string '%s' ignored"), params
.c_str()); 
1159 wxString 
wxGridCellFloatEditor::GetString() const 
1162     if ( m_precision 
== -1 && m_width 
!= -1) 
1164         // default precision 
1165         fmt
.Printf(_T("%%%d.f"), m_width
); 
1167     else if ( m_precision 
!= -1 && m_width 
== -1) 
1170         fmt
.Printf(_T("%%.%df"), m_precision
); 
1172     else if ( m_precision 
!= -1 && m_width 
!= -1 ) 
1174         fmt
.Printf(_T("%%%d.%df"), m_width
, m_precision
); 
1178         // default width/precision 
1182     return wxString::Format(fmt
, m_valueOld
); 
1185 bool wxGridCellFloatEditor::IsAcceptedKey(wxKeyEvent
& event
) 
1187     if ( wxGridCellEditor::IsAcceptedKey(event
) ) 
1189         int keycode 
= event
.GetKeyCode(); 
1190         printf("%d\n", keycode
); 
1191         // accept digits, 'e' as in '1e+6', also '-', '+', and '.' 
1193         tmpbuf
[0] = (char) keycode
; 
1195         wxString 
strbuf(tmpbuf
, *wxConvCurrent
); 
1197         bool is_decimal_point 
= 
1198             ( strbuf 
== wxLocale::GetInfo(wxLOCALE_DECIMAL_POINT
, 
1199                                           wxLOCALE_CAT_NUMBER
) ); 
1201         bool is_decimal_point 
= ( strbuf 
== _T(".") ); 
1203         if ( (keycode 
< 128) && 
1204              (wxIsdigit(keycode
) || tolower(keycode
) == 'e' || 
1205               is_decimal_point 
|| keycode 
== '+' || keycode 
== '-') ) 
1212 #endif // wxUSE_TEXTCTRL 
1216 // ---------------------------------------------------------------------------- 
1217 // wxGridCellBoolEditor 
1218 // ---------------------------------------------------------------------------- 
1220 void wxGridCellBoolEditor::Create(wxWindow
* parent
, 
1222                                   wxEvtHandler
* evtHandler
) 
1224     m_control 
= new wxCheckBox(parent
, id
, wxEmptyString
, 
1225                                wxDefaultPosition
, wxDefaultSize
, 
1228     wxGridCellEditor::Create(parent
, id
, evtHandler
); 
1231 void wxGridCellBoolEditor::SetSize(const wxRect
& r
) 
1233     bool resize 
= false; 
1234     wxSize size 
= m_control
->GetSize(); 
1235     wxCoord minSize 
= wxMin(r
.width
, r
.height
); 
1237     // check if the checkbox is not too big/small for this cell 
1238     wxSize sizeBest 
= m_control
->GetBestSize(); 
1239     if ( !(size 
== sizeBest
) ) 
1241         // reset to default size if it had been made smaller 
1247     if ( size
.x 
>= minSize 
|| size
.y 
>= minSize 
) 
1249         // leave 1 pixel margin 
1250         size
.x 
= size
.y 
= minSize 
- 2; 
1257         m_control
->SetSize(size
); 
1260     // position it in the centre of the rectangle (TODO: support alignment?) 
1262 #if defined(__WXGTK__) || defined (__WXMOTIF__) 
1263     // the checkbox without label still has some space to the right in wxGTK, 
1264     // so shift it to the right 
1266 #elif defined(__WXMSW__) 
1267     // here too, but in other way 
1272     int hAlign 
= wxALIGN_CENTRE
; 
1273     int vAlign 
= wxALIGN_CENTRE
; 
1275         GetCellAttr()->GetAlignment(& hAlign
, & vAlign
); 
1278     if (hAlign 
== wxALIGN_LEFT
) 
1284         y 
= r
.y 
+ r
.height
/2 - size
.y
/2; 
1286     else if (hAlign 
== wxALIGN_RIGHT
) 
1288         x 
= r
.x 
+ r
.width 
- size
.x 
- 2; 
1289         y 
= r
.y 
+ r
.height
/2 - size
.y
/2; 
1291     else if (hAlign 
== wxALIGN_CENTRE
) 
1293         x 
= r
.x 
+ r
.width
/2 - size
.x
/2; 
1294         y 
= r
.y 
+ r
.height
/2 - size
.y
/2; 
1297     m_control
->Move(x
, y
); 
1300 void wxGridCellBoolEditor::Show(bool show
, wxGridCellAttr 
*attr
) 
1302     m_control
->Show(show
); 
1306         wxColour colBg 
= attr 
? attr
->GetBackgroundColour() : *wxLIGHT_GREY
; 
1307         CBox()->SetBackgroundColour(colBg
); 
1311 void wxGridCellBoolEditor::BeginEdit(int row
, int col
, wxGrid
* grid
) 
1313     wxASSERT_MSG(m_control
, 
1314                  wxT("The wxGridCellEditor must be Created first!")); 
1316     if (grid
->GetTable()->CanGetValueAs(row
, col
, wxGRID_VALUE_BOOL
)) 
1317         m_startValue 
= grid
->GetTable()->GetValueAsBool(row
, col
); 
1320         wxString 
cellval( grid
->GetTable()->GetValue(row
, col
) ); 
1321         m_startValue 
= !( !cellval 
|| (cellval 
== wxT("0")) ); 
1323     CBox()->SetValue(m_startValue
); 
1327 bool wxGridCellBoolEditor::EndEdit(int row
, int col
, 
1330     wxASSERT_MSG(m_control
, 
1331                  wxT("The wxGridCellEditor must be Created first!")); 
1333     bool changed 
= false; 
1334     bool value 
= CBox()->GetValue(); 
1335     if ( value 
!= m_startValue 
) 
1340         if (grid
->GetTable()->CanGetValueAs(row
, col
, wxGRID_VALUE_BOOL
)) 
1341             grid
->GetTable()->SetValueAsBool(row
, col
, value
); 
1343             grid
->GetTable()->SetValue(row
, col
, value 
? _T("1") : wxEmptyString
); 
1349 void wxGridCellBoolEditor::Reset() 
1351     wxASSERT_MSG(m_control
, 
1352                  wxT("The wxGridCellEditor must be Created first!")); 
1354     CBox()->SetValue(m_startValue
); 
1357 void wxGridCellBoolEditor::StartingClick() 
1359     CBox()->SetValue(!CBox()->GetValue()); 
1362 bool wxGridCellBoolEditor::IsAcceptedKey(wxKeyEvent
& event
) 
1364     if ( wxGridCellEditor::IsAcceptedKey(event
) ) 
1366         int keycode 
= event
.GetKeyCode(); 
1379 void wxGridCellBoolEditor::StartingKey(wxKeyEvent
& event
) 
1381     int keycode 
= event
.GetKeyCode(); 
1385             CBox()->SetValue(!CBox()->GetValue()); 
1389             CBox()->SetValue(true); 
1393             CBox()->SetValue(false); 
1399 // return the value as "1" for true and the empty string for false 
1400 wxString 
wxGridCellBoolEditor::GetValue() const 
1402   bool bSet 
= CBox()->GetValue(); 
1403   return bSet 
? _T("1") : wxEmptyString
; 
1406 #endif // wxUSE_CHECKBOX 
1410 // ---------------------------------------------------------------------------- 
1411 // wxGridCellChoiceEditor 
1412 // ---------------------------------------------------------------------------- 
1414 wxGridCellChoiceEditor::wxGridCellChoiceEditor(const wxArrayString
& choices
, 
1416     : m_choices(choices
), 
1417       m_allowOthers(allowOthers
) { } 
1419 wxGridCellChoiceEditor::wxGridCellChoiceEditor(size_t count
, 
1420                                                const wxString choices
[], 
1422                       : m_allowOthers(allowOthers
) 
1426         m_choices
.Alloc(count
); 
1427         for ( size_t n 
= 0; n 
< count
; n
++ ) 
1429             m_choices
.Add(choices
[n
]); 
1434 wxGridCellEditor 
*wxGridCellChoiceEditor::Clone() const 
1436     wxGridCellChoiceEditor 
*editor 
= new wxGridCellChoiceEditor
; 
1437     editor
->m_allowOthers 
= m_allowOthers
; 
1438     editor
->m_choices 
= m_choices
; 
1443 void wxGridCellChoiceEditor::Create(wxWindow
* parent
, 
1445                                     wxEvtHandler
* evtHandler
) 
1447     m_control 
= new wxComboBox(parent
, id
, wxEmptyString
, 
1448                                wxDefaultPosition
, wxDefaultSize
, 
1450                                m_allowOthers 
? 0 : wxCB_READONLY
); 
1452     wxGridCellEditor::Create(parent
, id
, evtHandler
); 
1455 void wxGridCellChoiceEditor::PaintBackground(const wxRect
& rectCell
, 
1456                                              wxGridCellAttr 
* attr
) 
1458     // as we fill the entire client area, don't do anything here to minimize 
1461     // TODO: It doesn't actually fill the client area since the height of a 
1462     // combo always defaults to the standard...  Until someone has time to 
1463     // figure out the right rectangle to paint, just do it the normal way... 
1464     wxGridCellEditor::PaintBackground(rectCell
, attr
); 
1467 void wxGridCellChoiceEditor::BeginEdit(int row
, int col
, wxGrid
* grid
) 
1469     wxASSERT_MSG(m_control
, 
1470                  wxT("The wxGridCellEditor must be Created first!")); 
1472     wxGridCellEditorEvtHandler
* evtHandler 
= NULL
; 
1474         evtHandler 
= wxDynamicCast(m_control
->GetEventHandler(), wxGridCellEditorEvtHandler
); 
1476     // Don't immediately end if we get a kill focus event within BeginEdit 
1478         evtHandler
->SetInSetFocus(true); 
1480     m_startValue 
= grid
->GetTable()->GetValue(row
, col
); 
1483         Combo()->SetValue(m_startValue
); 
1486         // find the right position, or default to the first if not found 
1487         int pos 
= Combo()->FindString(m_startValue
); 
1488         if (pos 
== wxNOT_FOUND
) 
1490         Combo()->SetSelection(pos
); 
1492     Combo()->SetInsertionPointEnd(); 
1493     Combo()->SetFocus(); 
1497         // When dropping down the menu, a kill focus event 
1498         // happens after this point, so we can't reset the flag yet. 
1499 #if !defined(__WXGTK20__) 
1500         evtHandler
->SetInSetFocus(false); 
1505 bool wxGridCellChoiceEditor::EndEdit(int row
, int col
, 
1508     wxString value 
= Combo()->GetValue(); 
1509     if ( value 
== m_startValue 
) 
1512     grid
->GetTable()->SetValue(row
, col
, value
); 
1517 void wxGridCellChoiceEditor::Reset() 
1519     Combo()->SetValue(m_startValue
); 
1520     Combo()->SetInsertionPointEnd(); 
1523 void wxGridCellChoiceEditor::SetParameters(const wxString
& params
) 
1533     wxStringTokenizer 
tk(params
, _T(',')); 
1534     while ( tk
.HasMoreTokens() ) 
1536         m_choices
.Add(tk
.GetNextToken()); 
1540 // return the value in the text control 
1541 wxString 
wxGridCellChoiceEditor::GetValue() const 
1543   return Combo()->GetValue(); 
1546 #endif // wxUSE_COMBOBOX 
1548 // ---------------------------------------------------------------------------- 
1549 // wxGridCellEditorEvtHandler 
1550 // ---------------------------------------------------------------------------- 
1552 void wxGridCellEditorEvtHandler::OnKillFocus(wxFocusEvent
& event
) 
1554     // Don't disable the cell if we're just starting to edit it 
1559     m_grid
->DisableCellEditControl(); 
1564 void wxGridCellEditorEvtHandler::OnKeyDown(wxKeyEvent
& event
) 
1566     switch ( event
.GetKeyCode() ) 
1570             m_grid
->DisableCellEditControl(); 
1574             m_grid
->GetEventHandler()->ProcessEvent( event 
); 
1578         case WXK_NUMPAD_ENTER
: 
1579             if (!m_grid
->GetEventHandler()->ProcessEvent(event
)) 
1580                 m_editor
->HandleReturn(event
); 
1588 void wxGridCellEditorEvtHandler::OnChar(wxKeyEvent
& event
) 
1590     int row 
= m_grid
->GetGridCursorRow(); 
1591     int col 
= m_grid
->GetGridCursorCol(); 
1592     wxRect rect 
= m_grid
->CellToRect( row
, col 
); 
1594     m_grid
->GetGridWindow()->GetClientSize( &cw
, &ch 
); 
1595     // if cell width is smaller than grid client area, cell is wholly visible 
1596     bool wholeCellVisible 
= (rect
.GetWidth() < cw
); 
1598     switch ( event
.GetKeyCode() ) 
1603         case WXK_NUMPAD_ENTER
: 
1608             if( wholeCellVisible 
) 
1610                 // no special processing needed... 
1615             // do special processing for partly visible cell... 
1617             // get the widths of all cells previous to this one 
1619             for ( int i 
= 0; i 
< col
; i
++ ) 
1621                 colXPos 
+= m_grid
->GetColSize(i
); 
1624             int xUnit 
= 1, yUnit 
= 1; 
1625             m_grid
->GetScrollPixelsPerUnit(&xUnit
, &yUnit
); 
1628                 m_grid
->Scroll(colXPos
/xUnit
-1, m_grid
->GetScrollPos(wxVERTICAL
)); 
1632                 m_grid
->Scroll(colXPos
/xUnit
, m_grid
->GetScrollPos(wxVERTICAL
)); 
1639             if( wholeCellVisible 
) 
1641                 // no special processing needed... 
1646             // do special processing for partly visible cell... 
1649             wxString value 
= m_grid
->GetCellValue(row
, col
); 
1650             if ( wxEmptyString 
!= value 
) 
1652                 // get width of cell CONTENTS (text) 
1654                 wxFont font 
= m_grid
->GetCellFont(row
, col
); 
1655                 m_grid
->GetTextExtent(value
, &textWidth
, &y
, NULL
, NULL
, &font
); 
1656                 // try to RIGHT align the text by scrolling 
1657                 int client_right 
= m_grid
->GetGridWindow()->GetClientSize().GetWidth(); 
1658                 // (m_grid->GetScrollLineX()*2) is a factor for not scrolling to far, 
1659                 // otherwise the last part of the cell content might be hidden below the scroll bar 
1660                 // FIXME: maybe there is a more suitable correction? 
1661                 textWidth 
-= (client_right 
- (m_grid
->GetScrollLineX()*2)); 
1662                 if ( textWidth 
< 0 ) 
1668             // get the widths of all cells previous to this one 
1670             for ( int i 
= 0; i 
< col
; i
++ ) 
1672                 colXPos 
+= m_grid
->GetColSize(i
); 
1674             // and add the (modified) text width of the cell contents 
1675             // as we'd like to see the last part of the cell contents 
1676             colXPos 
+= textWidth
; 
1678             int xUnit 
= 1, yUnit 
= 1; 
1679             m_grid
->GetScrollPixelsPerUnit(&xUnit
, &yUnit
); 
1680             m_grid
->Scroll(colXPos
/xUnit
-1, m_grid
->GetScrollPos(wxVERTICAL
)); 
1690 // ---------------------------------------------------------------------------- 
1691 // wxGridCellWorker is an (almost) empty common base class for 
1692 // wxGridCellRenderer and wxGridCellEditor managing ref counting 
1693 // ---------------------------------------------------------------------------- 
1695 void wxGridCellWorker::SetParameters(const wxString
& WXUNUSED(params
)) 
1700 wxGridCellWorker::~wxGridCellWorker() 
1704 // ============================================================================ 
1706 // ============================================================================ 
1708 // ---------------------------------------------------------------------------- 
1709 // wxGridCellRenderer 
1710 // ---------------------------------------------------------------------------- 
1712 void wxGridCellRenderer::Draw(wxGrid
& grid
, 
1713                               wxGridCellAttr
& attr
, 
1716                               int WXUNUSED(row
), int WXUNUSED(col
), 
1719     dc
.SetBackgroundMode( wxSOLID 
); 
1721     // grey out fields if the grid is disabled 
1722     if ( grid
.IsEnabled() ) 
1726             dc
.SetBrush( wxBrush(grid
.GetSelectionBackground(), wxSOLID
) ); 
1730             dc
.SetBrush( wxBrush(attr
.GetBackgroundColour(), wxSOLID
) ); 
1735         dc
.SetBrush(wxBrush(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE
), wxSOLID
)); 
1738     dc
.SetPen( *wxTRANSPARENT_PEN 
); 
1739     dc
.DrawRectangle(rect
); 
1742 // ---------------------------------------------------------------------------- 
1743 // wxGridCellStringRenderer 
1744 // ---------------------------------------------------------------------------- 
1746 void wxGridCellStringRenderer::SetTextColoursAndFont(const wxGrid
& grid
, 
1747                                                      const wxGridCellAttr
& attr
, 
1751     dc
.SetBackgroundMode( wxTRANSPARENT 
); 
1753     // TODO some special colours for attr.IsReadOnly() case? 
1755     // different coloured text when the grid is disabled 
1756     if ( grid
.IsEnabled() ) 
1760           dc
.SetTextBackground( grid
.GetSelectionBackground() ); 
1761           dc
.SetTextForeground( grid
.GetSelectionForeground() ); 
1765           dc
.SetTextBackground( attr
.GetBackgroundColour() ); 
1766           dc
.SetTextForeground( attr
.GetTextColour() ); 
1771       dc
.SetTextBackground(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE
)); 
1772       dc
.SetTextForeground(wxSystemSettings::GetColour(wxSYS_COLOUR_GRAYTEXT
)); 
1775     dc
.SetFont( attr
.GetFont() ); 
1778 wxSize 
wxGridCellStringRenderer::DoGetBestSize(const wxGridCellAttr
& attr
, 
1780                                                const wxString
& text
) 
1782     wxCoord x 
= 0, y 
= 0, max_x 
= 0; 
1783     dc
.SetFont(attr
.GetFont()); 
1784     wxStringTokenizer 
tk(text
, _T('\n')); 
1785     while ( tk
.HasMoreTokens() ) 
1787         dc
.GetTextExtent(tk
.GetNextToken(), &x
, &y
); 
1788         max_x 
= wxMax(max_x
, x
); 
1791     y 
*= 1 + text
.Freq(wxT('\n')); // multiply by the number of lines. 
1793     return wxSize(max_x
, y
); 
1796 wxSize 
wxGridCellStringRenderer::GetBestSize(wxGrid
& grid
, 
1797                                              wxGridCellAttr
& attr
, 
1801     return DoGetBestSize(attr
, dc
, grid
.GetCellValue(row
, col
)); 
1804 void wxGridCellStringRenderer::Draw(wxGrid
& grid
, 
1805                                     wxGridCellAttr
& attr
, 
1807                                     const wxRect
& rectCell
, 
1811     wxRect rect 
= rectCell
; 
1814     // erase only this cells background, overflow cells should have been erased 
1815     wxGridCellRenderer::Draw(grid
, attr
, dc
, rectCell
, row
, col
, isSelected
); 
1818     attr
.GetAlignment(&hAlign
, &vAlign
); 
1820     int overflowCols 
= 0; 
1822     if (attr
.GetOverflow()) 
1824         int cols 
= grid
.GetNumberCols(); 
1825         int best_width 
= GetBestSize(grid
,attr
,dc
,row
,col
).GetWidth(); 
1826         int cell_rows
, cell_cols
; 
1827         attr
.GetSize( &cell_rows
, &cell_cols 
); // shouldn't get here if <=0 
1828         if ((best_width 
> rectCell
.width
) && (col 
< cols
) && grid
.GetTable()) 
1830             int i
, c_cols
, c_rows
; 
1831             for (i 
= col
+cell_cols
; i 
< cols
; i
++) 
1833                 bool is_empty 
= true; 
1834                 for (int j
=row
; j
<row
+cell_rows
; j
++) 
1836                     // check w/ anchor cell for multicell block 
1837                     grid
.GetCellSize(j
, i
, &c_rows
, &c_cols
); 
1838                     if (c_rows 
> 0) c_rows 
= 0; 
1839                     if (!grid
.GetTable()->IsEmptyCell(j
+c_rows
, i
)) 
1846                     rect
.width 
+= grid
.GetColSize(i
); 
1852                 if (rect
.width 
>= best_width
) 
1855             overflowCols 
= i 
- col 
- cell_cols 
+ 1; 
1856             if (overflowCols 
>= cols
) 
1857                 overflowCols 
= cols 
- 1; 
1860         if (overflowCols 
> 0) // redraw overflow cells w/ proper hilight 
1862             hAlign 
= wxALIGN_LEFT
; // if oveflowed then it's left aligned 
1864             clip
.x 
+= rectCell
.width
; 
1865             // draw each overflow cell individually 
1866             int col_end 
= col
+cell_cols
+overflowCols
; 
1867             if (col_end 
>= grid
.GetNumberCols()) 
1868                 col_end 
= grid
.GetNumberCols() - 1; 
1869             for (int i 
= col
+cell_cols
; i 
<= col_end
; i
++) 
1871                 clip
.width 
= grid
.GetColSize(i
) - 1; 
1872                 dc
.DestroyClippingRegion(); 
1873                 dc
.SetClippingRegion(clip
); 
1875                 SetTextColoursAndFont(grid
, attr
, dc
, 
1876                         grid
.IsInSelection(row
,i
)); 
1878                 grid
.DrawTextRectangle(dc
, grid
.GetCellValue(row
, col
), 
1879                         rect
, hAlign
, vAlign
); 
1880                 clip
.x 
+= grid
.GetColSize(i
) - 1; 
1886             dc
.DestroyClippingRegion(); 
1890     // now we only have to draw the text 
1891     SetTextColoursAndFont(grid
, attr
, dc
, isSelected
); 
1893     grid
.DrawTextRectangle(dc
, grid
.GetCellValue(row
, col
), 
1894                            rect
, hAlign
, vAlign
); 
1897 // ---------------------------------------------------------------------------- 
1898 // wxGridCellNumberRenderer 
1899 // ---------------------------------------------------------------------------- 
1901 wxString 
wxGridCellNumberRenderer::GetString(const wxGrid
& grid
, int row
, int col
) 
1903     wxGridTableBase 
*table 
= grid
.GetTable(); 
1905     if ( table
->CanGetValueAs(row
, col
, wxGRID_VALUE_NUMBER
) ) 
1907         text
.Printf(_T("%ld"), table
->GetValueAsLong(row
, col
)); 
1911         text 
= table
->GetValue(row
, col
); 
1917 void wxGridCellNumberRenderer::Draw(wxGrid
& grid
, 
1918                                     wxGridCellAttr
& attr
, 
1920                                     const wxRect
& rectCell
, 
1924     wxGridCellRenderer::Draw(grid
, attr
, dc
, rectCell
, row
, col
, isSelected
); 
1926     SetTextColoursAndFont(grid
, attr
, dc
, isSelected
); 
1928     // draw the text right aligned by default 
1930     attr
.GetAlignment(&hAlign
, &vAlign
); 
1931     hAlign 
= wxALIGN_RIGHT
; 
1933     wxRect rect 
= rectCell
; 
1936     grid
.DrawTextRectangle(dc
, GetString(grid
, row
, col
), rect
, hAlign
, vAlign
); 
1939 wxSize 
wxGridCellNumberRenderer::GetBestSize(wxGrid
& grid
, 
1940                                              wxGridCellAttr
& attr
, 
1944     return DoGetBestSize(attr
, dc
, GetString(grid
, row
, col
)); 
1947 // ---------------------------------------------------------------------------- 
1948 // wxGridCellFloatRenderer 
1949 // ---------------------------------------------------------------------------- 
1951 wxGridCellFloatRenderer::wxGridCellFloatRenderer(int width
, int precision
) 
1954     SetPrecision(precision
); 
1957 wxGridCellRenderer 
*wxGridCellFloatRenderer::Clone() const 
1959     wxGridCellFloatRenderer 
*renderer 
= new wxGridCellFloatRenderer
; 
1960     renderer
->m_width 
= m_width
; 
1961     renderer
->m_precision 
= m_precision
; 
1962     renderer
->m_format 
= m_format
; 
1967 wxString 
wxGridCellFloatRenderer::GetString(const wxGrid
& grid
, int row
, int col
) 
1969     wxGridTableBase 
*table 
= grid
.GetTable(); 
1974     if ( table
->CanGetValueAs(row
, col
, wxGRID_VALUE_FLOAT
) ) 
1976         val 
= table
->GetValueAsDouble(row
, col
); 
1981         text 
= table
->GetValue(row
, col
); 
1982         hasDouble 
= text
.ToDouble(&val
); 
1989             if ( m_width 
== -1 ) 
1991                 if ( m_precision 
== -1 ) 
1993                     // default width/precision 
1994                     m_format 
= _T("%f"); 
1998                     m_format
.Printf(_T("%%.%df"), m_precision
); 
2001             else if ( m_precision 
== -1 ) 
2003                 // default precision 
2004                 m_format
.Printf(_T("%%%d.f"), m_width
); 
2008                 m_format
.Printf(_T("%%%d.%df"), m_width
, m_precision
); 
2012         text
.Printf(m_format
, val
); 
2015     //else: text already contains the string 
2020 void wxGridCellFloatRenderer::Draw(wxGrid
& grid
, 
2021                                    wxGridCellAttr
& attr
, 
2023                                    const wxRect
& rectCell
, 
2027     wxGridCellRenderer::Draw(grid
, attr
, dc
, rectCell
, row
, col
, isSelected
); 
2029     SetTextColoursAndFont(grid
, attr
, dc
, isSelected
); 
2031     // draw the text right aligned by default 
2033     attr
.GetAlignment(&hAlign
, &vAlign
); 
2034     hAlign 
= wxALIGN_RIGHT
; 
2036     wxRect rect 
= rectCell
; 
2039     grid
.DrawTextRectangle(dc
, GetString(grid
, row
, col
), rect
, hAlign
, vAlign
); 
2042 wxSize 
wxGridCellFloatRenderer::GetBestSize(wxGrid
& grid
, 
2043                                             wxGridCellAttr
& attr
, 
2047     return DoGetBestSize(attr
, dc
, GetString(grid
, row
, col
)); 
2050 void wxGridCellFloatRenderer::SetParameters(const wxString
& params
) 
2054         // reset to defaults 
2060         wxString tmp 
= params
.BeforeFirst(_T(',')); 
2064             if ( tmp
.ToLong(&width
) ) 
2066                 SetWidth((int)width
); 
2070                 wxLogDebug(_T("Invalid wxGridCellFloatRenderer width parameter string '%s ignored"), params
.c_str()); 
2073         tmp 
= params
.AfterFirst(_T(',')); 
2077             if ( tmp
.ToLong(&precision
) ) 
2079                 SetPrecision((int)precision
); 
2083                 wxLogDebug(_T("Invalid wxGridCellFloatRenderer precision parameter string '%s ignored"), params
.c_str()); 
2090 // ---------------------------------------------------------------------------- 
2091 // wxGridCellBoolRenderer 
2092 // ---------------------------------------------------------------------------- 
2094 wxSize 
wxGridCellBoolRenderer::ms_sizeCheckMark
; 
2096 // FIXME these checkbox size calculations are really ugly... 
2098 // between checkmark and box 
2099 static const wxCoord wxGRID_CHECKMARK_MARGIN 
= 2; 
2101 wxSize 
wxGridCellBoolRenderer::GetBestSize(wxGrid
& grid
, 
2102                                            wxGridCellAttr
& WXUNUSED(attr
), 
2107     // compute it only once (no locks for MT safeness in GUI thread...) 
2108     if ( !ms_sizeCheckMark
.x 
) 
2110         // get checkbox size 
2111         wxCheckBox 
*checkbox 
= new wxCheckBox(&grid
, wxID_ANY
, wxEmptyString
); 
2112         wxSize size 
= checkbox
->GetBestSize(); 
2113         wxCoord checkSize 
= size
.y 
+ 2*wxGRID_CHECKMARK_MARGIN
; 
2115         // FIXME wxGTK::wxCheckBox::GetBestSize() gives "wrong" result 
2116 #if defined(__WXGTK__) || defined(__WXMOTIF__) 
2117         checkSize 
-= size
.y 
/ 2; 
2122         ms_sizeCheckMark
.x 
= ms_sizeCheckMark
.y 
= checkSize
; 
2125     return ms_sizeCheckMark
; 
2128 void wxGridCellBoolRenderer::Draw(wxGrid
& grid
, 
2129                                   wxGridCellAttr
& attr
, 
2135     wxGridCellRenderer::Draw(grid
, attr
, dc
, rect
, row
, col
, isSelected
); 
2137     // draw a check mark in the centre (ignoring alignment - TODO) 
2138     wxSize size 
= GetBestSize(grid
, attr
, dc
, row
, col
); 
2140     // don't draw outside the cell 
2141     wxCoord minSize 
= wxMin(rect
.width
, rect
.height
); 
2142     if ( size
.x 
>= minSize 
|| size
.y 
>= minSize 
) 
2144         // and even leave (at least) 1 pixel margin 
2145         size
.x 
= size
.y 
= minSize 
- 2; 
2148     // draw a border around checkmark 
2150     attr
.GetAlignment(& hAlign
, &vAlign
); 
2153     if (hAlign 
== wxALIGN_CENTRE
) 
2155         rectBorder
.x 
= rect
.x 
+ rect
.width
/2 - size
.x
/2; 
2156         rectBorder
.y 
= rect
.y 
+ rect
.height
/2 - size
.y
/2; 
2157         rectBorder
.width 
= size
.x
; 
2158         rectBorder
.height 
= size
.y
; 
2160     else if (hAlign 
== wxALIGN_LEFT
) 
2162         rectBorder
.x 
= rect
.x 
+ 2; 
2163         rectBorder
.y 
= rect
.y 
+ rect
.height
/2 - size
.y
/2; 
2164         rectBorder
.width 
= size
.x
; 
2165         rectBorder
.height 
= size
.y
; 
2167     else if (hAlign 
== wxALIGN_RIGHT
) 
2169         rectBorder
.x 
= rect
.x 
+ rect
.width 
- size
.x 
- 2; 
2170         rectBorder
.y 
= rect
.y 
+ rect
.height
/2 - size
.y
/2; 
2171         rectBorder
.width 
= size
.x
; 
2172         rectBorder
.height 
= size
.y
; 
2176     if ( grid
.GetTable()->CanGetValueAs(row
, col
, wxGRID_VALUE_BOOL
) ) 
2177         value 
= grid
.GetTable()->GetValueAsBool(row
, col
); 
2180         wxString 
cellval( grid
.GetTable()->GetValue(row
, col
) ); 
2181         value 
= !( !cellval 
|| (cellval 
== wxT("0")) ); 
2186         wxRect rectMark 
= rectBorder
; 
2188         // MSW DrawCheckMark() is weird (and should probably be changed...) 
2189         rectMark
.Inflate(-wxGRID_CHECKMARK_MARGIN
/2); 
2193         rectMark
.Inflate(-wxGRID_CHECKMARK_MARGIN
); 
2196         dc
.SetTextForeground(attr
.GetTextColour()); 
2197         dc
.DrawCheckMark(rectMark
); 
2200     dc
.SetBrush(*wxTRANSPARENT_BRUSH
); 
2201     dc
.SetPen(wxPen(attr
.GetTextColour(), 1, wxSOLID
)); 
2202     dc
.DrawRectangle(rectBorder
); 
2205 // ---------------------------------------------------------------------------- 
2207 // ---------------------------------------------------------------------------- 
2209 void wxGridCellAttr::Init(wxGridCellAttr 
*attrDefault
) 
2213     m_isReadOnly 
= Unset
; 
2218     m_attrkind 
= wxGridCellAttr::Cell
; 
2220     m_sizeRows 
= m_sizeCols 
= 1; 
2221     m_overflow 
= UnsetOverflow
; 
2223     SetDefAttr(attrDefault
); 
2226 wxGridCellAttr 
*wxGridCellAttr::Clone() const 
2228     wxGridCellAttr 
*attr 
= new wxGridCellAttr(m_defGridAttr
); 
2230     if ( HasTextColour() ) 
2231         attr
->SetTextColour(GetTextColour()); 
2232     if ( HasBackgroundColour() ) 
2233         attr
->SetBackgroundColour(GetBackgroundColour()); 
2235         attr
->SetFont(GetFont()); 
2236     if ( HasAlignment() ) 
2237         attr
->SetAlignment(m_hAlign
, m_vAlign
); 
2239     attr
->SetSize( m_sizeRows
, m_sizeCols 
); 
2243         attr
->SetRenderer(m_renderer
); 
2244         m_renderer
->IncRef(); 
2248         attr
->SetEditor(m_editor
); 
2253         attr
->SetReadOnly(); 
2255     attr
->SetKind( m_attrkind 
); 
2260 void wxGridCellAttr::MergeWith(wxGridCellAttr 
*mergefrom
) 
2262     if ( !HasTextColour() && mergefrom
->HasTextColour() ) 
2263         SetTextColour(mergefrom
->GetTextColour()); 
2264     if ( !HasBackgroundColour() && mergefrom
->HasBackgroundColour() ) 
2265         SetBackgroundColour(mergefrom
->GetBackgroundColour()); 
2266     if ( !HasFont() && mergefrom
->HasFont() ) 
2267         SetFont(mergefrom
->GetFont()); 
2268     if ( !HasAlignment() && mergefrom
->HasAlignment() ) 
2271         mergefrom
->GetAlignment( &hAlign
, &vAlign
); 
2272         SetAlignment(hAlign
, vAlign
); 
2274     if ( !HasSize() && mergefrom
->HasSize() ) 
2275         mergefrom
->GetSize( &m_sizeRows
, &m_sizeCols 
); 
2277     // Directly access member functions as GetRender/Editor don't just return 
2278     // m_renderer/m_editor 
2280     // Maybe add support for merge of Render and Editor? 
2281     if (!HasRenderer() && mergefrom
->HasRenderer() ) 
2283         m_renderer 
= mergefrom
->m_renderer
; 
2284         m_renderer
->IncRef(); 
2286     if ( !HasEditor() && mergefrom
->HasEditor() ) 
2288         m_editor 
=  mergefrom
->m_editor
; 
2291     if ( !HasReadWriteMode()  && mergefrom
->HasReadWriteMode() ) 
2292         SetReadOnly(mergefrom
->IsReadOnly()); 
2294     if (!HasOverflowMode()  && mergefrom
->HasOverflowMode() ) 
2295         SetOverflow(mergefrom
->GetOverflow()); 
2297     SetDefAttr(mergefrom
->m_defGridAttr
); 
2300 void wxGridCellAttr::SetSize(int num_rows
, int num_cols
) 
2302     // The size of a cell is normally 1,1 
2304     // If this cell is larger (2,2) then this is the top left cell 
2305     // the other cells that will be covered (lower right cells) must be 
2306     // set to negative or zero values such that 
2307     // row + num_rows of the covered cell points to the larger cell (this cell) 
2308     // same goes for the col + num_cols. 
2310     // Size of 0,0 is NOT valid, neither is <=0 and any positive value 
2312     wxASSERT_MSG( (!((num_rows
>0)&&(num_cols
<=0)) || 
2313                   !((num_rows
<=0)&&(num_cols
>0)) || 
2314                   !((num_rows
==0)&&(num_cols
==0))), 
2315                   wxT("wxGridCellAttr::SetSize only takes two postive values or negative/zero values")); 
2317     m_sizeRows 
= num_rows
; 
2318     m_sizeCols 
= num_cols
; 
2321 const wxColour
& wxGridCellAttr::GetTextColour() const 
2323     if (HasTextColour()) 
2327     else if (m_defGridAttr 
&& m_defGridAttr 
!= this) 
2329         return m_defGridAttr
->GetTextColour(); 
2333         wxFAIL_MSG(wxT("Missing default cell attribute")); 
2334         return wxNullColour
; 
2339 const wxColour
& wxGridCellAttr::GetBackgroundColour() const 
2341     if (HasBackgroundColour()) 
2343     else if (m_defGridAttr 
&& m_defGridAttr 
!= this) 
2344         return m_defGridAttr
->GetBackgroundColour(); 
2347         wxFAIL_MSG(wxT("Missing default cell attribute")); 
2348         return wxNullColour
; 
2353 const wxFont
& wxGridCellAttr::GetFont() const 
2357     else if (m_defGridAttr 
&& m_defGridAttr 
!= this) 
2358         return m_defGridAttr
->GetFont(); 
2361         wxFAIL_MSG(wxT("Missing default cell attribute")); 
2367 void wxGridCellAttr::GetAlignment(int *hAlign
, int *vAlign
) const 
2376     else if (m_defGridAttr 
&& m_defGridAttr 
!= this) 
2377         m_defGridAttr
->GetAlignment(hAlign
, vAlign
); 
2380         wxFAIL_MSG(wxT("Missing default cell attribute")); 
2384 void wxGridCellAttr::GetSize( int *num_rows
, int *num_cols 
) const 
2387         *num_rows 
= m_sizeRows
; 
2389         *num_cols 
= m_sizeCols
; 
2392 // GetRenderer and GetEditor use a slightly different decision path about 
2393 // which attribute to use.  If a non-default attr object has one then it is 
2394 // used, otherwise the default editor or renderer is fetched from the grid and 
2395 // used.  It should be the default for the data type of the cell.  If it is 
2396 // NULL (because the table has a type that the grid does not have in its 
2397 // registry,) then the grid's default editor or renderer is used. 
2399 wxGridCellRenderer
* wxGridCellAttr::GetRenderer(wxGrid
* grid
, int row
, int col
) const 
2401     wxGridCellRenderer 
*renderer
; 
2403     if ( m_renderer 
&& this != m_defGridAttr 
) 
2405         // use the cells renderer if it has one 
2406         renderer 
= m_renderer
; 
2409     else // no non default cell renderer 
2411         // get default renderer for the data type 
2414             // GetDefaultRendererForCell() will do IncRef() for us 
2415             renderer 
= grid
->GetDefaultRendererForCell(row
, col
); 
2424             if (m_defGridAttr 
&&  this != m_defGridAttr 
) 
2426                 // if we still don't have one then use the grid default 
2427                 // (no need for IncRef() here neither) 
2428                 renderer 
= m_defGridAttr
->GetRenderer(NULL
, 0, 0); 
2430             else // default grid attr 
2432                 // use m_renderer which we had decided not to use initially 
2433                 renderer 
= m_renderer
; 
2440     // we're supposed to always find something 
2441     wxASSERT_MSG(renderer
, wxT("Missing default cell renderer")); 
2446 // same as above, except for s/renderer/editor/g 
2447 wxGridCellEditor
* wxGridCellAttr::GetEditor(wxGrid
* grid
, int row
, int col
) const 
2449     wxGridCellEditor 
*editor
; 
2451     if ( m_editor 
&& this != m_defGridAttr 
) 
2453         // use the cells editor if it has one 
2457     else // no non default cell editor 
2459         // get default editor for the data type 
2462             // GetDefaultEditorForCell() will do IncRef() for us 
2463             editor 
= grid
->GetDefaultEditorForCell(row
, col
); 
2472             if ( m_defGridAttr 
&& this != m_defGridAttr 
) 
2474                 // if we still don't have one then use the grid default 
2475                 // (no need for IncRef() here neither) 
2476                 editor 
= m_defGridAttr
->GetEditor(NULL
, 0, 0); 
2478             else // default grid attr 
2480                 // use m_editor which we had decided not to use initially 
2488     // we're supposed to always find something 
2489     wxASSERT_MSG(editor
, wxT("Missing default cell editor")); 
2494 // ---------------------------------------------------------------------------- 
2495 // wxGridCellAttrData 
2496 // ---------------------------------------------------------------------------- 
2498 void wxGridCellAttrData::SetAttr(wxGridCellAttr 
*attr
, int row
, int col
) 
2500     int n 
= FindIndex(row
, col
); 
2501     if ( n 
== wxNOT_FOUND 
) 
2503         // add the attribute 
2504         m_attrs
.Add(new wxGridCellWithAttr(row
, col
, attr
)); 
2508         // free the old attribute 
2509         m_attrs
[(size_t)n
].attr
->DecRef(); 
2513             // change the attribute 
2514             m_attrs
[(size_t)n
].attr 
= attr
; 
2518             // remove this attribute 
2519             m_attrs
.RemoveAt((size_t)n
); 
2524 wxGridCellAttr 
*wxGridCellAttrData::GetAttr(int row
, int col
) const 
2526     wxGridCellAttr 
*attr 
= (wxGridCellAttr 
*)NULL
; 
2528     int n 
= FindIndex(row
, col
); 
2529     if ( n 
!= wxNOT_FOUND 
) 
2531         attr 
= m_attrs
[(size_t)n
].attr
; 
2538 void wxGridCellAttrData::UpdateAttrRows( size_t pos
, int numRows 
) 
2540     size_t count 
= m_attrs
.GetCount(); 
2541     for ( size_t n 
= 0; n 
< count
; n
++ ) 
2543         wxGridCellCoords
& coords 
= m_attrs
[n
].coords
; 
2544         wxCoord row 
= coords
.GetRow(); 
2545         if ((size_t)row 
>= pos
) 
2549                 // If rows inserted, include row counter where necessary 
2550                 coords
.SetRow(row 
+ numRows
); 
2552             else if (numRows 
< 0) 
2554                 // If rows deleted ... 
2555                 if ((size_t)row 
>= pos 
- numRows
) 
2557                     // ...either decrement row counter (if row still exists)... 
2558                     coords
.SetRow(row 
+ numRows
); 
2562                     // ...or remove the attribute 
2563                     // No need to DecRef the attribute itself since this is 
2564                     // done be wxGridCellWithAttr's destructor! 
2565                     m_attrs
.RemoveAt(n
); 
2574 void wxGridCellAttrData::UpdateAttrCols( size_t pos
, int numCols 
) 
2576     size_t count 
= m_attrs
.GetCount(); 
2577     for ( size_t n 
= 0; n 
< count
; n
++ ) 
2579         wxGridCellCoords
& coords 
= m_attrs
[n
].coords
; 
2580         wxCoord col 
= coords
.GetCol(); 
2581         if ( (size_t)col 
>= pos 
) 
2585                 // If rows inserted, include row counter where necessary 
2586                 coords
.SetCol(col 
+ numCols
); 
2588             else if (numCols 
< 0) 
2590                 // If rows deleted ... 
2591                 if ((size_t)col 
>= pos 
- numCols
) 
2593                     // ...either decrement row counter (if row still exists)... 
2594                     coords
.SetCol(col 
+ numCols
); 
2598                     // ...or remove the attribute 
2599                     // No need to DecRef the attribute itself since this is 
2600                     // done be wxGridCellWithAttr's destructor! 
2601                     m_attrs
.RemoveAt(n
); 
2609 int wxGridCellAttrData::FindIndex(int row
, int col
) const 
2611     size_t count 
= m_attrs
.GetCount(); 
2612     for ( size_t n 
= 0; n 
< count
; n
++ ) 
2614         const wxGridCellCoords
& coords 
= m_attrs
[n
].coords
; 
2615         if ( (coords
.GetRow() == row
) && (coords
.GetCol() == col
) ) 
2624 // ---------------------------------------------------------------------------- 
2625 // wxGridRowOrColAttrData 
2626 // ---------------------------------------------------------------------------- 
2628 wxGridRowOrColAttrData::~wxGridRowOrColAttrData() 
2630     size_t count 
= m_attrs
.Count(); 
2631     for ( size_t n 
= 0; n 
< count
; n
++ ) 
2633         m_attrs
[n
]->DecRef(); 
2637 wxGridCellAttr 
*wxGridRowOrColAttrData::GetAttr(int rowOrCol
) const 
2639     wxGridCellAttr 
*attr 
= (wxGridCellAttr 
*)NULL
; 
2641     int n 
= m_rowsOrCols
.Index(rowOrCol
); 
2642     if ( n 
!= wxNOT_FOUND 
) 
2644         attr 
= m_attrs
[(size_t)n
]; 
2651 void wxGridRowOrColAttrData::SetAttr(wxGridCellAttr 
*attr
, int rowOrCol
) 
2653     int i 
= m_rowsOrCols
.Index(rowOrCol
); 
2654     if ( i 
== wxNOT_FOUND 
) 
2656         // add the attribute 
2657         m_rowsOrCols
.Add(rowOrCol
); 
2662         size_t n 
= (size_t)i
; 
2665             // change the attribute 
2666             m_attrs
[n
]->DecRef(); 
2671             // remove this attribute 
2672             m_attrs
[n
]->DecRef(); 
2673             m_rowsOrCols
.RemoveAt(n
); 
2674             m_attrs
.RemoveAt(n
); 
2679 void wxGridRowOrColAttrData::UpdateAttrRowsOrCols( size_t pos
, int numRowsOrCols 
) 
2681     size_t count 
= m_attrs
.GetCount(); 
2682     for ( size_t n 
= 0; n 
< count
; n
++ ) 
2684         int & rowOrCol 
= m_rowsOrCols
[n
]; 
2685         if ( (size_t)rowOrCol 
>= pos 
) 
2687             if ( numRowsOrCols 
> 0 ) 
2689                 // If rows inserted, include row counter where necessary 
2690                 rowOrCol 
+= numRowsOrCols
; 
2692             else if ( numRowsOrCols 
< 0) 
2694                 // If rows deleted, either decrement row counter (if row still exists) 
2695                 if ((size_t)rowOrCol 
>= pos 
- numRowsOrCols
) 
2696                     rowOrCol 
+= numRowsOrCols
; 
2699                     m_rowsOrCols
.RemoveAt(n
); 
2700                     m_attrs
[n
]->DecRef(); 
2701                     m_attrs
.RemoveAt(n
); 
2710 // ---------------------------------------------------------------------------- 
2711 // wxGridCellAttrProvider 
2712 // ---------------------------------------------------------------------------- 
2714 wxGridCellAttrProvider::wxGridCellAttrProvider() 
2716     m_data 
= (wxGridCellAttrProviderData 
*)NULL
; 
2719 wxGridCellAttrProvider::~wxGridCellAttrProvider() 
2724 void wxGridCellAttrProvider::InitData() 
2726     m_data 
= new wxGridCellAttrProviderData
; 
2729 wxGridCellAttr 
*wxGridCellAttrProvider::GetAttr(int row
, int col
, 
2730                                                 wxGridCellAttr::wxAttrKind  kind 
) const 
2732     wxGridCellAttr 
*attr 
= (wxGridCellAttr 
*)NULL
; 
2737             case (wxGridCellAttr::Any
): 
2738                 // Get cached merge attributes. 
2739                 // Currently not used as no cache implemented as not mutable 
2740                 // attr = m_data->m_mergeAttr.GetAttr(row, col); 
2743                     // Basically implement old version. 
2744                     // Also check merge cache, so we don't have to re-merge every time.. 
2745                     wxGridCellAttr 
*attrcell 
= m_data
->m_cellAttrs
.GetAttr(row
, col
); 
2746                     wxGridCellAttr 
*attrrow 
= m_data
->m_rowAttrs
.GetAttr(row
); 
2747                     wxGridCellAttr 
*attrcol 
= m_data
->m_colAttrs
.GetAttr(col
); 
2749                     if ((attrcell 
!= attrrow
) && (attrrow 
!= attrcol
) && (attrcell 
!= attrcol
)) 
2751                         // Two or more are non NULL 
2752                         attr 
= new wxGridCellAttr
; 
2753                         attr
->SetKind(wxGridCellAttr::Merged
); 
2755                         // Order is important.. 
2758                             attr
->MergeWith(attrcell
); 
2763                             attr
->MergeWith(attrcol
); 
2768                             attr
->MergeWith(attrrow
); 
2772                         // store merge attr if cache implemented 
2774                         //m_data->m_mergeAttr.SetAttr(attr, row, col); 
2778                         // one or none is non null return it or null. 
2797             case (wxGridCellAttr::Cell
): 
2798                 attr 
= m_data
->m_cellAttrs
.GetAttr(row
, col
); 
2801             case (wxGridCellAttr::Col
): 
2802                 attr 
= m_data
->m_colAttrs
.GetAttr(col
); 
2805             case (wxGridCellAttr::Row
): 
2806                 attr 
= m_data
->m_rowAttrs
.GetAttr(row
); 
2811                 // (wxGridCellAttr::Default): 
2812                 // (wxGridCellAttr::Merged): 
2819 void wxGridCellAttrProvider::SetAttr(wxGridCellAttr 
*attr
, 
2825     m_data
->m_cellAttrs
.SetAttr(attr
, row
, col
); 
2828 void wxGridCellAttrProvider::SetRowAttr(wxGridCellAttr 
*attr
, int row
) 
2833     m_data
->m_rowAttrs
.SetAttr(attr
, row
); 
2836 void wxGridCellAttrProvider::SetColAttr(wxGridCellAttr 
*attr
, int col
) 
2841     m_data
->m_colAttrs
.SetAttr(attr
, col
); 
2844 void wxGridCellAttrProvider::UpdateAttrRows( size_t pos
, int numRows 
) 
2848         m_data
->m_cellAttrs
.UpdateAttrRows( pos
, numRows 
); 
2850         m_data
->m_rowAttrs
.UpdateAttrRowsOrCols( pos
, numRows 
); 
2854 void wxGridCellAttrProvider::UpdateAttrCols( size_t pos
, int numCols 
) 
2858         m_data
->m_cellAttrs
.UpdateAttrCols( pos
, numCols 
); 
2860         m_data
->m_colAttrs
.UpdateAttrRowsOrCols( pos
, numCols 
); 
2864 // ---------------------------------------------------------------------------- 
2865 // wxGridTypeRegistry 
2866 // ---------------------------------------------------------------------------- 
2868 wxGridTypeRegistry::~wxGridTypeRegistry() 
2870     size_t count 
= m_typeinfo
.Count(); 
2871     for ( size_t i 
= 0; i 
< count
; i
++ ) 
2872         delete m_typeinfo
[i
]; 
2876 void wxGridTypeRegistry::RegisterDataType(const wxString
& typeName
, 
2877                                           wxGridCellRenderer
* renderer
, 
2878                                           wxGridCellEditor
* editor
) 
2880     wxGridDataTypeInfo
* info 
= new wxGridDataTypeInfo(typeName
, renderer
, editor
); 
2882     // is it already registered? 
2883     int loc 
= FindRegisteredDataType(typeName
); 
2884     if ( loc 
!= wxNOT_FOUND 
) 
2886         delete m_typeinfo
[loc
]; 
2887         m_typeinfo
[loc
] = info
; 
2891         m_typeinfo
.Add(info
); 
2895 int wxGridTypeRegistry::FindRegisteredDataType(const wxString
& typeName
) 
2897     size_t count 
= m_typeinfo
.GetCount(); 
2898     for ( size_t i 
= 0; i 
< count
; i
++ ) 
2900         if ( typeName 
== m_typeinfo
[i
]->m_typeName 
) 
2909 int wxGridTypeRegistry::FindDataType(const wxString
& typeName
) 
2911     int index 
= FindRegisteredDataType(typeName
); 
2912     if ( index 
== wxNOT_FOUND 
) 
2914         // check whether this is one of the standard ones, in which case 
2915         // register it "on the fly" 
2917         if ( typeName 
== wxGRID_VALUE_STRING 
) 
2919             RegisterDataType(wxGRID_VALUE_STRING
, 
2920                              new wxGridCellStringRenderer
, 
2921                              new wxGridCellTextEditor
); 
2924 #endif // wxUSE_TEXTCTRL 
2926         if ( typeName 
== wxGRID_VALUE_BOOL 
) 
2928             RegisterDataType(wxGRID_VALUE_BOOL
, 
2929                              new wxGridCellBoolRenderer
, 
2930                              new wxGridCellBoolEditor
); 
2933 #endif // wxUSE_CHECKBOX 
2935         if ( typeName 
== wxGRID_VALUE_NUMBER 
) 
2937             RegisterDataType(wxGRID_VALUE_NUMBER
, 
2938                              new wxGridCellNumberRenderer
, 
2939                              new wxGridCellNumberEditor
); 
2941         else if ( typeName 
== wxGRID_VALUE_FLOAT 
) 
2943             RegisterDataType(wxGRID_VALUE_FLOAT
, 
2944                              new wxGridCellFloatRenderer
, 
2945                              new wxGridCellFloatEditor
); 
2948 #endif // wxUSE_TEXTCTRL 
2950         if ( typeName 
== wxGRID_VALUE_CHOICE 
) 
2952             RegisterDataType(wxGRID_VALUE_CHOICE
, 
2953                              new wxGridCellStringRenderer
, 
2954                              new wxGridCellChoiceEditor
); 
2957 #endif // wxUSE_COMBOBOX 
2962         // we get here only if just added the entry for this type, so return 
2964         index 
= m_typeinfo
.GetCount() - 1; 
2970 int wxGridTypeRegistry::FindOrCloneDataType(const wxString
& typeName
) 
2972     int index 
= FindDataType(typeName
); 
2973     if ( index 
== wxNOT_FOUND 
) 
2975         // the first part of the typename is the "real" type, anything after ':' 
2976         // are the parameters for the renderer 
2977         index 
= FindDataType(typeName
.BeforeFirst(_T(':'))); 
2978         if ( index 
== wxNOT_FOUND 
) 
2983         wxGridCellRenderer 
*renderer 
= GetRenderer(index
); 
2984         wxGridCellRenderer 
*rendererOld 
= renderer
; 
2985         renderer 
= renderer
->Clone(); 
2986         rendererOld
->DecRef(); 
2988         wxGridCellEditor 
*editor 
= GetEditor(index
); 
2989         wxGridCellEditor 
*editorOld 
= editor
; 
2990         editor 
= editor
->Clone(); 
2991         editorOld
->DecRef(); 
2993         // do it even if there are no parameters to reset them to defaults 
2994         wxString params 
= typeName
.AfterFirst(_T(':')); 
2995         renderer
->SetParameters(params
); 
2996         editor
->SetParameters(params
); 
2998         // register the new typename 
2999         RegisterDataType(typeName
, renderer
, editor
); 
3001         // we just registered it, it's the last one 
3002         index 
= m_typeinfo
.GetCount() - 1; 
3008 wxGridCellRenderer
* wxGridTypeRegistry::GetRenderer(int index
) 
3010     wxGridCellRenderer
* renderer 
= m_typeinfo
[index
]->m_renderer
; 
3016 wxGridCellEditor
* wxGridTypeRegistry::GetEditor(int index
) 
3018     wxGridCellEditor
* editor 
= m_typeinfo
[index
]->m_editor
; 
3024 // ---------------------------------------------------------------------------- 
3026 // ---------------------------------------------------------------------------- 
3028 IMPLEMENT_ABSTRACT_CLASS( wxGridTableBase
, wxObject 
) 
3031 wxGridTableBase::wxGridTableBase() 
3033     m_view 
= (wxGrid 
*) NULL
; 
3034     m_attrProvider 
= (wxGridCellAttrProvider 
*) NULL
; 
3037 wxGridTableBase::~wxGridTableBase() 
3039     delete m_attrProvider
; 
3042 void wxGridTableBase::SetAttrProvider(wxGridCellAttrProvider 
*attrProvider
) 
3044     delete m_attrProvider
; 
3045     m_attrProvider 
= attrProvider
; 
3048 bool wxGridTableBase::CanHaveAttributes() 
3050     if ( ! GetAttrProvider() ) 
3052         // use the default attr provider by default 
3053         SetAttrProvider(new wxGridCellAttrProvider
); 
3058 wxGridCellAttr 
*wxGridTableBase::GetAttr(int row
, int col
, wxGridCellAttr::wxAttrKind  kind
) 
3060     if ( m_attrProvider 
) 
3061         return m_attrProvider
->GetAttr(row
, col
, kind
); 
3063         return (wxGridCellAttr 
*)NULL
; 
3067 void wxGridTableBase::SetAttr(wxGridCellAttr
* attr
, int row
, int col
) 
3069     if ( m_attrProvider 
) 
3071         attr
->SetKind(wxGridCellAttr::Cell
); 
3072         m_attrProvider
->SetAttr(attr
, row
, col
); 
3076         // as we take ownership of the pointer and don't store it, we must 
3082 void wxGridTableBase::SetRowAttr(wxGridCellAttr 
*attr
, int row
) 
3084     if ( m_attrProvider 
) 
3086         attr
->SetKind(wxGridCellAttr::Row
); 
3087         m_attrProvider
->SetRowAttr(attr
, row
); 
3091         // as we take ownership of the pointer and don't store it, we must 
3097 void wxGridTableBase::SetColAttr(wxGridCellAttr 
*attr
, int col
) 
3099     if ( m_attrProvider 
) 
3101         attr
->SetKind(wxGridCellAttr::Col
); 
3102         m_attrProvider
->SetColAttr(attr
, col
); 
3106         // as we take ownership of the pointer and don't store it, we must 
3112 bool wxGridTableBase::InsertRows( size_t WXUNUSED(pos
), 
3113                                   size_t WXUNUSED(numRows
) ) 
3115     wxFAIL_MSG( wxT("Called grid table class function InsertRows\nbut your derived table class does not override this function") ); 
3120 bool wxGridTableBase::AppendRows( size_t WXUNUSED(numRows
) ) 
3122     wxFAIL_MSG( wxT("Called grid table class function AppendRows\nbut your derived table class does not override this function")); 
3127 bool wxGridTableBase::DeleteRows( size_t WXUNUSED(pos
), 
3128                                   size_t WXUNUSED(numRows
) ) 
3130     wxFAIL_MSG( wxT("Called grid table class function DeleteRows\nbut your derived table class does not override this function")); 
3135 bool wxGridTableBase::InsertCols( size_t WXUNUSED(pos
), 
3136                                   size_t WXUNUSED(numCols
) ) 
3138     wxFAIL_MSG( wxT("Called grid table class function InsertCols\nbut your derived table class does not override this function")); 
3143 bool wxGridTableBase::AppendCols( size_t WXUNUSED(numCols
) ) 
3145     wxFAIL_MSG(wxT("Called grid table class function AppendCols\nbut your derived table class does not override this function")); 
3150 bool wxGridTableBase::DeleteCols( size_t WXUNUSED(pos
), 
3151                                   size_t WXUNUSED(numCols
) ) 
3153     wxFAIL_MSG( wxT("Called grid table class function DeleteCols\nbut your derived table class does not override this function")); 
3158 wxString 
wxGridTableBase::GetRowLabelValue( int row 
) 
3161     s 
<< row 
+ 1; // RD: Starting the rows at zero confuses users, no matter 
3162                   //     how much it makes sense to us geeks. 
3166 wxString 
wxGridTableBase::GetColLabelValue( int col 
) 
3168     // default col labels are: 
3169     //   cols 0 to 25   : A-Z 
3170     //   cols 26 to 675 : AA-ZZ 
3175     for ( n 
= 1; ; n
++ ) 
3177         s 
+= (wxChar
) (_T('A') + (wxChar
)( col%26 
)); 
3183     // reverse the string... 
3185     for ( i 
= 0;  i 
< n
;  i
++ ) 
3193 wxString 
wxGridTableBase::GetTypeName( int WXUNUSED(row
), int WXUNUSED(col
) ) 
3195     return wxGRID_VALUE_STRING
; 
3198 bool wxGridTableBase::CanGetValueAs( int WXUNUSED(row
), int WXUNUSED(col
), 
3199                                      const wxString
& typeName 
) 
3201     return typeName 
== wxGRID_VALUE_STRING
; 
3204 bool wxGridTableBase::CanSetValueAs( int row
, int col
, const wxString
& typeName 
) 
3206     return CanGetValueAs(row
, col
, typeName
); 
3209 long wxGridTableBase::GetValueAsLong( int WXUNUSED(row
), int WXUNUSED(col
) ) 
3214 double wxGridTableBase::GetValueAsDouble( int WXUNUSED(row
), int WXUNUSED(col
) ) 
3219 bool wxGridTableBase::GetValueAsBool( int WXUNUSED(row
), int WXUNUSED(col
) ) 
3224 void wxGridTableBase::SetValueAsLong( int WXUNUSED(row
), int WXUNUSED(col
), 
3225                                       long WXUNUSED(value
) ) 
3229 void wxGridTableBase::SetValueAsDouble( int WXUNUSED(row
), int WXUNUSED(col
), 
3230                                         double WXUNUSED(value
) ) 
3234 void wxGridTableBase::SetValueAsBool( int WXUNUSED(row
), int WXUNUSED(col
), 
3235                                       bool WXUNUSED(value
) ) 
3240 void* wxGridTableBase::GetValueAsCustom( int WXUNUSED(row
), int WXUNUSED(col
), 
3241                                          const wxString
& WXUNUSED(typeName
) ) 
3246 void  wxGridTableBase::SetValueAsCustom( int WXUNUSED(row
), int WXUNUSED(col
), 
3247                                          const wxString
& WXUNUSED(typeName
), 
3248                                          void* WXUNUSED(value
) ) 
3252 ////////////////////////////////////////////////////////////////////// 
3254 // Message class for the grid table to send requests and notifications 
3258 wxGridTableMessage::wxGridTableMessage() 
3260     m_table 
= (wxGridTableBase 
*) NULL
; 
3266 wxGridTableMessage::wxGridTableMessage( wxGridTableBase 
*table
, int id
, 
3267                                         int commandInt1
, int commandInt2 
) 
3271     m_comInt1 
= commandInt1
; 
3272     m_comInt2 
= commandInt2
; 
3277 ////////////////////////////////////////////////////////////////////// 
3279 // A basic grid table for string data. An object of this class will 
3280 // created by wxGrid if you don't specify an alternative table class. 
3283 WX_DEFINE_OBJARRAY(wxGridStringArray
) 
3285 IMPLEMENT_DYNAMIC_CLASS( wxGridStringTable
, wxGridTableBase 
) 
3287 wxGridStringTable::wxGridStringTable() 
3292 wxGridStringTable::wxGridStringTable( int numRows
, int numCols 
) 
3295     m_data
.Alloc( numRows 
); 
3298     sa
.Alloc( numCols 
); 
3299     sa
.Add( wxEmptyString
, numCols 
); 
3301     m_data
.Add( sa
, numRows 
); 
3304 wxGridStringTable::~wxGridStringTable() 
3308 int wxGridStringTable::GetNumberRows() 
3310     return m_data
.GetCount(); 
3313 int wxGridStringTable::GetNumberCols() 
3315     if ( m_data
.GetCount() > 0 ) 
3316         return m_data
[0].GetCount(); 
3321 wxString 
wxGridStringTable::GetValue( int row
, int col 
) 
3323     wxCHECK_MSG( (row 
< GetNumberRows()) && (col 
< GetNumberCols()), 
3325                  _T("invalid row or column index in wxGridStringTable") ); 
3327     return m_data
[row
][col
]; 
3330 void wxGridStringTable::SetValue( int row
, int col
, const wxString
& value 
) 
3332     wxCHECK_RET( (row 
< GetNumberRows()) && (col 
< GetNumberCols()), 
3333                  _T("invalid row or column index in wxGridStringTable") ); 
3335     m_data
[row
][col
] = value
; 
3338 bool wxGridStringTable::IsEmptyCell( int row
, int col 
) 
3340     wxCHECK_MSG( (row 
< GetNumberRows()) && (col 
< GetNumberCols()), 
3342                   _T("invalid row or column index in wxGridStringTable") ); 
3344     return (m_data
[row
][col
] == wxEmptyString
); 
3347 void wxGridStringTable::Clear() 
3350     int numRows
, numCols
; 
3352     numRows 
= m_data
.GetCount(); 
3355         numCols 
= m_data
[0].GetCount(); 
3357         for ( row 
= 0;  row 
< numRows
;  row
++ ) 
3359             for ( col 
= 0;  col 
< numCols
;  col
++ ) 
3361                 m_data
[row
][col
] = wxEmptyString
; 
3368 bool wxGridStringTable::InsertRows( size_t pos
, size_t numRows 
) 
3370     size_t curNumRows 
= m_data
.GetCount(); 
3371     size_t curNumCols 
= ( curNumRows 
> 0 ? m_data
[0].GetCount() : 
3372                           ( GetView() ? GetView()->GetNumberCols() : 0 ) ); 
3374     if ( pos 
>= curNumRows 
) 
3376         return AppendRows( numRows 
); 
3380     sa
.Alloc( curNumCols 
); 
3381     sa
.Add( wxEmptyString
, curNumCols 
); 
3382     m_data
.Insert( sa
, pos
, numRows 
); 
3385         wxGridTableMessage 
msg( this, 
3386                                 wxGRIDTABLE_NOTIFY_ROWS_INSERTED
, 
3390         GetView()->ProcessTableMessage( msg 
); 
3396 bool wxGridStringTable::AppendRows( size_t numRows 
) 
3398     size_t curNumRows 
= m_data
.GetCount(); 
3399     size_t curNumCols 
= ( curNumRows 
> 0 
3400                          ? m_data
[0].GetCount() 
3401                          : ( GetView() ? GetView()->GetNumberCols() : 0 ) ); 
3404     if ( curNumCols 
> 0 ) 
3406         sa
.Alloc( curNumCols 
); 
3407         sa
.Add( wxEmptyString
, curNumCols 
); 
3410     m_data
.Add( sa
, numRows 
); 
3414         wxGridTableMessage 
msg( this, 
3415                                 wxGRIDTABLE_NOTIFY_ROWS_APPENDED
, 
3418         GetView()->ProcessTableMessage( msg 
); 
3424 bool wxGridStringTable::DeleteRows( size_t pos
, size_t numRows 
) 
3426     size_t curNumRows 
= m_data
.GetCount(); 
3428     if ( pos 
>= curNumRows 
) 
3430         wxFAIL_MSG( wxString::Format
 
3432                         wxT("Called wxGridStringTable::DeleteRows(pos=%lu, N=%lu)\nPos value is invalid for present table with %lu rows"), 
3434                         (unsigned long)numRows
, 
3435                         (unsigned long)curNumRows
 
3441     if ( numRows 
> curNumRows 
- pos 
) 
3443         numRows 
= curNumRows 
- pos
; 
3446     if ( numRows 
>= curNumRows 
) 
3452         m_data
.RemoveAt( pos
, numRows 
); 
3457         wxGridTableMessage 
msg( this, 
3458                                 wxGRIDTABLE_NOTIFY_ROWS_DELETED
, 
3462         GetView()->ProcessTableMessage( msg 
); 
3468 bool wxGridStringTable::InsertCols( size_t pos
, size_t numCols 
) 
3472     size_t curNumRows 
= m_data
.GetCount(); 
3473     size_t curNumCols 
= ( curNumRows 
> 0 
3474                          ? m_data
[0].GetCount() 
3475                          : ( GetView() ? GetView()->GetNumberCols() : 0 ) ); 
3477     if ( pos 
>= curNumCols 
) 
3479         return AppendCols( numCols 
); 
3482     for ( row 
= 0;  row 
< curNumRows
;  row
++ ) 
3484         for ( col 
= pos
;  col 
< pos 
+ numCols
;  col
++ ) 
3486             m_data
[row
].Insert( wxEmptyString
, col 
); 
3492         wxGridTableMessage 
msg( this, 
3493                                 wxGRIDTABLE_NOTIFY_COLS_INSERTED
, 
3497         GetView()->ProcessTableMessage( msg 
); 
3503 bool wxGridStringTable::AppendCols( size_t numCols 
) 
3507     size_t curNumRows 
= m_data
.GetCount(); 
3511         // TODO: something better than this ? 
3513         wxFAIL_MSG( wxT("Unable to append cols to a grid table with no rows.\nCall AppendRows() first") ); 
3518     for ( row 
= 0;  row 
< curNumRows
;  row
++ ) 
3520         m_data
[row
].Add( wxEmptyString
, numCols 
); 
3525         wxGridTableMessage 
msg( this, 
3526                                 wxGRIDTABLE_NOTIFY_COLS_APPENDED
, 
3529         GetView()->ProcessTableMessage( msg 
); 
3535 bool wxGridStringTable::DeleteCols( size_t pos
, size_t numCols 
) 
3539     size_t curNumRows 
= m_data
.GetCount(); 
3540     size_t curNumCols 
= ( curNumRows 
> 0 ? m_data
[0].GetCount() : 
3541                           ( GetView() ? GetView()->GetNumberCols() : 0 ) ); 
3543     if ( pos 
>= curNumCols 
) 
3545         wxFAIL_MSG( wxString::Format
 
3547                         wxT("Called wxGridStringTable::DeleteCols(pos=%lu, N=%lu)\nPos value is invalid for present table with %lu cols"), 
3549                         (unsigned long)numCols
, 
3550                         (unsigned long)curNumCols
 
3555     if ( numCols 
> curNumCols 
- pos 
) 
3557         numCols 
= curNumCols 
- pos
; 
3560     for ( row 
= 0;  row 
< curNumRows
;  row
++ ) 
3562         if ( numCols 
>= curNumCols 
) 
3564             m_data
[row
].Clear(); 
3568             m_data
[row
].RemoveAt( pos
, numCols 
); 
3574         wxGridTableMessage 
msg( this, 
3575                                 wxGRIDTABLE_NOTIFY_COLS_DELETED
, 
3579         GetView()->ProcessTableMessage( msg 
); 
3585 wxString 
wxGridStringTable::GetRowLabelValue( int row 
) 
3587     if ( row 
> (int)(m_rowLabels
.GetCount()) - 1 ) 
3589         // using default label 
3591         return wxGridTableBase::GetRowLabelValue( row 
); 
3595         return m_rowLabels
[ row 
]; 
3599 wxString 
wxGridStringTable::GetColLabelValue( int col 
) 
3601     if ( col 
> (int)(m_colLabels
.GetCount()) - 1 ) 
3603         // using default label 
3605         return wxGridTableBase::GetColLabelValue( col 
); 
3609         return m_colLabels
[ col 
]; 
3613 void wxGridStringTable::SetRowLabelValue( int row
, const wxString
& value 
) 
3615     if ( row 
> (int)(m_rowLabels
.GetCount()) - 1 ) 
3617         int n 
= m_rowLabels
.GetCount(); 
3619         for ( i 
= n
;  i 
<= row
;  i
++ ) 
3621             m_rowLabels
.Add( wxGridTableBase::GetRowLabelValue(i
) ); 
3625     m_rowLabels
[row
] = value
; 
3628 void wxGridStringTable::SetColLabelValue( int col
, const wxString
& value 
) 
3630     if ( col 
> (int)(m_colLabels
.GetCount()) - 1 ) 
3632         int n 
= m_colLabels
.GetCount(); 
3634         for ( i 
= n
;  i 
<= col
;  i
++ ) 
3636             m_colLabels
.Add( wxGridTableBase::GetColLabelValue(i
) ); 
3640     m_colLabels
[col
] = value
; 
3644 ////////////////////////////////////////////////////////////////////// 
3645 ////////////////////////////////////////////////////////////////////// 
3647 IMPLEMENT_DYNAMIC_CLASS( wxGridRowLabelWindow
, wxWindow 
) 
3649 BEGIN_EVENT_TABLE( wxGridRowLabelWindow
, wxWindow 
) 
3650     EVT_PAINT( wxGridRowLabelWindow::OnPaint 
) 
3651     EVT_MOUSEWHEEL( wxGridRowLabelWindow::OnMouseWheel
) 
3652     EVT_MOUSE_EVENTS( wxGridRowLabelWindow::OnMouseEvent 
) 
3653     EVT_KEY_DOWN( wxGridRowLabelWindow::OnKeyDown 
) 
3654     EVT_KEY_UP( wxGridRowLabelWindow::OnKeyUp 
) 
3655     EVT_CHAR ( wxGridRowLabelWindow::OnChar 
) 
3658 wxGridRowLabelWindow::wxGridRowLabelWindow( wxGrid 
*parent
, 
3660                                             const wxPoint 
&pos
, const wxSize 
&size 
) 
3661   : wxWindow( parent
, id
, pos
, size
, wxWANTS_CHARS
|wxBORDER_NONE
|wxFULL_REPAINT_ON_RESIZE 
) 
3666 void wxGridRowLabelWindow::OnPaint( wxPaintEvent
& WXUNUSED(event
) ) 
3670     // NO - don't do this because it will set both the x and y origin 
3671     // coords to match the parent scrolled window and we just want to 
3672     // set the y coord  - MB 
3674     // m_owner->PrepareDC( dc ); 
3677     m_owner
->CalcUnscrolledPosition( 0, 0, &x
, &y 
); 
3678     dc
.SetDeviceOrigin( 0, -y 
); 
3680     wxArrayInt rows 
= m_owner
->CalcRowLabelsExposed( GetUpdateRegion() ); 
3681     m_owner
->DrawRowLabels( dc 
, rows 
); 
3684 void wxGridRowLabelWindow::OnMouseEvent( wxMouseEvent
& event 
) 
3686     m_owner
->ProcessRowLabelMouseEvent( event 
); 
3689 void wxGridRowLabelWindow::OnMouseWheel( wxMouseEvent
& event 
) 
3691     m_owner
->GetEventHandler()->ProcessEvent(event
); 
3694 // This seems to be required for wxMotif otherwise the mouse 
3695 // cursor must be in the cell edit control to get key events 
3697 void wxGridRowLabelWindow::OnKeyDown( wxKeyEvent
& event 
) 
3699     if ( !m_owner
->GetEventHandler()->ProcessEvent( event 
) ) event
.Skip(); 
3702 void wxGridRowLabelWindow::OnKeyUp( wxKeyEvent
& event 
) 
3704     if ( !m_owner
->GetEventHandler()->ProcessEvent( event 
) ) event
.Skip(); 
3707 void wxGridRowLabelWindow::OnChar( wxKeyEvent
& event 
) 
3709     if ( !m_owner
->GetEventHandler()->ProcessEvent( event 
) ) event
.Skip(); 
3713 ////////////////////////////////////////////////////////////////////// 
3715 IMPLEMENT_DYNAMIC_CLASS( wxGridColLabelWindow
, wxWindow 
) 
3717 BEGIN_EVENT_TABLE( wxGridColLabelWindow
, wxWindow 
) 
3718     EVT_PAINT( wxGridColLabelWindow::OnPaint 
) 
3719     EVT_MOUSEWHEEL( wxGridColLabelWindow::OnMouseWheel
) 
3720     EVT_MOUSE_EVENTS( wxGridColLabelWindow::OnMouseEvent 
) 
3721     EVT_KEY_DOWN( wxGridColLabelWindow::OnKeyDown 
) 
3722     EVT_KEY_UP( wxGridColLabelWindow::OnKeyUp 
) 
3723     EVT_CHAR ( wxGridColLabelWindow::OnChar 
) 
3726 wxGridColLabelWindow::wxGridColLabelWindow( wxGrid 
*parent
, 
3728                                             const wxPoint 
&pos
, const wxSize 
&size 
) 
3729   : wxWindow( parent
, id
, pos
, size
, wxWANTS_CHARS
|wxBORDER_NONE
|wxFULL_REPAINT_ON_RESIZE 
) 
3734 void wxGridColLabelWindow::OnPaint( wxPaintEvent
& WXUNUSED(event
) ) 
3738     // NO - don't do this because it will set both the x and y origin 
3739     // coords to match the parent scrolled window and we just want to 
3740     // set the x coord  - MB 
3742     // m_owner->PrepareDC( dc ); 
3745     m_owner
->CalcUnscrolledPosition( 0, 0, &x
, &y 
); 
3746     dc
.SetDeviceOrigin( -x
, 0 ); 
3748     wxArrayInt cols 
= m_owner
->CalcColLabelsExposed( GetUpdateRegion() ); 
3749     m_owner
->DrawColLabels( dc 
, cols 
); 
3752 void wxGridColLabelWindow::OnMouseEvent( wxMouseEvent
& event 
) 
3754     m_owner
->ProcessColLabelMouseEvent( event 
); 
3757 void wxGridColLabelWindow::OnMouseWheel( wxMouseEvent
& event 
) 
3759     m_owner
->GetEventHandler()->ProcessEvent(event
); 
3762 // This seems to be required for wxMotif otherwise the mouse 
3763 // cursor must be in the cell edit control to get key events 
3765 void wxGridColLabelWindow::OnKeyDown( wxKeyEvent
& event 
) 
3767     if ( !m_owner
->GetEventHandler()->ProcessEvent( event 
) ) 
3771 void wxGridColLabelWindow::OnKeyUp( wxKeyEvent
& event 
) 
3773     if ( !m_owner
->GetEventHandler()->ProcessEvent( event 
) ) 
3777 void wxGridColLabelWindow::OnChar( wxKeyEvent
& event 
) 
3779     if ( !m_owner
->GetEventHandler()->ProcessEvent( event 
) ) 
3784 ////////////////////////////////////////////////////////////////////// 
3786 IMPLEMENT_DYNAMIC_CLASS( wxGridCornerLabelWindow
, wxWindow 
) 
3788 BEGIN_EVENT_TABLE( wxGridCornerLabelWindow
, wxWindow 
) 
3789     EVT_MOUSEWHEEL( wxGridCornerLabelWindow::OnMouseWheel
) 
3790     EVT_MOUSE_EVENTS( wxGridCornerLabelWindow::OnMouseEvent 
) 
3791     EVT_PAINT( wxGridCornerLabelWindow::OnPaint
) 
3792     EVT_KEY_DOWN( wxGridCornerLabelWindow::OnKeyDown 
) 
3793     EVT_KEY_UP( wxGridCornerLabelWindow::OnKeyUp 
) 
3794     EVT_CHAR ( wxGridCornerLabelWindow::OnChar 
) 
3797 wxGridCornerLabelWindow::wxGridCornerLabelWindow( wxGrid 
*parent
, 
3799                                                   const wxPoint 
&pos
, const wxSize 
&size 
) 
3800   : wxWindow( parent
, id
, pos
, size
, wxWANTS_CHARS
|wxBORDER_NONE
|wxFULL_REPAINT_ON_RESIZE 
) 
3805 void wxGridCornerLabelWindow::OnPaint( wxPaintEvent
& WXUNUSED(event
) ) 
3809     int client_height 
= 0; 
3810     int client_width 
= 0; 
3811     GetClientSize( &client_width
, &client_height 
); 
3813     // VZ: any reason for this ifdef? (FIXME) 
3818     rect
.SetWidth( client_width 
- 2 ); 
3819     rect
.SetHeight( client_height 
- 2 ); 
3821     wxRendererNative::Get().DrawHeaderButton( this, dc
, rect
, 0 ); 
3823     dc
.SetPen( wxPen(wxSystemSettings::GetColour(wxSYS_COLOUR_3DDKSHADOW
),1, wxSOLID
) ); 
3824     dc
.DrawLine( client_width
-1, client_height
-1, client_width
-1, 0 ); 
3825     dc
.DrawLine( client_width
-1, client_height
-1, 0, client_height
-1 ); 
3826     dc
.DrawLine( 0, 0, client_width
, 0 ); 
3827     dc
.DrawLine( 0, 0, 0, client_height 
); 
3829     dc
.SetPen( *wxWHITE_PEN 
); 
3830     dc
.DrawLine( 1, 1, client_width
-1, 1 ); 
3831     dc
.DrawLine( 1, 1, 1, client_height
-1 ); 
3832 #endif // __WXGTK__/!__WXGTK__ 
3835 void wxGridCornerLabelWindow::OnMouseEvent( wxMouseEvent
& event 
) 
3837     m_owner
->ProcessCornerLabelMouseEvent( event 
); 
3840 void wxGridCornerLabelWindow::OnMouseWheel( wxMouseEvent
& event 
) 
3842     m_owner
->GetEventHandler()->ProcessEvent(event
); 
3845 // This seems to be required for wxMotif otherwise the mouse 
3846 // cursor must be in the cell edit control to get key events 
3848 void wxGridCornerLabelWindow::OnKeyDown( wxKeyEvent
& event 
) 
3850     if ( !m_owner
->GetEventHandler()->ProcessEvent( event 
) ) event
.Skip(); 
3853 void wxGridCornerLabelWindow::OnKeyUp( wxKeyEvent
& event 
) 
3855     if ( !m_owner
->GetEventHandler()->ProcessEvent( event 
) ) event
.Skip(); 
3858 void wxGridCornerLabelWindow::OnChar( wxKeyEvent
& event 
) 
3860     if ( !m_owner
->GetEventHandler()->ProcessEvent( event 
) ) event
.Skip(); 
3864 ////////////////////////////////////////////////////////////////////// 
3866 IMPLEMENT_DYNAMIC_CLASS( wxGridWindow
, wxWindow 
) 
3868 BEGIN_EVENT_TABLE( wxGridWindow
, wxWindow 
) 
3869     EVT_PAINT( wxGridWindow::OnPaint 
) 
3870     EVT_MOUSEWHEEL( wxGridWindow::OnMouseWheel
) 
3871     EVT_MOUSE_EVENTS( wxGridWindow::OnMouseEvent 
) 
3872     EVT_KEY_DOWN( wxGridWindow::OnKeyDown 
) 
3873     EVT_KEY_UP( wxGridWindow::OnKeyUp 
) 
3874     EVT_CHAR ( wxGridWindow::OnChar 
) 
3875     EVT_SET_FOCUS( wxGridWindow::OnFocus 
) 
3876     EVT_KILL_FOCUS( wxGridWindow::OnFocus 
) 
3877     EVT_ERASE_BACKGROUND( wxGridWindow::OnEraseBackground 
) 
3880 wxGridWindow::wxGridWindow( wxGrid 
*parent
, 
3881                             wxGridRowLabelWindow 
*rowLblWin
, 
3882                             wxGridColLabelWindow 
*colLblWin
, 
3885                             const wxSize 
&size 
) 
3886             : wxWindow( parent
, id
, pos
, size
, wxWANTS_CHARS 
| wxBORDER_NONE 
| wxCLIP_CHILDREN
|wxFULL_REPAINT_ON_RESIZE
, 
3887                         wxT("grid window") ) 
3890     m_rowLabelWin 
= rowLblWin
; 
3891     m_colLabelWin 
= colLblWin
; 
3894 void wxGridWindow::OnPaint( wxPaintEvent 
&WXUNUSED(event
) ) 
3896     wxPaintDC 
dc( this ); 
3897     m_owner
->PrepareDC( dc 
); 
3898     wxRegion reg 
= GetUpdateRegion(); 
3899     wxGridCellCoordsArray DirtyCells 
= m_owner
->CalcCellsExposed( reg 
); 
3900     m_owner
->DrawGridCellArea( dc 
, DirtyCells
); 
3901 #if WXGRID_DRAW_LINES 
3902     m_owner
->DrawAllGridLines( dc
, reg 
); 
3904     m_owner
->DrawGridSpace( dc 
); 
3905     m_owner
->DrawHighlight( dc 
, DirtyCells 
); 
3908 void wxGridWindow::ScrollWindow( int dx
, int dy
, const wxRect 
*rect 
) 
3910     wxWindow::ScrollWindow( dx
, dy
, rect 
); 
3911     m_rowLabelWin
->ScrollWindow( 0, dy
, rect 
); 
3912     m_colLabelWin
->ScrollWindow( dx
, 0, rect 
); 
3915 void wxGridWindow::OnMouseEvent( wxMouseEvent
& event 
) 
3917     if (event
.ButtonDown(wxMOUSE_BTN_LEFT
) && FindFocus() != this) 
3920     m_owner
->ProcessGridCellMouseEvent( event 
); 
3923 void wxGridWindow::OnMouseWheel( wxMouseEvent
& event 
) 
3925     m_owner
->GetEventHandler()->ProcessEvent(event
); 
3928 // This seems to be required for wxMotif/wxGTK otherwise the mouse 
3929 // cursor must be in the cell edit control to get key events 
3931 void wxGridWindow::OnKeyDown( wxKeyEvent
& event 
) 
3933     if ( !m_owner
->GetEventHandler()->ProcessEvent( event 
) ) 
3937 void wxGridWindow::OnKeyUp( wxKeyEvent
& event 
) 
3939     if ( !m_owner
->GetEventHandler()->ProcessEvent( event 
) ) 
3943 void wxGridWindow::OnChar( wxKeyEvent
& event 
) 
3945     if ( !m_owner
->GetEventHandler()->ProcessEvent( event 
) ) 
3949 void wxGridWindow::OnEraseBackground( wxEraseEvent
& WXUNUSED(event
) ) 
3953 void wxGridWindow::OnFocus(wxFocusEvent
& event
) 
3955     if ( !m_owner
->GetEventHandler()->ProcessEvent( event 
) ) 
3959 ////////////////////////////////////////////////////////////////////// 
3961 // Internal Helper function for computing row or column from some 
3962 // (unscrolled) coordinate value, using either 
3963 // m_defaultRowHeight/m_defaultColWidth or binary search on array 
3964 // of m_rowBottoms/m_ColRights to speed up the search! 
3966 // Internal helper macros for simpler use of that function 
3968 static int CoordToRowOrCol(int coord
, int defaultDist
, int minDist
, 
3969                            const wxArrayInt
& BorderArray
, int nMax
, 
3972 #define internalXToCol(x) CoordToRowOrCol(x, m_defaultColWidth, \ 
3973                                           m_minAcceptableColWidth, \ 
3974                                           m_colRights, m_numCols, true) 
3975 #define internalYToRow(y) CoordToRowOrCol(y, m_defaultRowHeight, \ 
3976                                           m_minAcceptableRowHeight, \ 
3977                                           m_rowBottoms, m_numRows, true) 
3978 ///////////////////////////////////////////////////////////////////// 
3980 #if wxUSE_EXTENDED_RTTI 
3981 WX_DEFINE_FLAGS( wxGridStyle 
) 
3983 wxBEGIN_FLAGS( wxGridStyle 
) 
3984     // new style border flags, we put them first to 
3985     // use them for streaming out 
3986     wxFLAGS_MEMBER(wxBORDER_SIMPLE
) 
3987     wxFLAGS_MEMBER(wxBORDER_SUNKEN
) 
3988     wxFLAGS_MEMBER(wxBORDER_DOUBLE
) 
3989     wxFLAGS_MEMBER(wxBORDER_RAISED
) 
3990     wxFLAGS_MEMBER(wxBORDER_STATIC
) 
3991     wxFLAGS_MEMBER(wxBORDER_NONE
) 
3993     // old style border flags 
3994     wxFLAGS_MEMBER(wxSIMPLE_BORDER
) 
3995     wxFLAGS_MEMBER(wxSUNKEN_BORDER
) 
3996     wxFLAGS_MEMBER(wxDOUBLE_BORDER
) 
3997     wxFLAGS_MEMBER(wxRAISED_BORDER
) 
3998     wxFLAGS_MEMBER(wxSTATIC_BORDER
) 
3999     wxFLAGS_MEMBER(wxBORDER
) 
4001     // standard window styles 
4002     wxFLAGS_MEMBER(wxTAB_TRAVERSAL
) 
4003     wxFLAGS_MEMBER(wxCLIP_CHILDREN
) 
4004     wxFLAGS_MEMBER(wxTRANSPARENT_WINDOW
) 
4005     wxFLAGS_MEMBER(wxWANTS_CHARS
) 
4006     wxFLAGS_MEMBER(wxFULL_REPAINT_ON_RESIZE
) 
4007     wxFLAGS_MEMBER(wxALWAYS_SHOW_SB 
) 
4008     wxFLAGS_MEMBER(wxVSCROLL
) 
4009     wxFLAGS_MEMBER(wxHSCROLL
) 
4011 wxEND_FLAGS( wxGridStyle 
) 
4013 IMPLEMENT_DYNAMIC_CLASS_XTI(wxGrid
, wxScrolledWindow
,"wx/grid.h") 
4015 wxBEGIN_PROPERTIES_TABLE(wxGrid
) 
4016     wxHIDE_PROPERTY( Children 
) 
4017     wxPROPERTY_FLAGS( WindowStyle 
, wxGridStyle 
, long , SetWindowStyleFlag 
, GetWindowStyleFlag 
, EMPTY_MACROVALUE
, 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // style 
4018 wxEND_PROPERTIES_TABLE() 
4020 wxBEGIN_HANDLERS_TABLE(wxGrid
) 
4021 wxEND_HANDLERS_TABLE() 
4023 wxCONSTRUCTOR_5( wxGrid 
, wxWindow
* , Parent 
, wxWindowID 
, Id 
, wxPoint 
, Position 
, wxSize 
, Size 
, long , WindowStyle 
) 
4026  TODO : Expose more information of a list's layout etc. via appropriate objects (\81à la NotebookPageInfo) 
4029 IMPLEMENT_DYNAMIC_CLASS( wxGrid
, wxScrolledWindow 
) 
4032 BEGIN_EVENT_TABLE( wxGrid
, wxScrolledWindow 
) 
4033     EVT_PAINT( wxGrid::OnPaint 
) 
4034     EVT_SIZE( wxGrid::OnSize 
) 
4035     EVT_KEY_DOWN( wxGrid::OnKeyDown 
) 
4036     EVT_KEY_UP( wxGrid::OnKeyUp 
) 
4037     EVT_CHAR ( wxGrid::OnChar 
) 
4038     EVT_ERASE_BACKGROUND( wxGrid::OnEraseBackground 
) 
4043     // in order to make sure that a size event is not 
4044     // trigerred in a unfinished state 
4045     m_cornerLabelWin 
= NULL 
; 
4046     m_rowLabelWin 
= NULL 
; 
4047     m_colLabelWin 
= NULL 
; 
4051 wxGrid::wxGrid( wxWindow 
*parent
, 
4056                  const wxString
& name 
) 
4057   : wxScrolledWindow( parent
, id
, pos
, size
, (style 
| wxWANTS_CHARS
), name 
), 
4058     m_colMinWidths(GRID_HASH_SIZE
), 
4059     m_rowMinHeights(GRID_HASH_SIZE
) 
4062     SetBestFittingSize(size
); 
4065 bool wxGrid::Create(wxWindow 
*parent
, wxWindowID id
, 
4066                           const wxPoint
& pos
, const wxSize
& size
, 
4067                           long style
, const wxString
& name
) 
4069     if (!wxScrolledWindow::Create(parent
, id
, pos
, size
, 
4070                                   style 
| wxWANTS_CHARS 
, name
)) 
4073     m_colMinWidths 
= wxLongToLongHashMap(GRID_HASH_SIZE
) ; 
4074     m_rowMinHeights 
= wxLongToLongHashMap(GRID_HASH_SIZE
) ; 
4077     SetBestFittingSize(size
); 
4085     // Must do this or ~wxScrollHelper will pop the wrong event handler 
4086     SetTargetWindow(this); 
4088     wxSafeDecRef(m_defaultCellAttr
); 
4090 #ifdef DEBUG_ATTR_CACHE 
4091     size_t total 
= gs_nAttrCacheHits 
+ gs_nAttrCacheMisses
; 
4092     wxPrintf(_T("wxGrid attribute cache statistics: " 
4093                 "total: %u, hits: %u (%u%%)\n"), 
4094              total
, gs_nAttrCacheHits
, 
4095              total 
? (gs_nAttrCacheHits
*100) / total 
: 0); 
4101     delete m_typeRegistry
; 
4107 // ----- internal init and update functions 
4110 // NOTE: If using the default visual attributes works everywhere then this can 
4111 // be removed as well as the #else cases below. 
4112 #define _USE_VISATTR 0 
4115 #include "wx/listbox.h" 
4118 void wxGrid::Create() 
4120     m_created 
= false;    // set to true by CreateGrid 
4122     m_table        
= (wxGridTableBase 
*) NULL
; 
4125     m_cellEditCtrlEnabled 
= false; 
4127     m_defaultCellAttr 
= new wxGridCellAttr(); 
4129     // Set default cell attributes 
4130     m_defaultCellAttr
->SetDefAttr(m_defaultCellAttr
); 
4131     m_defaultCellAttr
->SetKind(wxGridCellAttr::Default
); 
4132     m_defaultCellAttr
->SetFont(GetFont()); 
4133     m_defaultCellAttr
->SetAlignment(wxALIGN_LEFT
, wxALIGN_TOP
); 
4134     m_defaultCellAttr
->SetRenderer(new wxGridCellStringRenderer
); 
4135     m_defaultCellAttr
->SetEditor(new wxGridCellTextEditor
); 
4138     wxVisualAttributes gva 
= wxListBox::GetClassDefaultAttributes(); 
4139     wxVisualAttributes lva 
= wxPanel::GetClassDefaultAttributes(); 
4141     m_defaultCellAttr
->SetTextColour(gva
.colFg
); 
4142     m_defaultCellAttr
->SetBackgroundColour(gva
.colBg
); 
4145     m_defaultCellAttr
->SetTextColour( 
4146         wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT
)); 
4147     m_defaultCellAttr
->SetBackgroundColour( 
4148         wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW
)); 
4153     m_currentCellCoords 
= wxGridNoCellCoords
; 
4155     m_rowLabelWidth 
= WXGRID_DEFAULT_ROW_LABEL_WIDTH
; 
4156     m_colLabelHeight 
= WXGRID_DEFAULT_COL_LABEL_HEIGHT
; 
4158     // create the type registry 
4159     m_typeRegistry 
= new wxGridTypeRegistry
; 
4162     // subwindow components that make up the wxGrid 
4163     m_cornerLabelWin 
= new wxGridCornerLabelWindow( this, 
4168     m_rowLabelWin 
= new wxGridRowLabelWindow( this, 
4173     m_colLabelWin 
= new wxGridColLabelWindow( this, 
4178     m_gridWin 
= new wxGridWindow( this, 
4185     SetTargetWindow( m_gridWin 
); 
4188     wxColour gfg 
= gva
.colFg
; 
4189     wxColour gbg 
= gva
.colBg
; 
4190     wxColour lfg 
= lva
.colFg
; 
4191     wxColour lbg 
= lva
.colBg
; 
4193     wxColour gfg 
= wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOWTEXT 
); 
4194     wxColour gbg 
= wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW 
); 
4195     wxColour lfg 
= wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOWTEXT 
); 
4196     wxColour lbg 
= wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE 
); 
4198     m_cornerLabelWin
->SetOwnForegroundColour(lfg
); 
4199     m_cornerLabelWin
->SetOwnBackgroundColour(lbg
); 
4200     m_rowLabelWin
->SetOwnForegroundColour(lfg
); 
4201     m_rowLabelWin
->SetOwnBackgroundColour(lbg
); 
4202     m_colLabelWin
->SetOwnForegroundColour(lfg
); 
4203     m_colLabelWin
->SetOwnBackgroundColour(lbg
); 
4205     m_gridWin
->SetOwnForegroundColour(gfg
); 
4206     m_gridWin
->SetOwnBackgroundColour(gbg
); 
4212 bool wxGrid::CreateGrid( int numRows
, int numCols
, 
4213                          wxGrid::wxGridSelectionModes selmode 
) 
4215     wxCHECK_MSG( !m_created
, 
4217                  wxT("wxGrid::CreateGrid or wxGrid::SetTable called more than once") ); 
4219     m_numRows 
= numRows
; 
4220     m_numCols 
= numCols
; 
4222     m_table 
= new wxGridStringTable( m_numRows
, m_numCols 
); 
4223     m_table
->SetView( this ); 
4225     m_selection 
= new wxGridSelection( this, selmode 
); 
4234 void wxGrid::SetSelectionMode(wxGrid::wxGridSelectionModes selmode
) 
4236     wxCHECK_RET( m_created
, 
4237                  wxT("Called wxGrid::SetSelectionMode() before calling CreateGrid()") ); 
4239     m_selection
->SetSelectionMode( selmode 
); 
4242 wxGrid::wxGridSelectionModes 
wxGrid::GetSelectionMode() const 
4244     wxCHECK_MSG( m_created
, wxGrid::wxGridSelectCells
, 
4245                  wxT("Called wxGrid::GetSelectionMode() before calling CreateGrid()") ); 
4247     return m_selection
->GetSelectionMode(); 
4250 bool wxGrid::SetTable( wxGridTableBase 
*table
, bool takeOwnership
, 
4251                        wxGrid::wxGridSelectionModes selmode 
) 
4255         // stop all processing 
4260             wxGridTableBase 
*t
=m_table
; 
4273         m_numRows 
= table
->GetNumberRows(); 
4274         m_numCols 
= table
->GetNumberCols(); 
4277         m_table
->SetView( this ); 
4278         m_ownTable 
= takeOwnership
; 
4279         m_selection 
= new wxGridSelection( this, selmode 
); 
4292     m_rowLabelWidth  
= WXGRID_DEFAULT_ROW_LABEL_WIDTH
; 
4293     m_colLabelHeight 
= WXGRID_DEFAULT_COL_LABEL_HEIGHT
; 
4295     if ( m_rowLabelWin 
) 
4297         m_labelBackgroundColour 
= m_rowLabelWin
->GetBackgroundColour(); 
4301         m_labelBackgroundColour 
= wxColour( _T("WHITE") ); 
4304     m_labelTextColour 
= wxColour( _T("BLACK") ); 
4307     m_attrCache
.row 
= -1; 
4308     m_attrCache
.col 
= -1; 
4309     m_attrCache
.attr 
= NULL
; 
4311     // TODO: something better than this ? 
4313     m_labelFont 
= this->GetFont(); 
4314     m_labelFont
.SetWeight( wxBOLD 
); 
4316     m_rowLabelHorizAlign 
= wxALIGN_CENTRE
; 
4317     m_rowLabelVertAlign  
= wxALIGN_CENTRE
; 
4319     m_colLabelHorizAlign 
= wxALIGN_CENTRE
; 
4320     m_colLabelVertAlign  
= wxALIGN_CENTRE
; 
4321     m_colLabelTextOrientation 
= wxHORIZONTAL
; 
4323     m_defaultColWidth  
= WXGRID_DEFAULT_COL_WIDTH
; 
4324     m_defaultRowHeight 
= m_gridWin
->GetCharHeight(); 
4326     m_minAcceptableColWidth  
= WXGRID_MIN_COL_WIDTH
; 
4327     m_minAcceptableRowHeight 
= WXGRID_MIN_ROW_HEIGHT
; 
4329 #if defined(__WXMOTIF__) || defined(__WXGTK__)  // see also text ctrl sizing in ShowCellEditControl() 
4330     m_defaultRowHeight 
+= 8; 
4332     m_defaultRowHeight 
+= 4; 
4335     m_gridLineColour 
= wxColour( 192,192,192 ); 
4336     m_gridLinesEnabled 
= true; 
4337     m_cellHighlightColour 
= *wxBLACK
; 
4338     m_cellHighlightPenWidth 
= 2; 
4339     m_cellHighlightROPenWidth 
= 1; 
4341     m_cursorMode  
= WXGRID_CURSOR_SELECT_CELL
; 
4342     m_winCapture 
= (wxWindow 
*)NULL
; 
4343     m_canDragRowSize 
= true; 
4344     m_canDragColSize 
= true; 
4345     m_canDragGridSize 
= true; 
4346     m_canDragCell 
= false; 
4348     m_dragRowOrCol 
= -1; 
4349     m_isDragging 
= false; 
4350     m_startDragPos 
= wxDefaultPosition
; 
4352     m_waitForSlowClick 
= false; 
4354     m_rowResizeCursor 
= wxCursor( wxCURSOR_SIZENS 
); 
4355     m_colResizeCursor 
= wxCursor( wxCURSOR_SIZEWE 
); 
4357     m_currentCellCoords 
= wxGridNoCellCoords
; 
4359     m_selectingTopLeft 
= wxGridNoCellCoords
; 
4360     m_selectingBottomRight 
= wxGridNoCellCoords
; 
4361     m_selectionBackground 
= wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT
); 
4362     m_selectionForeground 
= wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHTTEXT
); 
4364     m_editable 
= true;  // default for whole grid 
4366     m_inOnKeyDown 
= false; 
4372     m_scrollLineX 
= GRID_SCROLL_LINE_X
; 
4373     m_scrollLineY 
= GRID_SCROLL_LINE_Y
; 
4376 // ---------------------------------------------------------------------------- 
4377 // the idea is to call these functions only when necessary because they create 
4378 // quite big arrays which eat memory mostly unnecessary - in particular, if 
4379 // default widths/heights are used for all rows/columns, we may not use these 
4382 // with some extra code, it should be possible to only store the 
4383 // widths/heights different from default ones but this will be done later... 
4384 // ---------------------------------------------------------------------------- 
4386 void wxGrid::InitRowHeights() 
4388     m_rowHeights
.Empty(); 
4389     m_rowBottoms
.Empty(); 
4391     m_rowHeights
.Alloc( m_numRows 
); 
4392     m_rowBottoms
.Alloc( m_numRows 
); 
4396     m_rowHeights
.Add( m_defaultRowHeight
, m_numRows 
); 
4398     for ( int i 
= 0;  i 
< m_numRows
;  i
++ ) 
4400         rowBottom 
+= m_defaultRowHeight
; 
4401         m_rowBottoms
.Add( rowBottom 
); 
4405 void wxGrid::InitColWidths() 
4407     m_colWidths
.Empty(); 
4408     m_colRights
.Empty(); 
4410     m_colWidths
.Alloc( m_numCols 
); 
4411     m_colRights
.Alloc( m_numCols 
); 
4414     m_colWidths
.Add( m_defaultColWidth
, m_numCols 
); 
4416     for ( int i 
= 0;  i 
< m_numCols
;  i
++ ) 
4418         colRight 
+= m_defaultColWidth
; 
4419         m_colRights
.Add( colRight 
); 
4423 int wxGrid::GetColWidth(int col
) const 
4425     return m_colWidths
.IsEmpty() ? m_defaultColWidth 
: m_colWidths
[col
]; 
4428 int wxGrid::GetColLeft(int col
) const 
4430     return m_colRights
.IsEmpty() ? col 
* m_defaultColWidth
 
4431                                  : m_colRights
[col
] - m_colWidths
[col
]; 
4434 int wxGrid::GetColRight(int col
) const 
4436     return m_colRights
.IsEmpty() ? (col 
+ 1) * m_defaultColWidth
 
4440 int wxGrid::GetRowHeight(int row
) const 
4442     return m_rowHeights
.IsEmpty() ? m_defaultRowHeight 
: m_rowHeights
[row
]; 
4445 int wxGrid::GetRowTop(int row
) const 
4447     return m_rowBottoms
.IsEmpty() ? row 
* m_defaultRowHeight
 
4448                                   : m_rowBottoms
[row
] - m_rowHeights
[row
]; 
4451 int wxGrid::GetRowBottom(int row
) const 
4453     return m_rowBottoms
.IsEmpty() ? (row 
+ 1) * m_defaultRowHeight
 
4454                                   : m_rowBottoms
[row
]; 
4457 void wxGrid::CalcDimensions() 
4460     GetClientSize( &cw
, &ch 
); 
4462     if ( m_rowLabelWin
->IsShown() ) 
4463         cw 
-= m_rowLabelWidth
; 
4464     if ( m_colLabelWin
->IsShown() ) 
4465         ch 
-= m_colLabelHeight
; 
4468     int w 
= m_numCols 
> 0 ? GetColRight(m_numCols 
- 1) + m_extraWidth 
+ 1 : 0; 
4469     int h 
= m_numRows 
> 0 ? GetRowBottom(m_numRows 
- 1) + m_extraHeight 
+ 1 : 0; 
4471     // take into account editor if shown 
4472     if ( IsCellEditControlShown() ) 
4475       int r 
= m_currentCellCoords
.GetRow(); 
4476       int c 
= m_currentCellCoords
.GetCol(); 
4477       int x 
= GetColLeft(c
); 
4478       int y 
= GetRowTop(r
); 
4480       // how big is the editor 
4481       wxGridCellAttr
* attr 
= GetCellAttr(r
, c
); 
4482       wxGridCellEditor
* editor 
= attr
->GetEditor(this, r
, c
); 
4483       editor
->GetControl()->GetSize(&w2
, &h2
); 
4494     // preserve (more or less) the previous position 
4496     GetViewStart( &x
, &y 
); 
4498     // ensure the position is valid for the new scroll ranges 
4500         x 
= wxMax( w 
- 1, 0 ); 
4502         y 
= wxMax( h 
- 1, 0 ); 
4504     // do set scrollbar parameters 
4505     SetScrollbars( m_scrollLineX
, m_scrollLineY
, 
4506                    GetScrollX(w
), GetScrollY(h
), x
, y
, 
4507                    GetBatchCount() != 0); 
4509     // if our OnSize() hadn't been called (it would if we have scrollbars), we 
4510     // still must reposition the children 
4515 void wxGrid::CalcWindowSizes() 
4517     // escape if the window is has not been fully created yet 
4519     if ( m_cornerLabelWin 
== NULL 
) 
4523     GetClientSize( &cw
, &ch 
); 
4525     if ( m_cornerLabelWin 
&& m_cornerLabelWin
->IsShown() ) 
4526         m_cornerLabelWin
->SetSize( 0, 0, m_rowLabelWidth
, m_colLabelHeight 
); 
4528     if (  m_colLabelWin 
&& m_colLabelWin
->IsShown() ) 
4529         m_colLabelWin
->SetSize( m_rowLabelWidth
, 0, cw
-m_rowLabelWidth
, m_colLabelHeight
); 
4531     if ( m_rowLabelWin 
&& m_rowLabelWin
->IsShown() ) 
4532         m_rowLabelWin
->SetSize( 0, m_colLabelHeight
, m_rowLabelWidth
, ch
-m_colLabelHeight
); 
4534     if ( m_gridWin 
&& m_gridWin
->IsShown() ) 
4535         m_gridWin
->SetSize( m_rowLabelWidth
, m_colLabelHeight
, cw
-m_rowLabelWidth
, ch
-m_colLabelHeight
); 
4539 // this is called when the grid table sends a message to say that it 
4540 // has been redimensioned 
4542 bool wxGrid::Redimension( wxGridTableMessage
& msg 
) 
4545     bool result 
= false; 
4547     // Clear the attribute cache as the attribute might refer to a different 
4548     // cell than stored in the cache after adding/removing rows/columns. 
4550     // By the same reasoning, the editor should be dismissed if columns are 
4551     // added or removed. And for consistency, it should IMHO always be 
4552     // removed, not only if the cell "underneath" it actually changes. 
4553     // For now, I intentionally do not save the editor's content as the 
4554     // cell it might want to save that stuff to might no longer exist. 
4555     HideCellEditControl(); 
4557     // if we were using the default widths/heights so far, we must change them 
4559     if ( m_colWidths
.IsEmpty() ) 
4564     if ( m_rowHeights
.IsEmpty() ) 
4570     switch ( msg
.GetId() ) 
4572         case wxGRIDTABLE_NOTIFY_ROWS_INSERTED
: 
4574             size_t pos 
= msg
.GetCommandInt(); 
4575             int numRows 
= msg
.GetCommandInt2(); 
4577             m_numRows 
+= numRows
; 
4579             if ( !m_rowHeights
.IsEmpty() ) 
4581                 m_rowHeights
.Insert( m_defaultRowHeight
, pos
, numRows 
); 
4582                 m_rowBottoms
.Insert( 0, pos
, numRows 
); 
4585                 if ( pos 
> 0 ) bottom 
= m_rowBottoms
[pos
-1]; 
4587                 for ( i 
= pos
;  i 
< m_numRows
;  i
++ ) 
4589                     bottom 
+= m_rowHeights
[i
]; 
4590                     m_rowBottoms
[i
] = bottom
; 
4593             if ( m_currentCellCoords 
== wxGridNoCellCoords 
) 
4595                 // if we have just inserted cols into an empty grid the current 
4596                 // cell will be undefined... 
4598                 SetCurrentCell( 0, 0 ); 
4602                 m_selection
->UpdateRows( pos
, numRows 
); 
4603             wxGridCellAttrProvider 
* attrProvider 
= m_table
->GetAttrProvider(); 
4605                 attrProvider
->UpdateAttrRows( pos
, numRows 
); 
4607             if ( !GetBatchCount() ) 
4610                 m_rowLabelWin
->Refresh(); 
4616         case wxGRIDTABLE_NOTIFY_ROWS_APPENDED
: 
4618             int numRows 
= msg
.GetCommandInt(); 
4619             int oldNumRows 
= m_numRows
; 
4620             m_numRows 
+= numRows
; 
4622             if ( !m_rowHeights
.IsEmpty() ) 
4624                 m_rowHeights
.Add( m_defaultRowHeight
, numRows 
); 
4625                 m_rowBottoms
.Add( 0, numRows 
); 
4628                 if ( oldNumRows 
> 0 ) bottom 
= m_rowBottoms
[oldNumRows
-1]; 
4630                 for ( i 
= oldNumRows
;  i 
< m_numRows
;  i
++ ) 
4632                     bottom 
+= m_rowHeights
[i
]; 
4633                     m_rowBottoms
[i
] = bottom
; 
4636             if ( m_currentCellCoords 
== wxGridNoCellCoords 
) 
4638                 // if we have just inserted cols into an empty grid the current 
4639                 // cell will be undefined... 
4641                 SetCurrentCell( 0, 0 ); 
4643             if ( !GetBatchCount() ) 
4646                 m_rowLabelWin
->Refresh(); 
4652         case wxGRIDTABLE_NOTIFY_ROWS_DELETED
: 
4654             size_t pos 
= msg
.GetCommandInt(); 
4655             int numRows 
= msg
.GetCommandInt2(); 
4656             m_numRows 
-= numRows
; 
4658             if ( !m_rowHeights
.IsEmpty() ) 
4660                 m_rowHeights
.RemoveAt( pos
, numRows 
); 
4661                 m_rowBottoms
.RemoveAt( pos
, numRows 
); 
4664                 for ( i 
= 0;  i 
< m_numRows
;  i
++ ) 
4666                     h 
+= m_rowHeights
[i
]; 
4667                     m_rowBottoms
[i
] = h
; 
4672                 m_currentCellCoords 
= wxGridNoCellCoords
; 
4676                 if ( m_currentCellCoords
.GetRow() >= m_numRows 
) 
4677                     m_currentCellCoords
.Set( 0, 0 ); 
4681                 m_selection
->UpdateRows( pos
, -((int)numRows
) ); 
4682             wxGridCellAttrProvider 
* attrProvider 
= m_table
->GetAttrProvider(); 
4685                 attrProvider
->UpdateAttrRows( pos
, -((int)numRows
) ); 
4686 // ifdef'd out following patch from Paul Gammans 
4688                 // No need to touch column attributes, unless we 
4689                 // removed _all_ rows, in this case, we remove 
4690                 // all column attributes. 
4691                 // I hate to do this here, but the 
4692                 // needed data is not available inside UpdateAttrRows. 
4693                 if ( !GetNumberRows() ) 
4694                     attrProvider
->UpdateAttrCols( 0, -GetNumberCols() ); 
4697             if ( !GetBatchCount() ) 
4700                 m_rowLabelWin
->Refresh(); 
4706         case wxGRIDTABLE_NOTIFY_COLS_INSERTED
: 
4708             size_t pos 
= msg
.GetCommandInt(); 
4709             int numCols 
= msg
.GetCommandInt2(); 
4710             m_numCols 
+= numCols
; 
4712             if ( !m_colWidths
.IsEmpty() ) 
4714                 m_colWidths
.Insert( m_defaultColWidth
, pos
, numCols 
); 
4715                 m_colRights
.Insert( 0, pos
, numCols 
); 
4718                 if ( pos 
> 0 ) right 
= m_colRights
[pos
-1]; 
4720                 for ( i 
= pos
;  i 
< m_numCols
;  i
++ ) 
4722                     right 
+= m_colWidths
[i
]; 
4723                     m_colRights
[i
] = right
; 
4726             if ( m_currentCellCoords 
== wxGridNoCellCoords 
) 
4728                 // if we have just inserted cols into an empty grid the current 
4729                 // cell will be undefined... 
4731                 SetCurrentCell( 0, 0 ); 
4735                 m_selection
->UpdateCols( pos
, numCols 
); 
4736             wxGridCellAttrProvider 
* attrProvider 
= m_table
->GetAttrProvider(); 
4738                 attrProvider
->UpdateAttrCols( pos
, numCols 
); 
4739             if ( !GetBatchCount() ) 
4742                 m_colLabelWin
->Refresh(); 
4749         case wxGRIDTABLE_NOTIFY_COLS_APPENDED
: 
4751             int numCols 
= msg
.GetCommandInt(); 
4752             int oldNumCols 
= m_numCols
; 
4753             m_numCols 
+= numCols
; 
4754             if ( !m_colWidths
.IsEmpty() ) 
4756                 m_colWidths
.Add( m_defaultColWidth
, numCols 
); 
4757                 m_colRights
.Add( 0, numCols 
); 
4760                 if ( oldNumCols 
> 0 ) right 
= m_colRights
[oldNumCols
-1]; 
4762                 for ( i 
= oldNumCols
;  i 
< m_numCols
;  i
++ ) 
4764                     right 
+= m_colWidths
[i
]; 
4765                     m_colRights
[i
] = right
; 
4768             if ( m_currentCellCoords 
== wxGridNoCellCoords 
) 
4770                 // if we have just inserted cols into an empty grid the current 
4771                 // cell will be undefined... 
4773                 SetCurrentCell( 0, 0 ); 
4775             if ( !GetBatchCount() ) 
4778                 m_colLabelWin
->Refresh(); 
4784         case wxGRIDTABLE_NOTIFY_COLS_DELETED
: 
4786             size_t pos 
= msg
.GetCommandInt(); 
4787             int numCols 
= msg
.GetCommandInt2(); 
4788             m_numCols 
-= numCols
; 
4790             if ( !m_colWidths
.IsEmpty() ) 
4792                 m_colWidths
.RemoveAt( pos
, numCols 
); 
4793                 m_colRights
.RemoveAt( pos
, numCols 
); 
4796                 for ( i 
= 0;  i 
< m_numCols
;  i
++ ) 
4798                     w 
+= m_colWidths
[i
]; 
4804                 m_currentCellCoords 
= wxGridNoCellCoords
; 
4808                 if ( m_currentCellCoords
.GetCol() >= m_numCols 
) 
4809                   m_currentCellCoords
.Set( 0, 0 ); 
4813                 m_selection
->UpdateCols( pos
, -((int)numCols
) ); 
4814             wxGridCellAttrProvider 
* attrProvider 
= m_table
->GetAttrProvider(); 
4817                 attrProvider
->UpdateAttrCols( pos
, -((int)numCols
) ); 
4818 // ifdef'd out following patch from Paul Gammans 
4820                 // No need to touch row attributes, unless we 
4821                 // removed _all_ columns, in this case, we remove 
4822                 // all row attributes. 
4823                 // I hate to do this here, but the 
4824                 // needed data is not available inside UpdateAttrCols. 
4825                 if ( !GetNumberCols() ) 
4826                     attrProvider
->UpdateAttrRows( 0, -GetNumberRows() ); 
4829             if ( !GetBatchCount() ) 
4832                 m_colLabelWin
->Refresh(); 
4839     if (result 
&& !GetBatchCount() ) 
4840         m_gridWin
->Refresh(); 
4845 wxArrayInt 
wxGrid::CalcRowLabelsExposed( const wxRegion
& reg 
) 
4847     wxRegionIterator 
iter( reg 
); 
4850     wxArrayInt  rowlabels
; 
4857         // TODO: remove this when we can... 
4858         // There is a bug in wxMotif that gives garbage update 
4859         // rectangles if you jump-scroll a long way by clicking the 
4860         // scrollbar with middle button.  This is a work-around 
4862 #if defined(__WXMOTIF__) 
4864         m_gridWin
->GetClientSize( &cw
, &ch 
); 
4865         if ( r
.GetTop() > ch 
) r
.SetTop( 0 ); 
4866         r
.SetBottom( wxMin( r
.GetBottom(), ch 
) ); 
4869         // logical bounds of update region 
4872         CalcUnscrolledPosition( 0, r
.GetTop(), &dummy
, &top 
); 
4873         CalcUnscrolledPosition( 0, r
.GetBottom(), &dummy
, &bottom 
); 
4875         // find the row labels within these bounds 
4878         for ( row 
= internalYToRow(top
);  row 
< m_numRows
;  row
++ ) 
4880             if ( GetRowBottom(row
) < top 
) 
4883             if ( GetRowTop(row
) > bottom 
) 
4886             rowlabels
.Add( row 
); 
4896 wxArrayInt 
wxGrid::CalcColLabelsExposed( const wxRegion
& reg 
) 
4898     wxRegionIterator 
iter( reg 
); 
4901     wxArrayInt colLabels
; 
4908         // TODO: remove this when we can... 
4909         // There is a bug in wxMotif that gives garbage update 
4910         // rectangles if you jump-scroll a long way by clicking the 
4911         // scrollbar with middle button.  This is a work-around 
4913 #if defined(__WXMOTIF__) 
4915         m_gridWin
->GetClientSize( &cw
, &ch 
); 
4916         if ( r
.GetLeft() > cw 
) r
.SetLeft( 0 ); 
4917         r
.SetRight( wxMin( r
.GetRight(), cw 
) ); 
4920         // logical bounds of update region 
4923         CalcUnscrolledPosition( r
.GetLeft(), 0, &left
, &dummy 
); 
4924         CalcUnscrolledPosition( r
.GetRight(), 0, &right
, &dummy 
); 
4926         // find the cells within these bounds 
4929         for ( col 
= internalXToCol(left
);  col 
< m_numCols
;  col
++ ) 
4931             if ( GetColRight(col
) < left 
) 
4934             if ( GetColLeft(col
) > right 
) 
4937             colLabels
.Add( col 
); 
4946 wxGridCellCoordsArray 
wxGrid::CalcCellsExposed( const wxRegion
& reg 
) 
4948     wxRegionIterator 
iter( reg 
); 
4951     wxGridCellCoordsArray  cellsExposed
; 
4953     int left
, top
, right
, bottom
; 
4958         // TODO: remove this when we can... 
4959         // There is a bug in wxMotif that gives garbage update 
4960         // rectangles if you jump-scroll a long way by clicking the 
4961         // scrollbar with middle button.  This is a work-around 
4963 #if defined(__WXMOTIF__) 
4965         m_gridWin
->GetClientSize( &cw
, &ch 
); 
4966         if ( r
.GetTop() > ch 
) r
.SetTop( 0 ); 
4967         if ( r
.GetLeft() > cw 
) r
.SetLeft( 0 ); 
4968         r
.SetRight( wxMin( r
.GetRight(), cw 
) ); 
4969         r
.SetBottom( wxMin( r
.GetBottom(), ch 
) ); 
4972         // logical bounds of update region 
4974         CalcUnscrolledPosition( r
.GetLeft(), r
.GetTop(), &left
, &top 
); 
4975         CalcUnscrolledPosition( r
.GetRight(), r
.GetBottom(), &right
, &bottom 
); 
4977         // find the cells within these bounds 
4980         for ( row 
= internalYToRow(top
);  row 
< m_numRows
;  row
++ ) 
4982             if ( GetRowBottom(row
) <= top 
) 
4985             if ( GetRowTop(row
) > bottom 
) 
4988             for ( col 
= internalXToCol(left
);  col 
< m_numCols
;  col
++ ) 
4990                 if ( GetColRight(col
) <= left 
) 
4993                 if ( GetColLeft(col
) > right 
) 
4996                 cellsExposed
.Add( wxGridCellCoords( row
, col 
) ); 
5003     return cellsExposed
; 
5007 void wxGrid::ProcessRowLabelMouseEvent( wxMouseEvent
& event 
) 
5010     wxPoint 
pos( event
.GetPosition() ); 
5011     CalcUnscrolledPosition( pos
.x
, pos
.y
, &x
, &y 
); 
5013     if ( event
.Dragging() ) 
5017             m_isDragging 
= true; 
5018             m_rowLabelWin
->CaptureMouse(); 
5021         if ( event
.LeftIsDown() ) 
5023             switch ( m_cursorMode 
) 
5025                 case WXGRID_CURSOR_RESIZE_ROW
: 
5027                     int cw
, ch
, left
, dummy
; 
5028                     m_gridWin
->GetClientSize( &cw
, &ch 
); 
5029                     CalcUnscrolledPosition( 0, 0, &left
, &dummy 
); 
5031                     wxClientDC 
dc( m_gridWin 
); 
5034                                GetRowTop(m_dragRowOrCol
) + 
5035                                GetRowMinimalHeight(m_dragRowOrCol
) ); 
5036                     dc
.SetLogicalFunction(wxINVERT
); 
5037                     if ( m_dragLastPos 
>= 0 ) 
5039                         dc
.DrawLine( left
, m_dragLastPos
, left
+cw
, m_dragLastPos 
); 
5041                     dc
.DrawLine( left
, y
, left
+cw
, y 
); 
5046                 case WXGRID_CURSOR_SELECT_ROW
: 
5048                     if ( (row 
= YToRow( y 
)) >= 0 ) 
5052                             m_selection
->SelectRow( row
, 
5053                                                     event
.ControlDown(), 
5062                 // default label to suppress warnings about "enumeration value 
5063                 // 'xxx' not handled in switch 
5071     if ( m_isDragging 
&& (event
.Entering() || event
.Leaving()) ) 
5076         if (m_rowLabelWin
->HasCapture()) m_rowLabelWin
->ReleaseMouse(); 
5077         m_isDragging 
= false; 
5080     // ------------ Entering or leaving the window 
5082     if ( event
.Entering() || event
.Leaving() ) 
5084         ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
, m_rowLabelWin
); 
5088     // ------------ Left button pressed 
5090     else if ( event
.LeftDown() ) 
5092         // don't send a label click event for a hit on the 
5093         // edge of the row label - this is probably the user 
5094         // wanting to resize the row 
5096         if ( YToEdgeOfRow(y
) < 0 ) 
5100                  !SendEvent( wxEVT_GRID_LABEL_LEFT_CLICK
, row
, -1, event 
) ) 
5102                 if ( !event
.ShiftDown() && !event
.ControlDown() ) 
5106                     if ( event
.ShiftDown() ) 
5108                         m_selection
->SelectBlock( m_currentCellCoords
.GetRow(), 
5111                                                   GetNumberCols() - 1, 
5112                                                   event
.ControlDown(), 
5119                         m_selection
->SelectRow( row
, 
5120                                                 event
.ControlDown(), 
5127                 ChangeCursorMode(WXGRID_CURSOR_SELECT_ROW
, m_rowLabelWin
); 
5132             // starting to drag-resize a row 
5134             if ( CanDragRowSize() ) 
5135                 ChangeCursorMode(WXGRID_CURSOR_RESIZE_ROW
, m_rowLabelWin
); 
5140     // ------------ Left double click 
5142     else if (event
.LeftDClick() ) 
5144         row 
= YToEdgeOfRow(y
); 
5149                  !SendEvent( wxEVT_GRID_LABEL_LEFT_DCLICK
, row
, -1, event 
) ) 
5151                 // no default action at the moment 
5156             // adjust row height depending on label text 
5157             AutoSizeRowLabelSize( row 
); 
5159             ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
, m_colLabelWin
); 
5165     // ------------ Left button released 
5167     else if ( event
.LeftUp() ) 
5169         if ( m_cursorMode 
== WXGRID_CURSOR_RESIZE_ROW 
) 
5171             DoEndDragResizeRow(); 
5173             // Note: we are ending the event *after* doing 
5174             // default processing in this case 
5176             SendEvent( wxEVT_GRID_ROW_SIZE
, m_dragRowOrCol
, -1, event 
); 
5179         ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
, m_rowLabelWin
); 
5184     // ------------ Right button down 
5186     else if ( event
.RightDown() ) 
5190              !SendEvent( wxEVT_GRID_LABEL_RIGHT_CLICK
, row
, -1, event 
) ) 
5192             // no default action at the moment 
5197     // ------------ Right double click 
5199     else if ( event
.RightDClick() ) 
5203              !SendEvent( wxEVT_GRID_LABEL_RIGHT_DCLICK
, row
, -1, event 
) ) 
5205             // no default action at the moment 
5210     // ------------ No buttons down and mouse moving 
5212     else if ( event
.Moving() ) 
5214         m_dragRowOrCol 
= YToEdgeOfRow( y 
); 
5215         if ( m_dragRowOrCol 
>= 0 ) 
5217             if ( m_cursorMode 
== WXGRID_CURSOR_SELECT_CELL 
) 
5219                 // don't capture the mouse yet 
5220                 if ( CanDragRowSize() ) 
5221                     ChangeCursorMode(WXGRID_CURSOR_RESIZE_ROW
, m_rowLabelWin
, false); 
5224         else if ( m_cursorMode 
!= WXGRID_CURSOR_SELECT_CELL 
) 
5226             ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
, m_rowLabelWin
, false); 
5232 void wxGrid::ProcessColLabelMouseEvent( wxMouseEvent
& event 
) 
5235     wxPoint 
pos( event
.GetPosition() ); 
5236     CalcUnscrolledPosition( pos
.x
, pos
.y
, &x
, &y 
); 
5238     if ( event
.Dragging() ) 
5242             m_isDragging 
= true; 
5243             m_colLabelWin
->CaptureMouse(); 
5246         if ( event
.LeftIsDown() ) 
5248             switch ( m_cursorMode 
) 
5250                 case WXGRID_CURSOR_RESIZE_COL
: 
5252                     int cw
, ch
, dummy
, top
; 
5253                     m_gridWin
->GetClientSize( &cw
, &ch 
); 
5254                     CalcUnscrolledPosition( 0, 0, &dummy
, &top 
); 
5256                     wxClientDC 
dc( m_gridWin 
); 
5259                     x 
= wxMax( x
, GetColLeft(m_dragRowOrCol
) + 
5260                                   GetColMinimalWidth(m_dragRowOrCol
)); 
5261                     dc
.SetLogicalFunction(wxINVERT
); 
5262                     if ( m_dragLastPos 
>= 0 ) 
5264                         dc
.DrawLine( m_dragLastPos
, top
, m_dragLastPos
, top
+ch 
); 
5266                     dc
.DrawLine( x
, top
, x
, top
+ch 
); 
5271                 case WXGRID_CURSOR_SELECT_COL
: 
5273                     if ( (col 
= XToCol( x 
)) >= 0 ) 
5277                             m_selection
->SelectCol( col
, 
5278                                                     event
.ControlDown(), 
5287                 // default label to suppress warnings about "enumeration value 
5288                 // 'xxx' not handled in switch 
5296     if ( m_isDragging 
&& (event
.Entering() || event
.Leaving()) ) 
5301         if (m_colLabelWin
->HasCapture()) m_colLabelWin
->ReleaseMouse(); 
5302         m_isDragging 
= false; 
5305     // ------------ Entering or leaving the window 
5307     if ( event
.Entering() || event
.Leaving() ) 
5309         ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
, m_colLabelWin
); 
5313     // ------------ Left button pressed 
5315     else if ( event
.LeftDown() ) 
5317         // don't send a label click event for a hit on the 
5318         // edge of the col label - this is probably the user 
5319         // wanting to resize the col 
5321         if ( XToEdgeOfCol(x
) < 0 ) 
5325                  !SendEvent( wxEVT_GRID_LABEL_LEFT_CLICK
, -1, col
, event 
) ) 
5327                 if ( !event
.ShiftDown() && !event
.ControlDown() ) 
5331                     if ( event
.ShiftDown() ) 
5333                         m_selection
->SelectBlock( 0, 
5334                                                   m_currentCellCoords
.GetCol(), 
5335                                                   GetNumberRows() - 1, col
, 
5336                                                   event
.ControlDown(), 
5343                         m_selection
->SelectCol( col
, 
5344                                                 event
.ControlDown(), 
5351                 ChangeCursorMode(WXGRID_CURSOR_SELECT_COL
, m_colLabelWin
); 
5356             // starting to drag-resize a col 
5358             if ( CanDragColSize() ) 
5359                 ChangeCursorMode(WXGRID_CURSOR_RESIZE_COL
, m_colLabelWin
); 
5364     // ------------ Left double click 
5366     if ( event
.LeftDClick() ) 
5368         col 
= XToEdgeOfCol(x
); 
5373                  ! SendEvent( wxEVT_GRID_LABEL_LEFT_DCLICK
, -1, col
, event 
) ) 
5375                 // no default action at the moment 
5380             // adjust column width depending on label text 
5381             AutoSizeColLabelSize( col 
); 
5383             ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
, m_colLabelWin
); 
5389     // ------------ Left button released 
5391     else if ( event
.LeftUp() ) 
5393         if ( m_cursorMode 
== WXGRID_CURSOR_RESIZE_COL 
) 
5395             DoEndDragResizeCol(); 
5397             // Note: we are ending the event *after* doing 
5398             // default processing in this case 
5400             SendEvent( wxEVT_GRID_COL_SIZE
, -1, m_dragRowOrCol
, event 
); 
5403         ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
, m_colLabelWin
); 
5408     // ------------ Right button down 
5410     else if ( event
.RightDown() ) 
5414              !SendEvent( wxEVT_GRID_LABEL_RIGHT_CLICK
, -1, col
, event 
) ) 
5416             // no default action at the moment 
5421     // ------------ Right double click 
5423     else if ( event
.RightDClick() ) 
5427              !SendEvent( wxEVT_GRID_LABEL_RIGHT_DCLICK
, -1, col
, event 
) ) 
5429             // no default action at the moment 
5434     // ------------ No buttons down and mouse moving 
5436     else if ( event
.Moving() ) 
5438         m_dragRowOrCol 
= XToEdgeOfCol( x 
); 
5439         if ( m_dragRowOrCol 
>= 0 ) 
5441             if ( m_cursorMode 
== WXGRID_CURSOR_SELECT_CELL 
) 
5443                 // don't capture the cursor yet 
5444                 if ( CanDragColSize() ) 
5445                     ChangeCursorMode(WXGRID_CURSOR_RESIZE_COL
, m_colLabelWin
, false); 
5448         else if ( m_cursorMode 
!= WXGRID_CURSOR_SELECT_CELL 
) 
5450             ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
, m_colLabelWin
, false); 
5456 void wxGrid::ProcessCornerLabelMouseEvent( wxMouseEvent
& event 
) 
5458     if ( event
.LeftDown() ) 
5460         // indicate corner label by having both row and 
5463         if ( !SendEvent( wxEVT_GRID_LABEL_LEFT_CLICK
, -1, -1, event 
) ) 
5469     else if ( event
.LeftDClick() ) 
5471         SendEvent( wxEVT_GRID_LABEL_LEFT_DCLICK
, -1, -1, event 
); 
5474     else if ( event
.RightDown() ) 
5476         if ( !SendEvent( wxEVT_GRID_LABEL_RIGHT_CLICK
, -1, -1, event 
) ) 
5478             // no default action at the moment 
5482     else if ( event
.RightDClick() ) 
5484         if ( !SendEvent( wxEVT_GRID_LABEL_RIGHT_DCLICK
, -1, -1, event 
) ) 
5486             // no default action at the moment 
5491 void wxGrid::ChangeCursorMode(CursorMode mode
, 
5496     static const wxChar 
*cursorModes
[] = 
5505     wxLogTrace(_T("grid"), 
5506                _T("wxGrid cursor mode (mouse capture for %s): %s -> %s"), 
5507                win 
== m_colLabelWin 
? _T("colLabelWin") 
5508                                     : win 
? _T("rowLabelWin") 
5510                cursorModes
[m_cursorMode
], cursorModes
[mode
]); 
5511 #endif // __WXDEBUG__ 
5513     if ( mode 
== m_cursorMode 
&& 
5514          win 
== m_winCapture 
&& 
5515          captureMouse 
== (m_winCapture 
!= NULL
)) 
5520         // by default use the grid itself 
5526         if (m_winCapture
->HasCapture()) m_winCapture
->ReleaseMouse(); 
5527         m_winCapture 
= (wxWindow 
*)NULL
; 
5530     m_cursorMode 
= mode
; 
5532     switch ( m_cursorMode 
) 
5534         case WXGRID_CURSOR_RESIZE_ROW
: 
5535             win
->SetCursor( m_rowResizeCursor 
); 
5538         case WXGRID_CURSOR_RESIZE_COL
: 
5539             win
->SetCursor( m_colResizeCursor 
); 
5543             win
->SetCursor( *wxSTANDARD_CURSOR 
); 
5546     // we need to capture mouse when resizing 
5547     bool resize 
= m_cursorMode 
== WXGRID_CURSOR_RESIZE_ROW 
|| 
5548                   m_cursorMode 
== WXGRID_CURSOR_RESIZE_COL
; 
5550     if ( captureMouse 
&& resize 
) 
5552         win
->CaptureMouse(); 
5557 void wxGrid::ProcessGridCellMouseEvent( wxMouseEvent
& event 
) 
5560     wxPoint 
pos( event
.GetPosition() ); 
5561     CalcUnscrolledPosition( pos
.x
, pos
.y
, &x
, &y 
); 
5563     wxGridCellCoords coords
; 
5564     XYToCell( x
, y
, coords 
); 
5566     int cell_rows
, cell_cols
; 
5567     bool isFirstDrag 
= !m_isDragging
; 
5568     GetCellSize( coords
.GetRow(), coords
.GetCol(), &cell_rows
, &cell_cols 
); 
5569     if ((cell_rows 
< 0) || (cell_cols 
< 0)) 
5571         coords
.SetRow(coords
.GetRow() + cell_rows
); 
5572         coords
.SetCol(coords
.GetCol() + cell_cols
); 
5575     if ( event
.Dragging() ) 
5577         //wxLogDebug("pos(%d, %d) coords(%d, %d)", pos.x, pos.y, coords.GetRow(), coords.GetCol()); 
5579         // Don't start doing anything until the mouse has been dragged at 
5580         // least 3 pixels in any direction... 
5583             if (m_startDragPos 
== wxDefaultPosition
) 
5585                 m_startDragPos 
= pos
; 
5588             if (abs(m_startDragPos
.x 
- pos
.x
) < 4 && abs(m_startDragPos
.y 
- pos
.y
) < 4) 
5592         m_isDragging 
= true; 
5593         if ( m_cursorMode 
== WXGRID_CURSOR_SELECT_CELL 
) 
5595             // Hide the edit control, so it 
5596             // won't interfere with drag-shrinking. 
5597             if ( IsCellEditControlShown() ) 
5599                 HideCellEditControl(); 
5600                 SaveEditControlValue(); 
5603             // Have we captured the mouse yet? 
5606                 m_winCapture 
= m_gridWin
; 
5607                 m_winCapture
->CaptureMouse(); 
5610             if ( coords 
!= wxGridNoCellCoords 
) 
5612                 if ( event
.ControlDown() ) 
5614                     if ( m_selectingKeyboard 
== wxGridNoCellCoords
) 
5615                         m_selectingKeyboard 
= coords
; 
5616                     HighlightBlock ( m_selectingKeyboard
, coords 
); 
5618                 else if ( CanDragCell() ) 
5622                         if ( m_selectingKeyboard 
== wxGridNoCellCoords
) 
5623                             m_selectingKeyboard 
= coords
; 
5625                         SendEvent( wxEVT_GRID_CELL_BEGIN_DRAG
, 
5633                     if ( !IsSelection() ) 
5635                         HighlightBlock( coords
, coords 
); 
5639                         HighlightBlock( m_currentCellCoords
, coords 
); 
5643                 if (! IsVisible(coords
)) 
5645                     MakeCellVisible(coords
); 
5646                     // TODO: need to introduce a delay or something here.  The 
5647                     // scrolling is way to fast, at least on MSW - also on GTK. 
5651         else if ( m_cursorMode 
== WXGRID_CURSOR_RESIZE_ROW 
) 
5653             int cw
, ch
, left
, dummy
; 
5654             m_gridWin
->GetClientSize( &cw
, &ch 
); 
5655             CalcUnscrolledPosition( 0, 0, &left
, &dummy 
); 
5657             wxClientDC 
dc( m_gridWin 
); 
5659             y 
= wxMax( y
, GetRowTop(m_dragRowOrCol
) + 
5660                           GetRowMinimalHeight(m_dragRowOrCol
) ); 
5661             dc
.SetLogicalFunction(wxINVERT
); 
5662             if ( m_dragLastPos 
>= 0 ) 
5664                 dc
.DrawLine( left
, m_dragLastPos
, left
+cw
, m_dragLastPos 
); 
5666             dc
.DrawLine( left
, y
, left
+cw
, y 
); 
5669         else if ( m_cursorMode 
== WXGRID_CURSOR_RESIZE_COL 
) 
5671             int cw
, ch
, dummy
, top
; 
5672             m_gridWin
->GetClientSize( &cw
, &ch 
); 
5673             CalcUnscrolledPosition( 0, 0, &dummy
, &top 
); 
5675             wxClientDC 
dc( m_gridWin 
); 
5677             x 
= wxMax( x
, GetColLeft(m_dragRowOrCol
) + 
5678                           GetColMinimalWidth(m_dragRowOrCol
) ); 
5679             dc
.SetLogicalFunction(wxINVERT
); 
5680             if ( m_dragLastPos 
>= 0 ) 
5682                 dc
.DrawLine( m_dragLastPos
, top
, m_dragLastPos
, top
+ch 
); 
5684             dc
.DrawLine( x
, top
, x
, top
+ch 
); 
5691     m_isDragging 
= false; 
5692     m_startDragPos 
= wxDefaultPosition
; 
5694     // VZ: if we do this, the mode is reset to WXGRID_CURSOR_SELECT_CELL 
5695     //     immediately after it becomes WXGRID_CURSOR_RESIZE_ROW/COL under 
5698     if ( event
.Entering() || event
.Leaving() ) 
5700         ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
); 
5701         m_gridWin
->SetCursor( *wxSTANDARD_CURSOR 
); 
5706     // ------------ Left button pressed 
5708     if ( event
.LeftDown() && coords 
!= wxGridNoCellCoords 
) 
5710         if ( !SendEvent( wxEVT_GRID_CELL_LEFT_CLICK
, 
5715             if ( !event
.ControlDown() ) 
5717             if ( event
.ShiftDown() ) 
5721                     m_selection
->SelectBlock( m_currentCellCoords
.GetRow(), 
5722                                               m_currentCellCoords
.GetCol(), 
5725                                               event
.ControlDown(), 
5731             else if ( XToEdgeOfCol(x
) < 0  && 
5732                       YToEdgeOfRow(y
) < 0 ) 
5734                 DisableCellEditControl(); 
5735                 MakeCellVisible( coords 
); 
5737                 if ( event
.ControlDown() ) 
5741                         m_selection
->ToggleCellSelection( coords
.GetRow(), 
5743                                                           event
.ControlDown(), 
5748                     m_selectingTopLeft 
= wxGridNoCellCoords
; 
5749                     m_selectingBottomRight 
= wxGridNoCellCoords
; 
5750                     m_selectingKeyboard 
= coords
; 
5754                     m_waitForSlowClick 
= m_currentCellCoords 
== coords 
&& coords 
!= wxGridNoCellCoords
; 
5755                     SetCurrentCell( coords 
); 
5758                         if ( m_selection
->GetSelectionMode() != 
5759                                 wxGrid::wxGridSelectCells 
) 
5761                             HighlightBlock( coords
, coords 
); 
5770     // ------------ Left double click 
5772     else if ( event
.LeftDClick() && coords 
!= wxGridNoCellCoords 
) 
5774         DisableCellEditControl(); 
5776         if ( XToEdgeOfCol(x
) < 0  &&  YToEdgeOfRow(y
) < 0 ) 
5778             if ( !SendEvent( wxEVT_GRID_CELL_LEFT_DCLICK
, 
5783                 // we want double click to select a cell and start editing 
5784                 // (i.e. to behave in same way as sequence of two slow clicks): 
5785                 m_waitForSlowClick 
= true; 
5792     // ------------ Left button released 
5794     else if ( event
.LeftUp() ) 
5796         if ( m_cursorMode 
== WXGRID_CURSOR_SELECT_CELL 
) 
5800                 if (m_winCapture
->HasCapture()) m_winCapture
->ReleaseMouse(); 
5801                 m_winCapture 
= NULL
; 
5804             if ( coords 
== m_currentCellCoords 
&& m_waitForSlowClick 
&& CanEnableCellControl()) 
5807                 EnableCellEditControl(); 
5809                 wxGridCellAttr
* attr 
= GetCellAttr(coords
); 
5810                 wxGridCellEditor 
*editor 
= attr
->GetEditor(this, coords
.GetRow(), coords
.GetCol()); 
5811                 editor
->StartingClick(); 
5815                 m_waitForSlowClick 
= false; 
5817             else if ( m_selectingTopLeft 
!= wxGridNoCellCoords 
&& 
5818                  m_selectingBottomRight 
!= wxGridNoCellCoords 
) 
5822                     m_selection
->SelectBlock( m_selectingTopLeft
.GetRow(), 
5823                                               m_selectingTopLeft
.GetCol(), 
5824                                               m_selectingBottomRight
.GetRow(), 
5825                                               m_selectingBottomRight
.GetCol(), 
5826                                               event
.ControlDown(), 
5832                 m_selectingTopLeft 
= wxGridNoCellCoords
; 
5833                 m_selectingBottomRight 
= wxGridNoCellCoords
; 
5835                 // Show the edit control, if it has been hidden for 
5837                 ShowCellEditControl(); 
5840         else if ( m_cursorMode 
== WXGRID_CURSOR_RESIZE_ROW 
) 
5842             ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
); 
5843             DoEndDragResizeRow(); 
5845             // Note: we are ending the event *after* doing 
5846             // default processing in this case 
5848             SendEvent( wxEVT_GRID_ROW_SIZE
, m_dragRowOrCol
, -1, event 
); 
5850         else if ( m_cursorMode 
== WXGRID_CURSOR_RESIZE_COL 
) 
5852             ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
); 
5853             DoEndDragResizeCol(); 
5855             // Note: we are ending the event *after* doing 
5856             // default processing in this case 
5858             SendEvent( wxEVT_GRID_COL_SIZE
, -1, m_dragRowOrCol
, event 
); 
5865     // ------------ Right button down 
5867     else if ( event
.RightDown() && coords 
!= wxGridNoCellCoords 
) 
5869         DisableCellEditControl(); 
5870         if ( !SendEvent( wxEVT_GRID_CELL_RIGHT_CLICK
, 
5875             // no default action at the moment 
5880     // ------------ Right double click 
5882     else if ( event
.RightDClick() && coords 
!= wxGridNoCellCoords 
) 
5884         DisableCellEditControl(); 
5885         if ( !SendEvent( wxEVT_GRID_CELL_RIGHT_DCLICK
, 
5890             // no default action at the moment 
5894     // ------------ Moving and no button action 
5896     else if ( event
.Moving() && !event
.IsButton() ) 
5898         if ( coords
.GetRow() < 0 || coords
.GetCol() < 0 ) 
5900             // out of grid cell area 
5901             ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
); 
5905         int dragRow 
= YToEdgeOfRow( y 
); 
5906         int dragCol 
= XToEdgeOfCol( x 
); 
5908         // Dragging on the corner of a cell to resize in both 
5909         // directions is not implemented yet... 
5911         if ( dragRow 
>= 0 && dragCol 
>= 0 ) 
5913             ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
); 
5919             m_dragRowOrCol 
= dragRow
; 
5921             if ( m_cursorMode 
== WXGRID_CURSOR_SELECT_CELL 
) 
5923                 if ( CanDragRowSize() && CanDragGridSize() ) 
5924                     ChangeCursorMode(WXGRID_CURSOR_RESIZE_ROW
); 
5927         else if ( dragCol 
>= 0 ) 
5929             m_dragRowOrCol 
= dragCol
; 
5931             if ( m_cursorMode 
== WXGRID_CURSOR_SELECT_CELL 
) 
5933                 if ( CanDragColSize() && CanDragGridSize() ) 
5934                     ChangeCursorMode(WXGRID_CURSOR_RESIZE_COL
); 
5937         else // Neither on a row or col edge 
5939             if ( m_cursorMode 
!= WXGRID_CURSOR_SELECT_CELL 
) 
5941                 ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
); 
5948 void wxGrid::DoEndDragResizeRow() 
5950     if ( m_dragLastPos 
>= 0 ) 
5952         // erase the last line and resize the row 
5954         int cw
, ch
, left
, dummy
; 
5955         m_gridWin
->GetClientSize( &cw
, &ch 
); 
5956         CalcUnscrolledPosition( 0, 0, &left
, &dummy 
); 
5958         wxClientDC 
dc( m_gridWin 
); 
5960         dc
.SetLogicalFunction( wxINVERT 
); 
5961         dc
.DrawLine( left
, m_dragLastPos
, left
+cw
, m_dragLastPos 
); 
5962         HideCellEditControl(); 
5963         SaveEditControlValue(); 
5965         int rowTop 
= GetRowTop(m_dragRowOrCol
); 
5966         SetRowSize( m_dragRowOrCol
, 
5967                     wxMax( m_dragLastPos 
- rowTop
, m_minAcceptableRowHeight 
) ); 
5969         if ( !GetBatchCount() ) 
5971             // Only needed to get the correct rect.y: 
5972             wxRect 
rect ( CellToRect( m_dragRowOrCol
, 0 ) ); 
5974             CalcScrolledPosition(0, rect
.y
, &dummy
, &rect
.y
); 
5975             rect
.width 
= m_rowLabelWidth
; 
5976             rect
.height 
= ch 
- rect
.y
; 
5977             m_rowLabelWin
->Refresh( true, &rect 
); 
5979             // if there is a multicell block, paint all of it 
5982                 int i
, cell_rows
, cell_cols
, subtract_rows 
= 0; 
5983                 int leftCol 
= XToCol(left
); 
5984                 int rightCol 
= internalXToCol(left
+cw
); 
5987                     for (i
=leftCol
; i
<rightCol
; i
++) 
5989                         GetCellSize(m_dragRowOrCol
, i
, &cell_rows
, &cell_cols
); 
5990                         if (cell_rows 
< subtract_rows
) 
5991                             subtract_rows 
= cell_rows
; 
5993                     rect
.y 
= GetRowTop(m_dragRowOrCol 
+ subtract_rows
); 
5994                     CalcScrolledPosition(0, rect
.y
, &dummy
, &rect
.y
); 
5995                     rect
.height 
= ch 
- rect
.y
; 
5998             m_gridWin
->Refresh( false, &rect 
); 
6001         ShowCellEditControl(); 
6006 void wxGrid::DoEndDragResizeCol() 
6008     if ( m_dragLastPos 
>= 0 ) 
6010         // erase the last line and resize the col 
6012         int cw
, ch
, dummy
, top
; 
6013         m_gridWin
->GetClientSize( &cw
, &ch 
); 
6014         CalcUnscrolledPosition( 0, 0, &dummy
, &top 
); 
6016         wxClientDC 
dc( m_gridWin 
); 
6018         dc
.SetLogicalFunction( wxINVERT 
); 
6019         dc
.DrawLine( m_dragLastPos
, top
, m_dragLastPos
, top
+ch 
); 
6020         HideCellEditControl(); 
6021         SaveEditControlValue(); 
6023         int colLeft 
= GetColLeft(m_dragRowOrCol
); 
6024         SetColSize( m_dragRowOrCol
, 
6025                     wxMax( m_dragLastPos 
- colLeft
, 
6026                            GetColMinimalWidth(m_dragRowOrCol
) ) ); 
6028         if ( !GetBatchCount() ) 
6030             // Only needed to get the correct rect.x: 
6031             wxRect 
rect ( CellToRect( 0, m_dragRowOrCol 
) ); 
6033             CalcScrolledPosition(rect
.x
, 0, &rect
.x
, &dummy
); 
6034             rect
.width 
= cw 
- rect
.x
; 
6035             rect
.height 
= m_colLabelHeight
; 
6036             m_colLabelWin
->Refresh( true, &rect 
); 
6038             // if there is a multicell block, paint all of it 
6041                 int i
, cell_rows
, cell_cols
, subtract_cols 
= 0; 
6042                 int topRow 
= YToRow(top
); 
6043                 int bottomRow 
= internalYToRow(top
+cw
); 
6046                     for (i
=topRow
; i
<bottomRow
; i
++) 
6048                         GetCellSize(i
, m_dragRowOrCol
, &cell_rows
, &cell_cols
); 
6049                         if (cell_cols 
< subtract_cols
) 
6050                             subtract_cols 
= cell_cols
; 
6052                     rect
.x 
= GetColLeft(m_dragRowOrCol 
+ subtract_cols
); 
6053                     CalcScrolledPosition(rect
.x
, 0, &rect
.x
, &dummy
); 
6054                     rect
.width 
= cw 
- rect
.x
; 
6057             m_gridWin
->Refresh( false, &rect 
); 
6060         ShowCellEditControl(); 
6067 // ------ interaction with data model 
6069 bool wxGrid::ProcessTableMessage( wxGridTableMessage
& msg 
) 
6071     switch ( msg
.GetId() ) 
6073         case wxGRIDTABLE_REQUEST_VIEW_GET_VALUES
: 
6074             return GetModelValues(); 
6076         case wxGRIDTABLE_REQUEST_VIEW_SEND_VALUES
: 
6077             return SetModelValues(); 
6079         case wxGRIDTABLE_NOTIFY_ROWS_INSERTED
: 
6080         case wxGRIDTABLE_NOTIFY_ROWS_APPENDED
: 
6081         case wxGRIDTABLE_NOTIFY_ROWS_DELETED
: 
6082         case wxGRIDTABLE_NOTIFY_COLS_INSERTED
: 
6083         case wxGRIDTABLE_NOTIFY_COLS_APPENDED
: 
6084         case wxGRIDTABLE_NOTIFY_COLS_DELETED
: 
6085             return Redimension( msg 
); 
6094 // The behaviour of this function depends on the grid table class 
6095 // Clear() function.  For the default wxGridStringTable class the 
6096 // behavious is to replace all cell contents with wxEmptyString but 
6097 // not to change the number of rows or cols. 
6099 void wxGrid::ClearGrid() 
6103         if (IsCellEditControlEnabled()) 
6104             DisableCellEditControl(); 
6107         if ( !GetBatchCount() ) m_gridWin
->Refresh(); 
6112 bool wxGrid::InsertRows( int pos
, int numRows
, bool WXUNUSED(updateLabels
) ) 
6114     // TODO: something with updateLabels flag 
6118         wxFAIL_MSG( wxT("Called wxGrid::InsertRows() before calling CreateGrid()") ); 
6124         if (IsCellEditControlEnabled()) 
6125             DisableCellEditControl(); 
6127         bool done 
= m_table
->InsertRows( pos
, numRows 
); 
6130         // the table will have sent the results of the insert row 
6131         // operation to this view object as a grid table message 
6137 bool wxGrid::AppendRows( int numRows
, bool WXUNUSED(updateLabels
) ) 
6139     // TODO: something with updateLabels flag 
6143         wxFAIL_MSG( wxT("Called wxGrid::AppendRows() before calling CreateGrid()") ); 
6149         bool done 
= m_table 
&& m_table
->AppendRows( numRows 
); 
6151         // the table will have sent the results of the append row 
6152         // operation to this view object as a grid table message 
6158 bool wxGrid::DeleteRows( int pos
, int numRows
, bool WXUNUSED(updateLabels
) ) 
6160     // TODO: something with updateLabels flag 
6164         wxFAIL_MSG( wxT("Called wxGrid::DeleteRows() before calling CreateGrid()") ); 
6170         if (IsCellEditControlEnabled()) 
6171             DisableCellEditControl(); 
6173         bool done 
= m_table
->DeleteRows( pos
, numRows 
); 
6175         // the table will have sent the results of the delete row 
6176         // operation to this view object as a grid table message 
6182 bool wxGrid::InsertCols( int pos
, int numCols
, bool WXUNUSED(updateLabels
) ) 
6184     // TODO: something with updateLabels flag 
6188         wxFAIL_MSG( wxT("Called wxGrid::InsertCols() before calling CreateGrid()") ); 
6194         if (IsCellEditControlEnabled()) 
6195             DisableCellEditControl(); 
6197         bool done 
= m_table
->InsertCols( pos
, numCols 
); 
6199         // the table will have sent the results of the insert col 
6200         // operation to this view object as a grid table message 
6206 bool wxGrid::AppendCols( int numCols
, bool WXUNUSED(updateLabels
) ) 
6208     // TODO: something with updateLabels flag 
6212         wxFAIL_MSG( wxT("Called wxGrid::AppendCols() before calling CreateGrid()") ); 
6218         bool done 
= m_table
->AppendCols( numCols 
); 
6220         // the table will have sent the results of the append col 
6221         // operation to this view object as a grid table message 
6227 bool wxGrid::DeleteCols( int pos
, int numCols
, bool WXUNUSED(updateLabels
) ) 
6229     // TODO: something with updateLabels flag 
6233         wxFAIL_MSG( wxT("Called wxGrid::DeleteCols() before calling CreateGrid()") ); 
6239         if (IsCellEditControlEnabled()) 
6240             DisableCellEditControl(); 
6242         bool done 
= m_table
->DeleteCols( pos
, numCols 
); 
6244         // the table will have sent the results of the delete col 
6245         // operation to this view object as a grid table message 
6253 // ----- event handlers 
6256 // Generate a grid event based on a mouse event and 
6257 // return the result of ProcessEvent() 
6259 int wxGrid::SendEvent( const wxEventType type
, 
6261                         wxMouseEvent
& mouseEv 
) 
6266    if ( type 
== wxEVT_GRID_ROW_SIZE 
|| type 
== wxEVT_GRID_COL_SIZE 
) 
6268        int rowOrCol 
= (row 
== -1 ? col 
: row
); 
6270        wxGridSizeEvent 
gridEvt( GetId(), 
6274                mouseEv
.GetX() + GetRowLabelSize(), 
6275                mouseEv
.GetY() + GetColLabelSize(), 
6276                mouseEv
.ControlDown(), 
6277                mouseEv
.ShiftDown(), 
6279                mouseEv
.MetaDown() ); 
6281        claimed 
= GetEventHandler()->ProcessEvent(gridEvt
); 
6282        vetoed 
= !gridEvt
.IsAllowed(); 
6284    else if ( type 
== wxEVT_GRID_RANGE_SELECT 
) 
6286        // Right now, it should _never_ end up here! 
6287        wxGridRangeSelectEvent 
gridEvt( GetId(), 
6291                m_selectingBottomRight
, 
6293                mouseEv
.ControlDown(), 
6294                mouseEv
.ShiftDown(), 
6296                mouseEv
.MetaDown() ); 
6298        claimed 
= GetEventHandler()->ProcessEvent(gridEvt
); 
6299        vetoed 
= !gridEvt
.IsAllowed(); 
6303        wxGridEvent 
gridEvt( GetId(), 
6307                mouseEv
.GetX() + GetRowLabelSize(), 
6308                mouseEv
.GetY() + GetColLabelSize(), 
6310                mouseEv
.ControlDown(), 
6311                mouseEv
.ShiftDown(), 
6313                mouseEv
.MetaDown() ); 
6314        claimed 
= GetEventHandler()->ProcessEvent(gridEvt
); 
6315        vetoed 
= !gridEvt
.IsAllowed(); 
6318    // A Veto'd event may not be `claimed' so test this first 
6322    return claimed 
? 1 : 0; 
6326 // Generate a grid event of specified type and return the result 
6327 // of ProcessEvent(). 
6329 int wxGrid::SendEvent( const wxEventType type
, 
6335     if ( type 
== wxEVT_GRID_ROW_SIZE 
|| type 
== wxEVT_GRID_COL_SIZE 
) 
6337         int rowOrCol 
= (row 
== -1 ? col 
: row
); 
6339         wxGridSizeEvent 
gridEvt( GetId(), 
6344         claimed 
= GetEventHandler()->ProcessEvent(gridEvt
); 
6345         vetoed  
= !gridEvt
.IsAllowed(); 
6349         wxGridEvent 
gridEvt( GetId(), 
6354         claimed 
= GetEventHandler()->ProcessEvent(gridEvt
); 
6355         vetoed  
= !gridEvt
.IsAllowed(); 
6358     // A Veto'd event may not be `claimed' so test this first 
6362     return claimed 
? 1 : 0; 
6365 void wxGrid::OnPaint( wxPaintEvent
& WXUNUSED(event
) ) 
6367     wxPaintDC 
dc(this);  // needed to prevent zillions of paint events on MSW 
6370 void wxGrid::Refresh(bool eraseb
, const wxRect
* rect
) 
6372     // Don't do anything if between Begin/EndBatch... 
6373     // EndBatch() will do all this on the last nested one anyway. 
6374     if (! GetBatchCount()) 
6376         // Refresh to get correct scrolled position: 
6377         wxScrolledWindow::Refresh(eraseb
, rect
); 
6381             int rect_x
, rect_y
, rectWidth
, rectHeight
; 
6382             int width_label
, width_cell
, height_label
, height_cell
; 
6385             //Copy rectangle can get scroll offsets.. 
6386             rect_x 
= rect
->GetX(); 
6387             rect_y 
= rect
->GetY(); 
6388             rectWidth 
= rect
->GetWidth(); 
6389             rectHeight 
= rect
->GetHeight(); 
6391             width_label 
= m_rowLabelWidth 
- rect_x
; 
6392             if (width_label 
> rectWidth
) 
6393                 width_label 
= rectWidth
; 
6395             height_label 
= m_colLabelHeight 
- rect_y
; 
6396             if (height_label 
> rectHeight
) height_label 
= rectHeight
; 
6398             if (rect_x 
> m_rowLabelWidth
) 
6400                 x 
= rect_x 
- m_rowLabelWidth
; 
6401                 width_cell 
= rectWidth
; 
6406                 width_cell 
= rectWidth 
- (m_rowLabelWidth 
- rect_x
); 
6409             if (rect_y 
> m_colLabelHeight
) 
6411                 y 
= rect_y 
- m_colLabelHeight
; 
6412                 height_cell 
= rectHeight
; 
6417                 height_cell 
= rectHeight 
- (m_colLabelHeight 
- rect_y
); 
6420             // Paint corner label part intersecting rect. 
6421             if ( width_label 
> 0 && height_label 
> 0 ) 
6423                 wxRect 
anotherrect(rect_x
, rect_y
, width_label
, height_label
); 
6424                 m_cornerLabelWin
->Refresh(eraseb
, &anotherrect
); 
6427             // Paint col labels part intersecting rect. 
6428             if ( width_cell 
> 0 && height_label 
> 0 ) 
6430                 wxRect 
anotherrect(x
, rect_y
, width_cell
, height_label
); 
6431                 m_colLabelWin
->Refresh(eraseb
, &anotherrect
); 
6434             // Paint row labels part intersecting rect. 
6435             if ( width_label 
> 0 && height_cell 
> 0 ) 
6437                 wxRect 
anotherrect(rect_x
, y
, width_label
, height_cell
); 
6438                 m_rowLabelWin
->Refresh(eraseb
, &anotherrect
); 
6441             // Paint cell area part intersecting rect. 
6442             if ( width_cell 
> 0 && height_cell 
> 0 ) 
6444                 wxRect 
anotherrect(x
, y
, width_cell
, height_cell
); 
6445                 m_gridWin
->Refresh(eraseb
, &anotherrect
); 
6450             m_cornerLabelWin
->Refresh(eraseb
, NULL
); 
6451             m_colLabelWin
->Refresh(eraseb
, NULL
); 
6452             m_rowLabelWin
->Refresh(eraseb
, NULL
); 
6453             m_gridWin
->Refresh(eraseb
, NULL
); 
6458 void wxGrid::OnSize( wxSizeEvent
& event 
) 
6460     // position the child windows 
6463     // don't call CalcDimensions() from here, the base class handles the size 
6469 void wxGrid::OnKeyDown( wxKeyEvent
& event 
) 
6471     if ( m_inOnKeyDown 
) 
6473         // shouldn't be here - we are going round in circles... 
6475         wxFAIL_MSG( wxT("wxGrid::OnKeyDown called while already active") ); 
6478     m_inOnKeyDown 
= true; 
6480     // propagate the event up and see if it gets processed 
6482     wxWindow 
*parent 
= GetParent(); 
6483     wxKeyEvent 
keyEvt( event 
); 
6484     keyEvt
.SetEventObject( parent 
); 
6486     if ( !parent
->GetEventHandler()->ProcessEvent( keyEvt 
) ) 
6489         // try local handlers 
6491         switch ( event
.GetKeyCode() ) 
6494                 if ( event
.ControlDown() ) 
6496                     MoveCursorUpBlock( event
.ShiftDown() ); 
6500                     MoveCursorUp( event
.ShiftDown() ); 
6505                 if ( event
.ControlDown() ) 
6507                     MoveCursorDownBlock( event
.ShiftDown() ); 
6511                     MoveCursorDown( event
.ShiftDown() ); 
6516                 if ( event
.ControlDown() ) 
6518                     MoveCursorLeftBlock( event
.ShiftDown() ); 
6522                     MoveCursorLeft( event
.ShiftDown() ); 
6527                 if ( event
.ControlDown() ) 
6529                     MoveCursorRightBlock( event
.ShiftDown() ); 
6533                     MoveCursorRight( event
.ShiftDown() ); 
6538             case WXK_NUMPAD_ENTER
: 
6539                 if ( event
.ControlDown() ) 
6541                     event
.Skip();  // to let the edit control have the return 
6545                     if ( GetGridCursorRow() < GetNumberRows()-1 ) 
6547                         MoveCursorDown( event
.ShiftDown() ); 
6551                         // at the bottom of a column 
6552                         DisableCellEditControl(); 
6562                 if (event
.ShiftDown()) 
6564                     if ( GetGridCursorCol() > 0 ) 
6566                         MoveCursorLeft( false ); 
6571                         DisableCellEditControl(); 
6576                     if ( GetGridCursorCol() < GetNumberCols()-1 ) 
6578                         MoveCursorRight( false ); 
6583                         DisableCellEditControl(); 
6589                 if ( event
.ControlDown() ) 
6591                     MakeCellVisible( 0, 0 ); 
6592                     SetCurrentCell( 0, 0 ); 
6601                 if ( event
.ControlDown() ) 
6603                     MakeCellVisible( m_numRows
-1, m_numCols
-1 ); 
6604                     SetCurrentCell( m_numRows
-1, m_numCols
-1 ); 
6621                 if ( event
.ControlDown() ) 
6625                         m_selection
->ToggleCellSelection( m_currentCellCoords
.GetRow(), 
6626                                                           m_currentCellCoords
.GetCol(), 
6627                                                           event
.ControlDown(), 
6634                 if ( !IsEditable() ) 
6636                     MoveCursorRight( false ); 
6639                 // Otherwise fall through to default 
6647     m_inOnKeyDown 
= false; 
6650 void wxGrid::OnKeyUp( wxKeyEvent
& event 
) 
6652     // try local handlers 
6654     if ( event
.GetKeyCode() == WXK_SHIFT 
) 
6656         if ( m_selectingTopLeft 
!= wxGridNoCellCoords 
&& 
6657              m_selectingBottomRight 
!= wxGridNoCellCoords 
) 
6661                 m_selection
->SelectBlock( m_selectingTopLeft
.GetRow(), 
6662                                           m_selectingTopLeft
.GetCol(), 
6663                                           m_selectingBottomRight
.GetRow(), 
6664                                           m_selectingBottomRight
.GetCol(), 
6665                                           event
.ControlDown(), 
6672         m_selectingTopLeft 
= wxGridNoCellCoords
; 
6673         m_selectingBottomRight 
= wxGridNoCellCoords
; 
6674         m_selectingKeyboard 
= wxGridNoCellCoords
; 
6678 void wxGrid::OnChar( wxKeyEvent
& event 
) 
6680     // is it possible to edit the current cell at all? 
6681     if ( !IsCellEditControlEnabled() && CanEnableCellControl() ) 
6683         // yes, now check whether the cells editor accepts the key 
6684         int row 
= m_currentCellCoords
.GetRow(); 
6685         int col 
= m_currentCellCoords
.GetCol(); 
6686         wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
6687         wxGridCellEditor 
*editor 
= attr
->GetEditor(this, row
, col
); 
6689         // <F2> is special and will always start editing, for 
6690         // other keys - ask the editor itself 
6691         if ( (event
.GetKeyCode() == WXK_F2 
&& !event
.HasModifiers()) 
6692              || editor
->IsAcceptedKey(event
) ) 
6694             // ensure cell is visble 
6695             MakeCellVisible(row
, col
); 
6696             EnableCellEditControl(); 
6698             // a problem can arise if the cell is not completely 
6699             // visible (even after calling MakeCellVisible the 
6700             // control is not created and calling StartingKey will 
6702             if ( event
.GetKeyCode() != WXK_F2 
&& editor
->IsCreated() && m_cellEditCtrlEnabled 
) 
6703                 editor
->StartingKey(event
); 
6720 void wxGrid::OnEraseBackground(wxEraseEvent
&) 
6724 void wxGrid::SetCurrentCell( const wxGridCellCoords
& coords 
) 
6726     if ( SendEvent( wxEVT_GRID_SELECT_CELL
, coords
.GetRow(), coords
.GetCol() ) ) 
6728         // the event has been intercepted - do nothing 
6732     wxClientDC 
dc(m_gridWin
); 
6735     if ( m_currentCellCoords 
!= wxGridNoCellCoords 
) 
6737         DisableCellEditControl(); 
6739         if ( IsVisible( m_currentCellCoords
, false ) ) 
6742             r 
= BlockToDeviceRect(m_currentCellCoords
, m_currentCellCoords
); 
6743             if ( !m_gridLinesEnabled 
) 
6751             wxGridCellCoordsArray cells 
= CalcCellsExposed( r 
); 
6753             // Otherwise refresh redraws the highlight! 
6754             m_currentCellCoords 
= coords
; 
6756             DrawGridCellArea(dc
,cells
); 
6757             DrawAllGridLines( dc
, r 
); 
6761     m_currentCellCoords 
= coords
; 
6763     wxGridCellAttr
* attr 
= GetCellAttr(coords
); 
6764     DrawCellHighlight(dc
, attr
); 
6769 void wxGrid::HighlightBlock( int topRow
, int leftCol
, int bottomRow
, int rightCol 
) 
6772     wxGridCellCoords updateTopLeft
, updateBottomRight
; 
6776         if ( m_selection
->GetSelectionMode() == wxGrid::wxGridSelectRows 
) 
6779             rightCol 
= GetNumberCols() - 1; 
6781         else if ( m_selection
->GetSelectionMode() == wxGrid::wxGridSelectColumns 
) 
6784             bottomRow 
= GetNumberRows() - 1; 
6788     if ( topRow 
> bottomRow 
) 
6795     if ( leftCol 
> rightCol 
) 
6802     updateTopLeft 
= wxGridCellCoords( topRow
, leftCol 
); 
6803     updateBottomRight 
= wxGridCellCoords( bottomRow
, rightCol 
); 
6805     // First the case that we selected a completely new area 
6806     if ( m_selectingTopLeft 
== wxGridNoCellCoords 
|| 
6807          m_selectingBottomRight 
== wxGridNoCellCoords 
) 
6810         rect 
= BlockToDeviceRect( wxGridCellCoords ( topRow
, leftCol 
), 
6811                                   wxGridCellCoords ( bottomRow
, rightCol 
) ); 
6812         m_gridWin
->Refresh( false, &rect 
); 
6814     // Now handle changing an existing selection area. 
6815     else if ( m_selectingTopLeft 
!= updateTopLeft 
|| 
6816               m_selectingBottomRight 
!= updateBottomRight 
) 
6818         // Compute two optimal update rectangles: 
6819         // Either one rectangle is a real subset of the 
6820         // other, or they are (almost) disjoint! 
6822         bool    need_refresh
[4]; 
6826         need_refresh
[3] = false; 
6829         // Store intermediate values 
6830         wxCoord oldLeft   
= m_selectingTopLeft
.GetCol(); 
6831         wxCoord oldTop    
= m_selectingTopLeft
.GetRow(); 
6832         wxCoord oldRight  
= m_selectingBottomRight
.GetCol(); 
6833         wxCoord oldBottom 
= m_selectingBottomRight
.GetRow(); 
6835         // Determine the outer/inner coordinates. 
6836         if (oldLeft 
> leftCol
) 
6842         if (oldTop 
> topRow 
) 
6848         if (oldRight 
< rightCol 
) 
6851             oldRight 
= rightCol
; 
6854         if (oldBottom 
< bottomRow
) 
6857             oldBottom 
= bottomRow
; 
6861         // Now, either the stuff marked old is the outer 
6862         // rectangle or we don't have a situation where one 
6863         // is contained in the other. 
6865         if ( oldLeft 
< leftCol 
) 
6867             // Refresh the newly selected or deselected 
6868             // area to the left of the old or new selection. 
6869             need_refresh
[0] = true; 
6870             rect
[0] = BlockToDeviceRect( wxGridCellCoords ( oldTop
, 
6872                                          wxGridCellCoords ( oldBottom
, 
6876         if ( oldTop  
< topRow 
) 
6878             // Refresh the newly selected or deselected 
6879             // area above the old or new selection. 
6880             need_refresh
[1] = true; 
6881             rect
[1] = BlockToDeviceRect( wxGridCellCoords ( oldTop
, 
6883                                          wxGridCellCoords ( topRow 
- 1, 
6887         if ( oldRight 
> rightCol 
) 
6889             // Refresh the newly selected or deselected 
6890             // area to the right of the old or new selection. 
6891             need_refresh
[2] = true; 
6892             rect
[2] = BlockToDeviceRect( wxGridCellCoords ( oldTop
, 
6894                                          wxGridCellCoords ( oldBottom
, 
6898         if ( oldBottom 
> bottomRow 
) 
6900             // Refresh the newly selected or deselected 
6901             // area below the old or new selection. 
6902             need_refresh
[3] = true; 
6903             rect
[3] = BlockToDeviceRect( wxGridCellCoords ( bottomRow 
+ 1, 
6905                                          wxGridCellCoords ( oldBottom
, 
6909         // various Refresh() calls 
6910         for (i 
= 0; i 
< 4; i
++ ) 
6911             if ( need_refresh
[i
] && rect
[i
] != wxGridNoCellRect 
) 
6912                 m_gridWin
->Refresh( false, &(rect
[i
]) ); 
6915     m_selectingTopLeft 
= updateTopLeft
; 
6916     m_selectingBottomRight 
= updateBottomRight
; 
6920 // ------ functions to get/send data (see also public functions) 
6923 bool wxGrid::GetModelValues() 
6925     // Hide the editor, so it won't hide a changed value. 
6926     HideCellEditControl(); 
6930         // all we need to do is repaint the grid 
6932         m_gridWin
->Refresh(); 
6940 bool wxGrid::SetModelValues() 
6944     // Disable the editor, so it won't hide a changed value. 
6945     // Do we also want to save the current value of the editor first? 
6947     DisableCellEditControl(); 
6951         for ( row 
= 0;  row 
< m_numRows
;  row
++ ) 
6953             for ( col 
= 0;  col 
< m_numCols
;  col
++ ) 
6955                 m_table
->SetValue( row
, col
, GetCellValue(row
, col
) ); 
6967 // Note - this function only draws cells that are in the list of 
6968 // exposed cells (usually set from the update region by 
6969 // CalcExposedCells) 
6971 void wxGrid::DrawGridCellArea( wxDC
& dc
, const wxGridCellCoordsArray
& cells 
) 
6973     if ( !m_numRows 
|| !m_numCols 
) 
6976     int i
, numCells 
= cells
.GetCount(); 
6977     int row
, col
, cell_rows
, cell_cols
; 
6978     wxGridCellCoordsArray redrawCells
; 
6980     for ( i 
= numCells
-1; i 
>= 0;  i
-- ) 
6982         row 
= cells
[i
].GetRow(); 
6983         col 
= cells
[i
].GetCol(); 
6984         GetCellSize( row
, col
, &cell_rows
, &cell_cols 
); 
6986         // If this cell is part of a multicell block, find owner for repaint 
6987         if ( cell_rows 
<= 0 || cell_cols 
<= 0 ) 
6989             wxGridCellCoords 
cell(row
+cell_rows
, col
+cell_cols
); 
6990             bool marked 
= false; 
6991             for ( int j 
= 0;  j 
< numCells
;  j
++ ) 
6993                 if ( cell 
== cells
[j
] ) 
7001                 int count 
= redrawCells
.GetCount(); 
7002                 for (int j 
= 0; j 
< count
; j
++) 
7004                     if ( cell 
== redrawCells
[j
] ) 
7011                     redrawCells
.Add( cell 
); 
7013             continue; // don't bother drawing this cell 
7016         // If this cell is empty, find cell to left that might want to overflow 
7017         if (m_table 
&& m_table
->IsEmptyCell(row
, col
)) 
7019             for ( int l 
= 0; l 
< cell_rows
; l
++ ) 
7021                 // find a cell in this row to left alreay marked for repaint 
7023                 for (int k 
= 0; k 
< int(redrawCells
.GetCount()); k
++) 
7024                     if ((redrawCells
[k
].GetCol() < left
) && 
7025                         (redrawCells
[k
].GetRow() == row
)) 
7026                         left 
= redrawCells
[k
].GetCol(); 
7029                     left 
= 0; // oh well 
7031                 for (int j 
= col
-1; j 
>= left
; j
--) 
7033                     if (!m_table
->IsEmptyCell(row
+l
, j
)) 
7035                         if (GetCellOverflow(row
+l
, j
)) 
7037                             wxGridCellCoords 
cell(row
+l
, j
); 
7038                             bool marked 
= false; 
7040                             for (int k 
= 0; k 
< numCells
; k
++) 
7042                                 if ( cell 
== cells
[k
] ) 
7051                                 int count 
= redrawCells
.GetCount(); 
7052                                 for (int k 
= 0; k 
< count
; k
++) 
7054                                     if ( cell 
== redrawCells
[k
] ) 
7061                                     redrawCells
.Add( cell 
); 
7070         DrawCell( dc
, cells
[i
] ); 
7073     numCells 
= redrawCells
.GetCount(); 
7075     for ( i 
= numCells 
- 1; i 
>= 0;  i
-- ) 
7077         DrawCell( dc
, redrawCells
[i
] ); 
7082 void wxGrid::DrawGridSpace( wxDC
& dc 
) 
7085   m_gridWin
->GetClientSize( &cw
, &ch 
); 
7088   CalcUnscrolledPosition( cw
, ch
, &right
, &bottom 
); 
7090   int rightCol 
= m_numCols 
> 0 ? GetColRight(m_numCols 
- 1) : 0; 
7091   int bottomRow 
= m_numRows 
> 0 ? GetRowBottom(m_numRows 
- 1) : 0 ; 
7093   if ( right 
> rightCol 
|| bottom 
> bottomRow 
) 
7096       CalcUnscrolledPosition( 0, 0, &left
, &top 
); 
7098       dc
.SetBrush( wxBrush(GetDefaultCellBackgroundColour(), wxSOLID
) ); 
7099       dc
.SetPen( *wxTRANSPARENT_PEN 
); 
7101       if ( right 
> rightCol 
) 
7103           dc
.DrawRectangle( rightCol
, top
, right 
- rightCol
, ch
); 
7106       if ( bottom 
> bottomRow 
) 
7108           dc
.DrawRectangle( left
, bottomRow
, cw
, bottom 
- bottomRow
); 
7114 void wxGrid::DrawCell( wxDC
& dc
, const wxGridCellCoords
& coords 
) 
7116     int row 
= coords
.GetRow(); 
7117     int col 
= coords
.GetCol(); 
7119     if ( GetColWidth(col
) <= 0 || GetRowHeight(row
) <= 0 ) 
7122     // we draw the cell border ourselves 
7123 #if !WXGRID_DRAW_LINES 
7124     if ( m_gridLinesEnabled 
) 
7125         DrawCellBorder( dc
, coords 
); 
7128     wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
7130     bool isCurrent 
= coords 
== m_currentCellCoords
; 
7132     wxRect rect 
= CellToRect( row
, col 
); 
7134     // if the editor is shown, we should use it and not the renderer 
7135     // Note: However, only if it is really _shown_, i.e. not hidden! 
7136     if ( isCurrent 
&& IsCellEditControlShown() ) 
7138         // OSAF NB: this "#if..." is temporary and fixes a problem where the 
7139         // edit control is erased by this code after being rendered. 
7140         // On wxMac (QD build only), the cell editor is a wxTextCntl and is rendered 
7141         // implicitly, causing this out-of order render. 
7142 #if !defined(__WXMAC__) || wxMAC_USE_CORE_GRAPHICS 
7143         wxGridCellEditor 
*editor 
= attr
->GetEditor(this, row
, col
); 
7144         editor
->PaintBackground(rect
, attr
); 
7150         // but all the rest is drawn by the cell renderer and hence may be 
7152         wxGridCellRenderer 
*renderer 
= attr
->GetRenderer(this, row
, col
); 
7153         renderer
->Draw(*this, *attr
, dc
, rect
, row
, col
, IsInSelection(coords
)); 
7160 void wxGrid::DrawCellHighlight( wxDC
& dc
, const wxGridCellAttr 
*attr 
) 
7162     int row 
= m_currentCellCoords
.GetRow(); 
7163     int col 
= m_currentCellCoords
.GetCol(); 
7165     if ( GetColWidth(col
) <= 0 || GetRowHeight(row
) <= 0 ) 
7168     wxRect rect 
= CellToRect(row
, col
); 
7170     // hmmm... what could we do here to show that the cell is disabled? 
7171     // for now, I just draw a thinner border than for the other ones, but 
7172     // it doesn't look really good 
7174     int penWidth 
= attr
->IsReadOnly() ? m_cellHighlightROPenWidth 
: m_cellHighlightPenWidth
; 
7178         // The center of th drawn line is where the position/width/height of 
7179         // the rectangle is actually at, (on wxMSW atr least,) so we will 
7180         // reduce the size of the rectangle to compensate for the thickness of 
7181         // the line.  If this is too strange on non wxMSW platforms then 
7182         // please #ifdef this appropriately. 
7183         rect
.x 
+= penWidth 
/ 2; 
7184         rect
.y 
+= penWidth 
/ 2; 
7185         rect
.width 
-= penWidth 
- 1; 
7186         rect
.height 
-= penWidth 
- 1; 
7189         // Now draw the rectangle 
7190         // use the cellHighlightColour if the cell is inside a selection, this 
7191         // will ensure the cell is always visible. 
7192         dc
.SetPen(wxPen(IsInSelection(row
,col
) ? m_selectionForeground 
: m_cellHighlightColour
, penWidth
, wxSOLID
)); 
7193         dc
.SetBrush(*wxTRANSPARENT_BRUSH
); 
7194         dc
.DrawRectangle(rect
); 
7198         // VZ: my experiments with 3d borders... 
7200         // how to properly set colours for arbitrary bg? 
7201         wxCoord x1 
= rect
.x
, 
7203                 x2 
= rect
.x 
+ rect
.width 
- 1, 
7204                 y2 
= rect
.y 
+ rect
.height 
- 1; 
7206         dc
.SetPen(*wxWHITE_PEN
); 
7207         dc
.DrawLine(x1
, y1
, x2
, y1
); 
7208         dc
.DrawLine(x1
, y1
, x1
, y2
); 
7210         dc
.DrawLine(x1 
+ 1, y2 
- 1, x2 
- 1, y2 
- 1); 
7211         dc
.DrawLine(x2 
- 1, y1 
+ 1, x2 
- 1, y2 
); 
7213         dc
.SetPen(*wxBLACK_PEN
); 
7214         dc
.DrawLine(x1
, y2
, x2
, y2
); 
7215         dc
.DrawLine(x2
, y1
, x2
, y2
+1); 
7220 void wxGrid::DrawCellBorder( wxDC
& dc
, const wxGridCellCoords
& coords 
) 
7222     int row 
= coords
.GetRow(); 
7223     int col 
= coords
.GetCol(); 
7224     if ( GetColWidth(col
) <= 0 || GetRowHeight(row
) <= 0 ) 
7227     dc
.SetPen( wxPen(GetGridLineColour(), 1, wxSOLID
) ); 
7229     wxRect rect 
= CellToRect( row
, col 
); 
7231     // right hand border 
7233     dc
.DrawLine( rect
.x 
+ rect
.width
, rect
.y
, 
7234                  rect
.x 
+ rect
.width
, rect
.y 
+ rect
.height 
+ 1 ); 
7238     dc
.DrawLine( rect
.x
,              rect
.y 
+ rect
.height
, 
7239                  rect
.x 
+ rect
.width
, rect
.y 
+ rect
.height
); 
7242 void wxGrid::DrawHighlight(wxDC
& dc
,const  wxGridCellCoordsArray
& cells
) 
7244     // This if block was previously in wxGrid::OnPaint but that doesn't 
7245     // seem to get called under wxGTK - MB 
7247     if ( m_currentCellCoords 
== wxGridNoCellCoords  
&& 
7248          m_numRows 
&& m_numCols 
) 
7250         m_currentCellCoords
.Set(0, 0); 
7253     if ( IsCellEditControlShown() ) 
7255         // don't show highlight when the edit control is shown 
7259     // if the active cell was repainted, repaint its highlight too because it 
7260     // might have been damaged by the grid lines 
7261     size_t count 
= cells
.GetCount(); 
7262     for ( size_t n 
= 0; n 
< count
; n
++ ) 
7264         if ( cells
[n
] == m_currentCellCoords 
) 
7266             wxGridCellAttr
* attr 
= GetCellAttr(m_currentCellCoords
); 
7267             DrawCellHighlight(dc
, attr
); 
7275 // TODO: remove this ??? 
7276 // This is used to redraw all grid lines e.g. when the grid line colour 
7279 void wxGrid::DrawAllGridLines( wxDC
& dc
, const wxRegion 
& WXUNUSED(reg
) ) 
7281 #if !WXGRID_DRAW_LINES 
7285     if ( !m_gridLinesEnabled 
|| 
7290     int top
, bottom
, left
, right
; 
7292 #if 0  //#ifndef __WXGTK__ 
7296       m_gridWin
->GetClientSize(&cw
, &ch
); 
7298       // virtual coords of visible area 
7300       CalcUnscrolledPosition( 0, 0, &left
, &top 
); 
7301       CalcUnscrolledPosition( cw
, ch
, &right
, &bottom 
); 
7306       reg
.GetBox(x
, y
, w
, h
); 
7307       CalcUnscrolledPosition( x
, y
, &left
, &top 
); 
7308       CalcUnscrolledPosition( x 
+ w
, y 
+ h
, &right
, &bottom 
); 
7312       m_gridWin
->GetClientSize(&cw
, &ch
); 
7313       CalcUnscrolledPosition( 0, 0, &left
, &top 
); 
7314       CalcUnscrolledPosition( cw
, ch
, &right
, &bottom 
); 
7317     // avoid drawing grid lines past the last row and col 
7319     right 
= wxMin( right
, GetColRight(m_numCols 
- 1) ); 
7320     bottom 
= wxMin( bottom
, GetRowBottom(m_numRows 
- 1) ); 
7322     // no gridlines inside multicells, clip them out 
7323     int leftCol   
= internalXToCol(left
); 
7324     int topRow    
= internalYToRow(top
); 
7325     int rightCol  
= internalXToCol(right
); 
7326     int bottomRow 
= internalYToRow(bottom
); 
7329     // CS: I don't know why suddenly unscrolled coordinates are used for clipping 
7330     wxRegion 
clippedcells(0, 0, cw
, ch
); 
7332     int i
, j
, cell_rows
, cell_cols
; 
7335     for (j
=topRow
; j
<bottomRow
; j
++) 
7337         for (i
=leftCol
; i
<rightCol
; i
++) 
7339             GetCellSize( j
, i
, &cell_rows
, &cell_cols 
); 
7340             if ((cell_rows 
> 1) || (cell_cols 
> 1)) 
7342                 rect 
= CellToRect(j
,i
); 
7343                 CalcScrolledPosition( rect
.x
, rect
.y
, &rect
.x
, &rect
.y 
); 
7344                 clippedcells
.Subtract(rect
); 
7346             else if ((cell_rows 
< 0) || (cell_cols 
< 0)) 
7348                 rect 
= CellToRect(j
+cell_rows
, i
+cell_cols
); 
7349                 CalcScrolledPosition( rect
.x
, rect
.y
, &rect
.x
, &rect
.y 
); 
7350                 clippedcells
.Subtract(rect
); 
7355     wxRegion 
clippedcells( left 
, top
, right 
- left
, bottom 
- top
); 
7357     int i
, j
, cell_rows
, cell_cols
; 
7360     for (j
=topRow
; j
<bottomRow
; j
++) 
7362         for (i
=leftCol
; i
<rightCol
; i
++) 
7364             GetCellSize( j
, i
, &cell_rows
, &cell_cols 
); 
7365             if ((cell_rows 
> 1) || (cell_cols 
> 1)) 
7367                 rect 
= CellToRect(j
,i
); 
7368                 clippedcells
.Subtract(rect
); 
7370             else if ((cell_rows 
< 0) || (cell_cols 
< 0)) 
7372                 rect 
= CellToRect(j
+cell_rows
, i
+cell_cols
); 
7373                 clippedcells
.Subtract(rect
); 
7378     dc
.SetClippingRegion( clippedcells 
); 
7380     dc
.SetPen( wxPen(GetGridLineColour(), 1, wxSOLID
) ); 
7382     // horizontal grid lines 
7384     // already declared above - int i; 
7385     for ( i 
= internalYToRow(top
); i 
< m_numRows
; i
++ ) 
7387         int bot 
= GetRowBottom(i
) - 1; 
7396             dc
.DrawLine( left
, bot
, right
, bot 
); 
7400     // vertical grid lines 
7402     for ( i 
= internalXToCol(left
); i 
< m_numCols
; i
++ ) 
7404         int colRight 
= GetColRight(i
) - 1; 
7405         if ( colRight 
> right 
) 
7410         if ( colRight 
>= left 
) 
7412             dc
.DrawLine( colRight
, top
, colRight
, bottom 
); 
7415     dc
.DestroyClippingRegion(); 
7418 void wxGrid::DrawRowLabels( wxDC
& dc 
,const wxArrayInt
& rows
) 
7424     size_t numLabels 
= rows
.GetCount(); 
7426     for ( i 
= 0;  i 
< numLabels
;  i
++ ) 
7428         DrawRowLabel( dc
, rows
[i
] ); 
7432 void wxGrid::DrawRowLabel( wxDC
& dc
, int row 
) 
7434     if ( GetRowHeight(row
) <= 0 || m_rowLabelWidth 
<= 0 ) 
7440     rect
.SetY( GetRowTop(row
) + 1 ); 
7441     rect
.SetWidth( m_rowLabelWidth 
- 2 ); 
7442     rect
.SetHeight( GetRowHeight(row
) - 2 ); 
7444     CalcScrolledPosition( 0, rect
.y
, NULL
, &rect
.y 
); 
7446     wxWindowDC 
*win_dc 
= (wxWindowDC
*) &dc
; 
7448     wxRendererNative::Get().DrawHeaderButton( win_dc
->m_owner
, dc
, rect
, 0 ); 
7450     int rowTop 
= GetRowTop(row
), 
7451         rowBottom 
= GetRowBottom(row
) - 1; 
7453     dc
.SetPen( wxPen(wxSystemSettings::GetColour(wxSYS_COLOUR_3DDKSHADOW
),1, wxSOLID
) ); 
7454     dc
.DrawLine( m_rowLabelWidth
-1, rowTop
, 
7455                  m_rowLabelWidth
-1, rowBottom 
); 
7457     dc
.DrawLine( 0, rowTop
, 0, rowBottom 
); 
7459     dc
.DrawLine( 0, rowBottom
, m_rowLabelWidth
, rowBottom 
); 
7461     dc
.SetPen( *wxWHITE_PEN 
); 
7462     dc
.DrawLine( 1, rowTop
, 1, rowBottom 
); 
7463     dc
.DrawLine( 1, rowTop
, m_rowLabelWidth
-1, rowTop 
); 
7465     dc
.SetBackgroundMode( wxTRANSPARENT 
); 
7466     dc
.SetTextForeground( GetLabelTextColour() ); 
7467     dc
.SetFont( GetLabelFont() ); 
7470     GetRowLabelAlignment( &hAlign
, &vAlign 
); 
7473     rect
.SetY( GetRowTop(row
) + 2 ); 
7474     rect
.SetWidth( m_rowLabelWidth 
- 4 ); 
7475     rect
.SetHeight( GetRowHeight(row
) - 4 ); 
7476     DrawTextRectangle( dc
, GetRowLabelValue( row 
), rect
, hAlign
, vAlign 
); 
7479 void wxGrid::DrawColLabels( wxDC
& dc
,const wxArrayInt
& cols 
) 
7485     size_t numLabels 
= cols
.GetCount(); 
7487     for ( i 
= 0;  i 
< numLabels
;  i
++ ) 
7489         DrawColLabel( dc
, cols
[i
] ); 
7493 void wxGrid::DrawColLabel( wxDC
& dc
, int col 
) 
7495     if ( GetColWidth(col
) <= 0 || m_colLabelHeight 
<= 0 ) 
7498     int colLeft 
= GetColLeft(col
); 
7502     rect
.SetX( colLeft 
+ 1 ); 
7504     rect
.SetWidth( GetColWidth(col
) - 2 ); 
7505     rect
.SetHeight( m_colLabelHeight 
- 2 ); 
7507     wxWindowDC 
*win_dc 
= (wxWindowDC
*) &dc
; 
7509     wxRendererNative::Get().DrawHeaderButton( win_dc
->m_owner
, dc
, rect
, 0 ); 
7511     int colRight 
= GetColRight(col
) - 1; 
7513     dc
.SetPen( wxPen(wxSystemSettings::GetColour(wxSYS_COLOUR_3DDKSHADOW
),1, wxSOLID
) ); 
7514     dc
.DrawLine( colRight
, 0, 
7515                  colRight
, m_colLabelHeight
-1 ); 
7517     dc
.DrawLine( colLeft
, 0, colRight
, 0 ); 
7519     dc
.DrawLine( colLeft
, m_colLabelHeight
-1, 
7520                  colRight
+1, m_colLabelHeight
-1 ); 
7522     dc
.SetPen( *wxWHITE_PEN 
); 
7523     dc
.DrawLine( colLeft
, 1, colLeft
, m_colLabelHeight
-1 ); 
7524     dc
.DrawLine( colLeft
, 1, colRight
, 1 ); 
7526     dc
.SetBackgroundMode( wxTRANSPARENT 
); 
7527     dc
.SetTextForeground( GetLabelTextColour() ); 
7528     dc
.SetFont( GetLabelFont() ); 
7530     int hAlign
, vAlign
, orient
; 
7531     GetColLabelAlignment( &hAlign
, &vAlign 
); 
7532     orient 
= GetColLabelTextOrientation(); 
7534     rect
.SetX( colLeft 
+ 2 ); 
7536     rect
.SetWidth( GetColWidth(col
) - 4 ); 
7537     rect
.SetHeight( m_colLabelHeight 
- 4 ); 
7538     DrawTextRectangle( dc
, GetColLabelValue( col 
), rect
, hAlign
, vAlign
, orient 
); 
7541 void wxGrid::DrawTextRectangle( wxDC
& dc
, 
7542                                 const wxString
& value
, 
7546                                 int textOrientation 
) 
7548     wxArrayString lines
; 
7550     StringToLines( value
, lines 
); 
7552     //Forward to new API. 
7553     DrawTextRectangle(  dc
, 
7562 void wxGrid::DrawTextRectangle( wxDC
& dc
, 
7563                                const wxArrayString
& lines
, 
7567                                int textOrientation 
) 
7569     long textWidth 
= 0, textHeight 
= 0; 
7570     long lineWidth 
= 0, lineHeight 
= 0; 
7573     dc
.SetClippingRegion( rect 
); 
7575     nLines 
= lines
.GetCount(); 
7579         float x 
= 0.0, y 
= 0.0; 
7581         if ( textOrientation 
== wxHORIZONTAL 
) 
7582             GetTextBoxSize(dc
, lines
, &textWidth
, &textHeight
); 
7584             GetTextBoxSize( dc
, lines
, &textHeight
, &textWidth 
); 
7586         switch ( vertAlign 
) 
7588         case wxALIGN_BOTTOM
: 
7589             if ( textOrientation 
== wxHORIZONTAL 
) 
7590                 y 
= rect
.y 
+ (rect
.height 
- textHeight 
- 1); 
7592                 x 
= rect
.x 
+ rect
.width 
- textWidth
; 
7595         case wxALIGN_CENTRE
: 
7596             if ( textOrientation 
== wxHORIZONTAL 
) 
7597                 y 
= rect
.y 
+ ((rect
.height 
- textHeight
)/2); 
7599                 x 
= rect
.x 
+ ((rect
.width 
- textWidth
)/2); 
7604             if ( textOrientation 
== wxHORIZONTAL 
) 
7611         // Align each line of a multi-line label 
7612         for ( l 
= 0; l 
< nLines
; l
++ ) 
7614             dc
.GetTextExtent(lines
[l
], &lineWidth
, &lineHeight
); 
7616             switch ( horizAlign 
) 
7619                 if ( textOrientation 
== wxHORIZONTAL 
) 
7620                     x 
= rect
.x 
+ (rect
.width 
- lineWidth 
- 1); 
7622                     y 
= rect
.y 
+ lineWidth 
+ 1; 
7625             case wxALIGN_CENTRE
: 
7626                 if ( textOrientation 
== wxHORIZONTAL 
) 
7627                     x 
= rect
.x 
+ ((rect
.width 
- lineWidth
)/2); 
7629                     y 
= rect
.y 
+ rect
.height 
- ((rect
.height 
- lineWidth
)/2); 
7634                 if ( textOrientation 
== wxHORIZONTAL 
) 
7637                     y 
= rect
.y 
+ rect
.height 
- 1; 
7641             if ( textOrientation 
== wxHORIZONTAL 
) 
7643                 dc
.DrawText( lines
[l
], (int)x
, (int)y 
); 
7648                 dc
.DrawRotatedText( lines
[l
], (int)x
, (int)y
, 90.0 ); 
7654     dc
.DestroyClippingRegion(); 
7658 // Split multi line text up into an array of strings.  Any existing 
7659 // contents of the string array are preserved. 
7661 void wxGrid::StringToLines( const wxString
& value
, wxArrayString
& lines 
) 
7665     wxString eol 
= wxTextFile::GetEOL( wxTextFileType_Unix 
); 
7666     wxString tVal 
= wxTextFile::Translate( value
, wxTextFileType_Unix 
); 
7668     while ( startPos 
< (int)tVal
.length() ) 
7670         pos 
= tVal
.Mid(startPos
).Find( eol 
); 
7675         else if ( pos 
== 0 ) 
7677             lines
.Add( wxEmptyString 
); 
7681             lines
.Add( value
.Mid(startPos
, pos
) ); 
7683         startPos 
+= pos 
+ 1; 
7686     if ( startPos 
< (int)value
.length() ) 
7688         lines
.Add( value
.Mid( startPos 
) ); 
7693 void wxGrid::GetTextBoxSize( const wxDC
& dc
, 
7694                              const wxArrayString
& lines
, 
7695                              long *width
, long *height 
) 
7699     long lineW 
= 0, lineH 
= 0; 
7702     for ( i 
= 0;  i 
< lines
.GetCount();  i
++ ) 
7704         dc
.GetTextExtent( lines
[i
], &lineW
, &lineH 
); 
7705         w 
= wxMax( w
, lineW 
); 
7714 // ------ Batch processing. 
7716 void wxGrid::EndBatch() 
7718     if ( m_batchCount 
> 0 ) 
7721         if ( !m_batchCount 
) 
7724             m_rowLabelWin
->Refresh(); 
7725             m_colLabelWin
->Refresh(); 
7726             m_cornerLabelWin
->Refresh(); 
7727             m_gridWin
->Refresh(); 
7732 // Use this, rather than wxWindow::Refresh(), to force an immediate 
7733 // repainting of the grid. Has no effect if you are already inside a 
7734 // BeginBatch / EndBatch block. 
7736 void wxGrid::ForceRefresh() 
7742 bool wxGrid::Enable(bool enable
) 
7744     if ( !wxScrolledWindow::Enable(enable
) ) 
7747     // redraw in the new state 
7748     m_gridWin
->Refresh(); 
7755 // ------ Edit control functions 
7758 void wxGrid::EnableEditing( bool edit 
) 
7760     // TODO: improve this ? 
7762     if ( edit 
!= m_editable 
) 
7765             EnableCellEditControl(edit
); 
7770 void wxGrid::EnableCellEditControl( bool enable 
) 
7775     if ( enable 
!= m_cellEditCtrlEnabled 
) 
7779             if (SendEvent( wxEVT_GRID_EDITOR_SHOWN
) <0) 
7782             // this should be checked by the caller! 
7783             wxASSERT_MSG( CanEnableCellControl(), 
7784                           _T("can't enable editing for this cell!") ); 
7786             // do it before ShowCellEditControl() 
7787             m_cellEditCtrlEnabled 
= enable
; 
7789             ShowCellEditControl(); 
7793             //FIXME:add veto support 
7794             SendEvent( wxEVT_GRID_EDITOR_HIDDEN
); 
7796             HideCellEditControl(); 
7797             SaveEditControlValue(); 
7799             // do it after HideCellEditControl() 
7800             m_cellEditCtrlEnabled 
= enable
; 
7805 bool wxGrid::IsCurrentCellReadOnly() const 
7808     wxGridCellAttr
* attr 
= ((wxGrid 
*)this)->GetCellAttr(m_currentCellCoords
); 
7809     bool readonly 
= attr
->IsReadOnly(); 
7815 bool wxGrid::CanEnableCellControl() const 
7817     return m_editable 
&& (m_currentCellCoords 
!= wxGridNoCellCoords
) && 
7818         !IsCurrentCellReadOnly(); 
7822 bool wxGrid::IsCellEditControlEnabled() const 
7824     // the cell edit control might be disable for all cells or just for the 
7825     // current one if it's read only 
7826     return m_cellEditCtrlEnabled 
? !IsCurrentCellReadOnly() : false; 
7829 bool wxGrid::IsCellEditControlShown() const 
7831     bool isShown 
= false; 
7833     if ( m_cellEditCtrlEnabled 
) 
7835         int row 
= m_currentCellCoords
.GetRow(); 
7836         int col 
= m_currentCellCoords
.GetCol(); 
7837         wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
7838         wxGridCellEditor
* editor 
= attr
->GetEditor((wxGrid
*) this, row
, col
); 
7843             if ( editor
->IsCreated() ) 
7845                 isShown 
= editor
->GetControl()->IsShown(); 
7855 void wxGrid::ShowCellEditControl() 
7857     if ( IsCellEditControlEnabled() ) 
7859         if ( !IsVisible( m_currentCellCoords
, false ) ) 
7861             m_cellEditCtrlEnabled 
= false; 
7866             wxRect rect 
= CellToRect( m_currentCellCoords 
); 
7867             int row 
= m_currentCellCoords
.GetRow(); 
7868             int col 
= m_currentCellCoords
.GetCol(); 
7870             // if this is part of a multicell, find owner (topleft) 
7871             int cell_rows
, cell_cols
; 
7872             GetCellSize( row
, col
, &cell_rows
, &cell_cols 
); 
7873             if ( cell_rows 
<= 0 || cell_cols 
<= 0 ) 
7877                 m_currentCellCoords
.SetRow( row 
); 
7878                 m_currentCellCoords
.SetCol( col 
); 
7881             // convert to scrolled coords 
7883             CalcScrolledPosition( rect
.x
, rect
.y
, &rect
.x
, &rect
.y 
); 
7889             // done in PaintBackground() 
7891             // erase the highlight and the cell contents because the editor 
7892             // might not cover the entire cell 
7893             wxClientDC 
dc( m_gridWin 
); 
7895             dc
.SetBrush(*wxLIGHT_GREY_BRUSH
); //wxBrush(attr->GetBackgroundColour(), wxSOLID)); 
7896             dc
.SetPen(*wxTRANSPARENT_PEN
); 
7897             dc
.DrawRectangle(rect
); 
7900             // cell is shifted by one pixel 
7901             // However, don't allow x or y to become negative 
7902             // since the SetSize() method interprets that as 
7909             wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
7910             wxGridCellEditor
* editor 
= attr
->GetEditor(this, row
, col
); 
7911             if ( !editor
->IsCreated() ) 
7913                 editor
->Create(m_gridWin
, wxID_ANY
, 
7914                                new wxGridCellEditorEvtHandler(this, editor
)); 
7916                 wxGridEditorCreatedEvent 
evt(GetId(), 
7917                                              wxEVT_GRID_EDITOR_CREATED
, 
7921                                              editor
->GetControl()); 
7922                 GetEventHandler()->ProcessEvent(evt
); 
7926             // resize editor to overflow into righthand cells if allowed 
7927             int maxWidth 
= rect
.width
; 
7928             wxString value 
= GetCellValue(row
, col
); 
7929             if ( (value 
!= wxEmptyString
) && (attr
->GetOverflow()) ) 
7932                 GetTextExtent(value
, &maxWidth
, &y
, 
7933                         NULL
, NULL
, &attr
->GetFont()); 
7934                 if (maxWidth 
< rect
.width
) maxWidth 
= rect
.width
; 
7937             int client_right 
= m_gridWin
->GetClientSize().GetWidth(); 
7938             if (rect
.x
+maxWidth 
> client_right
) 
7939                 maxWidth 
= client_right 
- rect
.x
; 
7941             if ((maxWidth 
> rect
.width
) && (col 
< m_numCols
) && m_table
) 
7943                 GetCellSize( row
, col
, &cell_rows
, &cell_cols 
); 
7944                 // may have changed earlier 
7945                 for (int i 
= col
+cell_cols
; i 
< m_numCols
; i
++) 
7948                     GetCellSize( row
, i
, &c_rows
, &c_cols 
); 
7949                     // looks weird going over a multicell 
7950                     if (m_table
->IsEmptyCell(row
,i
) && 
7951                             (rect
.width 
< maxWidth
) && (c_rows 
== 1)) 
7952                         rect
.width 
+= GetColWidth(i
); 
7957                 if (rect
.GetRight() > client_right
) 
7958                     rect
.SetRight(client_right 
- 1); 
7961             editor
->SetCellAttr(attr
); 
7962             editor
->SetSize( rect 
); 
7963             editor
->GetControl()->Move(editor
->GetControl()->GetPosition().x 
+ nXMove
, editor
->GetControl()->GetPosition().y
); 
7964             editor
->Show( true, attr 
); 
7967             for (int i 
= 0; i 
< m_currentCellCoords
.GetCol(); i
++) 
7969                 colXPos 
+= GetColSize(i
); 
7971             int xUnit
=1, yUnit
=1; 
7972             GetScrollPixelsPerUnit(&xUnit
, &yUnit
); 
7973             if (m_currentCellCoords
.GetCol() != 0) 
7974                 Scroll(colXPos
/xUnit
-1, GetScrollPos(wxVERTICAL
)); 
7976                 Scroll(colXPos
/xUnit
, GetScrollPos(wxVERTICAL
)); 
7978             // recalc dimensions in case we need to 
7979             // expand the scrolled window to account for editor 
7982             editor
->BeginEdit(row
, col
, this); 
7983             editor
->SetCellAttr(NULL
); 
7991 void wxGrid::HideCellEditControl() 
7993     if ( IsCellEditControlEnabled() ) 
7995         int row 
= m_currentCellCoords
.GetRow(); 
7996         int col 
= m_currentCellCoords
.GetCol(); 
7998         wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
7999         wxGridCellEditor 
*editor 
= attr
->GetEditor(this, row
, col
); 
8000         editor
->Show( false ); 
8004         m_gridWin
->SetFocus(); 
8006         // refresh whole row to the right 
8007         wxRect 
rect( CellToRect(row
, col
) ); 
8008         CalcScrolledPosition(rect
.x
, rect
.y
, &rect
.x
, &rect
.y 
); 
8009         rect
.width 
= m_gridWin
->GetClientSize().GetWidth() - rect
.x
; 
8011         // ensure that the pixels under the focus ring get refreshed as well 
8012         rect
.Inflate(10, 10); 
8014         m_gridWin
->Refresh( false, &rect 
); 
8018 void wxGrid::SaveEditControlValue() 
8020     if ( IsCellEditControlEnabled() ) 
8022         int row 
= m_currentCellCoords
.GetRow(); 
8023         int col 
= m_currentCellCoords
.GetCol(); 
8025         wxString oldval 
= GetCellValue(row
, col
); 
8027         wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
8028         wxGridCellEditor
* editor 
= attr
->GetEditor(this, row
, col
); 
8029         bool changed 
= editor
->EndEdit(row
, col
, this); 
8036             if ( SendEvent( wxEVT_GRID_CELL_CHANGE
, 
8037                        m_currentCellCoords
.GetRow(), 
8038                        m_currentCellCoords
.GetCol() ) < 0 ) 
8040                 // Event has been vetoed, set the data back. 
8041                 SetCellValue(row
, col
, oldval
); 
8049 // ------ Grid location functions 
8050 //  Note that all of these functions work with the logical coordinates of 
8051 //  grid cells and labels so you will need to convert from device 
8052 //  coordinates for mouse events etc. 
8055 void wxGrid::XYToCell( int x
, int y
, wxGridCellCoords
& coords 
) 
8057     int row 
= YToRow(y
); 
8058     int col 
= XToCol(x
); 
8060     if ( row 
== -1  ||  col 
== -1 ) 
8062         coords 
= wxGridNoCellCoords
; 
8066         coords
.Set( row
, col 
); 
8071 // Internal Helper function for computing row or column from some 
8072 // (unscrolled) coordinate value, using either 
8073 // m_defaultRowHeight/m_defaultColWidth or binary search on array 
8074 // of m_rowBottoms/m_ColRights to speed up the search! 
8076 static int CoordToRowOrCol(int coord
, int defaultDist
, int minDist
, 
8077                            const wxArrayInt
& BorderArray
, int nMax
, 
8081         return clipToMinMax 
&& (nMax 
> 0) ? 0 : -1; 
8086     size_t i_max 
= coord 
/ defaultDist
, 
8089     if (BorderArray
.IsEmpty()) 
8091         if ((int) i_max 
< nMax
) 
8093         return clipToMinMax 
? nMax 
- 1 : -1; 
8096     if ( i_max 
>= BorderArray
.GetCount()) 
8097         i_max 
= BorderArray
.GetCount() - 1; 
8100         if ( coord 
>= BorderArray
[i_max
]) 
8104                 i_max 
= coord 
/ minDist
; 
8106                 i_max 
=  BorderArray
.GetCount() - 1; 
8109         if ( i_max 
>= BorderArray
.GetCount()) 
8110             i_max 
= BorderArray
.GetCount() - 1; 
8113     if ( coord 
>= BorderArray
[i_max
]) 
8114         return clipToMinMax 
? (int)i_max 
: -1; 
8115     if ( coord 
< BorderArray
[0] ) 
8118     while ( i_max 
- i_min 
> 0 ) 
8120         wxCHECK_MSG(BorderArray
[i_min
] <= coord 
&& coord 
< BorderArray
[i_max
], 
8121                     0, _T("wxGrid: internal error in CoordToRowOrCol")); 
8122         if (coord 
>=  BorderArray
[ i_max 
- 1]) 
8126         int median 
= i_min 
+ (i_max 
- i_min 
+ 1) / 2; 
8127         if (coord 
< BorderArray
[median
]) 
8136 int wxGrid::YToRow( int y 
) 
8138     return CoordToRowOrCol(y
, m_defaultRowHeight
, 
8139                            m_minAcceptableRowHeight
, m_rowBottoms
, m_numRows
, false); 
8142 int wxGrid::XToCol( int x 
) 
8144     return CoordToRowOrCol(x
, m_defaultColWidth
, 
8145                            m_minAcceptableColWidth
, m_colRights
, m_numCols
, false); 
8148 // return the row number that that the y coord is near the edge of, or 
8149 // -1 if not near an edge 
8151 int wxGrid::YToEdgeOfRow( int y 
) 
8154     i 
= internalYToRow(y
); 
8156     if ( GetRowHeight(i
) > WXGRID_LABEL_EDGE_ZONE 
) 
8158         // We know that we are in row i, test whether we are 
8159         // close enough to lower or upper border, respectively. 
8160         if ( abs(GetRowBottom(i
) - y
) < WXGRID_LABEL_EDGE_ZONE 
) 
8162         else if ( i 
> 0 && y 
- GetRowTop(i
) < WXGRID_LABEL_EDGE_ZONE 
) 
8169 // return the col number that that the x coord is near the edge of, or 
8170 // -1 if not near an edge 
8172 int wxGrid::XToEdgeOfCol( int x 
) 
8175     i 
= internalXToCol(x
); 
8177     if ( GetColWidth(i
) > WXGRID_LABEL_EDGE_ZONE 
) 
8179         // We know that we are in column i,  test whether we are 
8180         // close enough to right or left border, respectively. 
8181         if ( abs(GetColRight(i
) - x
) < WXGRID_LABEL_EDGE_ZONE 
) 
8183         else if ( i 
> 0 && x 
- GetColLeft(i
) < WXGRID_LABEL_EDGE_ZONE 
) 
8190 wxRect 
wxGrid::CellToRect( int row
, int col 
) 
8192     wxRect 
rect( -1, -1, -1, -1 ); 
8194     if ( row 
>= 0  &&  row 
< m_numRows  
&& 
8195          col 
>= 0  &&  col 
< m_numCols 
) 
8197         int i
, cell_rows
, cell_cols
; 
8198         rect
.width 
= rect
.height 
= 0; 
8199         GetCellSize( row
, col
, &cell_rows
, &cell_cols 
); 
8200         // if negative then find multicell owner 
8201         if (cell_rows 
< 0) row 
+= cell_rows
; 
8202         if (cell_cols 
< 0) col 
+= cell_cols
; 
8203         GetCellSize( row
, col
, &cell_rows
, &cell_cols 
); 
8205         rect
.x 
= GetColLeft(col
); 
8206         rect
.y 
= GetRowTop(row
); 
8207         for (i
=col
; i
<col
+cell_cols
; i
++) 
8208             rect
.width  
+= GetColWidth(i
); 
8209         for (i
=row
; i
<row
+cell_rows
; i
++) 
8210             rect
.height 
+= GetRowHeight(i
); 
8213     // if grid lines are enabled, then the area of the cell is a bit smaller 
8214     if (m_gridLinesEnabled
) 
8223 bool wxGrid::IsVisible( int row
, int col
, bool wholeCellVisible 
) 
8225     // get the cell rectangle in logical coords 
8227     wxRect 
r( CellToRect( row
, col 
) ); 
8229     // convert to device coords 
8231     int left
, top
, right
, bottom
; 
8232     CalcScrolledPosition( r
.GetLeft(), r
.GetTop(), &left
, &top 
); 
8233     CalcScrolledPosition( r
.GetRight(), r
.GetBottom(), &right
, &bottom 
); 
8235     // check against the client area of the grid window 
8238     m_gridWin
->GetClientSize( &cw
, &ch 
); 
8240     if ( wholeCellVisible 
) 
8242         // is the cell wholly visible ? 
8244         return ( left 
>= 0  &&  right 
<= cw  
&& 
8245                  top 
>= 0  &&  bottom 
<= ch 
); 
8249         // is the cell partly visible ? 
8251         return ( ((left 
>=0 && left 
< cw
) || (right 
> 0 && right 
<= cw
))  && 
8252                  ((top 
>=0 && top 
< ch
) || (bottom 
> 0 && bottom 
<= ch
)) ); 
8256 // make the specified cell location visible by doing a minimal amount 
8259 void wxGrid::MakeCellVisible( int row
, int col 
) 
8262     int xpos 
= -1, ypos 
= -1; 
8264     if ( row 
>= 0  &&  row 
< m_numRows  
&& 
8265          col 
>= 0  &&  col 
< m_numCols 
) 
8267         // get the cell rectangle in logical coords 
8269         wxRect 
r( CellToRect( row
, col 
) ); 
8271         // convert to device coords 
8273         int left
, top
, right
, bottom
; 
8274         CalcScrolledPosition( r
.GetLeft(), r
.GetTop(), &left
, &top 
); 
8275         CalcScrolledPosition( r
.GetRight(), r
.GetBottom(), &right
, &bottom 
); 
8278         m_gridWin
->GetClientSize( &cw
, &ch 
); 
8284         else if ( bottom 
> ch 
) 
8286             int h 
= r
.GetHeight(); 
8288             for ( i 
= row
-1;  i 
>= 0;  i
-- ) 
8290                 int rowHeight 
= GetRowHeight(i
); 
8291                 if ( h 
+ rowHeight 
> ch 
) 
8298             // we divide it later by GRID_SCROLL_LINE, make sure that we don't 
8299             // have rounding errors (this is important, because if we do, we 
8300             // might not scroll at all and some cells won't be redrawn) 
8302             // Sometimes GRID_SCROLL_LINE/2 is not enough, so just add a full 
8304             ypos 
+= m_scrollLineY
; 
8307         // special handling for wide cells - show always left part of the cell! 
8308         // Otherwise, e.g. when stepping from row to row, it would jump between 
8309         // left and right part of the cell on every step! 
8311         if ( left 
< 0 || (right
-left
) >= cw 
) 
8315         else if ( right 
> cw 
) 
8317             // position the view so that the cell is on the right 
8319             CalcUnscrolledPosition(0, 0, &x0
, &y0
); 
8320             xpos 
= x0 
+ (right 
- cw
); 
8322             // see comment for ypos above 
8323             xpos 
+= m_scrollLineX
; 
8326         if ( xpos 
!= -1  ||  ypos 
!= -1 ) 
8329                 xpos 
/= m_scrollLineX
; 
8331                 ypos 
/= m_scrollLineY
; 
8332             Scroll( xpos
, ypos 
); 
8340 // ------ Grid cursor movement functions 
8343 bool wxGrid::MoveCursorUp( bool expandSelection 
) 
8345     if ( m_currentCellCoords 
!= wxGridNoCellCoords  
&& 
8346          m_currentCellCoords
.GetRow() >= 0 ) 
8348         if ( expandSelection
) 
8350             if ( m_selectingKeyboard 
== wxGridNoCellCoords 
) 
8351                 m_selectingKeyboard 
= m_currentCellCoords
; 
8352             if ( m_selectingKeyboard
.GetRow() > 0 ) 
8354                 m_selectingKeyboard
.SetRow( m_selectingKeyboard
.GetRow() - 1 ); 
8355                 MakeCellVisible( m_selectingKeyboard
.GetRow(), 
8356                                  m_selectingKeyboard
.GetCol() ); 
8357                 HighlightBlock( m_currentCellCoords
, m_selectingKeyboard 
); 
8360         else if ( m_currentCellCoords
.GetRow() > 0 ) 
8362             int row 
= m_currentCellCoords
.GetRow() - 1; 
8363             int col 
= m_currentCellCoords
.GetCol(); 
8365             MakeCellVisible( row
, col 
); 
8366             SetCurrentCell( row
, col 
); 
8378 bool wxGrid::MoveCursorDown( bool expandSelection 
) 
8380     if ( m_currentCellCoords 
!= wxGridNoCellCoords  
&& 
8381          m_currentCellCoords
.GetRow() < m_numRows 
) 
8383         if ( expandSelection 
) 
8385             if ( m_selectingKeyboard 
== wxGridNoCellCoords 
) 
8386                 m_selectingKeyboard 
= m_currentCellCoords
; 
8387             if ( m_selectingKeyboard
.GetRow() < m_numRows
-1 ) 
8389                 m_selectingKeyboard
.SetRow( m_selectingKeyboard
.GetRow() + 1 ); 
8390                 MakeCellVisible( m_selectingKeyboard
.GetRow(), 
8391                         m_selectingKeyboard
.GetCol() ); 
8392                 HighlightBlock( m_currentCellCoords
, m_selectingKeyboard 
); 
8395         else if ( m_currentCellCoords
.GetRow() < m_numRows 
- 1 ) 
8397             int row 
= m_currentCellCoords
.GetRow() + 1; 
8398             int col 
= m_currentCellCoords
.GetCol(); 
8400             MakeCellVisible( row
, col 
); 
8401             SetCurrentCell( row
, col 
); 
8412 bool wxGrid::MoveCursorLeft( bool expandSelection 
) 
8414     if ( m_currentCellCoords 
!= wxGridNoCellCoords  
&& 
8415          m_currentCellCoords
.GetCol() >= 0 ) 
8417         if ( expandSelection 
) 
8419             if ( m_selectingKeyboard 
== wxGridNoCellCoords 
) 
8420                 m_selectingKeyboard 
= m_currentCellCoords
; 
8421             if ( m_selectingKeyboard
.GetCol() > 0 ) 
8423                 m_selectingKeyboard
.SetCol( m_selectingKeyboard
.GetCol() - 1 ); 
8424                 MakeCellVisible( m_selectingKeyboard
.GetRow(), 
8425                         m_selectingKeyboard
.GetCol() ); 
8426                 HighlightBlock( m_currentCellCoords
, m_selectingKeyboard 
); 
8429         else if ( m_currentCellCoords
.GetCol() > 0 ) 
8431             int row 
= m_currentCellCoords
.GetRow(); 
8432             int col 
= m_currentCellCoords
.GetCol() - 1; 
8434             MakeCellVisible( row
, col 
); 
8435             SetCurrentCell( row
, col 
); 
8446 bool wxGrid::MoveCursorRight( bool expandSelection 
) 
8448     if ( m_currentCellCoords 
!= wxGridNoCellCoords  
&& 
8449          m_currentCellCoords
.GetCol() < m_numCols 
) 
8451         if ( expandSelection 
) 
8453             if ( m_selectingKeyboard 
== wxGridNoCellCoords 
) 
8454                 m_selectingKeyboard 
= m_currentCellCoords
; 
8455             if ( m_selectingKeyboard
.GetCol() < m_numCols 
- 1 ) 
8457                 m_selectingKeyboard
.SetCol( m_selectingKeyboard
.GetCol() + 1 ); 
8458                 MakeCellVisible( m_selectingKeyboard
.GetRow(), 
8459                         m_selectingKeyboard
.GetCol() ); 
8460                 HighlightBlock( m_currentCellCoords
, m_selectingKeyboard 
); 
8463         else if ( m_currentCellCoords
.GetCol() < m_numCols 
- 1 ) 
8465             int row 
= m_currentCellCoords
.GetRow(); 
8466             int col 
= m_currentCellCoords
.GetCol() + 1; 
8468             MakeCellVisible( row
, col 
); 
8469             SetCurrentCell( row
, col 
); 
8480 bool wxGrid::MovePageUp() 
8482     if ( m_currentCellCoords 
== wxGridNoCellCoords 
) 
8485     int row 
= m_currentCellCoords
.GetRow(); 
8489         m_gridWin
->GetClientSize( &cw
, &ch 
); 
8491         int y 
= GetRowTop(row
); 
8492         int newRow 
= internalYToRow( y 
- ch 
+ 1 ); 
8494         if ( newRow 
== row 
) 
8496             //row > 0 , so newrow can never be less than 0 here. 
8500         MakeCellVisible( newRow
, m_currentCellCoords
.GetCol() ); 
8501         SetCurrentCell( newRow
, m_currentCellCoords
.GetCol() ); 
8509 bool wxGrid::MovePageDown() 
8511     if ( m_currentCellCoords 
== wxGridNoCellCoords 
) 
8514     int row 
= m_currentCellCoords
.GetRow(); 
8515     if ( (row
+1) < m_numRows 
) 
8518         m_gridWin
->GetClientSize( &cw
, &ch 
); 
8520         int y 
= GetRowTop(row
); 
8521         int newRow 
= internalYToRow( y 
+ ch 
); 
8522         if ( newRow 
== row 
) 
8524             // row < m_numRows , so newrow can't overflow here. 
8528         MakeCellVisible( newRow
, m_currentCellCoords
.GetCol() ); 
8529         SetCurrentCell( newRow
, m_currentCellCoords
.GetCol() ); 
8537 bool wxGrid::MoveCursorUpBlock( bool expandSelection 
) 
8540          m_currentCellCoords 
!= wxGridNoCellCoords  
&& 
8541          m_currentCellCoords
.GetRow() > 0 ) 
8543         int row 
= m_currentCellCoords
.GetRow(); 
8544         int col 
= m_currentCellCoords
.GetCol(); 
8546         if ( m_table
->IsEmptyCell(row
, col
) ) 
8548             // starting in an empty cell: find the next block of 
8554                 if ( !(m_table
->IsEmptyCell(row
, col
)) ) 
8558         else if ( m_table
->IsEmptyCell(row
-1, col
) ) 
8560             // starting at the top of a block: find the next block 
8566                 if ( !(m_table
->IsEmptyCell(row
, col
)) ) 
8572             // starting within a block: find the top of the block 
8577                 if ( m_table
->IsEmptyCell(row
, col
) ) 
8585         MakeCellVisible( row
, col 
); 
8586         if ( expandSelection 
) 
8588             m_selectingKeyboard 
= wxGridCellCoords( row
, col 
); 
8589             HighlightBlock( m_currentCellCoords
, m_selectingKeyboard 
); 
8594             SetCurrentCell( row
, col 
); 
8603 bool wxGrid::MoveCursorDownBlock( bool expandSelection 
) 
8606          m_currentCellCoords 
!= wxGridNoCellCoords  
&& 
8607          m_currentCellCoords
.GetRow() < m_numRows
-1 ) 
8609         int row 
= m_currentCellCoords
.GetRow(); 
8610         int col 
= m_currentCellCoords
.GetCol(); 
8612         if ( m_table
->IsEmptyCell(row
, col
) ) 
8614             // starting in an empty cell: find the next block of 
8617             while ( row 
< m_numRows
-1 ) 
8620                 if ( !(m_table
->IsEmptyCell(row
, col
)) ) 
8624         else if ( m_table
->IsEmptyCell(row
+1, col
) ) 
8626             // starting at the bottom of a block: find the next block 
8629             while ( row 
< m_numRows
-1 ) 
8632                 if ( !(m_table
->IsEmptyCell(row
, col
)) ) 
8638             // starting within a block: find the bottom of the block 
8640             while ( row 
< m_numRows
-1 ) 
8643                 if ( m_table
->IsEmptyCell(row
, col
) ) 
8651         MakeCellVisible( row
, col 
); 
8652         if ( expandSelection 
) 
8654             m_selectingKeyboard 
= wxGridCellCoords( row
, col 
); 
8655             HighlightBlock( m_currentCellCoords
, m_selectingKeyboard 
); 
8660             SetCurrentCell( row
, col 
); 
8669 bool wxGrid::MoveCursorLeftBlock( bool expandSelection 
) 
8672          m_currentCellCoords 
!= wxGridNoCellCoords  
&& 
8673          m_currentCellCoords
.GetCol() > 0 ) 
8675         int row 
= m_currentCellCoords
.GetRow(); 
8676         int col 
= m_currentCellCoords
.GetCol(); 
8678         if ( m_table
->IsEmptyCell(row
, col
) ) 
8680             // starting in an empty cell: find the next block of 
8686                 if ( !(m_table
->IsEmptyCell(row
, col
)) ) 
8690         else if ( m_table
->IsEmptyCell(row
, col
-1) ) 
8692             // starting at the left of a block: find the next block 
8698                 if ( !(m_table
->IsEmptyCell(row
, col
)) ) 
8704             // starting within a block: find the left of the block 
8709                 if ( m_table
->IsEmptyCell(row
, col
) ) 
8717         MakeCellVisible( row
, col 
); 
8718         if ( expandSelection 
) 
8720             m_selectingKeyboard 
= wxGridCellCoords( row
, col 
); 
8721             HighlightBlock( m_currentCellCoords
, m_selectingKeyboard 
); 
8726             SetCurrentCell( row
, col 
); 
8735 bool wxGrid::MoveCursorRightBlock( bool expandSelection 
) 
8738          m_currentCellCoords 
!= wxGridNoCellCoords  
&& 
8739          m_currentCellCoords
.GetCol() < m_numCols
-1 ) 
8741         int row 
= m_currentCellCoords
.GetRow(); 
8742         int col 
= m_currentCellCoords
.GetCol(); 
8744         if ( m_table
->IsEmptyCell(row
, col
) ) 
8746             // starting in an empty cell: find the next block of 
8749             while ( col 
< m_numCols
-1 ) 
8752                 if ( !(m_table
->IsEmptyCell(row
, col
)) ) 
8756         else if ( m_table
->IsEmptyCell(row
, col
+1) ) 
8758             // starting at the right of a block: find the next block 
8761             while ( col 
< m_numCols
-1 ) 
8764                 if ( !(m_table
->IsEmptyCell(row
, col
)) ) 
8770             // starting within a block: find the right of the block 
8772             while ( col 
< m_numCols
-1 ) 
8775                 if ( m_table
->IsEmptyCell(row
, col
) ) 
8783         MakeCellVisible( row
, col 
); 
8784         if ( expandSelection 
) 
8786             m_selectingKeyboard 
= wxGridCellCoords( row
, col 
); 
8787             HighlightBlock( m_currentCellCoords
, m_selectingKeyboard 
); 
8792             SetCurrentCell( row
, col 
); 
8804 // ------ Label values and formatting 
8807 void wxGrid::GetRowLabelAlignment( int *horiz
, int *vert 
) 
8809     *horiz 
= m_rowLabelHorizAlign
; 
8810     *vert  
= m_rowLabelVertAlign
; 
8813 void wxGrid::GetColLabelAlignment( int *horiz
, int *vert 
) 
8815     *horiz 
= m_colLabelHorizAlign
; 
8816     *vert  
= m_colLabelVertAlign
; 
8819 int wxGrid::GetColLabelTextOrientation() 
8821     return m_colLabelTextOrientation
; 
8824 wxString 
wxGrid::GetRowLabelValue( int row 
) 
8828         return m_table
->GetRowLabelValue( row 
); 
8838 wxString 
wxGrid::GetColLabelValue( int col 
) 
8842         return m_table
->GetColLabelValue( col 
); 
8853 void wxGrid::SetRowLabelSize( int width 
) 
8855     width 
= wxMax( width
, 0 ); 
8856     if ( width 
!= m_rowLabelWidth 
) 
8860             m_rowLabelWin
->Show( false ); 
8861             m_cornerLabelWin
->Show( false ); 
8863         else if ( m_rowLabelWidth 
== 0 ) 
8865             m_rowLabelWin
->Show( true ); 
8866             if ( m_colLabelHeight 
> 0 ) m_cornerLabelWin
->Show( true ); 
8869         m_rowLabelWidth 
= width
; 
8871         wxScrolledWindow::Refresh( true ); 
8876 void wxGrid::SetColLabelSize( int height 
) 
8878     height 
= wxMax( height
, 0 ); 
8879     if ( height 
!= m_colLabelHeight 
) 
8883             m_colLabelWin
->Show( false ); 
8884             m_cornerLabelWin
->Show( false ); 
8886         else if ( m_colLabelHeight 
== 0 ) 
8888             m_colLabelWin
->Show( true ); 
8889             if ( m_rowLabelWidth 
> 0 ) m_cornerLabelWin
->Show( true ); 
8892         m_colLabelHeight 
= height
; 
8894         wxScrolledWindow::Refresh( true ); 
8899 void wxGrid::SetLabelBackgroundColour( const wxColour
& colour 
) 
8901     if ( m_labelBackgroundColour 
!= colour 
) 
8903         m_labelBackgroundColour 
= colour
; 
8904         m_rowLabelWin
->SetBackgroundColour( colour 
); 
8905         m_colLabelWin
->SetBackgroundColour( colour 
); 
8906         m_cornerLabelWin
->SetBackgroundColour( colour 
); 
8908         if ( !GetBatchCount() ) 
8910             m_rowLabelWin
->Refresh(); 
8911             m_colLabelWin
->Refresh(); 
8912             m_cornerLabelWin
->Refresh(); 
8917 void wxGrid::SetLabelTextColour( const wxColour
& colour 
) 
8919     if ( m_labelTextColour 
!= colour 
) 
8921         m_labelTextColour 
= colour
; 
8922         if ( !GetBatchCount() ) 
8924             m_rowLabelWin
->Refresh(); 
8925             m_colLabelWin
->Refresh(); 
8930 void wxGrid::SetLabelFont( const wxFont
& font 
) 
8933     if ( !GetBatchCount() ) 
8935         m_rowLabelWin
->Refresh(); 
8936         m_colLabelWin
->Refresh(); 
8940 void wxGrid::SetRowLabelAlignment( int horiz
, int vert 
) 
8942     // allow old (incorrect) defs to be used 
8945         case wxLEFT
:   horiz 
= wxALIGN_LEFT
; break; 
8946         case wxRIGHT
:  horiz 
= wxALIGN_RIGHT
; break; 
8947         case wxCENTRE
: horiz 
= wxALIGN_CENTRE
; break; 
8952         case wxTOP
:    vert 
= wxALIGN_TOP
;    break; 
8953         case wxBOTTOM
: vert 
= wxALIGN_BOTTOM
; break; 
8954         case wxCENTRE
: vert 
= wxALIGN_CENTRE
; break; 
8957     if ( horiz 
== wxALIGN_LEFT 
|| horiz 
== wxALIGN_CENTRE 
|| horiz 
== wxALIGN_RIGHT 
) 
8959         m_rowLabelHorizAlign 
= horiz
; 
8962     if ( vert 
== wxALIGN_TOP 
|| vert 
== wxALIGN_CENTRE 
|| vert 
== wxALIGN_BOTTOM 
) 
8964         m_rowLabelVertAlign 
= vert
; 
8967     if ( !GetBatchCount() ) 
8969         m_rowLabelWin
->Refresh(); 
8973 void wxGrid::SetColLabelAlignment( int horiz
, int vert 
) 
8975     // allow old (incorrect) defs to be used 
8978         case wxLEFT
:   horiz 
= wxALIGN_LEFT
; break; 
8979         case wxRIGHT
:  horiz 
= wxALIGN_RIGHT
; break; 
8980         case wxCENTRE
: horiz 
= wxALIGN_CENTRE
; break; 
8985         case wxTOP
:    vert 
= wxALIGN_TOP
;    break; 
8986         case wxBOTTOM
: vert 
= wxALIGN_BOTTOM
; break; 
8987         case wxCENTRE
: vert 
= wxALIGN_CENTRE
; break; 
8990     if ( horiz 
== wxALIGN_LEFT 
|| horiz 
== wxALIGN_CENTRE 
|| horiz 
== wxALIGN_RIGHT 
) 
8992         m_colLabelHorizAlign 
= horiz
; 
8995     if ( vert 
== wxALIGN_TOP 
|| vert 
== wxALIGN_CENTRE 
|| vert 
== wxALIGN_BOTTOM 
) 
8997         m_colLabelVertAlign 
= vert
; 
9000     if ( !GetBatchCount() ) 
9002         m_colLabelWin
->Refresh(); 
9006 // Note: under MSW, the default column label font must be changed because it 
9007 //       does not support vertical printing 
9009 // Example: wxFont font(9, wxSWISS, wxNORMAL, wxBOLD); 
9010 //                      pGrid->SetLabelFont(font); 
9011 //                      pGrid->SetColLabelTextOrientation(wxVERTICAL); 
9013 void wxGrid::SetColLabelTextOrientation( int textOrientation 
) 
9015     if ( textOrientation 
== wxHORIZONTAL 
|| textOrientation 
== wxVERTICAL 
) 
9017         m_colLabelTextOrientation 
= textOrientation
; 
9020     if ( !GetBatchCount() ) 
9022         m_colLabelWin
->Refresh(); 
9026 void wxGrid::SetRowLabelValue( int row
, const wxString
& s 
) 
9030         m_table
->SetRowLabelValue( row
, s 
); 
9031         if ( !GetBatchCount() ) 
9033             wxRect rect 
= CellToRect( row
, 0); 
9034             if ( rect
.height 
> 0 ) 
9036                 CalcScrolledPosition(0, rect
.y
, &rect
.x
, &rect
.y
); 
9038                 rect
.width 
= m_rowLabelWidth
; 
9039                 m_rowLabelWin
->Refresh( true, &rect 
); 
9045 void wxGrid::SetColLabelValue( int col
, const wxString
& s 
) 
9049         m_table
->SetColLabelValue( col
, s 
); 
9050         if ( !GetBatchCount() ) 
9052             wxRect rect 
= CellToRect( 0, col 
); 
9053             if ( rect
.width 
> 0 ) 
9055                 CalcScrolledPosition(rect
.x
, 0, &rect
.x
, &rect
.y
); 
9057                 rect
.height 
= m_colLabelHeight
; 
9058                 m_colLabelWin
->Refresh( true, &rect 
); 
9064 void wxGrid::SetGridLineColour( const wxColour
& colour 
) 
9066     if ( m_gridLineColour 
!= colour 
) 
9068         m_gridLineColour 
= colour
; 
9070         wxClientDC 
dc( m_gridWin 
); 
9072         DrawAllGridLines( dc
, wxRegion() ); 
9077 void wxGrid::SetCellHighlightColour( const wxColour
& colour 
) 
9079     if ( m_cellHighlightColour 
!= colour 
) 
9081         m_cellHighlightColour 
= colour
; 
9083         wxClientDC 
dc( m_gridWin 
); 
9085         wxGridCellAttr
* attr 
= GetCellAttr(m_currentCellCoords
); 
9086         DrawCellHighlight(dc
, attr
); 
9091 void wxGrid::SetCellHighlightPenWidth(int width
) 
9093     if (m_cellHighlightPenWidth 
!= width
) 
9095         m_cellHighlightPenWidth 
= width
; 
9097         // Just redrawing the cell highlight is not enough since that won't 
9098         // make any visible change if the the thickness is getting smaller. 
9099         int row 
= m_currentCellCoords
.GetRow(); 
9100         int col 
= m_currentCellCoords
.GetCol(); 
9101         if ( GetColWidth(col
) <= 0 || GetRowHeight(row
) <= 0 ) 
9103         wxRect rect 
= CellToRect(row
, col
); 
9104         m_gridWin
->Refresh(true, &rect
); 
9108 void wxGrid::SetCellHighlightROPenWidth(int width
) 
9110     if (m_cellHighlightROPenWidth 
!= width
) 
9112         m_cellHighlightROPenWidth 
= width
; 
9114         // Just redrawing the cell highlight is not enough since that won't 
9115         // make any visible change if the the thickness is getting smaller. 
9116         int row 
= m_currentCellCoords
.GetRow(); 
9117         int col 
= m_currentCellCoords
.GetCol(); 
9118         if ( GetColWidth(col
) <= 0 || GetRowHeight(row
) <= 0 ) 
9120         wxRect rect 
= CellToRect(row
, col
); 
9121         m_gridWin
->Refresh(true, &rect
); 
9125 void wxGrid::EnableGridLines( bool enable 
) 
9127     if ( enable 
!= m_gridLinesEnabled 
) 
9129         m_gridLinesEnabled 
= enable
; 
9131         if ( !GetBatchCount() ) 
9135                 wxClientDC 
dc( m_gridWin 
); 
9137                 DrawAllGridLines( dc
, wxRegion() ); 
9141                 m_gridWin
->Refresh(); 
9148 int wxGrid::GetDefaultRowSize() 
9150     return m_defaultRowHeight
; 
9153 int wxGrid::GetRowSize( int row 
) 
9155     wxCHECK_MSG( row 
>= 0 && row 
< m_numRows
, 0, _T("invalid row index") ); 
9157     return GetRowHeight(row
); 
9160 int wxGrid::GetDefaultColSize() 
9162     return m_defaultColWidth
; 
9165 int wxGrid::GetColSize( int col 
) 
9167     wxCHECK_MSG( col 
>= 0 && col 
< m_numCols
, 0, _T("invalid column index") ); 
9169     return GetColWidth(col
); 
9172 // ============================================================================ 
9173 // access to the grid attributes: each of them has a default value in the grid 
9174 // itself and may be overidden on a per-cell basis 
9175 // ============================================================================ 
9177 // ---------------------------------------------------------------------------- 
9178 // setting default attributes 
9179 // ---------------------------------------------------------------------------- 
9181 void wxGrid::SetDefaultCellBackgroundColour( const wxColour
& col 
) 
9183     m_defaultCellAttr
->SetBackgroundColour(col
); 
9185     m_gridWin
->SetBackgroundColour(col
); 
9189 void wxGrid::SetDefaultCellTextColour( const wxColour
& col 
) 
9191     m_defaultCellAttr
->SetTextColour(col
); 
9194 void wxGrid::SetDefaultCellAlignment( int horiz
, int vert 
) 
9196     m_defaultCellAttr
->SetAlignment(horiz
, vert
); 
9199 void wxGrid::SetDefaultCellOverflow( bool allow 
) 
9201     m_defaultCellAttr
->SetOverflow(allow
); 
9204 void wxGrid::SetDefaultCellFont( const wxFont
& font 
) 
9206     m_defaultCellAttr
->SetFont(font
); 
9210 // For editors and renderers the type registry takes precedence over the 
9211 // default attr, so we need to register the new editor/renderer for the string 
9212 // data type in order to make setting a default editor/renderer appear to 
9215 void wxGrid::SetDefaultRenderer(wxGridCellRenderer 
*renderer
) 
9217     RegisterDataType(wxGRID_VALUE_STRING
, 
9219                      GetDefaultEditorForType(wxGRID_VALUE_STRING
)); 
9222 void wxGrid::SetDefaultEditor(wxGridCellEditor 
*editor
) 
9224     RegisterDataType(wxGRID_VALUE_STRING
, 
9225                      GetDefaultRendererForType(wxGRID_VALUE_STRING
), 
9229 // ---------------------------------------------------------------------------- 
9230 // access to the default attrbiutes 
9231 // ---------------------------------------------------------------------------- 
9233 wxColour 
wxGrid::GetDefaultCellBackgroundColour() 
9235     return m_defaultCellAttr
->GetBackgroundColour(); 
9238 wxColour 
wxGrid::GetDefaultCellTextColour() 
9240     return m_defaultCellAttr
->GetTextColour(); 
9243 wxFont 
wxGrid::GetDefaultCellFont() 
9245     return m_defaultCellAttr
->GetFont(); 
9248 void wxGrid::GetDefaultCellAlignment( int *horiz
, int *vert 
) 
9250     m_defaultCellAttr
->GetAlignment(horiz
, vert
); 
9253 bool wxGrid::GetDefaultCellOverflow() 
9255     return m_defaultCellAttr
->GetOverflow(); 
9258 wxGridCellRenderer 
*wxGrid::GetDefaultRenderer() const 
9260     return m_defaultCellAttr
->GetRenderer(NULL
, 0, 0); 
9263 wxGridCellEditor 
*wxGrid::GetDefaultEditor() const 
9265     return m_defaultCellAttr
->GetEditor(NULL
, 0, 0); 
9268 // ---------------------------------------------------------------------------- 
9269 // access to cell attributes 
9270 // ---------------------------------------------------------------------------- 
9272 wxColour 
wxGrid::GetCellBackgroundColour(int row
, int col
) 
9274     wxGridCellAttr 
*attr 
= GetCellAttr(row
, col
); 
9275     wxColour colour 
= attr
->GetBackgroundColour(); 
9280 wxColour 
wxGrid::GetCellTextColour( int row
, int col 
) 
9282     wxGridCellAttr 
*attr 
= GetCellAttr(row
, col
); 
9283     wxColour colour 
= attr
->GetTextColour(); 
9288 wxFont 
wxGrid::GetCellFont( int row
, int col 
) 
9290     wxGridCellAttr 
*attr 
= GetCellAttr(row
, col
); 
9291     wxFont font 
= attr
->GetFont(); 
9296 void wxGrid::GetCellAlignment( int row
, int col
, int *horiz
, int *vert 
) 
9298     wxGridCellAttr 
*attr 
= GetCellAttr(row
, col
); 
9299     attr
->GetAlignment(horiz
, vert
); 
9303 bool wxGrid::GetCellOverflow( int row
, int col 
) 
9305     wxGridCellAttr 
*attr 
= GetCellAttr(row
, col
); 
9306     bool allow 
= attr
->GetOverflow(); 
9312 void wxGrid::GetCellSize( int row
, int col
, int *num_rows
, int *num_cols 
) 
9314     wxGridCellAttr 
*attr 
= GetCellAttr(row
, col
); 
9315     attr
->GetSize( num_rows
, num_cols 
); 
9319 wxGridCellRenderer
* wxGrid::GetCellRenderer(int row
, int col
) 
9321     wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
9322     wxGridCellRenderer
* renderer 
= attr
->GetRenderer(this, row
, col
); 
9328 wxGridCellEditor
* wxGrid::GetCellEditor(int row
, int col
) 
9330     wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
9331     wxGridCellEditor
* editor 
= attr
->GetEditor(this, row
, col
); 
9337 bool wxGrid::IsReadOnly(int row
, int col
) const 
9339     wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
9340     bool isReadOnly 
= attr
->IsReadOnly(); 
9346 // ---------------------------------------------------------------------------- 
9347 // attribute support: cache, automatic provider creation, ... 
9348 // ---------------------------------------------------------------------------- 
9350 bool wxGrid::CanHaveAttributes() 
9357     return m_table
->CanHaveAttributes(); 
9360 void wxGrid::ClearAttrCache() 
9362     if ( m_attrCache
.row 
!= -1 ) 
9364         wxSafeDecRef(m_attrCache
.attr
); 
9365         m_attrCache
.attr 
= NULL
; 
9366         m_attrCache
.row 
= -1; 
9370 void wxGrid::CacheAttr(int row
, int col
, wxGridCellAttr 
*attr
) const 
9374         wxGrid 
*self 
= (wxGrid 
*)this;  // const_cast 
9376         self
->ClearAttrCache(); 
9377         self
->m_attrCache
.row 
= row
; 
9378         self
->m_attrCache
.col 
= col
; 
9379         self
->m_attrCache
.attr 
= attr
; 
9384 bool wxGrid::LookupAttr(int row
, int col
, wxGridCellAttr 
**attr
) const 
9386     if ( row 
== m_attrCache
.row 
&& col 
== m_attrCache
.col 
) 
9388         *attr 
= m_attrCache
.attr
; 
9389         wxSafeIncRef(m_attrCache
.attr
); 
9391 #ifdef DEBUG_ATTR_CACHE 
9392         gs_nAttrCacheHits
++; 
9399 #ifdef DEBUG_ATTR_CACHE 
9400         gs_nAttrCacheMisses
++; 
9407 wxGridCellAttr 
*wxGrid::GetCellAttr(int row
, int col
) const 
9409     wxGridCellAttr 
*attr 
= NULL
; 
9410     // Additional test to avoid looking at the cache e.g. for 
9411     // wxNoCellCoords, as this will confuse memory management. 
9414         if ( !LookupAttr(row
, col
, &attr
) ) 
9416             attr 
= m_table 
? m_table
->GetAttr(row
, col 
, wxGridCellAttr::Any
) 
9417                            : (wxGridCellAttr 
*)NULL
; 
9418             CacheAttr(row
, col
, attr
); 
9424         attr
->SetDefAttr(m_defaultCellAttr
); 
9428         attr 
= m_defaultCellAttr
; 
9435 wxGridCellAttr 
*wxGrid::GetOrCreateCellAttr(int row
, int col
) const 
9437     wxGridCellAttr 
*attr 
= (wxGridCellAttr 
*)NULL
; 
9438     bool canHave 
= ((wxGrid
*)this)->CanHaveAttributes(); 
9440     wxCHECK_MSG( canHave
, attr
, _T("Cell attributes not allowed")); 
9441     wxCHECK_MSG( m_table
, attr
, _T("must have a table") ); 
9443     attr 
= m_table
->GetAttr(row
, col
, wxGridCellAttr::Cell
); 
9446         attr 
= new wxGridCellAttr(m_defaultCellAttr
); 
9448         // artificially inc the ref count to match DecRef() in caller 
9450         m_table
->SetAttr(attr
, row
, col
); 
9456 // ---------------------------------------------------------------------------- 
9457 // setting column attributes (wrappers around SetColAttr) 
9458 // ---------------------------------------------------------------------------- 
9460 void wxGrid::SetColFormatBool(int col
) 
9462     SetColFormatCustom(col
, wxGRID_VALUE_BOOL
); 
9465 void wxGrid::SetColFormatNumber(int col
) 
9467     SetColFormatCustom(col
, wxGRID_VALUE_NUMBER
); 
9470 void wxGrid::SetColFormatFloat(int col
, int width
, int precision
) 
9472     wxString typeName 
= wxGRID_VALUE_FLOAT
; 
9473     if ( (width 
!= -1) || (precision 
!= -1) ) 
9475         typeName 
<< _T(':') << width 
<< _T(',') << precision
; 
9478     SetColFormatCustom(col
, typeName
); 
9481 void wxGrid::SetColFormatCustom(int col
, const wxString
& typeName
) 
9483     wxGridCellAttr 
*attr 
= m_table
->GetAttr(-1, col
, wxGridCellAttr::Col 
); 
9485         attr 
= new wxGridCellAttr
; 
9486     wxGridCellRenderer 
*renderer 
= GetDefaultRendererForType(typeName
); 
9487     attr
->SetRenderer(renderer
); 
9489     SetColAttr(col
, attr
); 
9493 // ---------------------------------------------------------------------------- 
9494 // setting cell attributes: this is forwarded to the table 
9495 // ---------------------------------------------------------------------------- 
9497 void wxGrid::SetAttr(int row
, int col
, wxGridCellAttr 
*attr
) 
9499     if ( CanHaveAttributes() ) 
9501         m_table
->SetAttr(attr
, row
, col
); 
9510 void wxGrid::SetRowAttr(int row
, wxGridCellAttr 
*attr
) 
9512     if ( CanHaveAttributes() ) 
9514         m_table
->SetRowAttr(attr
, row
); 
9523 void wxGrid::SetColAttr(int col
, wxGridCellAttr 
*attr
) 
9525     if ( CanHaveAttributes() ) 
9527         m_table
->SetColAttr(attr
, col
); 
9536 void wxGrid::SetCellBackgroundColour( int row
, int col
, const wxColour
& colour 
) 
9538     if ( CanHaveAttributes() ) 
9540         wxGridCellAttr 
*attr 
= GetOrCreateCellAttr(row
, col
); 
9541         attr
->SetBackgroundColour(colour
); 
9546 void wxGrid::SetCellTextColour( int row
, int col
, const wxColour
& colour 
) 
9548     if ( CanHaveAttributes() ) 
9550         wxGridCellAttr 
*attr 
= GetOrCreateCellAttr(row
, col
); 
9551         attr
->SetTextColour(colour
); 
9556 void wxGrid::SetCellFont( int row
, int col
, const wxFont
& font 
) 
9558     if ( CanHaveAttributes() ) 
9560         wxGridCellAttr 
*attr 
= GetOrCreateCellAttr(row
, col
); 
9561         attr
->SetFont(font
); 
9566 void wxGrid::SetCellAlignment( int row
, int col
, int horiz
, int vert 
) 
9568     if ( CanHaveAttributes() ) 
9570         wxGridCellAttr 
*attr 
= GetOrCreateCellAttr(row
, col
); 
9571         attr
->SetAlignment(horiz
, vert
); 
9576 void wxGrid::SetCellOverflow( int row
, int col
, bool allow 
) 
9578     if ( CanHaveAttributes() ) 
9580         wxGridCellAttr 
*attr 
= GetOrCreateCellAttr(row
, col
); 
9581         attr
->SetOverflow(allow
); 
9586 void wxGrid::SetCellSize( int row
, int col
, int num_rows
, int num_cols 
) 
9588     if ( CanHaveAttributes() ) 
9590         int cell_rows
, cell_cols
; 
9592         wxGridCellAttr 
*attr 
= GetOrCreateCellAttr(row
, col
); 
9593         attr
->GetSize(&cell_rows
, &cell_cols
); 
9594         attr
->SetSize(num_rows
, num_cols
); 
9597         // Cannot set the size of a cell to 0 or negative values 
9598         // While it is perfectly legal to do that, this function cannot 
9599         // handle all the possibilies, do it by hand by getting the CellAttr. 
9600         // You can only set the size of a cell to 1,1 or greater with this fn 
9601         wxASSERT_MSG( !((cell_rows 
< 1) || (cell_cols 
< 1)), 
9602                       wxT("wxGrid::SetCellSize setting cell size that is already part of another cell")); 
9603         wxASSERT_MSG( !((num_rows 
< 1) || (num_cols 
< 1)), 
9604                       wxT("wxGrid::SetCellSize setting cell size to < 1")); 
9606         // if this was already a multicell then "turn off" the other cells first 
9607         if ((cell_rows 
> 1) || (cell_rows 
> 1)) 
9610             for (j
=row
; j
<row
+cell_rows
; j
++) 
9612                 for (i
=col
; i
<col
+cell_cols
; i
++) 
9614                     if ((i 
!= col
) || (j 
!= row
)) 
9616                         wxGridCellAttr 
*attr_stub 
= GetOrCreateCellAttr(j
, i
); 
9617                         attr_stub
->SetSize( 1, 1 ); 
9618                         attr_stub
->DecRef(); 
9624         // mark the cells that will be covered by this cell to 
9625         // negative or zero values to point back at this cell 
9626         if (((num_rows 
> 1) || (num_cols 
> 1)) && (num_rows 
>= 1) && (num_cols 
>= 1)) 
9629             for (j
=row
; j
<row
+num_rows
; j
++) 
9631                 for (i
=col
; i
<col
+num_cols
; i
++) 
9633                     if ((i 
!= col
) || (j 
!= row
)) 
9635                         wxGridCellAttr 
*attr_stub 
= GetOrCreateCellAttr(j
, i
); 
9636                         attr_stub
->SetSize( row
-j
, col
-i 
); 
9637                         attr_stub
->DecRef(); 
9645 void wxGrid::SetCellRenderer(int row
, int col
, wxGridCellRenderer 
*renderer
) 
9647     if ( CanHaveAttributes() ) 
9649         wxGridCellAttr 
*attr 
= GetOrCreateCellAttr(row
, col
); 
9650         attr
->SetRenderer(renderer
); 
9655 void wxGrid::SetCellEditor(int row
, int col
, wxGridCellEditor
* editor
) 
9657     if ( CanHaveAttributes() ) 
9659         wxGridCellAttr 
*attr 
= GetOrCreateCellAttr(row
, col
); 
9660         attr
->SetEditor(editor
); 
9665 void wxGrid::SetReadOnly(int row
, int col
, bool isReadOnly
) 
9667     if ( CanHaveAttributes() ) 
9669         wxGridCellAttr 
*attr 
= GetOrCreateCellAttr(row
, col
); 
9670         attr
->SetReadOnly(isReadOnly
); 
9675 // ---------------------------------------------------------------------------- 
9676 // Data type registration 
9677 // ---------------------------------------------------------------------------- 
9679 void wxGrid::RegisterDataType(const wxString
& typeName
, 
9680                               wxGridCellRenderer
* renderer
, 
9681                               wxGridCellEditor
* editor
) 
9683     m_typeRegistry
->RegisterDataType(typeName
, renderer
, editor
); 
9687 wxGridCellEditor
* wxGrid::GetDefaultEditorForCell(int row
, int col
) const 
9689     wxString typeName 
= m_table
->GetTypeName(row
, col
); 
9690     return GetDefaultEditorForType(typeName
); 
9693 wxGridCellRenderer
* wxGrid::GetDefaultRendererForCell(int row
, int col
) const 
9695     wxString typeName 
= m_table
->GetTypeName(row
, col
); 
9696     return GetDefaultRendererForType(typeName
); 
9700 wxGrid::GetDefaultEditorForType(const wxString
& typeName
) const 
9702     int index 
= m_typeRegistry
->FindOrCloneDataType(typeName
); 
9703     if ( index 
== wxNOT_FOUND 
) 
9707         errStr
.Printf(wxT("Unknown data type name [%s]"), typeName
.c_str()); 
9708         wxFAIL_MSG(errStr
.c_str()); 
9713     return m_typeRegistry
->GetEditor(index
); 
9717 wxGrid::GetDefaultRendererForType(const wxString
& typeName
) const 
9719     int index 
= m_typeRegistry
->FindOrCloneDataType(typeName
); 
9720     if ( index 
== wxNOT_FOUND 
) 
9724         errStr
.Printf(wxT("Unknown data type name [%s]"), typeName
.c_str()); 
9725         wxFAIL_MSG(errStr
.c_str()); 
9730     return m_typeRegistry
->GetRenderer(index
); 
9733 // ---------------------------------------------------------------------------- 
9735 // ---------------------------------------------------------------------------- 
9737 void wxGrid::EnableDragRowSize( bool enable 
) 
9739     m_canDragRowSize 
= enable
; 
9742 void wxGrid::EnableDragColSize( bool enable 
) 
9744     m_canDragColSize 
= enable
; 
9747 void wxGrid::EnableDragGridSize( bool enable 
) 
9749     m_canDragGridSize 
= enable
; 
9752 void wxGrid::EnableDragCell( bool enable 
) 
9754     m_canDragCell 
= enable
; 
9757 void wxGrid::SetDefaultRowSize( int height
, bool resizeExistingRows 
) 
9759     m_defaultRowHeight 
= wxMax( height
, m_minAcceptableRowHeight 
); 
9761     if ( resizeExistingRows 
) 
9763         // since we are resizing all rows to the default row size, 
9764         // we can simply clear the row heights and row bottoms 
9765         // arrays (which also allows us to take advantage of 
9766         // some speed optimisations) 
9767         m_rowHeights
.Empty(); 
9768         m_rowBottoms
.Empty(); 
9769         if ( !GetBatchCount() ) 
9774 void wxGrid::SetRowSize( int row
, int height 
) 
9776     wxCHECK_RET( row 
>= 0 && row 
< m_numRows
, _T("invalid row index") ); 
9778     // See comment in SetColSize 
9779     if ( height 
< GetRowMinimalAcceptableHeight()) 
9782     if ( m_rowHeights
.IsEmpty() ) 
9784         // need to really create the array 
9788     int h 
= wxMax( 0, height 
); 
9789     int diff 
= h 
- m_rowHeights
[row
]; 
9791     m_rowHeights
[row
] = h
; 
9793     for ( i 
= row
;  i 
< m_numRows
;  i
++ ) 
9795         m_rowBottoms
[i
] += diff
; 
9797     if ( !GetBatchCount() ) 
9801 void wxGrid::SetDefaultColSize( int width
, bool resizeExistingCols 
) 
9803     m_defaultColWidth 
= wxMax( width
, m_minAcceptableColWidth 
); 
9805     if ( resizeExistingCols 
) 
9807         // since we are resizing all columns to the default column size, 
9808         // we can simply clear the col widths and col rights 
9809         // arrays (which also allows us to take advantage of 
9810         // some speed optimisations) 
9811         m_colWidths
.Empty(); 
9812         m_colRights
.Empty(); 
9813         if ( !GetBatchCount() ) 
9818 void wxGrid::SetColSize( int col
, int width 
) 
9820     wxCHECK_RET( col 
>= 0 && col 
< m_numCols
, _T("invalid column index") ); 
9822     // should we check that it's bigger than GetColMinimalWidth(col) here? 
9824     // No, because it is reasonable to assume the library user know's 
9825     // what he is doing. However whe should test against the weaker 
9826     // constariant of minimalAcceptableWidth, as this breaks rendering 
9828     // This test then fixes sf.net bug #645734 
9830     if ( width 
< GetColMinimalAcceptableWidth() ) 
9833     if ( m_colWidths
.IsEmpty() ) 
9835         // need to really create the array 
9839     // if < 0 calc new width from label 
9843       wxArrayString lines
; 
9844       wxClientDC 
dc(m_colLabelWin
); 
9845       dc
.SetFont(GetLabelFont()); 
9846       StringToLines(GetColLabelValue(col
), lines
); 
9847       GetTextBoxSize(dc
, lines
, &w
, &h
); 
9851     int w 
= wxMax( 0, width 
); 
9852     int diff 
= w 
- m_colWidths
[col
]; 
9853     m_colWidths
[col
] = w
; 
9856     for ( i 
= col
;  i 
< m_numCols
;  i
++ ) 
9858         m_colRights
[i
] += diff
; 
9861     if ( !GetBatchCount() ) 
9865 void wxGrid::SetColMinimalWidth( int col
, int width 
) 
9867     if (width 
> GetColMinimalAcceptableWidth()) 
9869         wxLongToLongHashMap::key_type key 
= (wxLongToLongHashMap::key_type
)col
; 
9870         m_colMinWidths
[key
] = width
; 
9874 void wxGrid::SetRowMinimalHeight( int row
, int width 
) 
9876     if (width 
> GetRowMinimalAcceptableHeight()) 
9878         wxLongToLongHashMap::key_type key 
= (wxLongToLongHashMap::key_type
)row
; 
9879         m_rowMinHeights
[key
] = width
; 
9883 int wxGrid::GetColMinimalWidth(int col
) const 
9885     wxLongToLongHashMap::key_type key 
= (wxLongToLongHashMap::key_type
)col
; 
9886     wxLongToLongHashMap::const_iterator it 
= m_colMinWidths
.find(key
); 
9888     return it 
!= m_colMinWidths
.end() ? (int)it
->second 
: m_minAcceptableColWidth
; 
9891 int wxGrid::GetRowMinimalHeight(int row
) const 
9893     wxLongToLongHashMap::key_type key 
= (wxLongToLongHashMap::key_type
)row
; 
9894     wxLongToLongHashMap::const_iterator it 
= m_rowMinHeights
.find(key
); 
9896     return it 
!= m_rowMinHeights
.end() ? (int)it
->second 
: m_minAcceptableRowHeight
; 
9899 void wxGrid::SetColMinimalAcceptableWidth( int width 
) 
9901     // We do allow a width of 0 since this gives us 
9902     // an easy way to temporarily hiding columns. 
9904         m_minAcceptableColWidth 
= width
; 
9907 void wxGrid::SetRowMinimalAcceptableHeight( int height 
) 
9909     // We do allow a height of 0 since this gives us 
9910     // an easy way to temporarily hiding rows. 
9912         m_minAcceptableRowHeight 
= height
; 
9915 int  wxGrid::GetColMinimalAcceptableWidth() const 
9917     return m_minAcceptableColWidth
; 
9920 int  wxGrid::GetRowMinimalAcceptableHeight() const 
9922     return m_minAcceptableRowHeight
; 
9925 // ---------------------------------------------------------------------------- 
9927 // ---------------------------------------------------------------------------- 
9929 void wxGrid::AutoSizeColOrRow( int colOrRow
, bool setAsMin
, bool column 
) 
9931     wxClientDC 
dc(m_gridWin
); 
9933     // cancel editing of cell 
9934     HideCellEditControl(); 
9935     SaveEditControlValue(); 
9937     // init both of them to avoid compiler warnings, even if we only need one 
9945     wxCoord extent
, extentMax 
= 0; 
9946     int max 
= column 
? m_numRows 
: m_numCols
; 
9947     for ( int rowOrCol 
= 0; rowOrCol 
< max
; rowOrCol
++ ) 
9954         wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
9955         wxGridCellRenderer
* renderer 
= attr
->GetRenderer(this, row
, col
); 
9958             wxSize size 
= renderer
->GetBestSize(*this, *attr
, dc
, row
, col
); 
9959             extent 
= column 
? size
.x 
: size
.y
; 
9960             if ( extent 
> extentMax 
) 
9971     // now also compare with the column label extent 
9973     dc
.SetFont( GetLabelFont() ); 
9977         dc
.GetTextExtent( GetColLabelValue(col
), &w
, &h 
); 
9978         if ( GetColLabelTextOrientation() == wxVERTICAL 
) 
9982         dc
.GetTextExtent( GetRowLabelValue(row
), &w
, &h 
); 
9984     extent 
= column 
? w 
: h
; 
9985     if ( extent 
> extentMax 
) 
9992         // empty column - give default extent (notice that if extentMax is less 
9993         // than default extent but != 0, it's ok) 
9994         extentMax 
= column 
? m_defaultColWidth 
: m_defaultRowHeight
; 
9999             // leave some space around text 
10007         SetColSize( col
, extentMax 
); 
10008         if ( !GetBatchCount() ) 
10011             m_gridWin
->GetClientSize( &cw
, &ch 
); 
10012             wxRect 
rect ( CellToRect( 0, col 
) ); 
10014             CalcScrolledPosition(rect
.x
, 0, &rect
.x
, &dummy
); 
10015             rect
.width 
= cw 
- rect
.x
; 
10016             rect
.height 
= m_colLabelHeight
; 
10017             m_colLabelWin
->Refresh( true, &rect 
); 
10022         SetRowSize(row
, extentMax
); 
10023         if ( !GetBatchCount() ) 
10026             m_gridWin
->GetClientSize( &cw
, &ch 
); 
10027             wxRect 
rect ( CellToRect( row
, 0 ) ); 
10029             CalcScrolledPosition(0, rect
.y
, &dummy
, &rect
.y
); 
10030             rect
.width 
= m_rowLabelWidth
; 
10031             rect
.height 
= ch 
- rect
.y
; 
10032             m_rowLabelWin
->Refresh( true, &rect 
); 
10038             SetColMinimalWidth(col
, extentMax
); 
10040             SetRowMinimalHeight(row
, extentMax
); 
10044 int wxGrid::SetOrCalcColumnSizes(bool calcOnly
, bool setAsMin
) 
10046     int width 
= m_rowLabelWidth
; 
10051     for ( int col 
= 0; col 
< m_numCols
; col
++ ) 
10055             AutoSizeColumn(col
, setAsMin
); 
10058         width 
+= GetColWidth(col
); 
10067 int wxGrid::SetOrCalcRowSizes(bool calcOnly
, bool setAsMin
) 
10069     int height 
= m_colLabelHeight
; 
10074     for ( int row 
= 0; row 
< m_numRows
; row
++ ) 
10077             AutoSizeRow(row
, setAsMin
); 
10079         height 
+= GetRowHeight(row
); 
10088 void wxGrid::AutoSize() 
10092     wxSize 
size(SetOrCalcColumnSizes(false), SetOrCalcRowSizes(false)); 
10094     // round up the size to a multiple of scroll step - this ensures that we 
10095     // won't get the scrollbars if we're sized exactly to this width 
10096     // CalcDimension adds m_extraWidth + 1 etc. to calculate the necessary 
10098     wxSize 
sizeFit(GetScrollX(size
.x 
+ m_extraWidth 
+ 1) * m_scrollLineX
, 
10099                    GetScrollY(size
.y 
+ m_extraHeight 
+ 1) * m_scrollLineY
); 
10101     // distribute the extra space between the columns/rows to avoid having 
10102     // extra white space 
10104     // Remove the extra m_extraWidth + 1 added above 
10105     wxCoord diff 
= sizeFit
.x 
- size
.x 
+ (m_extraWidth 
+ 1); 
10106     if ( diff 
&& m_numCols 
) 
10108         // try to resize the columns uniformly 
10109         wxCoord diffPerCol 
= diff 
/ m_numCols
; 
10112             for ( int col 
= 0; col 
< m_numCols
; col
++ ) 
10114                 SetColSize(col
, GetColWidth(col
) + diffPerCol
); 
10118         // add remaining amount to the last columns 
10119         diff 
-= diffPerCol 
* m_numCols
; 
10122             for ( int col 
= m_numCols 
- 1; col 
>= m_numCols 
- diff
; col
-- ) 
10124                 SetColSize(col
, GetColWidth(col
) + 1); 
10130     diff 
= sizeFit
.y 
- size
.y 
- (m_extraHeight 
+ 1); 
10131     if ( diff 
&& m_numRows 
) 
10133         // try to resize the columns uniformly 
10134         wxCoord diffPerRow 
= diff 
/ m_numRows
; 
10137             for ( int row 
= 0; row 
< m_numRows
; row
++ ) 
10139                 SetRowSize(row
, GetRowHeight(row
) + diffPerRow
); 
10143         // add remaining amount to the last rows 
10144         diff 
-= diffPerRow 
* m_numRows
; 
10147             for ( int row 
= m_numRows 
- 1; row 
>= m_numRows 
- diff
; row
-- ) 
10149                 SetRowSize(row
, GetRowHeight(row
) + 1); 
10156     SetClientSize(sizeFit
); 
10159 void wxGrid::AutoSizeRowLabelSize( int row 
) 
10161     wxArrayString lines
; 
10164     // Hide the edit control, so it 
10165     // won't interfere with drag-shrinking. 
10166     if ( IsCellEditControlShown() ) 
10168         HideCellEditControl(); 
10169         SaveEditControlValue(); 
10172     // autosize row height depending on label text 
10173     StringToLines( GetRowLabelValue( row 
), lines 
); 
10174     wxClientDC 
dc( m_rowLabelWin 
); 
10175     GetTextBoxSize( dc
, lines
, &w
, &h
); 
10176     if ( h 
< m_defaultRowHeight 
) 
10177         h 
= m_defaultRowHeight
; 
10178     SetRowSize(row
, h
); 
10182 void wxGrid::AutoSizeColLabelSize( int col 
) 
10184     wxArrayString lines
; 
10187     // Hide the edit control, so it 
10188     // won't interfer with drag-shrinking. 
10189     if ( IsCellEditControlShown() ) 
10191         HideCellEditControl(); 
10192         SaveEditControlValue(); 
10195     // autosize column width depending on label text 
10196     StringToLines( GetColLabelValue( col 
), lines 
); 
10197     wxClientDC 
dc( m_colLabelWin 
); 
10198     if ( GetColLabelTextOrientation() == wxHORIZONTAL 
) 
10199         GetTextBoxSize( dc
, lines
, &w
, &h
); 
10201         GetTextBoxSize( dc
, lines
, &h
, &w
); 
10202     if ( w 
< m_defaultColWidth 
) 
10203         w 
= m_defaultColWidth
; 
10204     SetColSize(col
, w
); 
10208 wxSize 
wxGrid::DoGetBestSize() const 
10210     // don't set sizes, only calculate them 
10211     wxGrid 
*self 
= (wxGrid 
*)this;  // const_cast 
10214     width 
= self
->SetOrCalcColumnSizes(true); 
10215     height 
= self
->SetOrCalcRowSizes(true); 
10222     // Round up to a multiple the scroll rate 
10223     // NOTE: this still doesn't get rid  of the scrollbars; 
10224     // is there any magic incantation for that? 
10226     GetScrollPixelsPerUnit(&xpu
, &ypu
); 
10228         width  
+= 1 + xpu 
- (width  
% xpu
); 
10230         height 
+= 1 + ypu 
- (height 
% ypu
); 
10232     // limit to 1/4 of the screen size 
10233     int maxwidth
, maxheight
; 
10234     wxDisplaySize( &maxwidth
, &maxheight 
); 
10237     if ( width 
> maxwidth 
) 
10239     if ( height 
> maxheight 
) 
10240         height 
= maxheight
; 
10242     wxSize 
best(width
, height
); 
10244     // NOTE: This size should be cached, but first we need to add calls to 
10245     // InvalidateBestSize everywhere that could change the results of this 
10247     // CacheBestSize(size); 
10257 wxPen
& wxGrid::GetDividerPen() const 
10262 // ---------------------------------------------------------------------------- 
10263 // cell value accessor functions 
10264 // ---------------------------------------------------------------------------- 
10266 void wxGrid::SetCellValue( int row
, int col
, const wxString
& s 
) 
10270         m_table
->SetValue( row
, col
, s 
); 
10271         if ( !GetBatchCount() ) 
10274             wxRect 
rect( CellToRect( row
, col 
) ); 
10276             rect
.width 
= m_gridWin
->GetClientSize().GetWidth(); 
10277             CalcScrolledPosition(0, rect
.y
, &dummy
, &rect
.y
); 
10278             m_gridWin
->Refresh( false, &rect 
); 
10281         if ( m_currentCellCoords
.GetRow() == row 
&& 
10282              m_currentCellCoords
.GetCol() == col 
&& 
10283              IsCellEditControlShown()) 
10284              // Note: If we are using IsCellEditControlEnabled, 
10285              // this interacts badly with calling SetCellValue from 
10286              // an EVT_GRID_CELL_CHANGE handler. 
10288             HideCellEditControl(); 
10289             ShowCellEditControl(); // will reread data from table 
10295 // ---------------------------------------------------------------------------- 
10296 // block, row and col selection 
10297 // ---------------------------------------------------------------------------- 
10299 void wxGrid::SelectRow( int row
, bool addToSelected 
) 
10301     if ( IsSelection() && !addToSelected 
) 
10305         m_selection
->SelectRow( row
, false, addToSelected 
); 
10308 void wxGrid::SelectCol( int col
, bool addToSelected 
) 
10310     if ( IsSelection() && !addToSelected 
) 
10314         m_selection
->SelectCol( col
, false, addToSelected 
); 
10317 void wxGrid::SelectBlock( int topRow
, int leftCol
, int bottomRow
, int rightCol
, 
10318                           bool addToSelected 
) 
10320     if ( IsSelection() && !addToSelected 
) 
10324         m_selection
->SelectBlock( topRow
, leftCol
, bottomRow
, rightCol
, 
10325                                   false, addToSelected 
); 
10328 void wxGrid::SelectAll() 
10330     if ( m_numRows 
> 0 && m_numCols 
> 0 ) 
10333             m_selection
->SelectBlock( 0, 0, m_numRows
-1, m_numCols
-1 ); 
10337 // ---------------------------------------------------------------------------- 
10338 // cell, row and col deselection 
10339 // ---------------------------------------------------------------------------- 
10341 void wxGrid::DeselectRow( int row 
) 
10343     if ( !m_selection 
) 
10346     if ( m_selection
->GetSelectionMode() == wxGrid::wxGridSelectRows 
) 
10348         if ( m_selection
->IsInSelection(row
, 0 ) ) 
10349             m_selection
->ToggleCellSelection( row
, 0); 
10353         int nCols 
= GetNumberCols(); 
10354         for ( int i 
= 0; i 
< nCols 
; i
++ ) 
10356             if ( m_selection
->IsInSelection(row
, i 
) ) 
10357                 m_selection
->ToggleCellSelection( row
, i
); 
10362 void wxGrid::DeselectCol( int col 
) 
10364     if ( !m_selection 
) 
10367     if ( m_selection
->GetSelectionMode() == wxGrid::wxGridSelectColumns 
) 
10369         if ( m_selection
->IsInSelection(0, col 
) ) 
10370             m_selection
->ToggleCellSelection( 0, col
); 
10374         int nRows 
= GetNumberRows(); 
10375         for ( int i 
= 0; i 
< nRows 
; i
++ ) 
10377             if ( m_selection
->IsInSelection(i
, col 
) ) 
10378                 m_selection
->ToggleCellSelection(i
, col
); 
10383 void wxGrid::DeselectCell( int row
, int col 
) 
10385     if ( m_selection 
&& m_selection
->IsInSelection(row
, col
) ) 
10386         m_selection
->ToggleCellSelection(row
, col
); 
10389 bool wxGrid::IsSelection() 
10391     return ( m_selection 
&& (m_selection
->IsSelection() || 
10392              ( m_selectingTopLeft 
!= wxGridNoCellCoords 
&& 
10393                m_selectingBottomRight 
!= wxGridNoCellCoords
) ) ); 
10396 bool wxGrid::IsInSelection( int row
, int col 
) const 
10398     return ( m_selection 
&& (m_selection
->IsInSelection( row
, col 
) || 
10399              ( row 
>= m_selectingTopLeft
.GetRow() && 
10400                col 
>= m_selectingTopLeft
.GetCol() && 
10401                row 
<= m_selectingBottomRight
.GetRow() && 
10402                col 
<= m_selectingBottomRight
.GetCol() )) ); 
10405 wxGridCellCoordsArray 
wxGrid::GetSelectedCells() const 
10409         wxGridCellCoordsArray a
; 
10413     return m_selection
->m_cellSelection
; 
10416 wxGridCellCoordsArray 
wxGrid::GetSelectionBlockTopLeft() const 
10420         wxGridCellCoordsArray a
; 
10424     return m_selection
->m_blockSelectionTopLeft
; 
10427 wxGridCellCoordsArray 
wxGrid::GetSelectionBlockBottomRight() const 
10431         wxGridCellCoordsArray a
; 
10435     return m_selection
->m_blockSelectionBottomRight
; 
10438 wxArrayInt 
wxGrid::GetSelectedRows() const 
10446     return m_selection
->m_rowSelection
; 
10449 wxArrayInt 
wxGrid::GetSelectedCols() const 
10457     return m_selection
->m_colSelection
; 
10460 void wxGrid::ClearSelection() 
10462     m_selectingTopLeft 
= wxGridNoCellCoords
; 
10463     m_selectingBottomRight 
= wxGridNoCellCoords
; 
10465         m_selection
->ClearSelection(); 
10469 // This function returns the rectangle that encloses the given block 
10470 // in device coords clipped to the client size of the grid window. 
10472 wxRect 
wxGrid::BlockToDeviceRect( const wxGridCellCoords 
&topLeft
, 
10473                                   const wxGridCellCoords 
&bottomRight 
) 
10475     wxRect 
rect( wxGridNoCellRect 
); 
10478     cellRect 
= CellToRect( topLeft 
); 
10479     if ( cellRect 
!= wxGridNoCellRect 
) 
10485         rect 
= wxRect(0, 0, 0, 0); 
10488     cellRect 
= CellToRect( bottomRight 
); 
10489     if ( cellRect 
!= wxGridNoCellRect 
) 
10495         return wxGridNoCellRect
; 
10499     int left 
= rect
.GetLeft(); 
10500     int top 
= rect
.GetTop(); 
10501     int right 
= rect
.GetRight(); 
10502     int bottom 
= rect
.GetBottom(); 
10504     int leftCol 
= topLeft
.GetCol(); 
10505     int topRow 
= topLeft
.GetRow(); 
10506     int rightCol 
= bottomRight
.GetCol(); 
10507     int bottomRow 
= bottomRight
.GetRow(); 
10515         leftCol 
= rightCol
; 
10525         topRow 
= bottomRow
; 
10529     for ( j 
= topRow
; j 
<= bottomRow
; j
++ ) 
10531         for ( i 
= leftCol
; i 
<= rightCol
; i
++ ) 
10533             if ((j 
== topRow
) || (j 
== bottomRow
) || (i 
== leftCol
) || (i 
== rightCol
)) 
10535                 cellRect 
= CellToRect( j
, i 
); 
10537                 if (cellRect
.x 
< left
) 
10539                 if (cellRect
.y 
< top
) 
10541                 if (cellRect
.x 
+ cellRect
.width 
> right
) 
10542                     right 
= cellRect
.x 
+ cellRect
.width
; 
10543                 if (cellRect
.y 
+ cellRect
.height 
> bottom
) 
10544                     bottom 
= cellRect
.y 
+ cellRect
.height
; 
10548                 i 
= rightCol
; // jump over inner cells. 
10553     // convert to scrolled coords 
10555     CalcScrolledPosition( left
, top
, &left
, &top 
); 
10556     CalcScrolledPosition( right
, bottom
, &right
, &bottom 
); 
10559     m_gridWin
->GetClientSize( &cw
, &ch 
); 
10561     if (right 
< 0 || bottom 
< 0 || left 
> cw 
|| top 
> ch
) 
10562         return wxRect(0,0,0,0); 
10564     rect
.SetLeft( wxMax(0, left
) ); 
10565     rect
.SetTop( wxMax(0, top
) ); 
10566     rect
.SetRight( wxMin(cw
, right
) ); 
10567     rect
.SetBottom( wxMin(ch
, bottom
) ); 
10572 // ---------------------------------------------------------------------------- 
10573 // grid event classes 
10574 // ---------------------------------------------------------------------------- 
10576 IMPLEMENT_DYNAMIC_CLASS( wxGridEvent
, wxNotifyEvent 
) 
10578 wxGridEvent::wxGridEvent( int id
, wxEventType type
, wxObject
* obj
, 
10579                           int row
, int col
, int x
, int y
, bool sel
, 
10580                           bool control
, bool shift
, bool alt
, bool meta 
) 
10581         : wxNotifyEvent( type
, id 
) 
10588     m_control 
= control
; 
10593     SetEventObject(obj
); 
10597 IMPLEMENT_DYNAMIC_CLASS( wxGridSizeEvent
, wxNotifyEvent 
) 
10599 wxGridSizeEvent::wxGridSizeEvent( int id
, wxEventType type
, wxObject
* obj
, 
10600                                   int rowOrCol
, int x
, int y
, 
10601                                   bool control
, bool shift
, bool alt
, bool meta 
) 
10602         : wxNotifyEvent( type
, id 
) 
10604     m_rowOrCol 
= rowOrCol
; 
10607     m_control 
= control
; 
10612     SetEventObject(obj
); 
10616 IMPLEMENT_DYNAMIC_CLASS( wxGridRangeSelectEvent
, wxNotifyEvent 
) 
10618 wxGridRangeSelectEvent::wxGridRangeSelectEvent(int id
, wxEventType type
, wxObject
* obj
, 
10619                                                const wxGridCellCoords
& topLeft
, 
10620                                                const wxGridCellCoords
& bottomRight
, 
10621                                                bool sel
, bool control
, 
10622                                                bool shift
, bool alt
, bool meta 
) 
10623         : wxNotifyEvent( type
, id 
) 
10625     m_topLeft     
= topLeft
; 
10626     m_bottomRight 
= bottomRight
; 
10628     m_control     
= control
; 
10633     SetEventObject(obj
); 
10637 IMPLEMENT_DYNAMIC_CLASS(wxGridEditorCreatedEvent
, wxCommandEvent
) 
10639 wxGridEditorCreatedEvent::wxGridEditorCreatedEvent(int id
, wxEventType type
, 
10640                                                    wxObject
* obj
, int row
, 
10641                                                    int col
, wxControl
* ctrl
) 
10642     : wxCommandEvent(type
, id
) 
10644     SetEventObject(obj
); 
10650 #endif // wxUSE_GRID