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, Santiago Palacios 
   8 // Copyright:   (c) Michael Bedward (mbedward@ozemail.com.au) 
   9 // Licence:     wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////////// 
  12 // For compilers that support precompilation, includes "wx/wx.h". 
  13 #include "wx/wxprec.h" 
  25     #include "wx/dcclient.h" 
  26     #include "wx/settings.h" 
  28     #include "wx/textctrl.h" 
  29     #include "wx/checkbox.h" 
  30     #include "wx/combobox.h" 
  31     #include "wx/valtext.h" 
  34     #include "wx/listbox.h" 
  37 #include "wx/textfile.h" 
  38 #include "wx/spinctrl.h" 
  39 #include "wx/tokenzr.h" 
  40 #include "wx/renderer.h" 
  42 #include "wx/generic/gridsel.h" 
  44 const wxChar wxGridNameStr
[] = wxT("grid"); 
  46 #if defined(__WXMOTIF__) 
  47     #define WXUNUSED_MOTIF(identifier)  WXUNUSED(identifier) 
  49     #define WXUNUSED_MOTIF(identifier)  identifier 
  52 #if defined(__WXGTK__) 
  53     #define WXUNUSED_GTK(identifier)    WXUNUSED(identifier) 
  55     #define WXUNUSED_GTK(identifier)    identifier 
  58 // Required for wxIs... functions 
  61 // ---------------------------------------------------------------------------- 
  63 // ---------------------------------------------------------------------------- 
  65 WX_DEFINE_ARRAY_WITH_DECL_PTR(wxGridCellAttr 
*, wxArrayAttrs
, 
  66                                  class WXDLLIMPEXP_ADV
); 
  68 struct wxGridCellWithAttr
 
  70     wxGridCellWithAttr(int row
, int col
, wxGridCellAttr 
*attr_
) 
  71         : coords(row
, col
), attr(attr_
) 
  76     wxGridCellWithAttr(const wxGridCellWithAttr
& other
) 
  77         : coords(other
.coords
), 
  83     wxGridCellWithAttr
& operator=(const wxGridCellWithAttr
& other
) 
  85         coords 
= other
.coords
; 
  86         if (attr 
!= other
.attr
) 
 100     wxGridCellCoords coords
; 
 101     wxGridCellAttr  
*attr
; 
 104 WX_DECLARE_OBJARRAY_WITH_DECL(wxGridCellWithAttr
, wxGridCellWithAttrArray
, 
 105                               class WXDLLIMPEXP_ADV
); 
 107 #include "wx/arrimpl.cpp" 
 109 WX_DEFINE_OBJARRAY(wxGridCellCoordsArray
) 
 110 WX_DEFINE_OBJARRAY(wxGridCellWithAttrArray
) 
 112 // ---------------------------------------------------------------------------- 
 114 // ---------------------------------------------------------------------------- 
 116 DEFINE_EVENT_TYPE(wxEVT_GRID_CELL_LEFT_CLICK
) 
 117 DEFINE_EVENT_TYPE(wxEVT_GRID_CELL_RIGHT_CLICK
) 
 118 DEFINE_EVENT_TYPE(wxEVT_GRID_CELL_LEFT_DCLICK
) 
 119 DEFINE_EVENT_TYPE(wxEVT_GRID_CELL_RIGHT_DCLICK
) 
 120 DEFINE_EVENT_TYPE(wxEVT_GRID_CELL_BEGIN_DRAG
) 
 121 DEFINE_EVENT_TYPE(wxEVT_GRID_LABEL_LEFT_CLICK
) 
 122 DEFINE_EVENT_TYPE(wxEVT_GRID_LABEL_RIGHT_CLICK
) 
 123 DEFINE_EVENT_TYPE(wxEVT_GRID_LABEL_LEFT_DCLICK
) 
 124 DEFINE_EVENT_TYPE(wxEVT_GRID_LABEL_RIGHT_DCLICK
) 
 125 DEFINE_EVENT_TYPE(wxEVT_GRID_ROW_SIZE
) 
 126 DEFINE_EVENT_TYPE(wxEVT_GRID_COL_SIZE
) 
 127 DEFINE_EVENT_TYPE(wxEVT_GRID_COL_MOVE
) 
 128 DEFINE_EVENT_TYPE(wxEVT_GRID_RANGE_SELECT
) 
 129 DEFINE_EVENT_TYPE(wxEVT_GRID_CELL_CHANGE
) 
 130 DEFINE_EVENT_TYPE(wxEVT_GRID_SELECT_CELL
) 
 131 DEFINE_EVENT_TYPE(wxEVT_GRID_EDITOR_SHOWN
) 
 132 DEFINE_EVENT_TYPE(wxEVT_GRID_EDITOR_HIDDEN
) 
 133 DEFINE_EVENT_TYPE(wxEVT_GRID_EDITOR_CREATED
) 
 135 // ---------------------------------------------------------------------------- 
 137 // ---------------------------------------------------------------------------- 
 139 // common base class for various grid subwindows 
 140 class WXDLLIMPEXP_ADV wxGridSubwindow 
: public wxWindow
 
 143     wxGridSubwindow() { m_owner 
= NULL
; } 
 144     wxGridSubwindow(wxGrid 
*owner
, 
 148                     int additionalStyle 
= 0, 
 149                     const wxString
& name 
= wxPanelNameStr
) 
 150         : wxWindow(owner
, id
, pos
, size
, 
 151                    wxBORDER_NONE 
| additionalStyle
, 
 157     virtual bool AcceptsFocus() const { return false; } 
 159     wxGrid 
*GetOwner() { return m_owner
; } 
 162     void OnMouseCaptureLost(wxMouseCaptureLostEvent
& event
); 
 166     DECLARE_EVENT_TABLE() 
 167     DECLARE_NO_COPY_CLASS(wxGridSubwindow
) 
 170 class WXDLLIMPEXP_ADV wxGridRowLabelWindow 
: public wxGridSubwindow
 
 173     wxGridRowLabelWindow() { } 
 174     wxGridRowLabelWindow( wxGrid 
*parent
, wxWindowID id
, 
 175                           const wxPoint 
&pos
, const wxSize 
&size 
); 
 178     void OnPaint( wxPaintEvent
& event 
); 
 179     void OnMouseEvent( wxMouseEvent
& event 
); 
 180     void OnMouseWheel( wxMouseEvent
& event 
); 
 182     DECLARE_DYNAMIC_CLASS(wxGridRowLabelWindow
) 
 183     DECLARE_EVENT_TABLE() 
 184     DECLARE_NO_COPY_CLASS(wxGridRowLabelWindow
) 
 188 class WXDLLIMPEXP_ADV wxGridColLabelWindow 
: public wxGridSubwindow
 
 191     wxGridColLabelWindow() { } 
 192     wxGridColLabelWindow( wxGrid 
*parent
, wxWindowID id
, 
 193                           const wxPoint 
&pos
, const wxSize 
&size 
); 
 196     void OnPaint( wxPaintEvent
& event 
); 
 197     void OnMouseEvent( wxMouseEvent
& event 
); 
 198     void OnMouseWheel( wxMouseEvent
& event 
); 
 200     DECLARE_DYNAMIC_CLASS(wxGridColLabelWindow
) 
 201     DECLARE_EVENT_TABLE() 
 202     DECLARE_NO_COPY_CLASS(wxGridColLabelWindow
) 
 206 class WXDLLIMPEXP_ADV wxGridCornerLabelWindow 
: public wxGridSubwindow
 
 209     wxGridCornerLabelWindow() { } 
 210     wxGridCornerLabelWindow( wxGrid 
*parent
, wxWindowID id
, 
 211                              const wxPoint 
&pos
, const wxSize 
&size 
); 
 214     void OnMouseEvent( wxMouseEvent
& event 
); 
 215     void OnMouseWheel( wxMouseEvent
& event 
); 
 216     void OnPaint( wxPaintEvent
& event 
); 
 218     DECLARE_DYNAMIC_CLASS(wxGridCornerLabelWindow
) 
 219     DECLARE_EVENT_TABLE() 
 220     DECLARE_NO_COPY_CLASS(wxGridCornerLabelWindow
) 
 223 class WXDLLIMPEXP_ADV wxGridWindow 
: public wxGridSubwindow
 
 228         m_rowLabelWin 
= NULL
; 
 229         m_colLabelWin 
= NULL
; 
 232     wxGridWindow( wxGrid 
*parent
, 
 233                   wxGridRowLabelWindow 
*rowLblWin
, 
 234                   wxGridColLabelWindow 
*colLblWin
, 
 235                   wxWindowID id
, const wxPoint 
&pos
, const wxSize 
&size 
); 
 237     void ScrollWindow( int dx
, int dy
, const wxRect 
*rect 
); 
 239     virtual bool AcceptsFocus() const { return true; } 
 242     wxGridRowLabelWindow     
*m_rowLabelWin
; 
 243     wxGridColLabelWindow     
*m_colLabelWin
; 
 245     void OnPaint( wxPaintEvent 
&event 
); 
 246     void OnMouseWheel( wxMouseEvent
& event 
); 
 247     void OnMouseEvent( wxMouseEvent
& event 
); 
 248     void OnKeyDown( wxKeyEvent
& ); 
 249     void OnKeyUp( wxKeyEvent
& ); 
 250     void OnChar( wxKeyEvent
& ); 
 251     void OnEraseBackground( wxEraseEvent
& ); 
 252     void OnFocus( wxFocusEvent
& ); 
 254     DECLARE_DYNAMIC_CLASS(wxGridWindow
) 
 255     DECLARE_EVENT_TABLE() 
 256     DECLARE_NO_COPY_CLASS(wxGridWindow
) 
 260 class wxGridCellEditorEvtHandler 
: public wxEvtHandler
 
 263     wxGridCellEditorEvtHandler(wxGrid
* grid
, wxGridCellEditor
* editor
) 
 270     void OnKillFocus(wxFocusEvent
& event
); 
 271     void OnKeyDown(wxKeyEvent
& event
); 
 272     void OnChar(wxKeyEvent
& event
); 
 274     void SetInSetFocus(bool inSetFocus
) { m_inSetFocus 
= inSetFocus
; } 
 278     wxGridCellEditor   
*m_editor
; 
 280     // Work around the fact that a focus kill event can be sent to 
 281     // a combobox within a set focus event. 
 284     DECLARE_EVENT_TABLE() 
 285     DECLARE_DYNAMIC_CLASS(wxGridCellEditorEvtHandler
) 
 286     DECLARE_NO_COPY_CLASS(wxGridCellEditorEvtHandler
) 
 290 IMPLEMENT_ABSTRACT_CLASS(wxGridCellEditorEvtHandler
, wxEvtHandler
) 
 292 BEGIN_EVENT_TABLE( wxGridCellEditorEvtHandler
, wxEvtHandler 
) 
 293     EVT_KILL_FOCUS( wxGridCellEditorEvtHandler::OnKillFocus 
) 
 294     EVT_KEY_DOWN( wxGridCellEditorEvtHandler::OnKeyDown 
) 
 295     EVT_CHAR( wxGridCellEditorEvtHandler::OnChar 
) 
 299 // ---------------------------------------------------------------------------- 
 300 // the internal data representation used by wxGridCellAttrProvider 
 301 // ---------------------------------------------------------------------------- 
 303 // this class stores attributes set for cells 
 304 class WXDLLIMPEXP_ADV wxGridCellAttrData
 
 307     void SetAttr(wxGridCellAttr 
*attr
, int row
, int col
); 
 308     wxGridCellAttr 
*GetAttr(int row
, int col
) const; 
 309     void UpdateAttrRows( size_t pos
, int numRows 
); 
 310     void UpdateAttrCols( size_t pos
, int numCols 
); 
 313     // searches for the attr for given cell, returns wxNOT_FOUND if not found 
 314     int FindIndex(int row
, int col
) const; 
 316     wxGridCellWithAttrArray m_attrs
; 
 319 // this class stores attributes set for rows or columns 
 320 class WXDLLIMPEXP_ADV wxGridRowOrColAttrData
 
 323     // empty ctor to suppress warnings 
 324     wxGridRowOrColAttrData() {} 
 325     ~wxGridRowOrColAttrData(); 
 327     void SetAttr(wxGridCellAttr 
*attr
, int rowOrCol
); 
 328     wxGridCellAttr 
*GetAttr(int rowOrCol
) const; 
 329     void UpdateAttrRowsOrCols( size_t pos
, int numRowsOrCols 
); 
 332     wxArrayInt m_rowsOrCols
; 
 333     wxArrayAttrs m_attrs
; 
 336 // NB: this is just a wrapper around 3 objects: one which stores cell 
 337 //     attributes, and 2 others for row/col ones 
 338 class WXDLLIMPEXP_ADV wxGridCellAttrProviderData
 
 341     wxGridCellAttrData m_cellAttrs
; 
 342     wxGridRowOrColAttrData m_rowAttrs
, 
 347 // ---------------------------------------------------------------------------- 
 348 // data structures used for the data type registry 
 349 // ---------------------------------------------------------------------------- 
 351 struct wxGridDataTypeInfo
 
 353     wxGridDataTypeInfo(const wxString
& typeName
, 
 354                        wxGridCellRenderer
* renderer
, 
 355                        wxGridCellEditor
* editor
) 
 356         : m_typeName(typeName
), m_renderer(renderer
), m_editor(editor
) 
 359     ~wxGridDataTypeInfo() 
 361         wxSafeDecRef(m_renderer
); 
 362         wxSafeDecRef(m_editor
); 
 366     wxGridCellRenderer
* m_renderer
; 
 367     wxGridCellEditor
*   m_editor
; 
 369     DECLARE_NO_COPY_CLASS(wxGridDataTypeInfo
) 
 373 WX_DEFINE_ARRAY_WITH_DECL_PTR(wxGridDataTypeInfo
*, wxGridDataTypeInfoArray
, 
 374                                  class WXDLLIMPEXP_ADV
); 
 377 class WXDLLIMPEXP_ADV wxGridTypeRegistry
 
 380   wxGridTypeRegistry() {} 
 381     ~wxGridTypeRegistry(); 
 383     void RegisterDataType(const wxString
& typeName
, 
 384                      wxGridCellRenderer
* renderer
, 
 385                      wxGridCellEditor
* editor
); 
 387     // find one of already registered data types 
 388     int FindRegisteredDataType(const wxString
& typeName
); 
 390     // try to FindRegisteredDataType(), if this fails and typeName is one of 
 391     // standard typenames, register it and return its index 
 392     int FindDataType(const wxString
& typeName
); 
 394     // try to FindDataType(), if it fails see if it is not one of already 
 395     // registered data types with some params in which case clone the 
 396     // registered data type and set params for it 
 397     int FindOrCloneDataType(const wxString
& typeName
); 
 399     wxGridCellRenderer
* GetRenderer(int index
); 
 400     wxGridCellEditor
*   GetEditor(int index
); 
 403     wxGridDataTypeInfoArray m_typeinfo
; 
 407 // ---------------------------------------------------------------------------- 
 408 // conditional compilation 
 409 // ---------------------------------------------------------------------------- 
 411 #ifndef WXGRID_DRAW_LINES 
 412 #define WXGRID_DRAW_LINES 1 
 415 // ---------------------------------------------------------------------------- 
 417 // ---------------------------------------------------------------------------- 
 419 //#define DEBUG_ATTR_CACHE 
 420 #ifdef DEBUG_ATTR_CACHE 
 421     static size_t gs_nAttrCacheHits 
= 0; 
 422     static size_t gs_nAttrCacheMisses 
= 0; 
 425 // ---------------------------------------------------------------------------- 
 427 // ---------------------------------------------------------------------------- 
 429 wxGridCellCoords 
wxGridNoCellCoords( -1, -1 ); 
 430 wxRect 
wxGridNoCellRect( -1, -1, -1, -1 ); 
 433 // TODO: this doesn't work at all, grid cells have different sizes and approx 
 434 //       calculations don't work as because of the size mismatch scrollbars 
 435 //       sometimes fail to be shown when they should be or vice versa 
 437 //       The scroll bars may be a little flakey once in a while, but that is 
 438 //       surely much less horrible than having scroll lines of only 1!!! 
 441 //       Well, it's still seriously broken so it might be better but needs 
 444 static const size_t GRID_SCROLL_LINE_X 
= 15;  // 1; 
 445 static const size_t GRID_SCROLL_LINE_Y 
= GRID_SCROLL_LINE_X
; 
 447 // the size of hash tables used a bit everywhere (the max number of elements 
 448 // in these hash tables is the number of rows/columns) 
 449 static const int GRID_HASH_SIZE 
= 100; 
 452 // ---------------------------------------------------------------------------- 
 454 // ---------------------------------------------------------------------------- 
 456 static inline int GetScrollX(int x
) 
 458     return (x 
+ GRID_SCROLL_LINE_X 
- 1) / GRID_SCROLL_LINE_X
; 
 461 static inline int GetScrollY(int y
) 
 463     return (y 
+ GRID_SCROLL_LINE_Y 
- 1) / GRID_SCROLL_LINE_Y
; 
 467 // ============================================================================ 
 469 // ============================================================================ 
 471 // ---------------------------------------------------------------------------- 
 473 // ---------------------------------------------------------------------------- 
 475 wxGridCellEditor::wxGridCellEditor() 
 481 wxGridCellEditor::~wxGridCellEditor() 
 486 void wxGridCellEditor::Create(wxWindow
* WXUNUSED(parent
), 
 487                               wxWindowID 
WXUNUSED(id
), 
 488                               wxEvtHandler
* evtHandler
) 
 491         m_control
->PushEventHandler(evtHandler
); 
 494 void wxGridCellEditor::PaintBackground(const wxRect
& rectCell
, 
 495                                        wxGridCellAttr 
*attr
) 
 497     // erase the background because we might not fill the cell 
 498     wxClientDC 
dc(m_control
->GetParent()); 
 499     wxGridWindow
* gridWindow 
= wxDynamicCast(m_control
->GetParent(), wxGridWindow
); 
 501         gridWindow
->GetOwner()->PrepareDC(dc
); 
 503     dc
.SetPen(*wxTRANSPARENT_PEN
); 
 504     dc
.SetBrush(wxBrush(attr
->GetBackgroundColour(), wxBRUSHSTYLE_SOLID
)); 
 505     dc
.DrawRectangle(rectCell
); 
 507     // redraw the control we just painted over 
 508     m_control
->Refresh(); 
 511 void wxGridCellEditor::Destroy() 
 515         m_control
->PopEventHandler( true /* delete it*/ ); 
 517         m_control
->Destroy(); 
 522 void wxGridCellEditor::Show(bool show
, wxGridCellAttr 
*attr
) 
 524     wxASSERT_MSG(m_control
, wxT("The wxGridCellEditor must be created first!")); 
 526     m_control
->Show(show
); 
 530         // set the colours/fonts if we have any 
 533             m_colFgOld 
= m_control
->GetForegroundColour(); 
 534             m_control
->SetForegroundColour(attr
->GetTextColour()); 
 536             m_colBgOld 
= m_control
->GetBackgroundColour(); 
 537             m_control
->SetBackgroundColour(attr
->GetBackgroundColour()); 
 539 // Workaround for GTK+1 font setting problem on some platforms 
 540 #if !defined(__WXGTK__) || defined(__WXGTK20__) 
 541             m_fontOld 
= m_control
->GetFont(); 
 542             m_control
->SetFont(attr
->GetFont()); 
 545             // can't do anything more in the base class version, the other 
 546             // attributes may only be used by the derived classes 
 551         // restore the standard colours fonts 
 552         if ( m_colFgOld
.Ok() ) 
 554             m_control
->SetForegroundColour(m_colFgOld
); 
 555             m_colFgOld 
= wxNullColour
; 
 558         if ( m_colBgOld
.Ok() ) 
 560             m_control
->SetBackgroundColour(m_colBgOld
); 
 561             m_colBgOld 
= wxNullColour
; 
 564 // Workaround for GTK+1 font setting problem on some platforms 
 565 #if !defined(__WXGTK__) || defined(__WXGTK20__) 
 566         if ( m_fontOld
.Ok() ) 
 568             m_control
->SetFont(m_fontOld
); 
 569             m_fontOld 
= wxNullFont
; 
 575 void wxGridCellEditor::SetSize(const wxRect
& rect
) 
 577     wxASSERT_MSG(m_control
, wxT("The wxGridCellEditor must be created first!")); 
 579     m_control
->SetSize(rect
, wxSIZE_ALLOW_MINUS_ONE
); 
 582 void wxGridCellEditor::HandleReturn(wxKeyEvent
& event
) 
 587 bool wxGridCellEditor::IsAcceptedKey(wxKeyEvent
& event
) 
 589     bool ctrl 
= event
.ControlDown(); 
 590     bool alt  
= event
.AltDown(); 
 593     // On the Mac the Alt key is more like shift and is used for entry of 
 594     // valid characters, so check for Ctrl and Meta instead. 
 595     alt 
= event
.MetaDown(); 
 598     // Assume it's not a valid char if ctrl or alt is down, but if both are 
 599     // down then it may be because of an AltGr key combination, so let them 
 600     // through in that case. 
 601     if ((ctrl 
|| alt
) && !(ctrl 
&& alt
)) 
 608     // If it's a F-Key or other special key then it shouldn't start the 
 610     if (event
.GetKeyCode() >= WXK_START
) 
 614     // if the unicode key code is not really a unicode character (it may 
 615     // be a function key or etc., the platforms appear to always give us a 
 616     // small value in this case) then fallback to the ASCII key code but 
 617     // don't do anything for function keys or etc. 
 618     key 
= event
.GetUnicodeKey(); 
 621         key 
= event
.GetKeyCode(); 
 622         keyOk 
= (key 
<= 127); 
 625     key 
= event
.GetKeyCode(); 
 626     keyOk 
= (key 
<= 255); 
 632 void wxGridCellEditor::StartingKey(wxKeyEvent
& event
) 
 637 void wxGridCellEditor::StartingClick() 
 643 // ---------------------------------------------------------------------------- 
 644 // wxGridCellTextEditor 
 645 // ---------------------------------------------------------------------------- 
 647 wxGridCellTextEditor::wxGridCellTextEditor() 
 652 void wxGridCellTextEditor::Create(wxWindow
* parent
, 
 654                                   wxEvtHandler
* evtHandler
) 
 656     DoCreate(parent
, id
, evtHandler
); 
 659 void wxGridCellTextEditor::DoCreate(wxWindow
* parent
, 
 661                                     wxEvtHandler
* evtHandler
, 
 664     style 
|= wxTE_PROCESS_ENTER 
| 
 669     m_control 
= new wxTextCtrl(parent
, id
, wxEmptyString
, 
 670                                wxDefaultPosition
, wxDefaultSize
, 
 673     // set max length allowed in the textctrl, if the parameter was set 
 674     if ( m_maxChars 
!= 0 ) 
 676         Text()->SetMaxLength(m_maxChars
); 
 679     wxGridCellEditor::Create(parent
, id
, evtHandler
); 
 682 void wxGridCellTextEditor::PaintBackground(const wxRect
& WXUNUSED(rectCell
), 
 683                                            wxGridCellAttr 
* WXUNUSED(attr
)) 
 685     // as we fill the entire client area, 
 686     // don't do anything here to minimize flicker 
 689 void wxGridCellTextEditor::SetSize(const wxRect
& rectOrig
) 
 691     wxRect 
rect(rectOrig
); 
 693     // Make the edit control large enough to allow for internal margins 
 695     // TODO: remove this if the text ctrl sizing is improved esp. for unix 
 697 #if defined(__WXGTK__) 
 705 #elif defined(__WXMSW__) 
 719     int extra_x 
= ( rect
.x 
> 2 ) ? 2 : 1; 
 720     int extra_y 
= ( rect
.y 
> 2 ) ? 2 : 1; 
 722     #if defined(__WXMOTIF__) 
 727     rect
.SetLeft( wxMax(0, rect
.x 
- extra_x
) ); 
 728     rect
.SetTop( wxMax(0, rect
.y 
- extra_y
) ); 
 729     rect
.SetRight( rect
.GetRight() + 2 * extra_x 
); 
 730     rect
.SetBottom( rect
.GetBottom() + 2 * extra_y 
); 
 733     wxGridCellEditor::SetSize(rect
); 
 736 void wxGridCellTextEditor::BeginEdit(int row
, int col
, wxGrid
* grid
) 
 738     wxASSERT_MSG(m_control
, wxT("The wxGridCellEditor must be created first!")); 
 740     m_startValue 
= grid
->GetTable()->GetValue(row
, col
); 
 742     DoBeginEdit(m_startValue
); 
 745 void wxGridCellTextEditor::DoBeginEdit(const wxString
& startValue
) 
 747     Text()->SetValue(startValue
); 
 748     Text()->SetInsertionPointEnd(); 
 749     Text()->SetSelection(-1, -1); 
 753 bool wxGridCellTextEditor::EndEdit(int row
, int col
, wxGrid
* grid
) 
 755     wxASSERT_MSG(m_control
, wxT("The wxGridCellEditor must be created first!")); 
 757     bool changed 
= false; 
 758     wxString value 
= Text()->GetValue(); 
 759     if (value 
!= m_startValue
) 
 763         grid
->GetTable()->SetValue(row
, col
, value
); 
 765     m_startValue 
= wxEmptyString
; 
 767     // No point in setting the text of the hidden control 
 768     //Text()->SetValue(m_startValue); 
 773 void wxGridCellTextEditor::Reset() 
 775     wxASSERT_MSG(m_control
, wxT("The wxGridCellEditor must be created first!")); 
 777     DoReset(m_startValue
); 
 780 void wxGridCellTextEditor::DoReset(const wxString
& startValue
) 
 782     Text()->SetValue(startValue
); 
 783     Text()->SetInsertionPointEnd(); 
 786 bool wxGridCellTextEditor::IsAcceptedKey(wxKeyEvent
& event
) 
 788     return wxGridCellEditor::IsAcceptedKey(event
); 
 791 void wxGridCellTextEditor::StartingKey(wxKeyEvent
& event
) 
 793     // Since this is now happening in the EVT_CHAR event EmulateKeyPress is no 
 794     // longer an appropriate way to get the character into the text control. 
 795     // Do it ourselves instead.  We know that if we get this far that we have 
 796     // a valid character, so not a whole lot of testing needs to be done. 
 798     wxTextCtrl
* tc 
= Text(); 
 803     ch 
= event
.GetUnicodeKey(); 
 805         ch 
= (wxChar
)event
.GetKeyCode(); 
 807     ch 
= (wxChar
)event
.GetKeyCode(); 
 813             // delete the character at the cursor 
 814             pos 
= tc
->GetInsertionPoint(); 
 815             if (pos 
< tc
->GetLastPosition()) 
 816                 tc
->Remove(pos
, pos 
+ 1); 
 820             // delete the character before the cursor 
 821             pos 
= tc
->GetInsertionPoint(); 
 823                 tc
->Remove(pos 
- 1, pos
); 
 832 void wxGridCellTextEditor::HandleReturn( wxKeyEvent
& 
 833                                          WXUNUSED_GTK(WXUNUSED_MOTIF(event
)) ) 
 835 #if defined(__WXMOTIF__) || defined(__WXGTK__) 
 836     // wxMotif needs a little extra help... 
 837     size_t pos 
= (size_t)( Text()->GetInsertionPoint() ); 
 838     wxString 
s( Text()->GetValue() ); 
 839     s 
= s
.Left(pos
) + wxT("\n") + s
.Mid(pos
); 
 841     Text()->SetInsertionPoint( pos 
); 
 843     // the other ports can handle a Return key press 
 849 void wxGridCellTextEditor::SetParameters(const wxString
& params
) 
 859         if ( params
.ToLong(&tmp
) ) 
 861             m_maxChars 
= (size_t)tmp
; 
 865             wxLogDebug( _T("Invalid wxGridCellTextEditor parameter string '%s' ignored"), params
.c_str() ); 
 870 // return the value in the text control 
 871 wxString 
wxGridCellTextEditor::GetValue() const 
 873     return Text()->GetValue(); 
 876 // ---------------------------------------------------------------------------- 
 877 // wxGridCellNumberEditor 
 878 // ---------------------------------------------------------------------------- 
 880 wxGridCellNumberEditor::wxGridCellNumberEditor(int min
, int max
) 
 886 void wxGridCellNumberEditor::Create(wxWindow
* parent
, 
 888                                     wxEvtHandler
* evtHandler
) 
 893         // create a spin ctrl 
 894         m_control 
= new wxSpinCtrl(parent
, wxID_ANY
, wxEmptyString
, 
 895                                    wxDefaultPosition
, wxDefaultSize
, 
 899         wxGridCellEditor::Create(parent
, id
, evtHandler
); 
 904         // just a text control 
 905         wxGridCellTextEditor::Create(parent
, id
, evtHandler
); 
 908         Text()->SetValidator(wxTextValidator(wxFILTER_NUMERIC
)); 
 913 void wxGridCellNumberEditor::BeginEdit(int row
, int col
, wxGrid
* grid
) 
 915     // first get the value 
 916     wxGridTableBase 
*table 
= grid
->GetTable(); 
 917     if ( table
->CanGetValueAs(row
, col
, wxGRID_VALUE_NUMBER
) ) 
 919         m_valueOld 
= table
->GetValueAsLong(row
, col
); 
 924         wxString sValue 
= table
->GetValue(row
, col
); 
 925         if (! sValue
.ToLong(&m_valueOld
) && ! sValue
.empty()) 
 927             wxFAIL_MSG( _T("this cell doesn't have numeric value") ); 
 935         Spin()->SetValue((int)m_valueOld
); 
 941         DoBeginEdit(GetString()); 
 945 bool wxGridCellNumberEditor::EndEdit(int row
, int col
, 
 955         value 
= Spin()->GetValue(); 
 956         changed 
= value 
!= m_valueOld
; 
 958             text 
= wxString::Format(wxT("%ld"), value
); 
 963         text 
= Text()->GetValue(); 
 964         changed 
= (text
.empty() || text
.ToLong(&value
)) && (value 
!= m_valueOld
); 
 969         if (grid
->GetTable()->CanSetValueAs(row
, col
, wxGRID_VALUE_NUMBER
)) 
 970             grid
->GetTable()->SetValueAsLong(row
, col
, value
); 
 972             grid
->GetTable()->SetValue(row
, col
, text
); 
 978 void wxGridCellNumberEditor::Reset() 
 983         Spin()->SetValue((int)m_valueOld
); 
 988         DoReset(GetString()); 
 992 bool wxGridCellNumberEditor::IsAcceptedKey(wxKeyEvent
& event
) 
 994     if ( wxGridCellEditor::IsAcceptedKey(event
) ) 
 996         int keycode 
= event
.GetKeyCode(); 
 997         if ( (keycode 
< 128) && 
 998              (wxIsdigit(keycode
) || keycode 
== '+' || keycode 
== '-')) 
1007 void wxGridCellNumberEditor::StartingKey(wxKeyEvent
& event
) 
1009     int keycode 
= event
.GetKeyCode(); 
1012         if ( wxIsdigit(keycode
) || keycode 
== '+' || keycode 
== '-') 
1014             wxGridCellTextEditor::StartingKey(event
); 
1016             // skip Skip() below 
1023         if ( wxIsdigit(keycode
) ) 
1025             wxSpinCtrl
* spin 
= (wxSpinCtrl
*)m_control
; 
1026             spin
->SetValue(keycode 
- '0'); 
1027             spin
->SetSelection(1,1); 
1036 void wxGridCellNumberEditor::SetParameters(const wxString
& params
) 
1047         if ( params
.BeforeFirst(_T(',')).ToLong(&tmp
) ) 
1051             if ( params
.AfterFirst(_T(',')).ToLong(&tmp
) ) 
1055                 // skip the error message below 
1060         wxLogDebug(_T("Invalid wxGridCellNumberEditor parameter string '%s' ignored"), params
.c_str()); 
1064 // return the value in the spin control if it is there (the text control otherwise) 
1065 wxString 
wxGridCellNumberEditor::GetValue() const 
1072         long value 
= Spin()->GetValue(); 
1073         s
.Printf(wxT("%ld"), value
); 
1078         s 
= Text()->GetValue(); 
1084 // ---------------------------------------------------------------------------- 
1085 // wxGridCellFloatEditor 
1086 // ---------------------------------------------------------------------------- 
1088 wxGridCellFloatEditor::wxGridCellFloatEditor(int width
, int precision
) 
1091     m_precision 
= precision
; 
1094 void wxGridCellFloatEditor::Create(wxWindow
* parent
, 
1096                                    wxEvtHandler
* evtHandler
) 
1098     wxGridCellTextEditor::Create(parent
, id
, evtHandler
); 
1100 #if wxUSE_VALIDATORS 
1101     Text()->SetValidator(wxTextValidator(wxFILTER_NUMERIC
)); 
1105 void wxGridCellFloatEditor::BeginEdit(int row
, int col
, wxGrid
* grid
) 
1107     // first get the value 
1108     wxGridTableBase 
*table 
= grid
->GetTable(); 
1109     if ( table
->CanGetValueAs(row
, col
, wxGRID_VALUE_FLOAT
) ) 
1111         m_valueOld 
= table
->GetValueAsDouble(row
, col
); 
1116         wxString sValue 
= table
->GetValue(row
, col
); 
1117         if (! sValue
.ToDouble(&m_valueOld
) && ! sValue
.empty()) 
1119             wxFAIL_MSG( _T("this cell doesn't have float value") ); 
1124     DoBeginEdit(GetString()); 
1127 bool wxGridCellFloatEditor::EndEdit(int row
, int col
, 
1131     wxString 
text(Text()->GetValue()); 
1133     if ( (text
.empty() || text
.ToDouble(&value
)) && 
1134             !wxIsSameDouble(value
, m_valueOld
) ) 
1136         if (grid
->GetTable()->CanSetValueAs(row
, col
, wxGRID_VALUE_FLOAT
)) 
1137             grid
->GetTable()->SetValueAsDouble(row
, col
, value
); 
1139             grid
->GetTable()->SetValue(row
, col
, text
); 
1147 void wxGridCellFloatEditor::Reset() 
1149     DoReset(GetString()); 
1152 void wxGridCellFloatEditor::StartingKey(wxKeyEvent
& event
) 
1154     int keycode 
= event
.GetKeyCode(); 
1156     tmpbuf
[0] = (char) keycode
; 
1158     wxString 
strbuf(tmpbuf
, *wxConvCurrent
); 
1161     bool is_decimal_point 
= ( strbuf 
== 
1162        wxLocale::GetInfo(wxLOCALE_DECIMAL_POINT
, wxLOCALE_CAT_NUMBER
) ); 
1164     bool is_decimal_point 
= ( strbuf 
== _T(".") ); 
1167     if ( wxIsdigit(keycode
) || keycode 
== '+' || keycode 
== '-' 
1168          || is_decimal_point 
) 
1170         wxGridCellTextEditor::StartingKey(event
); 
1172         // skip Skip() below 
1179 void wxGridCellFloatEditor::SetParameters(const wxString
& params
) 
1190         if ( params
.BeforeFirst(_T(',')).ToLong(&tmp
) ) 
1194             if ( params
.AfterFirst(_T(',')).ToLong(&tmp
) ) 
1196                 m_precision 
= (int)tmp
; 
1198                 // skip the error message below 
1203         wxLogDebug(_T("Invalid wxGridCellFloatEditor parameter string '%s' ignored"), params
.c_str()); 
1207 wxString 
wxGridCellFloatEditor::GetString() const 
1210     if ( m_precision 
== -1 && m_width 
!= -1) 
1212         // default precision 
1213         fmt
.Printf(_T("%%%d.f"), m_width
); 
1215     else if ( m_precision 
!= -1 && m_width 
== -1) 
1218         fmt
.Printf(_T("%%.%df"), m_precision
); 
1220     else if ( m_precision 
!= -1 && m_width 
!= -1 ) 
1222         fmt
.Printf(_T("%%%d.%df"), m_width
, m_precision
); 
1226         // default width/precision 
1230     return wxString::Format(fmt
, m_valueOld
); 
1233 bool wxGridCellFloatEditor::IsAcceptedKey(wxKeyEvent
& event
) 
1235     if ( wxGridCellEditor::IsAcceptedKey(event
) ) 
1237         const int keycode 
= event
.GetKeyCode(); 
1238         if ( isascii(keycode
) ) 
1241             tmpbuf
[0] = (char) keycode
; 
1243             wxString 
strbuf(tmpbuf
, *wxConvCurrent
); 
1246             const wxString decimalPoint 
= 
1247                 wxLocale::GetInfo(wxLOCALE_DECIMAL_POINT
, wxLOCALE_CAT_NUMBER
); 
1249             const wxString 
decimalPoint(_T('.')); 
1252             // accept digits, 'e' as in '1e+6', also '-', '+', and '.' 
1253             if ( wxIsdigit(keycode
) || 
1254                     tolower(keycode
) == 'e' || 
1255                         keycode 
== decimalPoint 
|| 
1267 #endif // wxUSE_TEXTCTRL 
1271 // ---------------------------------------------------------------------------- 
1272 // wxGridCellBoolEditor 
1273 // ---------------------------------------------------------------------------- 
1275 // the default values for GetValue() 
1276 wxString 
wxGridCellBoolEditor::ms_stringValues
[2] = { _T(""), _T("1") }; 
1278 void wxGridCellBoolEditor::Create(wxWindow
* parent
, 
1280                                   wxEvtHandler
* evtHandler
) 
1282     m_control 
= new wxCheckBox(parent
, id
, wxEmptyString
, 
1283                                wxDefaultPosition
, wxDefaultSize
, 
1286     wxGridCellEditor::Create(parent
, id
, evtHandler
); 
1289 void wxGridCellBoolEditor::SetSize(const wxRect
& r
) 
1291     bool resize 
= false; 
1292     wxSize size 
= m_control
->GetSize(); 
1293     wxCoord minSize 
= wxMin(r
.width
, r
.height
); 
1295     // check if the checkbox is not too big/small for this cell 
1296     wxSize sizeBest 
= m_control
->GetBestSize(); 
1297     if ( !(size 
== sizeBest
) ) 
1299         // reset to default size if it had been made smaller 
1305     if ( size
.x 
>= minSize 
|| size
.y 
>= minSize 
) 
1307         // leave 1 pixel margin 
1308         size
.x 
= size
.y 
= minSize 
- 2; 
1315         m_control
->SetSize(size
); 
1318     // position it in the centre of the rectangle (TODO: support alignment?) 
1320 #if defined(__WXGTK__) || defined (__WXMOTIF__) 
1321     // the checkbox without label still has some space to the right in wxGTK, 
1322     // so shift it to the right 
1324 #elif defined(__WXMSW__) 
1325     // here too, but in other way 
1330     int hAlign 
= wxALIGN_CENTRE
; 
1331     int vAlign 
= wxALIGN_CENTRE
; 
1333         GetCellAttr()->GetAlignment(& hAlign
, & vAlign
); 
1336     if (hAlign 
== wxALIGN_LEFT
) 
1344         y 
= r
.y 
+ r
.height 
/ 2 - size
.y 
/ 2; 
1346     else if (hAlign 
== wxALIGN_RIGHT
) 
1348         x 
= r
.x 
+ r
.width 
- size
.x 
- 2; 
1349         y 
= r
.y 
+ r
.height 
/ 2 - size
.y 
/ 2; 
1351     else if (hAlign 
== wxALIGN_CENTRE
) 
1353         x 
= r
.x 
+ r
.width 
/ 2 - size
.x 
/ 2; 
1354         y 
= r
.y 
+ r
.height 
/ 2 - size
.y 
/ 2; 
1357     m_control
->Move(x
, y
); 
1360 void wxGridCellBoolEditor::Show(bool show
, wxGridCellAttr 
*attr
) 
1362     m_control
->Show(show
); 
1366         wxColour colBg 
= attr 
? attr
->GetBackgroundColour() : *wxLIGHT_GREY
; 
1367         CBox()->SetBackgroundColour(colBg
); 
1371 void wxGridCellBoolEditor::BeginEdit(int row
, int col
, wxGrid
* grid
) 
1373     wxASSERT_MSG(m_control
, 
1374                  wxT("The wxGridCellEditor must be created first!")); 
1376     if (grid
->GetTable()->CanGetValueAs(row
, col
, wxGRID_VALUE_BOOL
)) 
1378         m_startValue 
= grid
->GetTable()->GetValueAsBool(row
, col
); 
1382         wxString 
cellval( grid
->GetTable()->GetValue(row
, col
) ); 
1384         if ( cellval 
== ms_stringValues
[false] ) 
1385             m_startValue 
= false; 
1386         else if ( cellval 
== ms_stringValues
[true] ) 
1387             m_startValue 
= true; 
1390             // do not try to be smart here and convert it to true or false 
1391             // because we'll still overwrite it with something different and 
1392             // this risks to be very surprising for the user code, let them 
1394             wxFAIL_MSG( _T("invalid value for a cell with bool editor!") ); 
1398     CBox()->SetValue(m_startValue
); 
1402 bool wxGridCellBoolEditor::EndEdit(int row
, int col
, 
1405     wxASSERT_MSG(m_control
, 
1406                  wxT("The wxGridCellEditor must be created first!")); 
1408     bool changed 
= false; 
1409     bool value 
= CBox()->GetValue(); 
1410     if ( value 
!= m_startValue 
) 
1415         wxGridTableBase 
* const table 
= grid
->GetTable(); 
1416         if ( table
->CanGetValueAs(row
, col
, wxGRID_VALUE_BOOL
) ) 
1417             table
->SetValueAsBool(row
, col
, value
); 
1419             table
->SetValue(row
, col
, GetValue()); 
1425 void wxGridCellBoolEditor::Reset() 
1427     wxASSERT_MSG(m_control
, 
1428                  wxT("The wxGridCellEditor must be created first!")); 
1430     CBox()->SetValue(m_startValue
); 
1433 void wxGridCellBoolEditor::StartingClick() 
1435     CBox()->SetValue(!CBox()->GetValue()); 
1438 bool wxGridCellBoolEditor::IsAcceptedKey(wxKeyEvent
& event
) 
1440     if ( wxGridCellEditor::IsAcceptedKey(event
) ) 
1442         int keycode 
= event
.GetKeyCode(); 
1455 void wxGridCellBoolEditor::StartingKey(wxKeyEvent
& event
) 
1457     int keycode 
= event
.GetKeyCode(); 
1461             CBox()->SetValue(!CBox()->GetValue()); 
1465             CBox()->SetValue(true); 
1469             CBox()->SetValue(false); 
1474 wxString 
wxGridCellBoolEditor::GetValue() const 
1476   return ms_stringValues
[CBox()->GetValue()]; 
1480 wxGridCellBoolEditor::UseStringValues(const wxString
& valueTrue
, 
1481                                       const wxString
& valueFalse
) 
1483     ms_stringValues
[false] = valueFalse
; 
1484     ms_stringValues
[true] = valueTrue
; 
1488 wxGridCellBoolEditor::IsTrueValue(const wxString
& value
) 
1490     return value 
== ms_stringValues
[true]; 
1493 #endif // wxUSE_CHECKBOX 
1497 // ---------------------------------------------------------------------------- 
1498 // wxGridCellChoiceEditor 
1499 // ---------------------------------------------------------------------------- 
1501 wxGridCellChoiceEditor::wxGridCellChoiceEditor(const wxArrayString
& choices
, 
1503     : m_choices(choices
), 
1504       m_allowOthers(allowOthers
) { } 
1506 wxGridCellChoiceEditor::wxGridCellChoiceEditor(size_t count
, 
1507                                                const wxString choices
[], 
1509                       : m_allowOthers(allowOthers
) 
1513         m_choices
.Alloc(count
); 
1514         for ( size_t n 
= 0; n 
< count
; n
++ ) 
1516             m_choices
.Add(choices
[n
]); 
1521 wxGridCellEditor 
*wxGridCellChoiceEditor::Clone() const 
1523     wxGridCellChoiceEditor 
*editor 
= new wxGridCellChoiceEditor
; 
1524     editor
->m_allowOthers 
= m_allowOthers
; 
1525     editor
->m_choices 
= m_choices
; 
1530 void wxGridCellChoiceEditor::Create(wxWindow
* parent
, 
1532                                     wxEvtHandler
* evtHandler
) 
1534     int style 
= wxTE_PROCESS_ENTER 
| 
1538     if ( !m_allowOthers 
) 
1539         style 
|= wxCB_READONLY
; 
1540     m_control 
= new wxComboBox(parent
, id
, wxEmptyString
, 
1541                                wxDefaultPosition
, wxDefaultSize
, 
1545     wxGridCellEditor::Create(parent
, id
, evtHandler
); 
1548 void wxGridCellChoiceEditor::PaintBackground(const wxRect
& rectCell
, 
1549                                              wxGridCellAttr 
* attr
) 
1551     // as we fill the entire client area, don't do anything here to minimize 
1554     // TODO: It doesn't actually fill the client area since the height of a 
1555     // combo always defaults to the standard.  Until someone has time to 
1556     // figure out the right rectangle to paint, just do it the normal way. 
1557     wxGridCellEditor::PaintBackground(rectCell
, attr
); 
1560 void wxGridCellChoiceEditor::BeginEdit(int row
, int col
, wxGrid
* grid
) 
1562     wxASSERT_MSG(m_control
, 
1563                  wxT("The wxGridCellEditor must be created first!")); 
1565     wxGridCellEditorEvtHandler
* evtHandler 
= NULL
; 
1567         evtHandler 
= wxDynamicCast(m_control
->GetEventHandler(), wxGridCellEditorEvtHandler
); 
1569     // Don't immediately end if we get a kill focus event within BeginEdit 
1571         evtHandler
->SetInSetFocus(true); 
1573     m_startValue 
= grid
->GetTable()->GetValue(row
, col
); 
1577         Combo()->SetValue(m_startValue
); 
1578         Combo()->SetInsertionPointEnd(); 
1580     else // the combobox is read-only 
1582         // find the right position, or default to the first if not found 
1583         int pos 
= Combo()->FindString(m_startValue
); 
1584         if (pos 
== wxNOT_FOUND
) 
1586         Combo()->SetSelection(pos
); 
1589     Combo()->SetFocus(); 
1593         // When dropping down the menu, a kill focus event 
1594         // happens after this point, so we can't reset the flag yet. 
1595 #if !defined(__WXGTK20__) 
1596         evtHandler
->SetInSetFocus(false); 
1601 bool wxGridCellChoiceEditor::EndEdit(int row
, int col
, 
1604     wxString value 
= Combo()->GetValue(); 
1605     if ( value 
== m_startValue 
) 
1608     grid
->GetTable()->SetValue(row
, col
, value
); 
1613 void wxGridCellChoiceEditor::Reset() 
1615     Combo()->SetValue(m_startValue
); 
1616     Combo()->SetInsertionPointEnd(); 
1619 void wxGridCellChoiceEditor::SetParameters(const wxString
& params
) 
1629     wxStringTokenizer 
tk(params
, _T(',')); 
1630     while ( tk
.HasMoreTokens() ) 
1632         m_choices
.Add(tk
.GetNextToken()); 
1636 // return the value in the text control 
1637 wxString 
wxGridCellChoiceEditor::GetValue() const 
1639   return Combo()->GetValue(); 
1642 #endif // wxUSE_COMBOBOX 
1644 // ---------------------------------------------------------------------------- 
1645 // wxGridCellEditorEvtHandler 
1646 // ---------------------------------------------------------------------------- 
1648 void wxGridCellEditorEvtHandler::OnKillFocus(wxFocusEvent
& event
) 
1650     // Don't disable the cell if we're just starting to edit it 
1655     m_grid
->DisableCellEditControl(); 
1660 void wxGridCellEditorEvtHandler::OnKeyDown(wxKeyEvent
& event
) 
1662     switch ( event
.GetKeyCode() ) 
1666             m_grid
->DisableCellEditControl(); 
1670             m_grid
->GetEventHandler()->ProcessEvent( event 
); 
1674         case WXK_NUMPAD_ENTER
: 
1675             if (!m_grid
->GetEventHandler()->ProcessEvent(event
)) 
1676                 m_editor
->HandleReturn(event
); 
1685 void wxGridCellEditorEvtHandler::OnChar(wxKeyEvent
& event
) 
1687     int row 
= m_grid
->GetGridCursorRow(); 
1688     int col 
= m_grid
->GetGridCursorCol(); 
1689     wxRect rect 
= m_grid
->CellToRect( row
, col 
); 
1691     m_grid
->GetGridWindow()->GetClientSize( &cw
, &ch 
); 
1693     // if cell width is smaller than grid client area, cell is wholly visible 
1694     bool wholeCellVisible 
= (rect
.GetWidth() < cw
); 
1696     switch ( event
.GetKeyCode() ) 
1701         case WXK_NUMPAD_ENTER
: 
1706             if ( wholeCellVisible 
) 
1708                 // no special processing needed... 
1713             // do special processing for partly visible cell... 
1715             // get the widths of all cells previous to this one 
1717             for ( int i 
= 0; i 
< col
; i
++ ) 
1719                 colXPos 
+= m_grid
->GetColSize(i
); 
1722             int xUnit 
= 1, yUnit 
= 1; 
1723             m_grid
->GetScrollPixelsPerUnit(&xUnit
, &yUnit
); 
1726                 m_grid
->Scroll(colXPos 
/ xUnit 
- 1, m_grid
->GetScrollPos(wxVERTICAL
)); 
1730                 m_grid
->Scroll(colXPos 
/ xUnit
, m_grid
->GetScrollPos(wxVERTICAL
)); 
1738             if ( wholeCellVisible 
) 
1740                 // no special processing needed... 
1745             // do special processing for partly visible cell... 
1748             wxString value 
= m_grid
->GetCellValue(row
, col
); 
1749             if ( wxEmptyString 
!= value 
) 
1751                 // get width of cell CONTENTS (text) 
1753                 wxFont font 
= m_grid
->GetCellFont(row
, col
); 
1754                 m_grid
->GetTextExtent(value
, &textWidth
, &y
, NULL
, NULL
, &font
); 
1756                 // try to RIGHT align the text by scrolling 
1757                 int client_right 
= m_grid
->GetGridWindow()->GetClientSize().GetWidth(); 
1759                 // (m_grid->GetScrollLineX()*2) is a factor for not scrolling to far, 
1760                 // otherwise the last part of the cell content might be hidden below the scroll bar 
1761                 // FIXME: maybe there is a more suitable correction? 
1762                 textWidth 
-= (client_right 
- (m_grid
->GetScrollLineX() * 2)); 
1763                 if ( textWidth 
< 0 ) 
1769             // get the widths of all cells previous to this one 
1771             for ( int i 
= 0; i 
< col
; i
++ ) 
1773                 colXPos 
+= m_grid
->GetColSize(i
); 
1776             // and add the (modified) text width of the cell contents 
1777             // as we'd like to see the last part of the cell contents 
1778             colXPos 
+= textWidth
; 
1780             int xUnit 
= 1, yUnit 
= 1; 
1781             m_grid
->GetScrollPixelsPerUnit(&xUnit
, &yUnit
); 
1782             m_grid
->Scroll(colXPos 
/ xUnit 
- 1, m_grid
->GetScrollPos(wxVERTICAL
)); 
1793 // ---------------------------------------------------------------------------- 
1794 // wxGridCellWorker is an (almost) empty common base class for 
1795 // wxGridCellRenderer and wxGridCellEditor managing ref counting 
1796 // ---------------------------------------------------------------------------- 
1798 void wxGridCellWorker::SetParameters(const wxString
& WXUNUSED(params
)) 
1803 wxGridCellWorker::~wxGridCellWorker() 
1807 // ============================================================================ 
1809 // ============================================================================ 
1811 // ---------------------------------------------------------------------------- 
1812 // wxGridCellRenderer 
1813 // ---------------------------------------------------------------------------- 
1815 void wxGridCellRenderer::Draw(wxGrid
& grid
, 
1816                               wxGridCellAttr
& attr
, 
1819                               int WXUNUSED(row
), int WXUNUSED(col
), 
1822     dc
.SetBackgroundMode( wxBRUSHSTYLE_SOLID 
); 
1824     // grey out fields if the grid is disabled 
1825     if ( grid
.IsEnabled() ) 
1830             if ( grid
.HasFocus() ) 
1831                 clr 
= grid
.GetSelectionBackground(); 
1833                 clr 
= wxSystemSettings::GetColour(wxSYS_COLOUR_BTNSHADOW
); 
1834             dc
.SetBrush( wxBrush(clr
, wxBRUSHSTYLE_SOLID
) ); 
1838             dc
.SetBrush( wxBrush(attr
.GetBackgroundColour(), wxBRUSHSTYLE_SOLID
) ); 
1843         dc
.SetBrush(wxBrush(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE
), wxBRUSHSTYLE_SOLID
)); 
1846     dc
.SetPen( *wxTRANSPARENT_PEN 
); 
1847     dc
.DrawRectangle(rect
); 
1850 // ---------------------------------------------------------------------------- 
1851 // wxGridCellStringRenderer 
1852 // ---------------------------------------------------------------------------- 
1854 void wxGridCellStringRenderer::SetTextColoursAndFont(const wxGrid
& grid
, 
1855                                                      const wxGridCellAttr
& attr
, 
1859     dc
.SetBackgroundMode( wxBRUSHSTYLE_TRANSPARENT 
); 
1861     // TODO some special colours for attr.IsReadOnly() case? 
1863     // different coloured text when the grid is disabled 
1864     if ( grid
.IsEnabled() ) 
1869             if ( grid
.HasFocus() ) 
1870                 clr 
= grid
.GetSelectionBackground(); 
1872                 clr 
= wxSystemSettings::GetColour(wxSYS_COLOUR_BTNSHADOW
); 
1873             dc
.SetTextBackground( clr 
); 
1874             dc
.SetTextForeground( grid
.GetSelectionForeground() ); 
1878             dc
.SetTextBackground( attr
.GetBackgroundColour() ); 
1879             dc
.SetTextForeground( attr
.GetTextColour() ); 
1884         dc
.SetTextBackground(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE
)); 
1885         dc
.SetTextForeground(wxSystemSettings::GetColour(wxSYS_COLOUR_GRAYTEXT
)); 
1888     dc
.SetFont( attr
.GetFont() ); 
1891 wxSize 
wxGridCellStringRenderer::DoGetBestSize(const wxGridCellAttr
& attr
, 
1893                                                const wxString
& text
) 
1895     wxCoord x 
= 0, y 
= 0, max_x 
= 0; 
1896     dc
.SetFont(attr
.GetFont()); 
1897     wxStringTokenizer 
tk(text
, _T('\n')); 
1898     while ( tk
.HasMoreTokens() ) 
1900         dc
.GetTextExtent(tk
.GetNextToken(), &x
, &y
); 
1901         max_x 
= wxMax(max_x
, x
); 
1904     y 
*= 1 + text
.Freq(wxT('\n')); // multiply by the number of lines. 
1906     return wxSize(max_x
, y
); 
1909 wxSize 
wxGridCellStringRenderer::GetBestSize(wxGrid
& grid
, 
1910                                              wxGridCellAttr
& attr
, 
1914     return DoGetBestSize(attr
, dc
, grid
.GetCellValue(row
, col
)); 
1917 void wxGridCellStringRenderer::Draw(wxGrid
& grid
, 
1918                                     wxGridCellAttr
& attr
, 
1920                                     const wxRect
& rectCell
, 
1924     wxRect rect 
= rectCell
; 
1927     // erase only this cells background, overflow cells should have been erased 
1928     wxGridCellRenderer::Draw(grid
, attr
, dc
, rectCell
, row
, col
, isSelected
); 
1931     attr
.GetAlignment(&hAlign
, &vAlign
); 
1933     int overflowCols 
= 0; 
1935     if (attr
.GetOverflow()) 
1937         int cols 
= grid
.GetNumberCols(); 
1938         int best_width 
= GetBestSize(grid
,attr
,dc
,row
,col
).GetWidth(); 
1939         int cell_rows
, cell_cols
; 
1940         attr
.GetSize( &cell_rows
, &cell_cols 
); // shouldn't get here if <= 0 
1941         if ((best_width 
> rectCell
.width
) && (col 
< cols
) && grid
.GetTable()) 
1943             int i
, c_cols
, c_rows
; 
1944             for (i 
= col
+cell_cols
; i 
< cols
; i
++) 
1946                 bool is_empty 
= true; 
1947                 for (int j
=row
; j 
< row 
+ cell_rows
; j
++) 
1949                     // check w/ anchor cell for multicell block 
1950                     grid
.GetCellSize(j
, i
, &c_rows
, &c_cols
); 
1953                     if (!grid
.GetTable()->IsEmptyCell(j 
+ c_rows
, i
)) 
1962                     rect
.width 
+= grid
.GetColSize(i
); 
1970                 if (rect
.width 
>= best_width
) 
1974             overflowCols 
= i 
- col 
- cell_cols 
+ 1; 
1975             if (overflowCols 
>= cols
) 
1976                 overflowCols 
= cols 
- 1; 
1979         if (overflowCols 
> 0) // redraw overflow cells w/ proper hilight 
1981             hAlign 
= wxALIGN_LEFT
; // if oveflowed then it's left aligned 
1983             clip
.x 
+= rectCell
.width
; 
1984             // draw each overflow cell individually 
1985             int col_end 
= col 
+ cell_cols 
+ overflowCols
; 
1986             if (col_end 
>= grid
.GetNumberCols()) 
1987                 col_end 
= grid
.GetNumberCols() - 1; 
1988             for (int i 
= col 
+ cell_cols
; i 
<= col_end
; i
++) 
1990                 clip
.width 
= grid
.GetColSize(i
) - 1; 
1991                 dc
.DestroyClippingRegion(); 
1992                 dc
.SetClippingRegion(clip
); 
1994                 SetTextColoursAndFont(grid
, attr
, dc
, 
1995                         grid
.IsInSelection(row
,i
)); 
1997                 grid
.DrawTextRectangle(dc
, grid
.GetCellValue(row
, col
), 
1998                         rect
, hAlign
, vAlign
); 
1999                 clip
.x 
+= grid
.GetColSize(i
) - 1; 
2005             dc
.DestroyClippingRegion(); 
2009     // now we only have to draw the text 
2010     SetTextColoursAndFont(grid
, attr
, dc
, isSelected
); 
2012     grid
.DrawTextRectangle(dc
, grid
.GetCellValue(row
, col
), 
2013                            rect
, hAlign
, vAlign
); 
2016 // ---------------------------------------------------------------------------- 
2017 // wxGridCellNumberRenderer 
2018 // ---------------------------------------------------------------------------- 
2020 wxString 
wxGridCellNumberRenderer::GetString(const wxGrid
& grid
, int row
, int col
) 
2022     wxGridTableBase 
*table 
= grid
.GetTable(); 
2024     if ( table
->CanGetValueAs(row
, col
, wxGRID_VALUE_NUMBER
) ) 
2026         text
.Printf(_T("%ld"), table
->GetValueAsLong(row
, col
)); 
2030         text 
= table
->GetValue(row
, col
); 
2036 void wxGridCellNumberRenderer::Draw(wxGrid
& grid
, 
2037                                     wxGridCellAttr
& attr
, 
2039                                     const wxRect
& rectCell
, 
2043     wxGridCellRenderer::Draw(grid
, attr
, dc
, rectCell
, row
, col
, isSelected
); 
2045     SetTextColoursAndFont(grid
, attr
, dc
, isSelected
); 
2047     // draw the text right aligned by default 
2049     attr
.GetAlignment(&hAlign
, &vAlign
); 
2050     hAlign 
= wxALIGN_RIGHT
; 
2052     wxRect rect 
= rectCell
; 
2055     grid
.DrawTextRectangle(dc
, GetString(grid
, row
, col
), rect
, hAlign
, vAlign
); 
2058 wxSize 
wxGridCellNumberRenderer::GetBestSize(wxGrid
& grid
, 
2059                                              wxGridCellAttr
& attr
, 
2063     return DoGetBestSize(attr
, dc
, GetString(grid
, row
, col
)); 
2066 // ---------------------------------------------------------------------------- 
2067 // wxGridCellFloatRenderer 
2068 // ---------------------------------------------------------------------------- 
2070 wxGridCellFloatRenderer::wxGridCellFloatRenderer(int width
, int precision
) 
2073     SetPrecision(precision
); 
2076 wxGridCellRenderer 
*wxGridCellFloatRenderer::Clone() const 
2078     wxGridCellFloatRenderer 
*renderer 
= new wxGridCellFloatRenderer
; 
2079     renderer
->m_width 
= m_width
; 
2080     renderer
->m_precision 
= m_precision
; 
2081     renderer
->m_format 
= m_format
; 
2086 wxString 
wxGridCellFloatRenderer::GetString(const wxGrid
& grid
, int row
, int col
) 
2088     wxGridTableBase 
*table 
= grid
.GetTable(); 
2093     if ( table
->CanGetValueAs(row
, col
, wxGRID_VALUE_FLOAT
) ) 
2095         val 
= table
->GetValueAsDouble(row
, col
); 
2100         text 
= table
->GetValue(row
, col
); 
2101         hasDouble 
= text
.ToDouble(&val
); 
2108             if ( m_width 
== -1 ) 
2110                 if ( m_precision 
== -1 ) 
2112                     // default width/precision 
2113                     m_format 
= _T("%f"); 
2117                     m_format
.Printf(_T("%%.%df"), m_precision
); 
2120             else if ( m_precision 
== -1 ) 
2122                 // default precision 
2123                 m_format
.Printf(_T("%%%d.f"), m_width
); 
2127                 m_format
.Printf(_T("%%%d.%df"), m_width
, m_precision
); 
2131         text
.Printf(m_format
, val
); 
2134     //else: text already contains the string 
2139 void wxGridCellFloatRenderer::Draw(wxGrid
& grid
, 
2140                                    wxGridCellAttr
& attr
, 
2142                                    const wxRect
& rectCell
, 
2146     wxGridCellRenderer::Draw(grid
, attr
, dc
, rectCell
, row
, col
, isSelected
); 
2148     SetTextColoursAndFont(grid
, attr
, dc
, isSelected
); 
2150     // draw the text right aligned by default 
2152     attr
.GetAlignment(&hAlign
, &vAlign
); 
2153     hAlign 
= wxALIGN_RIGHT
; 
2155     wxRect rect 
= rectCell
; 
2158     grid
.DrawTextRectangle(dc
, GetString(grid
, row
, col
), rect
, hAlign
, vAlign
); 
2161 wxSize 
wxGridCellFloatRenderer::GetBestSize(wxGrid
& grid
, 
2162                                             wxGridCellAttr
& attr
, 
2166     return DoGetBestSize(attr
, dc
, GetString(grid
, row
, col
)); 
2169 void wxGridCellFloatRenderer::SetParameters(const wxString
& params
) 
2173         // reset to defaults 
2179         wxString tmp 
= params
.BeforeFirst(_T(',')); 
2183             if ( tmp
.ToLong(&width
) ) 
2185                 SetWidth((int)width
); 
2189                 wxLogDebug(_T("Invalid wxGridCellFloatRenderer width parameter string '%s ignored"), params
.c_str()); 
2193         tmp 
= params
.AfterFirst(_T(',')); 
2197             if ( tmp
.ToLong(&precision
) ) 
2199                 SetPrecision((int)precision
); 
2203                 wxLogDebug(_T("Invalid wxGridCellFloatRenderer precision parameter string '%s ignored"), params
.c_str()); 
2209 // ---------------------------------------------------------------------------- 
2210 // wxGridCellBoolRenderer 
2211 // ---------------------------------------------------------------------------- 
2213 wxSize 
wxGridCellBoolRenderer::ms_sizeCheckMark
; 
2215 // FIXME these checkbox size calculations are really ugly... 
2217 // between checkmark and box 
2218 static const wxCoord wxGRID_CHECKMARK_MARGIN 
= 2; 
2220 wxSize 
wxGridCellBoolRenderer::GetBestSize(wxGrid
& grid
, 
2221                                            wxGridCellAttr
& WXUNUSED(attr
), 
2226     // compute it only once (no locks for MT safeness in GUI thread...) 
2227     if ( !ms_sizeCheckMark
.x 
) 
2229         // get checkbox size 
2230         wxCheckBox 
*checkbox 
= new wxCheckBox(&grid
, wxID_ANY
, wxEmptyString
); 
2231         wxSize size 
= checkbox
->GetBestSize(); 
2232         wxCoord checkSize 
= size
.y 
+ 2 * wxGRID_CHECKMARK_MARGIN
; 
2234 #if defined(__WXMOTIF__) 
2235         checkSize 
-= size
.y 
/ 2; 
2240         ms_sizeCheckMark
.x 
= ms_sizeCheckMark
.y 
= checkSize
; 
2243     return ms_sizeCheckMark
; 
2246 void wxGridCellBoolRenderer::Draw(wxGrid
& grid
, 
2247                                   wxGridCellAttr
& attr
, 
2253     wxGridCellRenderer::Draw(grid
, attr
, dc
, rect
, row
, col
, isSelected
); 
2255     // draw a check mark in the centre (ignoring alignment - TODO) 
2256     wxSize size 
= GetBestSize(grid
, attr
, dc
, row
, col
); 
2258     // don't draw outside the cell 
2259     wxCoord minSize 
= wxMin(rect
.width
, rect
.height
); 
2260     if ( size
.x 
>= minSize 
|| size
.y 
>= minSize 
) 
2262         // and even leave (at least) 1 pixel margin 
2263         size
.x 
= size
.y 
= minSize
; 
2266     // draw a border around checkmark 
2268     attr
.GetAlignment(&hAlign
, &vAlign
); 
2271     if (hAlign 
== wxALIGN_CENTRE
) 
2273         rectBorder
.x 
= rect
.x 
+ rect
.width 
/ 2 - size
.x 
/ 2; 
2274         rectBorder
.y 
= rect
.y 
+ rect
.height 
/ 2 - size
.y 
/ 2; 
2275         rectBorder
.width 
= size
.x
; 
2276         rectBorder
.height 
= size
.y
; 
2278     else if (hAlign 
== wxALIGN_LEFT
) 
2280         rectBorder
.x 
= rect
.x 
+ 2; 
2281         rectBorder
.y 
= rect
.y 
+ rect
.height 
/ 2 - size
.y 
/ 2; 
2282         rectBorder
.width 
= size
.x
; 
2283         rectBorder
.height 
= size
.y
; 
2285     else if (hAlign 
== wxALIGN_RIGHT
) 
2287         rectBorder
.x 
= rect
.x 
+ rect
.width 
- size
.x 
- 2; 
2288         rectBorder
.y 
= rect
.y 
+ rect
.height 
/ 2 - size
.y 
/ 2; 
2289         rectBorder
.width 
= size
.x
; 
2290         rectBorder
.height 
= size
.y
; 
2294     if ( grid
.GetTable()->CanGetValueAs(row
, col
, wxGRID_VALUE_BOOL
) ) 
2296         value 
= grid
.GetTable()->GetValueAsBool(row
, col
); 
2300         wxString 
cellval( grid
.GetTable()->GetValue(row
, col
) ); 
2301         value 
= wxGridCellBoolEditor::IsTrueValue(cellval
); 
2306         flags 
|= wxCONTROL_CHECKED
; 
2308     wxRendererNative::Get().DrawCheckBox( &grid
, dc
, rectBorder
, flags 
); 
2311 // ---------------------------------------------------------------------------- 
2313 // ---------------------------------------------------------------------------- 
2315 void wxGridCellAttr::Init(wxGridCellAttr 
*attrDefault
) 
2319     m_isReadOnly 
= Unset
; 
2324     m_attrkind 
= wxGridCellAttr::Cell
; 
2326     m_sizeRows 
= m_sizeCols 
= 1; 
2327     m_overflow 
= UnsetOverflow
; 
2329     SetDefAttr(attrDefault
); 
2332 wxGridCellAttr 
*wxGridCellAttr::Clone() const 
2334     wxGridCellAttr 
*attr 
= new wxGridCellAttr(m_defGridAttr
); 
2336     if ( HasTextColour() ) 
2337         attr
->SetTextColour(GetTextColour()); 
2338     if ( HasBackgroundColour() ) 
2339         attr
->SetBackgroundColour(GetBackgroundColour()); 
2341         attr
->SetFont(GetFont()); 
2342     if ( HasAlignment() ) 
2343         attr
->SetAlignment(m_hAlign
, m_vAlign
); 
2345     attr
->SetSize( m_sizeRows
, m_sizeCols 
); 
2349         attr
->SetRenderer(m_renderer
); 
2350         m_renderer
->IncRef(); 
2354         attr
->SetEditor(m_editor
); 
2359         attr
->SetReadOnly(); 
2361     attr
->SetOverflow( m_overflow 
== Overflow 
); 
2362     attr
->SetKind( m_attrkind 
); 
2367 void wxGridCellAttr::MergeWith(wxGridCellAttr 
*mergefrom
) 
2369     if ( !HasTextColour() && mergefrom
->HasTextColour() ) 
2370         SetTextColour(mergefrom
->GetTextColour()); 
2371     if ( !HasBackgroundColour() && mergefrom
->HasBackgroundColour() ) 
2372         SetBackgroundColour(mergefrom
->GetBackgroundColour()); 
2373     if ( !HasFont() && mergefrom
->HasFont() ) 
2374         SetFont(mergefrom
->GetFont()); 
2375     if ( !HasAlignment() && mergefrom
->HasAlignment() ) 
2378         mergefrom
->GetAlignment( &hAlign
, &vAlign
); 
2379         SetAlignment(hAlign
, vAlign
); 
2381     if ( !HasSize() && mergefrom
->HasSize() ) 
2382         mergefrom
->GetSize( &m_sizeRows
, &m_sizeCols 
); 
2384     // Directly access member functions as GetRender/Editor don't just return 
2385     // m_renderer/m_editor 
2387     // Maybe add support for merge of Render and Editor? 
2388     if (!HasRenderer() && mergefrom
->HasRenderer() ) 
2390         m_renderer 
= mergefrom
->m_renderer
; 
2391         m_renderer
->IncRef(); 
2393     if ( !HasEditor() && mergefrom
->HasEditor() ) 
2395         m_editor 
=  mergefrom
->m_editor
; 
2398     if ( !HasReadWriteMode() && mergefrom
->HasReadWriteMode() ) 
2399         SetReadOnly(mergefrom
->IsReadOnly()); 
2401     if (!HasOverflowMode() && mergefrom
->HasOverflowMode() ) 
2402         SetOverflow(mergefrom
->GetOverflow()); 
2404     SetDefAttr(mergefrom
->m_defGridAttr
); 
2407 void wxGridCellAttr::SetSize(int num_rows
, int num_cols
) 
2409     // The size of a cell is normally 1,1 
2411     // If this cell is larger (2,2) then this is the top left cell 
2412     // the other cells that will be covered (lower right cells) must be 
2413     // set to negative or zero values such that 
2414     // row + num_rows of the covered cell points to the larger cell (this cell) 
2415     // same goes for the col + num_cols. 
2417     // Size of 0,0 is NOT valid, neither is <=0 and any positive value 
2419     wxASSERT_MSG( (!((num_rows 
> 0) && (num_cols 
<= 0)) || 
2420                   !((num_rows 
<= 0) && (num_cols 
> 0)) || 
2421                   !((num_rows 
== 0) && (num_cols 
== 0))), 
2422                   wxT("wxGridCellAttr::SetSize only takes two postive values or negative/zero values")); 
2424     m_sizeRows 
= num_rows
; 
2425     m_sizeCols 
= num_cols
; 
2428 const wxColour
& wxGridCellAttr::GetTextColour() const 
2430     if (HasTextColour()) 
2434     else if (m_defGridAttr 
&& m_defGridAttr 
!= this) 
2436         return m_defGridAttr
->GetTextColour(); 
2440         wxFAIL_MSG(wxT("Missing default cell attribute")); 
2441         return wxNullColour
; 
2445 const wxColour
& wxGridCellAttr::GetBackgroundColour() const 
2447     if (HasBackgroundColour()) 
2451     else if (m_defGridAttr 
&& m_defGridAttr 
!= this) 
2453         return m_defGridAttr
->GetBackgroundColour(); 
2457         wxFAIL_MSG(wxT("Missing default cell attribute")); 
2458         return wxNullColour
; 
2462 const wxFont
& wxGridCellAttr::GetFont() const 
2468     else if (m_defGridAttr 
&& m_defGridAttr 
!= this) 
2470         return m_defGridAttr
->GetFont(); 
2474         wxFAIL_MSG(wxT("Missing default cell attribute")); 
2479 void wxGridCellAttr::GetAlignment(int *hAlign
, int *vAlign
) const 
2488     else if (m_defGridAttr 
&& m_defGridAttr 
!= this) 
2490         m_defGridAttr
->GetAlignment(hAlign
, vAlign
); 
2494         wxFAIL_MSG(wxT("Missing default cell attribute")); 
2498 void wxGridCellAttr::GetSize( int *num_rows
, int *num_cols 
) const 
2501         *num_rows 
= m_sizeRows
; 
2503         *num_cols 
= m_sizeCols
; 
2506 // GetRenderer and GetEditor use a slightly different decision path about 
2507 // which attribute to use.  If a non-default attr object has one then it is 
2508 // used, otherwise the default editor or renderer is fetched from the grid and 
2509 // used.  It should be the default for the data type of the cell.  If it is 
2510 // NULL (because the table has a type that the grid does not have in its 
2511 // registry), then the grid's default editor or renderer is used. 
2513 wxGridCellRenderer
* wxGridCellAttr::GetRenderer(const wxGrid
* grid
, int row
, int col
) const 
2515     wxGridCellRenderer 
*renderer 
= NULL
; 
2517     if ( m_renderer 
&& this != m_defGridAttr 
) 
2519         // use the cells renderer if it has one 
2520         renderer 
= m_renderer
; 
2523     else // no non-default cell renderer 
2525         // get default renderer for the data type 
2528             // GetDefaultRendererForCell() will do IncRef() for us 
2529             renderer 
= grid
->GetDefaultRendererForCell(row
, col
); 
2532         if ( renderer 
== NULL 
) 
2534             if ( (m_defGridAttr 
!= NULL
) && (m_defGridAttr 
!= this) ) 
2536                 // if we still don't have one then use the grid default 
2537                 // (no need for IncRef() here neither) 
2538                 renderer 
= m_defGridAttr
->GetRenderer(NULL
, 0, 0); 
2540             else // default grid attr 
2542                 // use m_renderer which we had decided not to use initially 
2543                 renderer 
= m_renderer
; 
2550     // we're supposed to always find something 
2551     wxASSERT_MSG(renderer
, wxT("Missing default cell renderer")); 
2556 // same as above, except for s/renderer/editor/g 
2557 wxGridCellEditor
* wxGridCellAttr::GetEditor(const wxGrid
* grid
, int row
, int col
) const 
2559     wxGridCellEditor 
*editor 
= NULL
; 
2561     if ( m_editor 
&& this != m_defGridAttr 
) 
2563         // use the cells editor if it has one 
2567     else // no non default cell editor 
2569         // get default editor for the data type 
2572             // GetDefaultEditorForCell() will do IncRef() for us 
2573             editor 
= grid
->GetDefaultEditorForCell(row
, col
); 
2576         if ( editor 
== NULL 
) 
2578             if ( (m_defGridAttr 
!= NULL
) && (m_defGridAttr 
!= this) ) 
2580                 // if we still don't have one then use the grid default 
2581                 // (no need for IncRef() here neither) 
2582                 editor 
= m_defGridAttr
->GetEditor(NULL
, 0, 0); 
2584             else // default grid attr 
2586                 // use m_editor which we had decided not to use initially 
2594     // we're supposed to always find something 
2595     wxASSERT_MSG(editor
, wxT("Missing default cell editor")); 
2600 // ---------------------------------------------------------------------------- 
2601 // wxGridCellAttrData 
2602 // ---------------------------------------------------------------------------- 
2604 void wxGridCellAttrData::SetAttr(wxGridCellAttr 
*attr
, int row
, int col
) 
2606     int n 
= FindIndex(row
, col
); 
2607     if ( n 
== wxNOT_FOUND 
) 
2611             // add the attribute 
2612             m_attrs
.Add(new wxGridCellWithAttr(row
, col
, attr
)); 
2614         //else: nothing to do 
2616     else // we already have an attribute for this cell 
2620             // change the attribute 
2621             m_attrs
[(size_t)n
].attr 
= attr
; 
2625             // remove this attribute 
2626             m_attrs
.RemoveAt((size_t)n
); 
2631 wxGridCellAttr 
*wxGridCellAttrData::GetAttr(int row
, int col
) const 
2633     wxGridCellAttr 
*attr 
= (wxGridCellAttr 
*)NULL
; 
2635     int n 
= FindIndex(row
, col
); 
2636     if ( n 
!= wxNOT_FOUND 
) 
2638         attr 
= m_attrs
[(size_t)n
].attr
; 
2645 void wxGridCellAttrData::UpdateAttrRows( size_t pos
, int numRows 
) 
2647     size_t count 
= m_attrs
.GetCount(); 
2648     for ( size_t n 
= 0; n 
< count
; n
++ ) 
2650         wxGridCellCoords
& coords 
= m_attrs
[n
].coords
; 
2651         wxCoord row 
= coords
.GetRow(); 
2652         if ((size_t)row 
>= pos
) 
2656                 // If rows inserted, include row counter where necessary 
2657                 coords
.SetRow(row 
+ numRows
); 
2659             else if (numRows 
< 0) 
2661                 // If rows deleted ... 
2662                 if ((size_t)row 
>= pos 
- numRows
) 
2664                     // ...either decrement row counter (if row still exists)... 
2665                     coords
.SetRow(row 
+ numRows
); 
2669                     // ...or remove the attribute 
2670                     m_attrs
.RemoveAt(n
); 
2679 void wxGridCellAttrData::UpdateAttrCols( size_t pos
, int numCols 
) 
2681     size_t count 
= m_attrs
.GetCount(); 
2682     for ( size_t n 
= 0; n 
< count
; n
++ ) 
2684         wxGridCellCoords
& coords 
= m_attrs
[n
].coords
; 
2685         wxCoord col 
= coords
.GetCol(); 
2686         if ( (size_t)col 
>= pos 
) 
2690                 // If rows inserted, include row counter where necessary 
2691                 coords
.SetCol(col 
+ numCols
); 
2693             else if (numCols 
< 0) 
2695                 // If rows deleted ... 
2696                 if ((size_t)col 
>= pos 
- numCols
) 
2698                     // ...either decrement row counter (if row still exists)... 
2699                     coords
.SetCol(col 
+ numCols
); 
2703                     // ...or remove the attribute 
2704                     m_attrs
.RemoveAt(n
); 
2713 int wxGridCellAttrData::FindIndex(int row
, int col
) const 
2715     size_t count 
= m_attrs
.GetCount(); 
2716     for ( size_t n 
= 0; n 
< count
; n
++ ) 
2718         const wxGridCellCoords
& coords 
= m_attrs
[n
].coords
; 
2719         if ( (coords
.GetRow() == row
) && (coords
.GetCol() == col
) ) 
2728 // ---------------------------------------------------------------------------- 
2729 // wxGridRowOrColAttrData 
2730 // ---------------------------------------------------------------------------- 
2732 wxGridRowOrColAttrData::~wxGridRowOrColAttrData() 
2734     size_t count 
= m_attrs
.GetCount(); 
2735     for ( size_t n 
= 0; n 
< count
; n
++ ) 
2737         m_attrs
[n
]->DecRef(); 
2741 wxGridCellAttr 
*wxGridRowOrColAttrData::GetAttr(int rowOrCol
) const 
2743     wxGridCellAttr 
*attr 
= (wxGridCellAttr 
*)NULL
; 
2745     int n 
= m_rowsOrCols
.Index(rowOrCol
); 
2746     if ( n 
!= wxNOT_FOUND 
) 
2748         attr 
= m_attrs
[(size_t)n
]; 
2755 void wxGridRowOrColAttrData::SetAttr(wxGridCellAttr 
*attr
, int rowOrCol
) 
2757     int i 
= m_rowsOrCols
.Index(rowOrCol
); 
2758     if ( i 
== wxNOT_FOUND 
) 
2762             // add the attribute 
2763             m_rowsOrCols
.Add(rowOrCol
); 
2766         // nothing to remove 
2770         size_t n 
= (size_t)i
; 
2771         if ( m_attrs
[n
] == attr 
) 
2776             // change the attribute 
2777             m_attrs
[n
]->DecRef(); 
2782             // remove this attribute 
2783             m_attrs
[n
]->DecRef(); 
2784             m_rowsOrCols
.RemoveAt(n
); 
2785             m_attrs
.RemoveAt(n
); 
2790 void wxGridRowOrColAttrData::UpdateAttrRowsOrCols( size_t pos
, int numRowsOrCols 
) 
2792     size_t count 
= m_attrs
.GetCount(); 
2793     for ( size_t n 
= 0; n 
< count
; n
++ ) 
2795         int & rowOrCol 
= m_rowsOrCols
[n
]; 
2796         if ( (size_t)rowOrCol 
>= pos 
) 
2798             if ( numRowsOrCols 
> 0 ) 
2800                 // If rows inserted, include row counter where necessary 
2801                 rowOrCol 
+= numRowsOrCols
; 
2803             else if ( numRowsOrCols 
< 0) 
2805                 // If rows deleted, either decrement row counter (if row still exists) 
2806                 if ((size_t)rowOrCol 
>= pos 
- numRowsOrCols
) 
2807                     rowOrCol 
+= numRowsOrCols
; 
2810                     m_rowsOrCols
.RemoveAt(n
); 
2811                     m_attrs
[n
]->DecRef(); 
2812                     m_attrs
.RemoveAt(n
); 
2821 // ---------------------------------------------------------------------------- 
2822 // wxGridCellAttrProvider 
2823 // ---------------------------------------------------------------------------- 
2825 wxGridCellAttrProvider::wxGridCellAttrProvider() 
2827     m_data 
= (wxGridCellAttrProviderData 
*)NULL
; 
2830 wxGridCellAttrProvider::~wxGridCellAttrProvider() 
2835 void wxGridCellAttrProvider::InitData() 
2837     m_data 
= new wxGridCellAttrProviderData
; 
2840 wxGridCellAttr 
*wxGridCellAttrProvider::GetAttr(int row
, int col
, 
2841                                                 wxGridCellAttr::wxAttrKind  kind 
) const 
2843     wxGridCellAttr 
*attr 
= (wxGridCellAttr 
*)NULL
; 
2848             case (wxGridCellAttr::Any
): 
2849                 // Get cached merge attributes. 
2850                 // Currently not used as no cache implemented as not mutable 
2851                 // attr = m_data->m_mergeAttr.GetAttr(row, col); 
2854                     // Basically implement old version. 
2855                     // Also check merge cache, so we don't have to re-merge every time.. 
2856                     wxGridCellAttr 
*attrcell 
= m_data
->m_cellAttrs
.GetAttr(row
, col
); 
2857                     wxGridCellAttr 
*attrrow 
= m_data
->m_rowAttrs
.GetAttr(row
); 
2858                     wxGridCellAttr 
*attrcol 
= m_data
->m_colAttrs
.GetAttr(col
); 
2860                     if ((attrcell 
!= attrrow
) && (attrrow 
!= attrcol
) && (attrcell 
!= attrcol
)) 
2862                         // Two or more are non NULL 
2863                         attr 
= new wxGridCellAttr
; 
2864                         attr
->SetKind(wxGridCellAttr::Merged
); 
2866                         // Order is important.. 
2869                             attr
->MergeWith(attrcell
); 
2874                             attr
->MergeWith(attrcol
); 
2879                             attr
->MergeWith(attrrow
); 
2883                         // store merge attr if cache implemented 
2885                         //m_data->m_mergeAttr.SetAttr(attr, row, col); 
2889                         // one or none is non null return it or null. 
2908             case (wxGridCellAttr::Cell
): 
2909                 attr 
= m_data
->m_cellAttrs
.GetAttr(row
, col
); 
2912             case (wxGridCellAttr::Col
): 
2913                 attr 
= m_data
->m_colAttrs
.GetAttr(col
); 
2916             case (wxGridCellAttr::Row
): 
2917                 attr 
= m_data
->m_rowAttrs
.GetAttr(row
); 
2922                 // (wxGridCellAttr::Default): 
2923                 // (wxGridCellAttr::Merged): 
2931 void wxGridCellAttrProvider::SetAttr(wxGridCellAttr 
*attr
, 
2937     m_data
->m_cellAttrs
.SetAttr(attr
, row
, col
); 
2940 void wxGridCellAttrProvider::SetRowAttr(wxGridCellAttr 
*attr
, int row
) 
2945     m_data
->m_rowAttrs
.SetAttr(attr
, row
); 
2948 void wxGridCellAttrProvider::SetColAttr(wxGridCellAttr 
*attr
, int col
) 
2953     m_data
->m_colAttrs
.SetAttr(attr
, col
); 
2956 void wxGridCellAttrProvider::UpdateAttrRows( size_t pos
, int numRows 
) 
2960         m_data
->m_cellAttrs
.UpdateAttrRows( pos
, numRows 
); 
2962         m_data
->m_rowAttrs
.UpdateAttrRowsOrCols( pos
, numRows 
); 
2966 void wxGridCellAttrProvider::UpdateAttrCols( size_t pos
, int numCols 
) 
2970         m_data
->m_cellAttrs
.UpdateAttrCols( pos
, numCols 
); 
2972         m_data
->m_colAttrs
.UpdateAttrRowsOrCols( pos
, numCols 
); 
2976 // ---------------------------------------------------------------------------- 
2977 // wxGridTypeRegistry 
2978 // ---------------------------------------------------------------------------- 
2980 wxGridTypeRegistry::~wxGridTypeRegistry() 
2982     size_t count 
= m_typeinfo
.GetCount(); 
2983     for ( size_t i 
= 0; i 
< count
; i
++ ) 
2984         delete m_typeinfo
[i
]; 
2987 void wxGridTypeRegistry::RegisterDataType(const wxString
& typeName
, 
2988                                           wxGridCellRenderer
* renderer
, 
2989                                           wxGridCellEditor
* editor
) 
2991     wxGridDataTypeInfo
* info 
= new wxGridDataTypeInfo(typeName
, renderer
, editor
); 
2993     // is it already registered? 
2994     int loc 
= FindRegisteredDataType(typeName
); 
2995     if ( loc 
!= wxNOT_FOUND 
) 
2997         delete m_typeinfo
[loc
]; 
2998         m_typeinfo
[loc
] = info
; 
3002         m_typeinfo
.Add(info
); 
3006 int wxGridTypeRegistry::FindRegisteredDataType(const wxString
& typeName
) 
3008     size_t count 
= m_typeinfo
.GetCount(); 
3009     for ( size_t i 
= 0; i 
< count
; i
++ ) 
3011         if ( typeName 
== m_typeinfo
[i
]->m_typeName 
) 
3020 int wxGridTypeRegistry::FindDataType(const wxString
& typeName
) 
3022     int index 
= FindRegisteredDataType(typeName
); 
3023     if ( index 
== wxNOT_FOUND 
) 
3025         // check whether this is one of the standard ones, in which case 
3026         // register it "on the fly" 
3028         if ( typeName 
== wxGRID_VALUE_STRING 
) 
3030             RegisterDataType(wxGRID_VALUE_STRING
, 
3031                              new wxGridCellStringRenderer
, 
3032                              new wxGridCellTextEditor
); 
3035 #endif // wxUSE_TEXTCTRL 
3037         if ( typeName 
== wxGRID_VALUE_BOOL 
) 
3039             RegisterDataType(wxGRID_VALUE_BOOL
, 
3040                              new wxGridCellBoolRenderer
, 
3041                              new wxGridCellBoolEditor
); 
3044 #endif // wxUSE_CHECKBOX 
3046         if ( typeName 
== wxGRID_VALUE_NUMBER 
) 
3048             RegisterDataType(wxGRID_VALUE_NUMBER
, 
3049                              new wxGridCellNumberRenderer
, 
3050                              new wxGridCellNumberEditor
); 
3052         else if ( typeName 
== wxGRID_VALUE_FLOAT 
) 
3054             RegisterDataType(wxGRID_VALUE_FLOAT
, 
3055                              new wxGridCellFloatRenderer
, 
3056                              new wxGridCellFloatEditor
); 
3059 #endif // wxUSE_TEXTCTRL 
3061         if ( typeName 
== wxGRID_VALUE_CHOICE 
) 
3063             RegisterDataType(wxGRID_VALUE_CHOICE
, 
3064                              new wxGridCellStringRenderer
, 
3065                              new wxGridCellChoiceEditor
); 
3068 #endif // wxUSE_COMBOBOX 
3073         // we get here only if just added the entry for this type, so return 
3075         index 
= m_typeinfo
.GetCount() - 1; 
3081 int wxGridTypeRegistry::FindOrCloneDataType(const wxString
& typeName
) 
3083     int index 
= FindDataType(typeName
); 
3084     if ( index 
== wxNOT_FOUND 
) 
3086         // the first part of the typename is the "real" type, anything after ':' 
3087         // are the parameters for the renderer 
3088         index 
= FindDataType(typeName
.BeforeFirst(_T(':'))); 
3089         if ( index 
== wxNOT_FOUND 
) 
3094         wxGridCellRenderer 
*renderer 
= GetRenderer(index
); 
3095         wxGridCellRenderer 
*rendererOld 
= renderer
; 
3096         renderer 
= renderer
->Clone(); 
3097         rendererOld
->DecRef(); 
3099         wxGridCellEditor 
*editor 
= GetEditor(index
); 
3100         wxGridCellEditor 
*editorOld 
= editor
; 
3101         editor 
= editor
->Clone(); 
3102         editorOld
->DecRef(); 
3104         // do it even if there are no parameters to reset them to defaults 
3105         wxString params 
= typeName
.AfterFirst(_T(':')); 
3106         renderer
->SetParameters(params
); 
3107         editor
->SetParameters(params
); 
3109         // register the new typename 
3110         RegisterDataType(typeName
, renderer
, editor
); 
3112         // we just registered it, it's the last one 
3113         index 
= m_typeinfo
.GetCount() - 1; 
3119 wxGridCellRenderer
* wxGridTypeRegistry::GetRenderer(int index
) 
3121     wxGridCellRenderer
* renderer 
= m_typeinfo
[index
]->m_renderer
; 
3128 wxGridCellEditor
* wxGridTypeRegistry::GetEditor(int index
) 
3130     wxGridCellEditor
* editor 
= m_typeinfo
[index
]->m_editor
; 
3137 // ---------------------------------------------------------------------------- 
3139 // ---------------------------------------------------------------------------- 
3141 IMPLEMENT_ABSTRACT_CLASS( wxGridTableBase
, wxObject 
) 
3143 wxGridTableBase::wxGridTableBase() 
3145     m_view 
= (wxGrid 
*) NULL
; 
3146     m_attrProvider 
= (wxGridCellAttrProvider 
*) NULL
; 
3149 wxGridTableBase::~wxGridTableBase() 
3151     delete m_attrProvider
; 
3154 void wxGridTableBase::SetAttrProvider(wxGridCellAttrProvider 
*attrProvider
) 
3156     delete m_attrProvider
; 
3157     m_attrProvider 
= attrProvider
; 
3160 bool wxGridTableBase::CanHaveAttributes() 
3162     if ( ! GetAttrProvider() ) 
3164         // use the default attr provider by default 
3165         SetAttrProvider(new wxGridCellAttrProvider
); 
3171 wxGridCellAttr 
*wxGridTableBase::GetAttr(int row
, int col
, wxGridCellAttr::wxAttrKind  kind
) 
3173     if ( m_attrProvider 
) 
3174         return m_attrProvider
->GetAttr(row
, col
, kind
); 
3176         return (wxGridCellAttr 
*)NULL
; 
3179 void wxGridTableBase::SetAttr(wxGridCellAttr
* attr
, int row
, int col
) 
3181     if ( m_attrProvider 
) 
3184             attr
->SetKind(wxGridCellAttr::Cell
); 
3185         m_attrProvider
->SetAttr(attr
, row
, col
); 
3189         // as we take ownership of the pointer and don't store it, we must 
3195 void wxGridTableBase::SetRowAttr(wxGridCellAttr 
*attr
, int row
) 
3197     if ( m_attrProvider 
) 
3199         attr
->SetKind(wxGridCellAttr::Row
); 
3200         m_attrProvider
->SetRowAttr(attr
, row
); 
3204         // as we take ownership of the pointer and don't store it, we must 
3210 void wxGridTableBase::SetColAttr(wxGridCellAttr 
*attr
, int col
) 
3212     if ( m_attrProvider 
) 
3214         attr
->SetKind(wxGridCellAttr::Col
); 
3215         m_attrProvider
->SetColAttr(attr
, col
); 
3219         // as we take ownership of the pointer and don't store it, we must 
3225 bool wxGridTableBase::InsertRows( size_t WXUNUSED(pos
), 
3226                                   size_t WXUNUSED(numRows
) ) 
3228     wxFAIL_MSG( wxT("Called grid table class function InsertRows\nbut your derived table class does not override this function") ); 
3233 bool wxGridTableBase::AppendRows( size_t WXUNUSED(numRows
) ) 
3235     wxFAIL_MSG( wxT("Called grid table class function AppendRows\nbut your derived table class does not override this function")); 
3240 bool wxGridTableBase::DeleteRows( size_t WXUNUSED(pos
), 
3241                                   size_t WXUNUSED(numRows
) ) 
3243     wxFAIL_MSG( wxT("Called grid table class function DeleteRows\nbut your derived table class does not override this function")); 
3248 bool wxGridTableBase::InsertCols( size_t WXUNUSED(pos
), 
3249                                   size_t WXUNUSED(numCols
) ) 
3251     wxFAIL_MSG( wxT("Called grid table class function InsertCols\nbut your derived table class does not override this function")); 
3256 bool wxGridTableBase::AppendCols( size_t WXUNUSED(numCols
) ) 
3258     wxFAIL_MSG(wxT("Called grid table class function AppendCols\nbut your derived table class does not override this function")); 
3263 bool wxGridTableBase::DeleteCols( size_t WXUNUSED(pos
), 
3264                                   size_t WXUNUSED(numCols
) ) 
3266     wxFAIL_MSG( wxT("Called grid table class function DeleteCols\nbut your derived table class does not override this function")); 
3271 wxString 
wxGridTableBase::GetRowLabelValue( int row 
) 
3275     // RD: Starting the rows at zero confuses users, 
3276     // no matter how much it makes sense to us geeks. 
3282 wxString 
wxGridTableBase::GetColLabelValue( int col 
) 
3284     // default col labels are: 
3285     //   cols 0 to 25   : A-Z 
3286     //   cols 26 to 675 : AA-ZZ 
3291     for ( n 
= 1; ; n
++ ) 
3293         s 
+= (wxChar
) (_T('A') + (wxChar
)(col 
% 26)); 
3299     // reverse the string... 
3301     for ( i 
= 0; i 
< n
; i
++ ) 
3309 wxString 
wxGridTableBase::GetTypeName( int WXUNUSED(row
), int WXUNUSED(col
) ) 
3311     return wxGRID_VALUE_STRING
; 
3314 bool wxGridTableBase::CanGetValueAs( int WXUNUSED(row
), int WXUNUSED(col
), 
3315                                      const wxString
& typeName 
) 
3317     return typeName 
== wxGRID_VALUE_STRING
; 
3320 bool wxGridTableBase::CanSetValueAs( int row
, int col
, const wxString
& typeName 
) 
3322     return CanGetValueAs(row
, col
, typeName
); 
3325 long wxGridTableBase::GetValueAsLong( int WXUNUSED(row
), int WXUNUSED(col
) ) 
3330 double wxGridTableBase::GetValueAsDouble( int WXUNUSED(row
), int WXUNUSED(col
) ) 
3335 bool wxGridTableBase::GetValueAsBool( int WXUNUSED(row
), int WXUNUSED(col
) ) 
3340 void wxGridTableBase::SetValueAsLong( int WXUNUSED(row
), int WXUNUSED(col
), 
3341                                       long WXUNUSED(value
) ) 
3345 void wxGridTableBase::SetValueAsDouble( int WXUNUSED(row
), int WXUNUSED(col
), 
3346                                         double WXUNUSED(value
) ) 
3350 void wxGridTableBase::SetValueAsBool( int WXUNUSED(row
), int WXUNUSED(col
), 
3351                                       bool WXUNUSED(value
) ) 
3355 void* wxGridTableBase::GetValueAsCustom( int WXUNUSED(row
), int WXUNUSED(col
), 
3356                                          const wxString
& WXUNUSED(typeName
) ) 
3361 void  wxGridTableBase::SetValueAsCustom( int WXUNUSED(row
), int WXUNUSED(col
), 
3362                                          const wxString
& WXUNUSED(typeName
), 
3363                                          void* WXUNUSED(value
) ) 
3367 ////////////////////////////////////////////////////////////////////// 
3369 // Message class for the grid table to send requests and notifications 
3373 wxGridTableMessage::wxGridTableMessage() 
3375     m_table 
= (wxGridTableBase 
*) NULL
; 
3381 wxGridTableMessage::wxGridTableMessage( wxGridTableBase 
*table
, int id
, 
3382                                         int commandInt1
, int commandInt2 
) 
3386     m_comInt1 
= commandInt1
; 
3387     m_comInt2 
= commandInt2
; 
3390 ////////////////////////////////////////////////////////////////////// 
3392 // A basic grid table for string data. An object of this class will 
3393 // created by wxGrid if you don't specify an alternative table class. 
3396 WX_DEFINE_OBJARRAY(wxGridStringArray
) 
3398 IMPLEMENT_DYNAMIC_CLASS( wxGridStringTable
, wxGridTableBase 
) 
3400 wxGridStringTable::wxGridStringTable() 
3405 wxGridStringTable::wxGridStringTable( int numRows
, int numCols 
) 
3408     m_data
.Alloc( numRows 
); 
3411     sa
.Alloc( numCols 
); 
3412     sa
.Add( wxEmptyString
, numCols 
); 
3414     m_data
.Add( sa
, numRows 
); 
3417 wxGridStringTable::~wxGridStringTable() 
3421 int wxGridStringTable::GetNumberRows() 
3423     return m_data
.GetCount(); 
3426 int wxGridStringTable::GetNumberCols() 
3428     if ( m_data
.GetCount() > 0 ) 
3429         return m_data
[0].GetCount(); 
3434 wxString 
wxGridStringTable::GetValue( int row
, int col 
) 
3436     wxCHECK_MSG( (row 
< GetNumberRows()) && (col 
< GetNumberCols()), 
3438                  _T("invalid row or column index in wxGridStringTable") ); 
3440     return m_data
[row
][col
]; 
3443 void wxGridStringTable::SetValue( int row
, int col
, const wxString
& value 
) 
3445     wxCHECK_RET( (row 
< GetNumberRows()) && (col 
< GetNumberCols()), 
3446                  _T("invalid row or column index in wxGridStringTable") ); 
3448     m_data
[row
][col
] = value
; 
3451 bool wxGridStringTable::IsEmptyCell( int row
, int col 
) 
3453     wxCHECK_MSG( (row 
< GetNumberRows()) && (col 
< GetNumberCols()), 
3455                   _T("invalid row or column index in wxGridStringTable") ); 
3457     return (m_data
[row
][col
] == wxEmptyString
); 
3460 void wxGridStringTable::Clear() 
3463     int numRows
, numCols
; 
3465     numRows 
= m_data
.GetCount(); 
3468         numCols 
= m_data
[0].GetCount(); 
3470         for ( row 
= 0; row 
< numRows
; row
++ ) 
3472             for ( col 
= 0; col 
< numCols
; col
++ ) 
3474                 m_data
[row
][col
] = wxEmptyString
; 
3480 bool wxGridStringTable::InsertRows( size_t pos
, size_t numRows 
) 
3482     size_t curNumRows 
= m_data
.GetCount(); 
3483     size_t curNumCols 
= ( curNumRows 
> 0 ? m_data
[0].GetCount() : 
3484                           ( GetView() ? GetView()->GetNumberCols() : 0 ) ); 
3486     if ( pos 
>= curNumRows 
) 
3488         return AppendRows( numRows 
); 
3492     sa
.Alloc( curNumCols 
); 
3493     sa
.Add( wxEmptyString
, curNumCols 
); 
3494     m_data
.Insert( sa
, pos
, numRows 
); 
3498         wxGridTableMessage 
msg( this, 
3499                                 wxGRIDTABLE_NOTIFY_ROWS_INSERTED
, 
3503         GetView()->ProcessTableMessage( msg 
); 
3509 bool wxGridStringTable::AppendRows( size_t numRows 
) 
3511     size_t curNumRows 
= m_data
.GetCount(); 
3512     size_t curNumCols 
= ( curNumRows 
> 0 
3513                          ? m_data
[0].GetCount() 
3514                          : ( GetView() ? GetView()->GetNumberCols() : 0 ) ); 
3517     if ( curNumCols 
> 0 ) 
3519         sa
.Alloc( curNumCols 
); 
3520         sa
.Add( wxEmptyString
, curNumCols 
); 
3523     m_data
.Add( sa
, numRows 
); 
3527         wxGridTableMessage 
msg( this, 
3528                                 wxGRIDTABLE_NOTIFY_ROWS_APPENDED
, 
3531         GetView()->ProcessTableMessage( msg 
); 
3537 bool wxGridStringTable::DeleteRows( size_t pos
, size_t numRows 
) 
3539     size_t curNumRows 
= m_data
.GetCount(); 
3541     if ( pos 
>= curNumRows 
) 
3543         wxFAIL_MSG( wxString::Format
 
3545                         wxT("Called wxGridStringTable::DeleteRows(pos=%lu, N=%lu)\nPos value is invalid for present table with %lu rows"), 
3547                         (unsigned long)numRows
, 
3548                         (unsigned long)curNumRows
 
3554     if ( numRows 
> curNumRows 
- pos 
) 
3556         numRows 
= curNumRows 
- pos
; 
3559     if ( numRows 
>= curNumRows 
) 
3565         m_data
.RemoveAt( pos
, numRows 
); 
3570         wxGridTableMessage 
msg( this, 
3571                                 wxGRIDTABLE_NOTIFY_ROWS_DELETED
, 
3575         GetView()->ProcessTableMessage( msg 
); 
3581 bool wxGridStringTable::InsertCols( size_t pos
, size_t numCols 
) 
3585     size_t curNumRows 
= m_data
.GetCount(); 
3586     size_t curNumCols 
= ( curNumRows 
> 0 
3587                          ? m_data
[0].GetCount() 
3588                          : ( GetView() ? GetView()->GetNumberCols() : 0 ) ); 
3590     if ( pos 
>= curNumCols 
) 
3592         return AppendCols( numCols 
); 
3595     if ( !m_colLabels
.IsEmpty() ) 
3597         m_colLabels
.Insert( wxEmptyString
, pos
, numCols 
); 
3600         for ( i 
= pos
; i 
< pos 
+ numCols
; i
++ ) 
3601             m_colLabels
[i
] = wxGridTableBase::GetColLabelValue( i 
); 
3604     for ( row 
= 0; row 
< curNumRows
; row
++ ) 
3606         for ( col 
= pos
; col 
< pos 
+ numCols
; col
++ ) 
3608             m_data
[row
].Insert( wxEmptyString
, col 
); 
3614         wxGridTableMessage 
msg( this, 
3615                                 wxGRIDTABLE_NOTIFY_COLS_INSERTED
, 
3619         GetView()->ProcessTableMessage( msg 
); 
3625 bool wxGridStringTable::AppendCols( size_t numCols 
) 
3629     size_t curNumRows 
= m_data
.GetCount(); 
3634         // TODO: something better than this ? 
3636         wxFAIL_MSG( wxT("Unable to append cols to a grid table with no rows.\nCall AppendRows() first") ); 
3641     for ( row 
= 0; row 
< curNumRows
; row
++ ) 
3643         m_data
[row
].Add( wxEmptyString
, numCols 
); 
3648         wxGridTableMessage 
msg( this, 
3649                                 wxGRIDTABLE_NOTIFY_COLS_APPENDED
, 
3652         GetView()->ProcessTableMessage( msg 
); 
3658 bool wxGridStringTable::DeleteCols( size_t pos
, size_t numCols 
) 
3662     size_t curNumRows 
= m_data
.GetCount(); 
3663     size_t curNumCols 
= ( curNumRows 
> 0 ? m_data
[0].GetCount() : 
3664                           ( GetView() ? GetView()->GetNumberCols() : 0 ) ); 
3666     if ( pos 
>= curNumCols 
) 
3668         wxFAIL_MSG( wxString::Format
 
3670                         wxT("Called wxGridStringTable::DeleteCols(pos=%lu, N=%lu)\nPos value is invalid for present table with %lu cols"), 
3672                         (unsigned long)numCols
, 
3673                         (unsigned long)curNumCols
 
3680         colID 
= GetView()->GetColAt( pos 
); 
3684     if ( numCols 
> curNumCols 
- colID 
) 
3686         numCols 
= curNumCols 
- colID
; 
3689     if ( !m_colLabels
.IsEmpty() ) 
3691         // m_colLabels stores just as many elements as it needs, e.g. if only 
3692         // the label of the first column had been set it would have only one 
3693         // element and not numCols, so account for it 
3694         int nToRm 
= m_colLabels
.size() - colID
; 
3696             m_colLabels
.RemoveAt( colID
, nToRm 
); 
3699     for ( row 
= 0; row 
< curNumRows
; row
++ ) 
3701         if ( numCols 
>= curNumCols 
) 
3703             m_data
[row
].Clear(); 
3707             m_data
[row
].RemoveAt( colID
, numCols 
); 
3713         wxGridTableMessage 
msg( this, 
3714                                 wxGRIDTABLE_NOTIFY_COLS_DELETED
, 
3718         GetView()->ProcessTableMessage( msg 
); 
3724 wxString 
wxGridStringTable::GetRowLabelValue( int row 
) 
3726     if ( row 
> (int)(m_rowLabels
.GetCount()) - 1 ) 
3728         // using default label 
3730         return wxGridTableBase::GetRowLabelValue( row 
); 
3734         return m_rowLabels
[row
]; 
3738 wxString 
wxGridStringTable::GetColLabelValue( int col 
) 
3740     if ( col 
> (int)(m_colLabels
.GetCount()) - 1 ) 
3742         // using default label 
3744         return wxGridTableBase::GetColLabelValue( col 
); 
3748         return m_colLabels
[col
]; 
3752 void wxGridStringTable::SetRowLabelValue( int row
, const wxString
& value 
) 
3754     if ( row 
> (int)(m_rowLabels
.GetCount()) - 1 ) 
3756         int n 
= m_rowLabels
.GetCount(); 
3759         for ( i 
= n
; i 
<= row
; i
++ ) 
3761             m_rowLabels
.Add( wxGridTableBase::GetRowLabelValue(i
) ); 
3765     m_rowLabels
[row
] = value
; 
3768 void wxGridStringTable::SetColLabelValue( int col
, const wxString
& value 
) 
3770     if ( col 
> (int)(m_colLabels
.GetCount()) - 1 ) 
3772         int n 
= m_colLabels
.GetCount(); 
3775         for ( i 
= n
; i 
<= col
; i
++ ) 
3777             m_colLabels
.Add( wxGridTableBase::GetColLabelValue(i
) ); 
3781     m_colLabels
[col
] = value
; 
3785 ////////////////////////////////////////////////////////////////////// 
3786 ////////////////////////////////////////////////////////////////////// 
3788 BEGIN_EVENT_TABLE(wxGridSubwindow
, wxWindow
) 
3789     EVT_MOUSE_CAPTURE_LOST(wxGridSubwindow::OnMouseCaptureLost
) 
3792 void wxGridSubwindow::OnMouseCaptureLost(wxMouseCaptureLostEvent
& WXUNUSED(event
)) 
3794     m_owner
->CancelMouseCapture(); 
3797 IMPLEMENT_DYNAMIC_CLASS( wxGridRowLabelWindow
, wxWindow 
) 
3799 BEGIN_EVENT_TABLE( wxGridRowLabelWindow
, wxGridSubwindow 
) 
3800     EVT_PAINT( wxGridRowLabelWindow::OnPaint 
) 
3801     EVT_MOUSEWHEEL( wxGridRowLabelWindow::OnMouseWheel 
) 
3802     EVT_MOUSE_EVENTS( wxGridRowLabelWindow::OnMouseEvent 
) 
3805 wxGridRowLabelWindow::wxGridRowLabelWindow( wxGrid 
*parent
, 
3807                                             const wxPoint 
&pos
, const wxSize 
&size 
) 
3808   : wxGridSubwindow(parent
, id
, pos
, size
) 
3813 void wxGridRowLabelWindow::OnPaint( wxPaintEvent
& WXUNUSED(event
) ) 
3817     // NO - don't do this because it will set both the x and y origin 
3818     // coords to match the parent scrolled window and we just want to 
3819     // set the y coord  - MB 
3821     // m_owner->PrepareDC( dc ); 
3824     m_owner
->CalcUnscrolledPosition( 0, 0, &x
, &y 
); 
3825     wxPoint pt 
= dc
.GetDeviceOrigin(); 
3826     dc
.SetDeviceOrigin( pt
.x
, pt
.y
-y 
); 
3828     wxArrayInt rows 
= m_owner
->CalcRowLabelsExposed( GetUpdateRegion() ); 
3829     m_owner
->DrawRowLabels( dc
, rows 
); 
3832 void wxGridRowLabelWindow::OnMouseEvent( wxMouseEvent
& event 
) 
3834     m_owner
->ProcessRowLabelMouseEvent( event 
); 
3837 void wxGridRowLabelWindow::OnMouseWheel( wxMouseEvent
& event 
) 
3839     m_owner
->GetEventHandler()->ProcessEvent( event 
); 
3842 ////////////////////////////////////////////////////////////////////// 
3844 IMPLEMENT_DYNAMIC_CLASS( wxGridColLabelWindow
, wxWindow 
) 
3846 BEGIN_EVENT_TABLE( wxGridColLabelWindow
, wxGridSubwindow 
) 
3847     EVT_PAINT( wxGridColLabelWindow::OnPaint 
) 
3848     EVT_MOUSEWHEEL( wxGridColLabelWindow::OnMouseWheel 
) 
3849     EVT_MOUSE_EVENTS( wxGridColLabelWindow::OnMouseEvent 
) 
3852 wxGridColLabelWindow::wxGridColLabelWindow( wxGrid 
*parent
, 
3854                                             const wxPoint 
&pos
, const wxSize 
&size 
) 
3855   : wxGridSubwindow(parent
, id
, pos
, size
) 
3860 void wxGridColLabelWindow::OnPaint( wxPaintEvent
& WXUNUSED(event
) ) 
3864     // NO - don't do this because it will set both the x and y origin 
3865     // coords to match the parent scrolled window and we just want to 
3866     // set the x coord  - MB 
3868     // m_owner->PrepareDC( dc ); 
3871     m_owner
->CalcUnscrolledPosition( 0, 0, &x
, &y 
); 
3872     wxPoint pt 
= dc
.GetDeviceOrigin(); 
3873     if (GetLayoutDirection() == wxLayout_RightToLeft
) 
3874         dc
.SetDeviceOrigin( pt
.x
+x
, pt
.y 
); 
3876         dc
.SetDeviceOrigin( pt
.x
-x
, pt
.y 
); 
3878     wxArrayInt cols 
= m_owner
->CalcColLabelsExposed( GetUpdateRegion() ); 
3879     m_owner
->DrawColLabels( dc
, cols 
); 
3882 void wxGridColLabelWindow::OnMouseEvent( wxMouseEvent
& event 
) 
3884     m_owner
->ProcessColLabelMouseEvent( event 
); 
3887 void wxGridColLabelWindow::OnMouseWheel( wxMouseEvent
& event 
) 
3889     m_owner
->GetEventHandler()->ProcessEvent( event 
); 
3892 ////////////////////////////////////////////////////////////////////// 
3894 IMPLEMENT_DYNAMIC_CLASS( wxGridCornerLabelWindow
, wxWindow 
) 
3896 BEGIN_EVENT_TABLE( wxGridCornerLabelWindow
, wxGridSubwindow 
) 
3897     EVT_MOUSEWHEEL( wxGridCornerLabelWindow::OnMouseWheel 
) 
3898     EVT_MOUSE_EVENTS( wxGridCornerLabelWindow::OnMouseEvent 
) 
3899     EVT_PAINT( wxGridCornerLabelWindow::OnPaint 
) 
3902 wxGridCornerLabelWindow::wxGridCornerLabelWindow( wxGrid 
*parent
, 
3904                                                   const wxPoint 
&pos
, const wxSize 
&size 
) 
3905   : wxGridSubwindow(parent
, id
, pos
, size
) 
3910 void wxGridCornerLabelWindow::OnPaint( wxPaintEvent
& WXUNUSED(event
) ) 
3914     int client_height 
= 0; 
3915     int client_width 
= 0; 
3916     GetClientSize( &client_width
, &client_height 
); 
3918     // VZ: any reason for this ifdef? (FIXME) 
3924     rect
.SetWidth( client_width 
- 2 ); 
3925     rect
.SetHeight( client_height 
- 2 ); 
3927     wxRendererNative::Get().DrawHeaderButton( this, dc
, rect
, 0 ); 
3929     dc
.SetPen( wxPen(wxSystemSettings::GetColour(wxSYS_COLOUR_3DSHADOW
), 1, wxPENSTYLE_SOLID
) ); 
3930     dc
.DrawLine( client_width 
- 1, client_height 
- 1, client_width 
- 1, 0 ); 
3931     dc
.DrawLine( client_width 
- 1, client_height 
- 1, 0, client_height 
- 1 ); 
3932     dc
.DrawLine( 0, 0, client_width
, 0 ); 
3933     dc
.DrawLine( 0, 0, 0, client_height 
); 
3935     dc
.SetPen( *wxWHITE_PEN 
); 
3936     dc
.DrawLine( 1, 1, client_width 
- 1, 1 ); 
3937     dc
.DrawLine( 1, 1, 1, client_height 
- 1 ); 
3941 void wxGridCornerLabelWindow::OnMouseEvent( wxMouseEvent
& event 
) 
3943     m_owner
->ProcessCornerLabelMouseEvent( event 
); 
3946 void wxGridCornerLabelWindow::OnMouseWheel( wxMouseEvent
& event 
) 
3948     m_owner
->GetEventHandler()->ProcessEvent(event
); 
3951 ////////////////////////////////////////////////////////////////////// 
3953 IMPLEMENT_DYNAMIC_CLASS( wxGridWindow
, wxWindow 
) 
3955 BEGIN_EVENT_TABLE( wxGridWindow
, wxGridSubwindow 
) 
3956     EVT_PAINT( wxGridWindow::OnPaint 
) 
3957     EVT_MOUSEWHEEL( wxGridWindow::OnMouseWheel 
) 
3958     EVT_MOUSE_EVENTS( wxGridWindow::OnMouseEvent 
) 
3959     EVT_KEY_DOWN( wxGridWindow::OnKeyDown 
) 
3960     EVT_KEY_UP( wxGridWindow::OnKeyUp 
) 
3961     EVT_CHAR( wxGridWindow::OnChar 
) 
3962     EVT_SET_FOCUS( wxGridWindow::OnFocus 
) 
3963     EVT_KILL_FOCUS( wxGridWindow::OnFocus 
) 
3964     EVT_ERASE_BACKGROUND( wxGridWindow::OnEraseBackground 
) 
3967 wxGridWindow::wxGridWindow( wxGrid 
*parent
, 
3968                             wxGridRowLabelWindow 
*rowLblWin
, 
3969                             wxGridColLabelWindow 
*colLblWin
, 
3972                             const wxSize 
&size 
) 
3973             : wxGridSubwindow(parent
, id
, pos
, size
, 
3974                               wxWANTS_CHARS 
| wxCLIP_CHILDREN
, 
3975                               wxT("grid window") ) 
3978     m_rowLabelWin 
= rowLblWin
; 
3979     m_colLabelWin 
= colLblWin
; 
3982 void wxGridWindow::OnPaint( wxPaintEvent 
&WXUNUSED(event
) ) 
3984     wxPaintDC 
dc( this ); 
3985     m_owner
->PrepareDC( dc 
); 
3986     wxRegion reg 
= GetUpdateRegion(); 
3987     wxGridCellCoordsArray dirtyCells 
= m_owner
->CalcCellsExposed( reg 
); 
3988     m_owner
->DrawGridCellArea( dc
, dirtyCells 
); 
3990 #if WXGRID_DRAW_LINES 
3991     m_owner
->DrawAllGridLines( dc
, reg 
); 
3994     m_owner
->DrawGridSpace( dc 
); 
3995     m_owner
->DrawHighlight( dc
, dirtyCells 
); 
3998 void wxGridWindow::ScrollWindow( int dx
, int dy
, const wxRect 
*rect 
) 
4000     wxWindow::ScrollWindow( dx
, dy
, rect 
); 
4001     m_rowLabelWin
->ScrollWindow( 0, dy
, rect 
); 
4002     m_colLabelWin
->ScrollWindow( dx
, 0, rect 
); 
4005 void wxGridWindow::OnMouseEvent( wxMouseEvent
& event 
) 
4007     if (event
.ButtonDown(wxMOUSE_BTN_LEFT
) && FindFocus() != this) 
4010     m_owner
->ProcessGridCellMouseEvent( event 
); 
4013 void wxGridWindow::OnMouseWheel( wxMouseEvent
& event 
) 
4015     m_owner
->GetEventHandler()->ProcessEvent( event 
); 
4018 // This seems to be required for wxMotif/wxGTK otherwise the mouse 
4019 // cursor must be in the cell edit control to get key events 
4021 void wxGridWindow::OnKeyDown( wxKeyEvent
& event 
) 
4023     if ( !m_owner
->GetEventHandler()->ProcessEvent( event 
) ) 
4027 void wxGridWindow::OnKeyUp( wxKeyEvent
& event 
) 
4029     if ( !m_owner
->GetEventHandler()->ProcessEvent( event 
) ) 
4033 void wxGridWindow::OnChar( wxKeyEvent
& event 
) 
4035     if ( !m_owner
->GetEventHandler()->ProcessEvent( event 
) ) 
4039 void wxGridWindow::OnEraseBackground( wxEraseEvent
& WXUNUSED(event
) ) 
4043 void wxGridWindow::OnFocus(wxFocusEvent
& event
) 
4045     // and if we have any selection, it has to be repainted, because it 
4046     // uses different colour when the grid is not focused: 
4047     if ( m_owner
->IsSelection() ) 
4053         // NB: Note that this code is in "else" branch only because the other 
4054         //     branch refreshes everything and so there's no point in calling 
4055         //     Refresh() again, *not* because it should only be done if 
4056         //     !IsSelection(). If the above code is ever optimized to refresh 
4057         //     only selected area, this needs to be moved out of the "else" 
4058         //     branch so that it's always executed. 
4060         // current cell cursor {dis,re}appears on focus change: 
4061         const wxGridCellCoords 
cursorCoords(m_owner
->GetGridCursorRow(), 
4062                                             m_owner
->GetGridCursorCol()); 
4063         const wxRect cursor 
= 
4064             m_owner
->BlockToDeviceRect(cursorCoords
, cursorCoords
); 
4065         Refresh(true, &cursor
); 
4068     if ( !m_owner
->GetEventHandler()->ProcessEvent( event 
) ) 
4072 ////////////////////////////////////////////////////////////////////// 
4074 // Internal Helper function for computing row or column from some 
4075 // (unscrolled) coordinate value, using either 
4076 // m_defaultRowHeight/m_defaultColWidth or binary search on array 
4077 // of m_rowBottoms/m_ColRights to speed up the search! 
4079 // Internal helper macros for simpler use of that function 
4081 static int CoordToRowOrCol(int coord
, int defaultDist
, int minDist
, 
4082                            const wxArrayInt
& BorderArray
, int nMax
, 
4085 #define internalXToCol(x) XToCol(x, true) 
4086 #define internalYToRow(y) CoordToRowOrCol(y, m_defaultRowHeight, \ 
4087                                           m_minAcceptableRowHeight, \ 
4088                                           m_rowBottoms, m_numRows, true) 
4090 ///////////////////////////////////////////////////////////////////// 
4092 #if wxUSE_EXTENDED_RTTI 
4093 WX_DEFINE_FLAGS( wxGridStyle 
) 
4095 wxBEGIN_FLAGS( wxGridStyle 
) 
4096     // new style border flags, we put them first to 
4097     // use them for streaming out 
4098     wxFLAGS_MEMBER(wxBORDER_SIMPLE
) 
4099     wxFLAGS_MEMBER(wxBORDER_SUNKEN
) 
4100     wxFLAGS_MEMBER(wxBORDER_DOUBLE
) 
4101     wxFLAGS_MEMBER(wxBORDER_RAISED
) 
4102     wxFLAGS_MEMBER(wxBORDER_STATIC
) 
4103     wxFLAGS_MEMBER(wxBORDER_NONE
) 
4105     // old style border flags 
4106     wxFLAGS_MEMBER(wxSIMPLE_BORDER
) 
4107     wxFLAGS_MEMBER(wxSUNKEN_BORDER
) 
4108     wxFLAGS_MEMBER(wxDOUBLE_BORDER
) 
4109     wxFLAGS_MEMBER(wxRAISED_BORDER
) 
4110     wxFLAGS_MEMBER(wxSTATIC_BORDER
) 
4111     wxFLAGS_MEMBER(wxBORDER
) 
4113     // standard window styles 
4114     wxFLAGS_MEMBER(wxTAB_TRAVERSAL
) 
4115     wxFLAGS_MEMBER(wxCLIP_CHILDREN
) 
4116     wxFLAGS_MEMBER(wxTRANSPARENT_WINDOW
) 
4117     wxFLAGS_MEMBER(wxWANTS_CHARS
) 
4118     wxFLAGS_MEMBER(wxFULL_REPAINT_ON_RESIZE
) 
4119     wxFLAGS_MEMBER(wxALWAYS_SHOW_SB
) 
4120     wxFLAGS_MEMBER(wxVSCROLL
) 
4121     wxFLAGS_MEMBER(wxHSCROLL
) 
4123 wxEND_FLAGS( wxGridStyle 
) 
4125 IMPLEMENT_DYNAMIC_CLASS_XTI(wxGrid
, wxScrolledWindow
,"wx/grid.h") 
4127 wxBEGIN_PROPERTIES_TABLE(wxGrid
) 
4128     wxHIDE_PROPERTY( Children 
) 
4129     wxPROPERTY_FLAGS( WindowStyle 
, wxGridStyle 
, long , SetWindowStyleFlag 
, GetWindowStyleFlag 
, EMPTY_MACROVALUE
, 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // style 
4130 wxEND_PROPERTIES_TABLE() 
4132 wxBEGIN_HANDLERS_TABLE(wxGrid
) 
4133 wxEND_HANDLERS_TABLE() 
4135 wxCONSTRUCTOR_5( wxGrid 
, wxWindow
* , Parent 
, wxWindowID 
, Id 
, wxPoint 
, Position 
, wxSize 
, Size 
, long , WindowStyle 
) 
4138  TODO : Expose more information of a list's layout, etc. via appropriate objects (e.g., NotebookPageInfo) 
4141 IMPLEMENT_DYNAMIC_CLASS( wxGrid
, wxScrolledWindow 
) 
4144 BEGIN_EVENT_TABLE( wxGrid
, wxScrolledWindow 
) 
4145     EVT_PAINT( wxGrid::OnPaint 
) 
4146     EVT_SIZE( wxGrid::OnSize 
) 
4147     EVT_KEY_DOWN( wxGrid::OnKeyDown 
) 
4148     EVT_KEY_UP( wxGrid::OnKeyUp 
) 
4149     EVT_CHAR ( wxGrid::OnChar 
) 
4150     EVT_ERASE_BACKGROUND( wxGrid::OnEraseBackground 
) 
4158 wxGrid::wxGrid( wxWindow 
*parent
, 
4163                  const wxString
& name 
) 
4166     Create(parent
, id
, pos
, size
, style
, name
); 
4169 bool wxGrid::Create(wxWindow 
*parent
, wxWindowID id
, 
4170                           const wxPoint
& pos
, const wxSize
& size
, 
4171                           long style
, const wxString
& name
) 
4173     if (!wxScrolledWindow::Create(parent
, id
, pos
, size
, 
4174                                   style 
| wxWANTS_CHARS
, name
)) 
4177     m_colMinWidths 
= wxLongToLongHashMap(GRID_HASH_SIZE
); 
4178     m_rowMinHeights 
= wxLongToLongHashMap(GRID_HASH_SIZE
); 
4181     SetInitialSize(size
); 
4189     // Must do this or ~wxScrollHelper will pop the wrong event handler 
4190     SetTargetWindow(this); 
4192     wxSafeDecRef(m_defaultCellAttr
); 
4194 #ifdef DEBUG_ATTR_CACHE 
4195     size_t total 
= gs_nAttrCacheHits 
+ gs_nAttrCacheMisses
; 
4196     wxPrintf(_T("wxGrid attribute cache statistics: " 
4197                 "total: %u, hits: %u (%u%%)\n"), 
4198              total
, gs_nAttrCacheHits
, 
4199              total 
? (gs_nAttrCacheHits
*100) / total 
: 0); 
4202     // if we own the table, just delete it, otherwise at least don't leave it 
4203     // with dangling view pointer 
4206     else if ( m_table 
&& m_table
->GetView() == this ) 
4207         m_table
->SetView(NULL
); 
4209     delete m_typeRegistry
; 
4214 // ----- internal init and update functions 
4217 // NOTE: If using the default visual attributes works everywhere then this can 
4218 // be removed as well as the #else cases below. 
4219 #define _USE_VISATTR 0 
4221 void wxGrid::Create() 
4223     // create the type registry 
4224     m_typeRegistry 
= new wxGridTypeRegistry
; 
4226     m_cellEditCtrlEnabled 
= false; 
4228     m_defaultCellAttr 
= new wxGridCellAttr(); 
4230     // Set default cell attributes 
4231     m_defaultCellAttr
->SetDefAttr(m_defaultCellAttr
); 
4232     m_defaultCellAttr
->SetKind(wxGridCellAttr::Default
); 
4233     m_defaultCellAttr
->SetFont(GetFont()); 
4234     m_defaultCellAttr
->SetAlignment(wxALIGN_LEFT
, wxALIGN_TOP
); 
4235     m_defaultCellAttr
->SetRenderer(new wxGridCellStringRenderer
); 
4236     m_defaultCellAttr
->SetEditor(new wxGridCellTextEditor
); 
4239     wxVisualAttributes gva 
= wxListBox::GetClassDefaultAttributes(); 
4240     wxVisualAttributes lva 
= wxPanel::GetClassDefaultAttributes(); 
4242     m_defaultCellAttr
->SetTextColour(gva
.colFg
); 
4243     m_defaultCellAttr
->SetBackgroundColour(gva
.colBg
); 
4246     m_defaultCellAttr
->SetTextColour( 
4247         wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT
)); 
4248     m_defaultCellAttr
->SetBackgroundColour( 
4249         wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW
)); 
4254     m_currentCellCoords 
= wxGridNoCellCoords
; 
4256     m_rowLabelWidth 
= WXGRID_DEFAULT_ROW_LABEL_WIDTH
; 
4257     m_colLabelHeight 
= WXGRID_DEFAULT_COL_LABEL_HEIGHT
; 
4259     // subwindow components that make up the wxGrid 
4260     m_rowLabelWin 
= new wxGridRowLabelWindow( this, 
4265     m_colLabelWin 
= new wxGridColLabelWindow( this, 
4270     m_cornerLabelWin 
= new wxGridCornerLabelWindow( this, 
4275     m_gridWin 
= new wxGridWindow( this, 
4282     SetTargetWindow( m_gridWin 
); 
4285     wxColour gfg 
= gva
.colFg
; 
4286     wxColour gbg 
= gva
.colBg
; 
4287     wxColour lfg 
= lva
.colFg
; 
4288     wxColour lbg 
= lva
.colBg
; 
4290     wxColour gfg 
= wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOWTEXT 
); 
4291     wxColour gbg 
= wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW 
); 
4292     wxColour lfg 
= wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOWTEXT 
); 
4293     wxColour lbg 
= wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE 
); 
4296     m_cornerLabelWin
->SetOwnForegroundColour(lfg
); 
4297     m_cornerLabelWin
->SetOwnBackgroundColour(lbg
); 
4298     m_rowLabelWin
->SetOwnForegroundColour(lfg
); 
4299     m_rowLabelWin
->SetOwnBackgroundColour(lbg
); 
4300     m_colLabelWin
->SetOwnForegroundColour(lfg
); 
4301     m_colLabelWin
->SetOwnBackgroundColour(lbg
); 
4303     m_gridWin
->SetOwnForegroundColour(gfg
); 
4304     m_gridWin
->SetOwnBackgroundColour(gbg
); 
4309 bool wxGrid::CreateGrid( int numRows
, int numCols
, 
4310                          wxGrid::wxGridSelectionModes selmode 
) 
4312     wxCHECK_MSG( !m_created
, 
4314                  wxT("wxGrid::CreateGrid or wxGrid::SetTable called more than once") ); 
4316     m_numRows 
= numRows
; 
4317     m_numCols 
= numCols
; 
4319     m_table 
= new wxGridStringTable( m_numRows
, m_numCols 
); 
4320     m_table
->SetView( this ); 
4322     m_selection 
= new wxGridSelection( this, selmode 
); 
4331 void wxGrid::SetSelectionMode(wxGrid::wxGridSelectionModes selmode
) 
4333     wxCHECK_RET( m_created
, 
4334                  wxT("Called wxGrid::SetSelectionMode() before calling CreateGrid()") ); 
4336     m_selection
->SetSelectionMode( selmode 
); 
4339 wxGrid::wxGridSelectionModes 
wxGrid::GetSelectionMode() const 
4341     wxCHECK_MSG( m_created
, wxGrid::wxGridSelectCells
, 
4342                  wxT("Called wxGrid::GetSelectionMode() before calling CreateGrid()") ); 
4344     return m_selection
->GetSelectionMode(); 
4347 bool wxGrid::SetTable( wxGridTableBase 
*table
, bool takeOwnership
, 
4348                        wxGrid::wxGridSelectionModes selmode 
) 
4350     bool checkSelection 
= false; 
4353         // stop all processing 
4358             m_table
->SetView(0); 
4370         checkSelection 
= true; 
4372         // kill row and column size arrays 
4373         m_colWidths
.Empty(); 
4374         m_colRights
.Empty(); 
4375         m_rowHeights
.Empty(); 
4376         m_rowBottoms
.Empty(); 
4381         m_numRows 
= table
->GetNumberRows(); 
4382         m_numCols 
= table
->GetNumberCols(); 
4385         m_table
->SetView( this ); 
4386         m_ownTable 
= takeOwnership
; 
4387         m_selection 
= new wxGridSelection( this, selmode 
); 
4390             // If the newly set table is smaller than the 
4391             // original one current cell and selection regions 
4392             // might be invalid, 
4393             m_selectingKeyboard 
= wxGridNoCellCoords
; 
4394             m_currentCellCoords 
= 
4395               wxGridCellCoords(wxMin(m_numRows
, m_currentCellCoords
.GetRow()), 
4396                                wxMin(m_numCols
, m_currentCellCoords
.GetCol())); 
4397             if (m_selectingTopLeft
.GetRow() >= m_numRows 
|| 
4398                 m_selectingTopLeft
.GetCol() >= m_numCols
) 
4400                 m_selectingTopLeft 
= wxGridNoCellCoords
; 
4401                 m_selectingBottomRight 
= wxGridNoCellCoords
; 
4404                 m_selectingBottomRight 
= 
4405                   wxGridCellCoords(wxMin(m_numRows
, 
4406                                          m_selectingBottomRight
.GetRow()), 
4408                                          m_selectingBottomRight
.GetCol())); 
4418 void wxGrid::InitVars() 
4422     m_cornerLabelWin 
= NULL
; 
4423     m_rowLabelWin 
= NULL
; 
4424     m_colLabelWin 
= NULL
; 
4431     m_defaultCellAttr 
= NULL
; 
4432     m_typeRegistry 
= NULL
; 
4433     m_winCapture 
= NULL
; 
4438     m_rowLabelWidth  
= WXGRID_DEFAULT_ROW_LABEL_WIDTH
; 
4439     m_colLabelHeight 
= WXGRID_DEFAULT_COL_LABEL_HEIGHT
; 
4441     if ( m_rowLabelWin 
) 
4443         m_labelBackgroundColour 
= m_rowLabelWin
->GetBackgroundColour(); 
4447         m_labelBackgroundColour 
= *wxWHITE
; 
4450     m_labelTextColour 
= *wxBLACK
; 
4453     m_attrCache
.row 
= -1; 
4454     m_attrCache
.col 
= -1; 
4455     m_attrCache
.attr 
= NULL
; 
4457     // TODO: something better than this ? 
4459     m_labelFont 
= this->GetFont(); 
4460     m_labelFont
.SetWeight( wxBOLD 
); 
4462     m_rowLabelHorizAlign 
= wxALIGN_CENTRE
; 
4463     m_rowLabelVertAlign  
= wxALIGN_CENTRE
; 
4465     m_colLabelHorizAlign 
= wxALIGN_CENTRE
; 
4466     m_colLabelVertAlign  
= wxALIGN_CENTRE
; 
4467     m_colLabelTextOrientation 
= wxHORIZONTAL
; 
4469     m_defaultColWidth  
= WXGRID_DEFAULT_COL_WIDTH
; 
4470     m_defaultRowHeight 
= m_gridWin
->GetCharHeight(); 
4472     m_minAcceptableColWidth  
= WXGRID_MIN_COL_WIDTH
; 
4473     m_minAcceptableRowHeight 
= WXGRID_MIN_ROW_HEIGHT
; 
4475 #if defined(__WXMOTIF__) || defined(__WXGTK__)  // see also text ctrl sizing in ShowCellEditControl() 
4476     m_defaultRowHeight 
+= 8; 
4478     m_defaultRowHeight 
+= 4; 
4481     m_gridLineColour 
= wxColour( 192,192,192 ); 
4482     m_gridLinesEnabled 
= true; 
4483     m_cellHighlightColour 
= *wxBLACK
; 
4484     m_cellHighlightPenWidth 
= 2; 
4485     m_cellHighlightROPenWidth 
= 1; 
4487     m_canDragColMove 
= false; 
4489     m_cursorMode  
= WXGRID_CURSOR_SELECT_CELL
; 
4490     m_winCapture 
= (wxWindow 
*)NULL
; 
4491     m_canDragRowSize 
= true; 
4492     m_canDragColSize 
= true; 
4493     m_canDragGridSize 
= true; 
4494     m_canDragCell 
= false; 
4496     m_dragRowOrCol 
= -1; 
4497     m_isDragging 
= false; 
4498     m_startDragPos 
= wxDefaultPosition
; 
4499     m_nativeColumnLabels 
= false; 
4501     m_waitForSlowClick 
= false; 
4503     m_rowResizeCursor 
= wxCursor( wxCURSOR_SIZENS 
); 
4504     m_colResizeCursor 
= wxCursor( wxCURSOR_SIZEWE 
); 
4506     m_currentCellCoords 
= wxGridNoCellCoords
; 
4510     m_selectionBackground 
= wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT
); 
4511     m_selectionForeground 
= wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHTTEXT
); 
4513     m_editable 
= true;  // default for whole grid 
4515     m_inOnKeyDown 
= false; 
4521     m_scrollLineX 
= GRID_SCROLL_LINE_X
; 
4522     m_scrollLineY 
= GRID_SCROLL_LINE_Y
; 
4525 // ---------------------------------------------------------------------------- 
4526 // the idea is to call these functions only when necessary because they create 
4527 // quite big arrays which eat memory mostly unnecessary - in particular, if 
4528 // default widths/heights are used for all rows/columns, we may not use these 
4531 // with some extra code, it should be possible to only store the widths/heights 
4532 // different from default ones (resulting in space savings for huge grids) but 
4533 // this is not done currently 
4534 // ---------------------------------------------------------------------------- 
4536 void wxGrid::InitRowHeights() 
4538     m_rowHeights
.Empty(); 
4539     m_rowBottoms
.Empty(); 
4541     m_rowHeights
.Alloc( m_numRows 
); 
4542     m_rowBottoms
.Alloc( m_numRows 
); 
4544     m_rowHeights
.Add( m_defaultRowHeight
, m_numRows 
); 
4547     for ( int i 
= 0; i 
< m_numRows
; i
++ ) 
4549         rowBottom 
+= m_defaultRowHeight
; 
4550         m_rowBottoms
.Add( rowBottom 
); 
4554 void wxGrid::InitColWidths() 
4556     m_colWidths
.Empty(); 
4557     m_colRights
.Empty(); 
4559     m_colWidths
.Alloc( m_numCols 
); 
4560     m_colRights
.Alloc( m_numCols 
); 
4562     m_colWidths
.Add( m_defaultColWidth
, m_numCols 
); 
4565     for ( int i 
= 0; i 
< m_numCols
; i
++ ) 
4567         colRight 
= ( GetColPos( i 
) + 1 ) * m_defaultColWidth
; 
4568         m_colRights
.Add( colRight 
); 
4572 int wxGrid::GetColWidth(int col
) const 
4574     return m_colWidths
.IsEmpty() ? m_defaultColWidth 
: m_colWidths
[col
]; 
4577 int wxGrid::GetColLeft(int col
) const 
4579     return m_colRights
.IsEmpty() ? GetColPos( col 
) * m_defaultColWidth
 
4580                                  : m_colRights
[col
] - m_colWidths
[col
]; 
4583 int wxGrid::GetColRight(int col
) const 
4585     return m_colRights
.IsEmpty() ? (GetColPos( col 
) + 1) * m_defaultColWidth
 
4589 int wxGrid::GetRowHeight(int row
) const 
4591     return m_rowHeights
.IsEmpty() ? m_defaultRowHeight 
: m_rowHeights
[row
]; 
4594 int wxGrid::GetRowTop(int row
) const 
4596     return m_rowBottoms
.IsEmpty() ? row 
* m_defaultRowHeight
 
4597                                   : m_rowBottoms
[row
] - m_rowHeights
[row
]; 
4600 int wxGrid::GetRowBottom(int row
) const 
4602     return m_rowBottoms
.IsEmpty() ? (row 
+ 1) * m_defaultRowHeight
 
4603                                   : m_rowBottoms
[row
]; 
4606 void wxGrid::CalcDimensions() 
4608     // compute the size of the scrollable area 
4609     int w 
= m_numCols 
> 0 ? GetColRight(GetColAt(m_numCols 
- 1)) : 0; 
4610     int h 
= m_numRows 
> 0 ? GetRowBottom(m_numRows 
- 1) : 0; 
4615     // take into account editor if shown 
4616     if ( IsCellEditControlShown() ) 
4619         int r 
= m_currentCellCoords
.GetRow(); 
4620         int c 
= m_currentCellCoords
.GetCol(); 
4621         int x 
= GetColLeft(c
); 
4622         int y 
= GetRowTop(r
); 
4624         // how big is the editor 
4625         wxGridCellAttr
* attr 
= GetCellAttr(r
, c
); 
4626         wxGridCellEditor
* editor 
= attr
->GetEditor(this, r
, c
); 
4627         editor
->GetControl()->GetSize(&w2
, &h2
); 
4638     // preserve (more or less) the previous position 
4640     GetViewStart( &x
, &y 
); 
4642     // ensure the position is valid for the new scroll ranges 
4644         x 
= wxMax( w 
- 1, 0 ); 
4646         y 
= wxMax( h 
- 1, 0 ); 
4648     // do set scrollbar parameters 
4649     SetScrollbars( m_scrollLineX
, m_scrollLineY
, 
4650                    GetScrollX(w
), GetScrollY(h
), 
4652                    GetBatchCount() != 0); 
4654     // if our OnSize() hadn't been called (it would if we have scrollbars), we 
4655     // still must reposition the children 
4659 void wxGrid::CalcWindowSizes() 
4661     // escape if the window is has not been fully created yet 
4663     if ( m_cornerLabelWin 
== NULL 
) 
4667     GetClientSize( &cw
, &ch 
); 
4669     // this block of code tries to work around the following problem: the grid 
4670     // could have been just resized to have enough space to show the full grid 
4671     // window contents without the scrollbars, but its client size could be 
4672     // not big enough because the grid has the scrollbars right now and so the 
4673     // scrollbars would remain even though we don't need them any more 
4675     // to prevent this from happening, check if we have enough space for 
4676     // everything without the scrollbars and explicitly disable them then 
4677     wxSize size 
= GetSize() - GetWindowBorderSize(); 
4678     if ( size 
!= wxSize(cw
, ch
) ) 
4680         // check if we have enough space for grid window after accounting for 
4681         // the fixed size elements 
4682         size
.x 
-= m_rowLabelWidth
; 
4683         size
.y 
-= m_colLabelHeight
; 
4685         const wxSize vsize 
= m_gridWin
->GetVirtualSize(); 
4687         if ( size
.x 
>= vsize
.x 
&& size
.y 
>= vsize
.y 
) 
4689             // yes, we do, so remove the scrollbars and use the new client size 
4690             // (which should be the same as full window size - borders now) 
4691             SetScrollbars(0, 0, 0, 0); 
4692             GetClientSize(&cw
, &ch
); 
4696     // the grid may be too small to have enough space for the labels yet, don't 
4697     // size the windows to negative sizes in this case 
4698     int gw 
= cw 
- m_rowLabelWidth
; 
4699     int gh 
= ch 
- m_colLabelHeight
; 
4705     if ( m_cornerLabelWin 
&& m_cornerLabelWin
->IsShown() ) 
4706         m_cornerLabelWin
->SetSize( 0, 0, m_rowLabelWidth
, m_colLabelHeight 
); 
4708     if ( m_colLabelWin 
&& m_colLabelWin
->IsShown() ) 
4709         m_colLabelWin
->SetSize( m_rowLabelWidth
, 0, gw
, m_colLabelHeight 
); 
4711     if ( m_rowLabelWin 
&& m_rowLabelWin
->IsShown() ) 
4712         m_rowLabelWin
->SetSize( 0, m_colLabelHeight
, m_rowLabelWidth
, gh 
); 
4714     if ( m_gridWin 
&& m_gridWin
->IsShown() ) 
4715         m_gridWin
->SetSize( m_rowLabelWidth
, m_colLabelHeight
, gw
, gh 
); 
4718 // this is called when the grid table sends a message 
4719 // to indicate that it has been redimensioned 
4721 bool wxGrid::Redimension( wxGridTableMessage
& msg 
) 
4724     bool result 
= false; 
4726     // Clear the attribute cache as the attribute might refer to a different 
4727     // cell than stored in the cache after adding/removing rows/columns. 
4730     // By the same reasoning, the editor should be dismissed if columns are 
4731     // added or removed. And for consistency, it should IMHO always be 
4732     // removed, not only if the cell "underneath" it actually changes. 
4733     // For now, I intentionally do not save the editor's content as the 
4734     // cell it might want to save that stuff to might no longer exist. 
4735     HideCellEditControl(); 
4738     // if we were using the default widths/heights so far, we must change them 
4740     if ( m_colWidths
.IsEmpty() ) 
4745     if ( m_rowHeights
.IsEmpty() ) 
4751     switch ( msg
.GetId() ) 
4753         case wxGRIDTABLE_NOTIFY_ROWS_INSERTED
: 
4755             size_t pos 
= msg
.GetCommandInt(); 
4756             int numRows 
= msg
.GetCommandInt2(); 
4758             m_numRows 
+= numRows
; 
4760             if ( !m_rowHeights
.IsEmpty() ) 
4762                 m_rowHeights
.Insert( m_defaultRowHeight
, pos
, numRows 
); 
4763                 m_rowBottoms
.Insert( 0, pos
, numRows 
); 
4767                     bottom 
= m_rowBottoms
[pos 
- 1]; 
4769                 for ( i 
= pos
; i 
< m_numRows
; i
++ ) 
4771                     bottom 
+= m_rowHeights
[i
]; 
4772                     m_rowBottoms
[i
] = bottom
; 
4776             if ( m_currentCellCoords 
== wxGridNoCellCoords 
) 
4778                 // if we have just inserted cols into an empty grid the current 
4779                 // cell will be undefined... 
4781                 SetCurrentCell( 0, 0 ); 
4785                 m_selection
->UpdateRows( pos
, numRows 
); 
4786             wxGridCellAttrProvider 
* attrProvider 
= m_table
->GetAttrProvider(); 
4788                 attrProvider
->UpdateAttrRows( pos
, numRows 
); 
4790             if ( !GetBatchCount() ) 
4793                 m_rowLabelWin
->Refresh(); 
4799         case wxGRIDTABLE_NOTIFY_ROWS_APPENDED
: 
4801             int numRows 
= msg
.GetCommandInt(); 
4802             int oldNumRows 
= m_numRows
; 
4803             m_numRows 
+= numRows
; 
4805             if ( !m_rowHeights
.IsEmpty() ) 
4807                 m_rowHeights
.Add( m_defaultRowHeight
, numRows 
); 
4808                 m_rowBottoms
.Add( 0, numRows 
); 
4811                 if ( oldNumRows 
> 0 ) 
4812                     bottom 
= m_rowBottoms
[oldNumRows 
- 1]; 
4814                 for ( i 
= oldNumRows
; i 
< m_numRows
; i
++ ) 
4816                     bottom 
+= m_rowHeights
[i
]; 
4817                     m_rowBottoms
[i
] = bottom
; 
4821             if ( m_currentCellCoords 
== wxGridNoCellCoords 
) 
4823                 // if we have just inserted cols into an empty grid the current 
4824                 // cell will be undefined... 
4826                 SetCurrentCell( 0, 0 ); 
4829             if ( !GetBatchCount() ) 
4832                 m_rowLabelWin
->Refresh(); 
4838         case wxGRIDTABLE_NOTIFY_ROWS_DELETED
: 
4840             size_t pos 
= msg
.GetCommandInt(); 
4841             int numRows 
= msg
.GetCommandInt2(); 
4842             m_numRows 
-= numRows
; 
4844             if ( !m_rowHeights
.IsEmpty() ) 
4846                 m_rowHeights
.RemoveAt( pos
, numRows 
); 
4847                 m_rowBottoms
.RemoveAt( pos
, numRows 
); 
4850                 for ( i 
= 0; i 
< m_numRows
; i
++ ) 
4852                     h 
+= m_rowHeights
[i
]; 
4853                     m_rowBottoms
[i
] = h
; 
4859                 m_currentCellCoords 
= wxGridNoCellCoords
; 
4863                 if ( m_currentCellCoords
.GetRow() >= m_numRows 
) 
4864                     m_currentCellCoords
.Set( 0, 0 ); 
4868                 m_selection
->UpdateRows( pos
, -((int)numRows
) ); 
4869             wxGridCellAttrProvider 
* attrProvider 
= m_table
->GetAttrProvider(); 
4872                 attrProvider
->UpdateAttrRows( pos
, -((int)numRows
) ); 
4874 // ifdef'd out following patch from Paul Gammans 
4876                 // No need to touch column attributes, unless we 
4877                 // removed _all_ rows, in this case, we remove 
4878                 // all column attributes. 
4879                 // I hate to do this here, but the 
4880                 // needed data is not available inside UpdateAttrRows. 
4881                 if ( !GetNumberRows() ) 
4882                     attrProvider
->UpdateAttrCols( 0, -GetNumberCols() ); 
4886             if ( !GetBatchCount() ) 
4889                 m_rowLabelWin
->Refresh(); 
4895         case wxGRIDTABLE_NOTIFY_COLS_INSERTED
: 
4897             size_t pos 
= msg
.GetCommandInt(); 
4898             int numCols 
= msg
.GetCommandInt2(); 
4899             m_numCols 
+= numCols
; 
4901             if ( !m_colAt
.IsEmpty() ) 
4903                 //Shift the column IDs 
4905                 for ( i 
= 0; i 
< m_numCols 
- numCols
; i
++ ) 
4907                     if ( m_colAt
[i
] >= (int)pos 
) 
4908                         m_colAt
[i
] += numCols
; 
4911                 m_colAt
.Insert( pos
, pos
, numCols 
); 
4913                 //Set the new columns' positions 
4914                 for ( i 
= pos 
+ 1; i 
< (int)pos 
+ numCols
; i
++ ) 
4920             if ( !m_colWidths
.IsEmpty() ) 
4922                 m_colWidths
.Insert( m_defaultColWidth
, pos
, numCols 
); 
4923                 m_colRights
.Insert( 0, pos
, numCols 
); 
4927                     right 
= m_colRights
[GetColAt( pos 
- 1 )]; 
4930                 for ( colPos 
= pos
; colPos 
< m_numCols
; colPos
++ ) 
4932                     i 
= GetColAt( colPos 
); 
4934                     right 
+= m_colWidths
[i
]; 
4935                     m_colRights
[i
] = right
; 
4939             if ( m_currentCellCoords 
== wxGridNoCellCoords 
) 
4941                 // if we have just inserted cols into an empty grid the current 
4942                 // cell will be undefined... 
4944                 SetCurrentCell( 0, 0 ); 
4948                 m_selection
->UpdateCols( pos
, numCols 
); 
4949             wxGridCellAttrProvider 
* attrProvider 
= m_table
->GetAttrProvider(); 
4951                 attrProvider
->UpdateAttrCols( pos
, numCols 
); 
4952             if ( !GetBatchCount() ) 
4955                 m_colLabelWin
->Refresh(); 
4961         case wxGRIDTABLE_NOTIFY_COLS_APPENDED
: 
4963             int numCols 
= msg
.GetCommandInt(); 
4964             int oldNumCols 
= m_numCols
; 
4965             m_numCols 
+= numCols
; 
4967             if ( !m_colAt
.IsEmpty() ) 
4969                 m_colAt
.Add( 0, numCols 
); 
4971                 //Set the new columns' positions 
4973                 for ( i 
= oldNumCols
; i 
< m_numCols
; i
++ ) 
4979             if ( !m_colWidths
.IsEmpty() ) 
4981                 m_colWidths
.Add( m_defaultColWidth
, numCols 
); 
4982                 m_colRights
.Add( 0, numCols 
); 
4985                 if ( oldNumCols 
> 0 ) 
4986                     right 
= m_colRights
[GetColAt( oldNumCols 
- 1 )]; 
4989                 for ( colPos 
= oldNumCols
; colPos 
< m_numCols
; colPos
++ ) 
4991                     i 
= GetColAt( colPos 
); 
4993                     right 
+= m_colWidths
[i
]; 
4994                     m_colRights
[i
] = right
; 
4998             if ( m_currentCellCoords 
== wxGridNoCellCoords 
) 
5000                 // if we have just inserted cols into an empty grid the current 
5001                 // cell will be undefined... 
5003                 SetCurrentCell( 0, 0 ); 
5005             if ( !GetBatchCount() ) 
5008                 m_colLabelWin
->Refresh(); 
5014         case wxGRIDTABLE_NOTIFY_COLS_DELETED
: 
5016             size_t pos 
= msg
.GetCommandInt(); 
5017             int numCols 
= msg
.GetCommandInt2(); 
5018             m_numCols 
-= numCols
; 
5020             if ( !m_colAt
.IsEmpty() ) 
5022                 int colID 
= GetColAt( pos 
); 
5024                 m_colAt
.RemoveAt( pos
, numCols 
); 
5026                 //Shift the column IDs 
5028                 for ( colPos 
= 0; colPos 
< m_numCols
; colPos
++ ) 
5030                     if ( m_colAt
[colPos
] > colID 
) 
5031                         m_colAt
[colPos
] -= numCols
; 
5035             if ( !m_colWidths
.IsEmpty() ) 
5037                 m_colWidths
.RemoveAt( pos
, numCols 
); 
5038                 m_colRights
.RemoveAt( pos
, numCols 
); 
5042                 for ( colPos 
= 0; colPos 
< m_numCols
; colPos
++ ) 
5044                     i 
= GetColAt( colPos 
); 
5046                     w 
+= m_colWidths
[i
]; 
5053                 m_currentCellCoords 
= wxGridNoCellCoords
; 
5057                 if ( m_currentCellCoords
.GetCol() >= m_numCols 
) 
5058                   m_currentCellCoords
.Set( 0, 0 ); 
5062                 m_selection
->UpdateCols( pos
, -((int)numCols
) ); 
5063             wxGridCellAttrProvider 
* attrProvider 
= m_table
->GetAttrProvider(); 
5066                 attrProvider
->UpdateAttrCols( pos
, -((int)numCols
) ); 
5068 // ifdef'd out following patch from Paul Gammans 
5070                 // No need to touch row attributes, unless we 
5071                 // removed _all_ columns, in this case, we remove 
5072                 // all row attributes. 
5073                 // I hate to do this here, but the 
5074                 // needed data is not available inside UpdateAttrCols. 
5075                 if ( !GetNumberCols() ) 
5076                     attrProvider
->UpdateAttrRows( 0, -GetNumberRows() ); 
5080             if ( !GetBatchCount() ) 
5083                 m_colLabelWin
->Refresh(); 
5090     if (result 
&& !GetBatchCount() ) 
5091         m_gridWin
->Refresh(); 
5096 wxArrayInt 
wxGrid::CalcRowLabelsExposed( const wxRegion
& reg 
) const 
5098     wxRegionIterator 
iter( reg 
); 
5101     wxArrayInt  rowlabels
; 
5108         // TODO: remove this when we can... 
5109         // There is a bug in wxMotif that gives garbage update 
5110         // rectangles if you jump-scroll a long way by clicking the 
5111         // scrollbar with middle button.  This is a work-around 
5113 #if defined(__WXMOTIF__) 
5115         m_gridWin
->GetClientSize( &cw
, &ch 
); 
5116         if ( r
.GetTop() > ch 
) 
5118         r
.SetBottom( wxMin( r
.GetBottom(), ch 
) ); 
5121         // logical bounds of update region 
5124         CalcUnscrolledPosition( 0, r
.GetTop(), &dummy
, &top 
); 
5125         CalcUnscrolledPosition( 0, r
.GetBottom(), &dummy
, &bottom 
); 
5127         // find the row labels within these bounds 
5130         for ( row 
= internalYToRow(top
); row 
< m_numRows
; row
++ ) 
5132             if ( GetRowBottom(row
) < top 
) 
5135             if ( GetRowTop(row
) > bottom 
) 
5138             rowlabels
.Add( row 
); 
5147 wxArrayInt 
wxGrid::CalcColLabelsExposed( const wxRegion
& reg 
) const 
5149     wxRegionIterator 
iter( reg 
); 
5152     wxArrayInt colLabels
; 
5159         // TODO: remove this when we can... 
5160         // There is a bug in wxMotif that gives garbage update 
5161         // rectangles if you jump-scroll a long way by clicking the 
5162         // scrollbar with middle button.  This is a work-around 
5164 #if defined(__WXMOTIF__) 
5166         m_gridWin
->GetClientSize( &cw
, &ch 
); 
5167         if ( r
.GetLeft() > cw 
) 
5169         r
.SetRight( wxMin( r
.GetRight(), cw 
) ); 
5172         // logical bounds of update region 
5175         CalcUnscrolledPosition( r
.GetLeft(), 0, &left
, &dummy 
); 
5176         CalcUnscrolledPosition( r
.GetRight(), 0, &right
, &dummy 
); 
5178         // find the cells within these bounds 
5182         for ( colPos 
= GetColPos( internalXToCol(left
) ); colPos 
< m_numCols
; colPos
++ ) 
5184             col 
= GetColAt( colPos 
); 
5186             if ( GetColRight(col
) < left 
) 
5189             if ( GetColLeft(col
) > right 
) 
5192             colLabels
.Add( col 
); 
5201 wxGridCellCoordsArray 
wxGrid::CalcCellsExposed( const wxRegion
& reg 
) const 
5203     wxRegionIterator 
iter( reg 
); 
5206     wxGridCellCoordsArray  cellsExposed
; 
5208     int left
, top
, right
, bottom
; 
5213         // TODO: remove this when we can... 
5214         // There is a bug in wxMotif that gives garbage update 
5215         // rectangles if you jump-scroll a long way by clicking the 
5216         // scrollbar with middle button.  This is a work-around 
5218 #if defined(__WXMOTIF__) 
5220         m_gridWin
->GetClientSize( &cw
, &ch 
); 
5221         if ( r
.GetTop() > ch 
) r
.SetTop( 0 ); 
5222         if ( r
.GetLeft() > cw 
) r
.SetLeft( 0 ); 
5223         r
.SetRight( wxMin( r
.GetRight(), cw 
) ); 
5224         r
.SetBottom( wxMin( r
.GetBottom(), ch 
) ); 
5227         // logical bounds of update region 
5229         CalcUnscrolledPosition( r
.GetLeft(), r
.GetTop(), &left
, &top 
); 
5230         CalcUnscrolledPosition( r
.GetRight(), r
.GetBottom(), &right
, &bottom 
); 
5232         // find the cells within these bounds 
5235         for ( row 
= internalYToRow(top
); row 
< m_numRows
; row
++ ) 
5237             if ( GetRowBottom(row
) <= top 
) 
5240             if ( GetRowTop(row
) > bottom 
) 
5244             for ( colPos 
= GetColPos( internalXToCol(left
) ); colPos 
< m_numCols
; colPos
++ ) 
5246                 col 
= GetColAt( colPos 
); 
5248                 if ( GetColRight(col
) <= left 
) 
5251                 if ( GetColLeft(col
) > right 
) 
5254                 cellsExposed
.Add( wxGridCellCoords( row
, col 
) ); 
5261     return cellsExposed
; 
5265 void wxGrid::ProcessRowLabelMouseEvent( wxMouseEvent
& event 
) 
5268     wxPoint 
pos( event
.GetPosition() ); 
5269     CalcUnscrolledPosition( pos
.x
, pos
.y
, &x
, &y 
); 
5271     if ( event
.Dragging() ) 
5275             m_isDragging 
= true; 
5276             m_rowLabelWin
->CaptureMouse(); 
5279         if ( event
.LeftIsDown() ) 
5281             switch ( m_cursorMode 
) 
5283                 case WXGRID_CURSOR_RESIZE_ROW
: 
5285                     int cw
, ch
, left
, dummy
; 
5286                     m_gridWin
->GetClientSize( &cw
, &ch 
); 
5287                     CalcUnscrolledPosition( 0, 0, &left
, &dummy 
); 
5289                     wxClientDC 
dc( m_gridWin 
); 
5292                                GetRowTop(m_dragRowOrCol
) + 
5293                                GetRowMinimalHeight(m_dragRowOrCol
) ); 
5294                     dc
.SetLogicalFunction(wxINVERT
); 
5295                     if ( m_dragLastPos 
>= 0 ) 
5297                         dc
.DrawLine( left
, m_dragLastPos
, left
+cw
, m_dragLastPos 
); 
5299                     dc
.DrawLine( left
, y
, left
+cw
, y 
); 
5304                 case WXGRID_CURSOR_SELECT_ROW
: 
5306                     if ( (row 
= YToRow( y 
)) >= 0 ) 
5310                             m_selection
->SelectRow( row
, 
5311                                                     event
.ControlDown(), 
5320                 // default label to suppress warnings about "enumeration value 
5321                 // 'xxx' not handled in switch 
5329     if ( m_isDragging 
&& (event
.Entering() || event
.Leaving()) ) 
5334         if (m_rowLabelWin
->HasCapture()) 
5335             m_rowLabelWin
->ReleaseMouse(); 
5336         m_isDragging 
= false; 
5339     // ------------ Entering or leaving the window 
5341     if ( event
.Entering() || event
.Leaving() ) 
5343         ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
, m_rowLabelWin
); 
5346     // ------------ Left button pressed 
5348     else if ( event
.LeftDown() ) 
5350         // don't send a label click event for a hit on the 
5351         // edge of the row label - this is probably the user 
5352         // wanting to resize the row 
5354         if ( YToEdgeOfRow(y
) < 0 ) 
5358                  !SendEvent( wxEVT_GRID_LABEL_LEFT_CLICK
, row
, -1, event 
) ) 
5360                 if ( !event
.ShiftDown() && !event
.CmdDown() ) 
5364                     if ( event
.ShiftDown() ) 
5366                         m_selection
->SelectBlock( m_currentCellCoords
.GetRow(), 
5369                                                   GetNumberCols() - 1, 
5370                                                   event
.ControlDown(), 
5377                         m_selection
->SelectRow( row
, 
5378                                                 event
.ControlDown(), 
5385                 ChangeCursorMode(WXGRID_CURSOR_SELECT_ROW
, m_rowLabelWin
); 
5390             // starting to drag-resize a row 
5391             if ( CanDragRowSize() ) 
5392                 ChangeCursorMode(WXGRID_CURSOR_RESIZE_ROW
, m_rowLabelWin
); 
5396     // ------------ Left double click 
5398     else if (event
.LeftDClick() ) 
5400         row 
= YToEdgeOfRow(y
); 
5405                  !SendEvent( wxEVT_GRID_LABEL_LEFT_DCLICK
, row
, -1, event 
) ) 
5407                 // no default action at the moment 
5412             // adjust row height depending on label text 
5413             AutoSizeRowLabelSize( row 
); 
5415             ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
, m_colLabelWin
); 
5420     // ------------ Left button released 
5422     else if ( event
.LeftUp() ) 
5424         if ( m_cursorMode 
== WXGRID_CURSOR_RESIZE_ROW 
) 
5426             DoEndDragResizeRow(); 
5428             // Note: we are ending the event *after* doing 
5429             // default processing in this case 
5431             SendEvent( wxEVT_GRID_ROW_SIZE
, m_dragRowOrCol
, -1, event 
); 
5434         ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
, m_rowLabelWin
); 
5438     // ------------ Right button down 
5440     else if ( event
.RightDown() ) 
5444              !SendEvent( wxEVT_GRID_LABEL_RIGHT_CLICK
, row
, -1, event 
) ) 
5446             // no default action at the moment 
5450     // ------------ Right double click 
5452     else if ( event
.RightDClick() ) 
5456              !SendEvent( wxEVT_GRID_LABEL_RIGHT_DCLICK
, row
, -1, event 
) ) 
5458             // no default action at the moment 
5462     // ------------ No buttons down and mouse moving 
5464     else if ( event
.Moving() ) 
5466         m_dragRowOrCol 
= YToEdgeOfRow( y 
); 
5467         if ( m_dragRowOrCol 
>= 0 ) 
5469             if ( m_cursorMode 
== WXGRID_CURSOR_SELECT_CELL 
) 
5471                 // don't capture the mouse yet 
5472                 if ( CanDragRowSize() ) 
5473                     ChangeCursorMode(WXGRID_CURSOR_RESIZE_ROW
, m_rowLabelWin
, false); 
5476         else if ( m_cursorMode 
!= WXGRID_CURSOR_SELECT_CELL 
) 
5478             ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
, m_rowLabelWin
, false); 
5483 void wxGrid::ProcessColLabelMouseEvent( wxMouseEvent
& event 
) 
5486     wxPoint 
pos( event
.GetPosition() ); 
5487     CalcUnscrolledPosition( pos
.x
, pos
.y
, &x
, &y 
); 
5489     if ( event
.Dragging() ) 
5493             m_isDragging 
= true; 
5494             m_colLabelWin
->CaptureMouse(); 
5496             if ( m_cursorMode 
== WXGRID_CURSOR_MOVE_COL 
) 
5497                 m_dragRowOrCol 
= XToCol( x 
); 
5500         if ( event
.LeftIsDown() ) 
5502             switch ( m_cursorMode 
) 
5504                 case WXGRID_CURSOR_RESIZE_COL
: 
5506                     int cw
, ch
, dummy
, top
; 
5507                     m_gridWin
->GetClientSize( &cw
, &ch 
); 
5508                     CalcUnscrolledPosition( 0, 0, &dummy
, &top 
); 
5510                     wxClientDC 
dc( m_gridWin 
); 
5513                     x 
= wxMax( x
, GetColLeft(m_dragRowOrCol
) + 
5514                                   GetColMinimalWidth(m_dragRowOrCol
)); 
5515                     dc
.SetLogicalFunction(wxINVERT
); 
5516                     if ( m_dragLastPos 
>= 0 ) 
5518                         dc
.DrawLine( m_dragLastPos
, top
, m_dragLastPos
, top 
+ ch 
); 
5520                     dc
.DrawLine( x
, top
, x
, top 
+ ch 
); 
5525                 case WXGRID_CURSOR_SELECT_COL
: 
5527                     if ( (col 
= XToCol( x 
)) >= 0 ) 
5531                             m_selection
->SelectCol( col
, 
5532                                                     event
.ControlDown(), 
5541                 case WXGRID_CURSOR_MOVE_COL
: 
5544                         m_moveToCol 
= GetColAt( 0 ); 
5546                         m_moveToCol 
= XToCol( x 
); 
5550                     if ( m_moveToCol 
< 0 ) 
5551                         markerX 
= GetColRight( GetColAt( m_numCols 
- 1 ) ); 
5553                         markerX 
= GetColLeft( m_moveToCol 
); 
5555                     if ( markerX 
!= m_dragLastPos 
) 
5557                         wxClientDC 
dc( m_colLabelWin 
); 
5560                         m_colLabelWin
->GetClientSize( &cw
, &ch 
); 
5564                         //Clean up the last indicator 
5565                         if ( m_dragLastPos 
>= 0 ) 
5567                             wxPen 
pen( m_colLabelWin
->GetBackgroundColour(), 2 ); 
5569                             dc
.DrawLine( m_dragLastPos 
+ 1, 0, m_dragLastPos 
+ 1, ch 
); 
5570                             dc
.SetPen(wxNullPen
); 
5572                             if ( XToCol( m_dragLastPos 
) != -1 ) 
5573                                 DrawColLabel( dc
, XToCol( m_dragLastPos 
) ); 
5576                         //Moving to the same place? Don't draw a marker 
5577                         if ( (m_moveToCol 
== m_dragRowOrCol
) 
5578                           || (GetColPos( m_moveToCol 
) == GetColPos( m_dragRowOrCol 
) + 1) 
5579                           || (m_moveToCol 
< 0 && m_dragRowOrCol 
== GetColAt( m_numCols 
- 1 ))) 
5586                         wxPen 
pen( *wxBLUE
, 2 ); 
5589                         dc
.DrawLine( markerX
, 0, markerX
, ch 
); 
5591                         dc
.SetPen(wxNullPen
); 
5593                         m_dragLastPos 
= markerX 
- 1; 
5598                 // default label to suppress warnings about "enumeration value 
5599                 // 'xxx' not handled in switch 
5607     if ( m_isDragging 
&& (event
.Entering() || event
.Leaving()) ) 
5612         if (m_colLabelWin
->HasCapture()) 
5613             m_colLabelWin
->ReleaseMouse(); 
5614         m_isDragging 
= false; 
5617     // ------------ Entering or leaving the window 
5619     if ( event
.Entering() || event
.Leaving() ) 
5621         ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
, m_colLabelWin
); 
5624     // ------------ Left button pressed 
5626     else if ( event
.LeftDown() ) 
5628         // don't send a label click event for a hit on the 
5629         // edge of the col label - this is probably the user 
5630         // wanting to resize the col 
5632         if ( XToEdgeOfCol(x
) < 0 ) 
5636                  !SendEvent( wxEVT_GRID_LABEL_LEFT_CLICK
, -1, col
, event 
) ) 
5638                 if ( m_canDragColMove 
) 
5640                     //Show button as pressed 
5641                     wxClientDC 
dc( m_colLabelWin 
); 
5642                     int colLeft 
= GetColLeft( col 
); 
5643                     int colRight 
= GetColRight( col 
) - 1; 
5644                     dc
.SetPen( wxPen( m_colLabelWin
->GetBackgroundColour(), 1 ) ); 
5645                     dc
.DrawLine( colLeft
, 1, colLeft
, m_colLabelHeight
-1 ); 
5646                     dc
.DrawLine( colLeft
, 1, colRight
, 1 ); 
5648                     ChangeCursorMode(WXGRID_CURSOR_MOVE_COL
, m_colLabelWin
); 
5652                     if ( !event
.ShiftDown() && !event
.CmdDown() ) 
5656                         if ( event
.ShiftDown() ) 
5658                             m_selection
->SelectBlock( 0, 
5659                                                       m_currentCellCoords
.GetCol(), 
5660                                                       GetNumberRows() - 1, col
, 
5661                                                       event
.ControlDown(), 
5668                             m_selection
->SelectCol( col
, 
5669                                                     event
.ControlDown(), 
5676                     ChangeCursorMode(WXGRID_CURSOR_SELECT_COL
, m_colLabelWin
); 
5682             // starting to drag-resize a col 
5684             if ( CanDragColSize() ) 
5685                 ChangeCursorMode(WXGRID_CURSOR_RESIZE_COL
, m_colLabelWin
); 
5689     // ------------ Left double click 
5691     if ( event
.LeftDClick() ) 
5693         col 
= XToEdgeOfCol(x
); 
5698                  ! SendEvent( wxEVT_GRID_LABEL_LEFT_DCLICK
, -1, col
, event 
) ) 
5700                 // no default action at the moment 
5705             // adjust column width depending on label text 
5706             AutoSizeColLabelSize( col 
); 
5708             ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
, m_colLabelWin
); 
5713     // ------------ Left button released 
5715     else if ( event
.LeftUp() ) 
5717         switch ( m_cursorMode 
) 
5719             case WXGRID_CURSOR_RESIZE_COL
: 
5720                 DoEndDragResizeCol(); 
5722                 // Note: we are ending the event *after* doing 
5723                 // default processing in this case 
5725                 SendEvent( wxEVT_GRID_COL_SIZE
, -1, m_dragRowOrCol
, event 
); 
5728             case WXGRID_CURSOR_MOVE_COL
: 
5731                 SendEvent( wxEVT_GRID_COL_MOVE
, -1, m_dragRowOrCol
, event 
); 
5734             case WXGRID_CURSOR_SELECT_COL
: 
5735             case WXGRID_CURSOR_SELECT_CELL
: 
5736             case WXGRID_CURSOR_RESIZE_ROW
: 
5737             case WXGRID_CURSOR_SELECT_ROW
: 
5738                 // nothing to do (?) 
5742         ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
, m_colLabelWin
); 
5746     // ------------ Right button down 
5748     else if ( event
.RightDown() ) 
5752              !SendEvent( wxEVT_GRID_LABEL_RIGHT_CLICK
, -1, col
, event 
) ) 
5754             // no default action at the moment 
5758     // ------------ Right double click 
5760     else if ( event
.RightDClick() ) 
5764              !SendEvent( wxEVT_GRID_LABEL_RIGHT_DCLICK
, -1, col
, event 
) ) 
5766             // no default action at the moment 
5770     // ------------ No buttons down and mouse moving 
5772     else if ( event
.Moving() ) 
5774         m_dragRowOrCol 
= XToEdgeOfCol( x 
); 
5775         if ( m_dragRowOrCol 
>= 0 ) 
5777             if ( m_cursorMode 
== WXGRID_CURSOR_SELECT_CELL 
) 
5779                 // don't capture the cursor yet 
5780                 if ( CanDragColSize() ) 
5781                     ChangeCursorMode(WXGRID_CURSOR_RESIZE_COL
, m_colLabelWin
, false); 
5784         else if ( m_cursorMode 
!= WXGRID_CURSOR_SELECT_CELL 
) 
5786             ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
, m_colLabelWin
, false); 
5791 void wxGrid::ProcessCornerLabelMouseEvent( wxMouseEvent
& event 
) 
5793     if ( event
.LeftDown() ) 
5795         // indicate corner label by having both row and 
5798         if ( !SendEvent( wxEVT_GRID_LABEL_LEFT_CLICK
, -1, -1, event 
) ) 
5803     else if ( event
.LeftDClick() ) 
5805         SendEvent( wxEVT_GRID_LABEL_LEFT_DCLICK
, -1, -1, event 
); 
5807     else if ( event
.RightDown() ) 
5809         if ( !SendEvent( wxEVT_GRID_LABEL_RIGHT_CLICK
, -1, -1, event 
) ) 
5811             // no default action at the moment 
5814     else if ( event
.RightDClick() ) 
5816         if ( !SendEvent( wxEVT_GRID_LABEL_RIGHT_DCLICK
, -1, -1, event 
) ) 
5818             // no default action at the moment 
5823 void wxGrid::CancelMouseCapture() 
5825     // cancel operation currently in progress, whatever it is 
5828         m_isDragging 
= false; 
5829         m_cursorMode 
= WXGRID_CURSOR_SELECT_CELL
; 
5830         m_winCapture
->SetCursor( *wxSTANDARD_CURSOR 
); 
5831         m_winCapture 
= NULL
; 
5833         // remove traces of whatever we drew on screen 
5838 void wxGrid::ChangeCursorMode(CursorMode mode
, 
5843     static const wxChar 
*cursorModes
[] = 
5853     wxLogTrace(_T("grid"), 
5854                _T("wxGrid cursor mode (mouse capture for %s): %s -> %s"), 
5855                win 
== m_colLabelWin 
? _T("colLabelWin") 
5856                                     : win 
? _T("rowLabelWin") 
5858                cursorModes
[m_cursorMode
], cursorModes
[mode
]); 
5861     if ( mode 
== m_cursorMode 
&& 
5862          win 
== m_winCapture 
&& 
5863          captureMouse 
== (m_winCapture 
!= NULL
)) 
5868         // by default use the grid itself 
5874         if (m_winCapture
->HasCapture()) 
5875             m_winCapture
->ReleaseMouse(); 
5876         m_winCapture 
= (wxWindow 
*)NULL
; 
5879     m_cursorMode 
= mode
; 
5881     switch ( m_cursorMode 
) 
5883         case WXGRID_CURSOR_RESIZE_ROW
: 
5884             win
->SetCursor( m_rowResizeCursor 
); 
5887         case WXGRID_CURSOR_RESIZE_COL
: 
5888             win
->SetCursor( m_colResizeCursor 
); 
5891         case WXGRID_CURSOR_MOVE_COL
: 
5892             win
->SetCursor( wxCursor(wxCURSOR_HAND
) ); 
5896             win
->SetCursor( *wxSTANDARD_CURSOR 
); 
5900     // we need to capture mouse when resizing 
5901     bool resize 
= m_cursorMode 
== WXGRID_CURSOR_RESIZE_ROW 
|| 
5902                   m_cursorMode 
== WXGRID_CURSOR_RESIZE_COL
; 
5904     if ( captureMouse 
&& resize 
) 
5906         win
->CaptureMouse(); 
5911 void wxGrid::ProcessGridCellMouseEvent( wxMouseEvent
& event 
) 
5914     wxPoint 
pos( event
.GetPosition() ); 
5915     CalcUnscrolledPosition( pos
.x
, pos
.y
, &x
, &y 
); 
5917     wxGridCellCoords coords
; 
5918     XYToCell( x
, y
, coords 
); 
5920     int cell_rows
, cell_cols
; 
5921     bool isFirstDrag 
= !m_isDragging
; 
5922     GetCellSize( coords
.GetRow(), coords
.GetCol(), &cell_rows
, &cell_cols 
); 
5923     if ((cell_rows 
< 0) || (cell_cols 
< 0)) 
5925         coords
.SetRow(coords
.GetRow() + cell_rows
); 
5926         coords
.SetCol(coords
.GetCol() + cell_cols
); 
5929     if ( event
.Dragging() ) 
5931         //wxLogDebug("pos(%d, %d) coords(%d, %d)", pos.x, pos.y, coords.GetRow(), coords.GetCol()); 
5933         // Don't start doing anything until the mouse has been dragged at 
5934         // least 3 pixels in any direction... 
5937             if (m_startDragPos 
== wxDefaultPosition
) 
5939                 m_startDragPos 
= pos
; 
5942             if (abs(m_startDragPos
.x 
- pos
.x
) < 4 && abs(m_startDragPos
.y 
- pos
.y
) < 4) 
5946         m_isDragging 
= true; 
5947         if ( m_cursorMode 
== WXGRID_CURSOR_SELECT_CELL 
) 
5949             // Hide the edit control, so it 
5950             // won't interfere with drag-shrinking. 
5951             if ( IsCellEditControlShown() ) 
5953                 HideCellEditControl(); 
5954                 SaveEditControlValue(); 
5957             if ( coords 
!= wxGridNoCellCoords 
) 
5959                 if ( event
.CmdDown() ) 
5961                     if ( m_selectingKeyboard 
== wxGridNoCellCoords
) 
5962                         m_selectingKeyboard 
= coords
; 
5963                     HighlightBlock( m_selectingKeyboard
, coords 
); 
5965                 else if ( CanDragCell() ) 
5969                         if ( m_selectingKeyboard 
== wxGridNoCellCoords
) 
5970                             m_selectingKeyboard 
= coords
; 
5972                         SendEvent( wxEVT_GRID_CELL_BEGIN_DRAG
, 
5981                     if ( !IsSelection() ) 
5983                         HighlightBlock( coords
, coords 
); 
5987                         HighlightBlock( m_currentCellCoords
, coords 
); 
5991                 if (! IsVisible(coords
)) 
5993                     MakeCellVisible(coords
); 
5994                     // TODO: need to introduce a delay or something here.  The 
5995                     // scrolling is way to fast, at least on MSW - also on GTK. 
5998             // Have we captured the mouse yet? 
6001                 m_winCapture 
= m_gridWin
; 
6002                 m_winCapture
->CaptureMouse(); 
6007         else if ( m_cursorMode 
== WXGRID_CURSOR_RESIZE_ROW 
) 
6009             int cw
, ch
, left
, dummy
; 
6010             m_gridWin
->GetClientSize( &cw
, &ch 
); 
6011             CalcUnscrolledPosition( 0, 0, &left
, &dummy 
); 
6013             wxClientDC 
dc( m_gridWin 
); 
6015             y 
= wxMax( y
, GetRowTop(m_dragRowOrCol
) + 
6016                           GetRowMinimalHeight(m_dragRowOrCol
) ); 
6017             dc
.SetLogicalFunction(wxINVERT
); 
6018             if ( m_dragLastPos 
>= 0 ) 
6020                 dc
.DrawLine( left
, m_dragLastPos
, left
+cw
, m_dragLastPos 
); 
6022             dc
.DrawLine( left
, y
, left
+cw
, y 
); 
6025         else if ( m_cursorMode 
== WXGRID_CURSOR_RESIZE_COL 
) 
6027             int cw
, ch
, dummy
, top
; 
6028             m_gridWin
->GetClientSize( &cw
, &ch 
); 
6029             CalcUnscrolledPosition( 0, 0, &dummy
, &top 
); 
6031             wxClientDC 
dc( m_gridWin 
); 
6033             x 
= wxMax( x
, GetColLeft(m_dragRowOrCol
) + 
6034                           GetColMinimalWidth(m_dragRowOrCol
) ); 
6035             dc
.SetLogicalFunction(wxINVERT
); 
6036             if ( m_dragLastPos 
>= 0 ) 
6038                 dc
.DrawLine( m_dragLastPos
, top
, m_dragLastPos
, top 
+ ch 
); 
6040             dc
.DrawLine( x
, top
, x
, top 
+ ch 
); 
6047     m_isDragging 
= false; 
6048     m_startDragPos 
= wxDefaultPosition
; 
6050     // VZ: if we do this, the mode is reset to WXGRID_CURSOR_SELECT_CELL 
6051     //     immediately after it becomes WXGRID_CURSOR_RESIZE_ROW/COL under 
6054     if ( event
.Entering() || event
.Leaving() ) 
6056         ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
); 
6057         m_gridWin
->SetCursor( *wxSTANDARD_CURSOR 
); 
6062     // ------------ Left button pressed 
6064     if ( event
.LeftDown() && coords 
!= wxGridNoCellCoords 
) 
6066         if ( !SendEvent( wxEVT_GRID_CELL_LEFT_CLICK
, 
6071             if ( !event
.CmdDown() ) 
6073             if ( event
.ShiftDown() ) 
6077                     m_selection
->SelectBlock( m_currentCellCoords
.GetRow(), 
6078                                               m_currentCellCoords
.GetCol(), 
6081                                               event
.ControlDown(), 
6087             else if ( XToEdgeOfCol(x
) < 0 && 
6088                       YToEdgeOfRow(y
) < 0 ) 
6090                 DisableCellEditControl(); 
6091                 MakeCellVisible( coords 
); 
6093                 if ( event
.CmdDown() ) 
6097                         m_selection
->ToggleCellSelection( coords
.GetRow(), 
6099                                                           event
.ControlDown(), 
6104                     m_selectingTopLeft 
= wxGridNoCellCoords
; 
6105                     m_selectingBottomRight 
= wxGridNoCellCoords
; 
6106                     m_selectingKeyboard 
= coords
; 
6110                     m_waitForSlowClick 
= m_currentCellCoords 
== coords 
&& coords 
!= wxGridNoCellCoords
; 
6111                     SetCurrentCell( coords 
); 
6114                         if ( m_selection
->GetSelectionMode() != 
6115                                 wxGrid::wxGridSelectCells 
) 
6117                             HighlightBlock( coords
, coords 
); 
6125     // ------------ Left double click 
6127     else if ( event
.LeftDClick() && coords 
!= wxGridNoCellCoords 
) 
6129         DisableCellEditControl(); 
6131         if ( XToEdgeOfCol(x
) < 0 && YToEdgeOfRow(y
) < 0 ) 
6133             if ( !SendEvent( wxEVT_GRID_CELL_LEFT_DCLICK
, 
6138                 // we want double click to select a cell and start editing 
6139                 // (i.e. to behave in same way as sequence of two slow clicks): 
6140                 m_waitForSlowClick 
= true; 
6145     // ------------ Left button released 
6147     else if ( event
.LeftUp() ) 
6149         if ( m_cursorMode 
== WXGRID_CURSOR_SELECT_CELL 
) 
6153                 if (m_winCapture
->HasCapture()) 
6154                     m_winCapture
->ReleaseMouse(); 
6155                 m_winCapture 
= NULL
; 
6158             if ( coords 
== m_currentCellCoords 
&& m_waitForSlowClick 
&& CanEnableCellControl() ) 
6161                 EnableCellEditControl(); 
6163                 wxGridCellAttr 
*attr 
= GetCellAttr(coords
); 
6164                 wxGridCellEditor 
*editor 
= attr
->GetEditor(this, coords
.GetRow(), coords
.GetCol()); 
6165                 editor
->StartingClick(); 
6169                 m_waitForSlowClick 
= false; 
6171             else if ( m_selectingTopLeft 
!= wxGridNoCellCoords 
&& 
6172                  m_selectingBottomRight 
!= wxGridNoCellCoords 
) 
6176                     m_selection
->SelectBlock( m_selectingTopLeft
.GetRow(), 
6177                                               m_selectingTopLeft
.GetCol(), 
6178                                               m_selectingBottomRight
.GetRow(), 
6179                                               m_selectingBottomRight
.GetCol(), 
6180                                               event
.ControlDown(), 
6186                 m_selectingTopLeft 
= wxGridNoCellCoords
; 
6187                 m_selectingBottomRight 
= wxGridNoCellCoords
; 
6189                 // Show the edit control, if it has been hidden for 
6191                 ShowCellEditControl(); 
6194         else if ( m_cursorMode 
== WXGRID_CURSOR_RESIZE_ROW 
) 
6196             ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
); 
6197             DoEndDragResizeRow(); 
6199             // Note: we are ending the event *after* doing 
6200             // default processing in this case 
6202             SendEvent( wxEVT_GRID_ROW_SIZE
, m_dragRowOrCol
, -1, event 
); 
6204         else if ( m_cursorMode 
== WXGRID_CURSOR_RESIZE_COL 
) 
6206             ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
); 
6207             DoEndDragResizeCol(); 
6209             // Note: we are ending the event *after* doing 
6210             // default processing in this case 
6212             SendEvent( wxEVT_GRID_COL_SIZE
, -1, m_dragRowOrCol
, event 
); 
6218     // ------------ Right button down 
6220     else if ( event
.RightDown() && coords 
!= wxGridNoCellCoords 
) 
6222         DisableCellEditControl(); 
6223         if ( !SendEvent( wxEVT_GRID_CELL_RIGHT_CLICK
, 
6228             // no default action at the moment 
6232     // ------------ Right double click 
6234     else if ( event
.RightDClick() && coords 
!= wxGridNoCellCoords 
) 
6236         DisableCellEditControl(); 
6237         if ( !SendEvent( wxEVT_GRID_CELL_RIGHT_DCLICK
, 
6242             // no default action at the moment 
6246     // ------------ Moving and no button action 
6248     else if ( event
.Moving() && !event
.IsButton() ) 
6250         if ( coords
.GetRow() < 0 || coords
.GetCol() < 0 ) 
6252             // out of grid cell area 
6253             ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
); 
6257         int dragRow 
= YToEdgeOfRow( y 
); 
6258         int dragCol 
= XToEdgeOfCol( x 
); 
6260         // Dragging on the corner of a cell to resize in both 
6261         // directions is not implemented yet... 
6263         if ( dragRow 
>= 0 && dragCol 
>= 0 ) 
6265             ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
); 
6271             m_dragRowOrCol 
= dragRow
; 
6273             if ( m_cursorMode 
== WXGRID_CURSOR_SELECT_CELL 
) 
6275                 if ( CanDragRowSize() && CanDragGridSize() ) 
6276                     ChangeCursorMode(WXGRID_CURSOR_RESIZE_ROW
, NULL
, false); 
6279         else if ( dragCol 
>= 0 ) 
6281             m_dragRowOrCol 
= dragCol
; 
6283             if ( m_cursorMode 
== WXGRID_CURSOR_SELECT_CELL 
) 
6285                 if ( CanDragColSize() && CanDragGridSize() ) 
6286                     ChangeCursorMode(WXGRID_CURSOR_RESIZE_COL
, NULL
, false); 
6289         else // Neither on a row or col edge 
6291             if ( m_cursorMode 
!= WXGRID_CURSOR_SELECT_CELL 
) 
6293                 ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
); 
6299 void wxGrid::DoEndDragResizeRow() 
6301     if ( m_dragLastPos 
>= 0 ) 
6303         // erase the last line and resize the row 
6305         int cw
, ch
, left
, dummy
; 
6306         m_gridWin
->GetClientSize( &cw
, &ch 
); 
6307         CalcUnscrolledPosition( 0, 0, &left
, &dummy 
); 
6309         wxClientDC 
dc( m_gridWin 
); 
6311         dc
.SetLogicalFunction( wxINVERT 
); 
6312         dc
.DrawLine( left
, m_dragLastPos
, left 
+ cw
, m_dragLastPos 
); 
6313         HideCellEditControl(); 
6314         SaveEditControlValue(); 
6316         int rowTop 
= GetRowTop(m_dragRowOrCol
); 
6317         SetRowSize( m_dragRowOrCol
, 
6318                     wxMax( m_dragLastPos 
- rowTop
, m_minAcceptableRowHeight 
) ); 
6320         if ( !GetBatchCount() ) 
6322             // Only needed to get the correct rect.y: 
6323             wxRect 
rect ( CellToRect( m_dragRowOrCol
, 0 ) ); 
6325             CalcScrolledPosition(0, rect
.y
, &dummy
, &rect
.y
); 
6326             rect
.width 
= m_rowLabelWidth
; 
6327             rect
.height 
= ch 
- rect
.y
; 
6328             m_rowLabelWin
->Refresh( true, &rect 
); 
6331             // if there is a multicell block, paint all of it 
6334                 int i
, cell_rows
, cell_cols
, subtract_rows 
= 0; 
6335                 int leftCol 
= XToCol(left
); 
6336                 int rightCol 
= internalXToCol(left 
+ cw
); 
6339                     for (i
=leftCol
; i
<rightCol
; i
++) 
6341                         GetCellSize(m_dragRowOrCol
, i
, &cell_rows
, &cell_cols
); 
6342                         if (cell_rows 
< subtract_rows
) 
6343                             subtract_rows 
= cell_rows
; 
6345                     rect
.y 
= GetRowTop(m_dragRowOrCol 
+ subtract_rows
); 
6346                     CalcScrolledPosition(0, rect
.y
, &dummy
, &rect
.y
); 
6347                     rect
.height 
= ch 
- rect
.y
; 
6350             m_gridWin
->Refresh( false, &rect 
); 
6353         ShowCellEditControl(); 
6358 void wxGrid::DoEndDragResizeCol() 
6360     if ( m_dragLastPos 
>= 0 ) 
6362         // erase the last line and resize the col 
6364         int cw
, ch
, dummy
, top
; 
6365         m_gridWin
->GetClientSize( &cw
, &ch 
); 
6366         CalcUnscrolledPosition( 0, 0, &dummy
, &top 
); 
6368         wxClientDC 
dc( m_gridWin 
); 
6370         dc
.SetLogicalFunction( wxINVERT 
); 
6371         dc
.DrawLine( m_dragLastPos
, top
, m_dragLastPos
, top 
+ ch 
); 
6372         HideCellEditControl(); 
6373         SaveEditControlValue(); 
6375         int colLeft 
= GetColLeft(m_dragRowOrCol
); 
6376         SetColSize( m_dragRowOrCol
, 
6377                     wxMax( m_dragLastPos 
- colLeft
, 
6378                            GetColMinimalWidth(m_dragRowOrCol
) ) ); 
6380         if ( !GetBatchCount() ) 
6382             // Only needed to get the correct rect.x: 
6383             wxRect 
rect ( CellToRect( 0, m_dragRowOrCol 
) ); 
6385             CalcScrolledPosition(rect
.x
, 0, &rect
.x
, &dummy
); 
6386             rect
.width 
= cw 
- rect
.x
; 
6387             rect
.height 
= m_colLabelHeight
; 
6388             m_colLabelWin
->Refresh( true, &rect 
); 
6391             // if there is a multicell block, paint all of it 
6394                 int i
, cell_rows
, cell_cols
, subtract_cols 
= 0; 
6395                 int topRow 
= YToRow(top
); 
6396                 int bottomRow 
= internalYToRow(top 
+ cw
); 
6399                     for (i
=topRow
; i
<bottomRow
; i
++) 
6401                         GetCellSize(i
, m_dragRowOrCol
, &cell_rows
, &cell_cols
); 
6402                         if (cell_cols 
< subtract_cols
) 
6403                             subtract_cols 
= cell_cols
; 
6406                     rect
.x 
= GetColLeft(m_dragRowOrCol 
+ subtract_cols
); 
6407                     CalcScrolledPosition(rect
.x
, 0, &rect
.x
, &dummy
); 
6408                     rect
.width 
= cw 
- rect
.x
; 
6412             m_gridWin
->Refresh( false, &rect 
); 
6415         ShowCellEditControl(); 
6419 void wxGrid::DoEndDragMoveCol() 
6421     //The user clicked on the column but didn't actually drag 
6422     if ( m_dragLastPos 
< 0 ) 
6424         m_colLabelWin
->Refresh();   //Do this to "unpress" the column 
6429     if ( m_moveToCol 
== -1 ) 
6430         newPos 
= m_numCols 
- 1; 
6433         newPos 
= GetColPos( m_moveToCol 
); 
6434         if ( newPos 
> GetColPos( m_dragRowOrCol 
) ) 
6438     SetColPos( m_dragRowOrCol
, newPos 
); 
6441 void wxGrid::SetColPos( int colID
, int newPos 
) 
6443     if ( m_colAt
.IsEmpty() ) 
6445         m_colAt
.Alloc( m_numCols 
); 
6448         for ( i 
= 0; i 
< m_numCols
; i
++ ) 
6454     int oldPos 
= GetColPos( colID 
); 
6456     //Reshuffle the m_colAt array 
6457     if ( newPos 
> oldPos 
) 
6460         for ( i 
= oldPos
; i 
< newPos
; i
++ ) 
6462             m_colAt
[i
] = m_colAt
[i
+1]; 
6468         for ( i 
= oldPos
; i 
> newPos
; i
-- ) 
6470             m_colAt
[i
] = m_colAt
[i
-1]; 
6474     m_colAt
[newPos
] = colID
; 
6476     //Recalculate the column rights 
6477     if ( !m_colWidths
.IsEmpty() ) 
6481         for ( colPos 
= 0; colPos 
< m_numCols
; colPos
++ ) 
6483             int colID 
= GetColAt( colPos 
); 
6485             colRight 
+= m_colWidths
[colID
]; 
6486             m_colRights
[colID
] = colRight
; 
6490     m_colLabelWin
->Refresh(); 
6491     m_gridWin
->Refresh(); 
6496 void wxGrid::EnableDragColMove( bool enable 
) 
6498     if ( m_canDragColMove 
== enable 
) 
6501     m_canDragColMove 
= enable
; 
6503     if ( !m_canDragColMove 
) 
6507         //Recalculate the column rights 
6508         if ( !m_colWidths
.IsEmpty() ) 
6512             for ( colPos 
= 0; colPos 
< m_numCols
; colPos
++ ) 
6514                 colRight 
+= m_colWidths
[colPos
]; 
6515                 m_colRights
[colPos
] = colRight
; 
6519         m_colLabelWin
->Refresh(); 
6520         m_gridWin
->Refresh(); 
6526 // ------ interaction with data model 
6528 bool wxGrid::ProcessTableMessage( wxGridTableMessage
& msg 
) 
6530     switch ( msg
.GetId() ) 
6532         case wxGRIDTABLE_REQUEST_VIEW_GET_VALUES
: 
6533             return GetModelValues(); 
6535         case wxGRIDTABLE_REQUEST_VIEW_SEND_VALUES
: 
6536             return SetModelValues(); 
6538         case wxGRIDTABLE_NOTIFY_ROWS_INSERTED
: 
6539         case wxGRIDTABLE_NOTIFY_ROWS_APPENDED
: 
6540         case wxGRIDTABLE_NOTIFY_ROWS_DELETED
: 
6541         case wxGRIDTABLE_NOTIFY_COLS_INSERTED
: 
6542         case wxGRIDTABLE_NOTIFY_COLS_APPENDED
: 
6543         case wxGRIDTABLE_NOTIFY_COLS_DELETED
: 
6544             return Redimension( msg 
); 
6551 // The behaviour of this function depends on the grid table class 
6552 // Clear() function. For the default wxGridStringTable class the 
6553 // behavious is to replace all cell contents with wxEmptyString but 
6554 // not to change the number of rows or cols. 
6556 void wxGrid::ClearGrid() 
6560         if (IsCellEditControlEnabled()) 
6561             DisableCellEditControl(); 
6564         if (!GetBatchCount()) 
6565             m_gridWin
->Refresh(); 
6569 bool wxGrid::InsertRows( int pos
, int numRows
, bool WXUNUSED(updateLabels
) ) 
6571     // TODO: something with updateLabels flag 
6575         wxFAIL_MSG( wxT("Called wxGrid::InsertRows() before calling CreateGrid()") ); 
6581         if (IsCellEditControlEnabled()) 
6582             DisableCellEditControl(); 
6584         bool done 
= m_table
->InsertRows( pos
, numRows 
); 
6587         // the table will have sent the results of the insert row 
6588         // operation to this view object as a grid table message 
6594 bool wxGrid::AppendRows( int numRows
, bool WXUNUSED(updateLabels
) ) 
6596     // TODO: something with updateLabels flag 
6600         wxFAIL_MSG( wxT("Called wxGrid::AppendRows() before calling CreateGrid()") ); 
6606         bool done 
= m_table 
&& m_table
->AppendRows( numRows 
); 
6609         // the table will have sent the results of the append row 
6610         // operation to this view object as a grid table message 
6616 bool wxGrid::DeleteRows( int pos
, int numRows
, bool WXUNUSED(updateLabels
) ) 
6618     // TODO: something with updateLabels flag 
6622         wxFAIL_MSG( wxT("Called wxGrid::DeleteRows() before calling CreateGrid()") ); 
6628         if (IsCellEditControlEnabled()) 
6629             DisableCellEditControl(); 
6631         bool done 
= m_table
->DeleteRows( pos
, numRows 
); 
6633         // the table will have sent the results of the delete row 
6634         // operation to this view object as a grid table message 
6640 bool wxGrid::InsertCols( int pos
, int numCols
, bool WXUNUSED(updateLabels
) ) 
6642     // TODO: something with updateLabels flag 
6646         wxFAIL_MSG( wxT("Called wxGrid::InsertCols() before calling CreateGrid()") ); 
6652         if (IsCellEditControlEnabled()) 
6653             DisableCellEditControl(); 
6655         bool done 
= m_table
->InsertCols( pos
, numCols 
); 
6657         // the table will have sent the results of the insert col 
6658         // operation to this view object as a grid table message 
6664 bool wxGrid::AppendCols( int numCols
, bool WXUNUSED(updateLabels
) ) 
6666     // TODO: something with updateLabels flag 
6670         wxFAIL_MSG( wxT("Called wxGrid::AppendCols() before calling CreateGrid()") ); 
6676         bool done 
= m_table
->AppendCols( numCols 
); 
6678         // the table will have sent the results of the append col 
6679         // operation to this view object as a grid table message 
6685 bool wxGrid::DeleteCols( int pos
, int numCols
, bool WXUNUSED(updateLabels
) ) 
6687     // TODO: something with updateLabels flag 
6691         wxFAIL_MSG( wxT("Called wxGrid::DeleteCols() before calling CreateGrid()") ); 
6697         if (IsCellEditControlEnabled()) 
6698             DisableCellEditControl(); 
6700         bool done 
= m_table
->DeleteCols( pos
, numCols 
); 
6702         // the table will have sent the results of the delete col 
6703         // operation to this view object as a grid table message 
6710 // ----- event handlers 
6713 // Generate a grid event based on a mouse event and 
6714 // return the result of ProcessEvent() 
6716 int wxGrid::SendEvent( const wxEventType type
, 
6718                         wxMouseEvent
& mouseEv 
) 
6720    bool claimed
, vetoed
; 
6722    if ( type 
== wxEVT_GRID_ROW_SIZE 
|| type 
== wxEVT_GRID_COL_SIZE 
) 
6724        int rowOrCol 
= (row 
== -1 ? col 
: row
); 
6726        wxGridSizeEvent 
gridEvt( GetId(), 
6730                mouseEv
.GetX() + GetRowLabelSize(), 
6731                mouseEv
.GetY() + GetColLabelSize(), 
6732                mouseEv
.ControlDown(), 
6733                mouseEv
.ShiftDown(), 
6735                mouseEv
.MetaDown() ); 
6737        claimed 
= GetEventHandler()->ProcessEvent(gridEvt
); 
6738        vetoed 
= !gridEvt
.IsAllowed(); 
6740    else if ( type 
== wxEVT_GRID_RANGE_SELECT 
) 
6742        // Right now, it should _never_ end up here! 
6743        wxGridRangeSelectEvent 
gridEvt( GetId(), 
6747                m_selectingBottomRight
, 
6749                mouseEv
.ControlDown(), 
6750                mouseEv
.ShiftDown(), 
6752                mouseEv
.MetaDown() ); 
6754        claimed 
= GetEventHandler()->ProcessEvent(gridEvt
); 
6755        vetoed 
= !gridEvt
.IsAllowed(); 
6757    else if ( type 
== wxEVT_GRID_LABEL_LEFT_CLICK 
|| 
6758              type 
== wxEVT_GRID_LABEL_LEFT_DCLICK 
|| 
6759              type 
== wxEVT_GRID_LABEL_RIGHT_CLICK 
|| 
6760              type 
== wxEVT_GRID_LABEL_RIGHT_DCLICK 
) 
6762        wxPoint pos 
= mouseEv
.GetPosition(); 
6764        if ( mouseEv
.GetEventObject() == GetGridRowLabelWindow() ) 
6765            pos
.y 
+= GetColLabelSize(); 
6766        if ( mouseEv
.GetEventObject() == GetGridColLabelWindow() ) 
6767            pos
.x 
+= GetRowLabelSize(); 
6769        wxGridEvent 
gridEvt( GetId(), 
6776                mouseEv
.ControlDown(), 
6777                mouseEv
.ShiftDown(), 
6779                mouseEv
.MetaDown() ); 
6780        claimed 
= GetEventHandler()->ProcessEvent(gridEvt
); 
6781        vetoed 
= !gridEvt
.IsAllowed(); 
6785        wxGridEvent 
gridEvt( GetId(), 
6789                mouseEv
.GetX() + GetRowLabelSize(), 
6790                mouseEv
.GetY() + GetColLabelSize(), 
6792                mouseEv
.ControlDown(), 
6793                mouseEv
.ShiftDown(), 
6795                mouseEv
.MetaDown() ); 
6796        claimed 
= GetEventHandler()->ProcessEvent(gridEvt
); 
6797        vetoed 
= !gridEvt
.IsAllowed(); 
6800    // A Veto'd event may not be `claimed' so test this first 
6804    return claimed 
? 1 : 0; 
6807 // Generate a grid event of specified type and return the result 
6808 // of ProcessEvent(). 
6810 int wxGrid::SendEvent( const wxEventType type
, 
6813    bool claimed
, vetoed
; 
6815     if ( type 
== wxEVT_GRID_ROW_SIZE 
|| type 
== wxEVT_GRID_COL_SIZE 
) 
6817         int rowOrCol 
= (row 
== -1 ? col 
: row
); 
6819         wxGridSizeEvent 
gridEvt( GetId(), type
, this, rowOrCol 
); 
6821         claimed 
= GetEventHandler()->ProcessEvent(gridEvt
); 
6822         vetoed  
= !gridEvt
.IsAllowed(); 
6826         wxGridEvent 
gridEvt( GetId(), type
, this, row
, col 
); 
6828         claimed 
= GetEventHandler()->ProcessEvent(gridEvt
); 
6829         vetoed  
= !gridEvt
.IsAllowed(); 
6832     // A Veto'd event may not be `claimed' so test this first 
6836     return claimed 
? 1 : 0; 
6839 void wxGrid::OnPaint( wxPaintEvent
& WXUNUSED(event
) ) 
6841     // needed to prevent zillions of paint events on MSW 
6845 void wxGrid::Refresh(bool eraseb
, const wxRect
* rect
) 
6847     // Don't do anything if between Begin/EndBatch... 
6848     // EndBatch() will do all this on the last nested one anyway. 
6849     if ( m_created 
&& !GetBatchCount() ) 
6851         // Refresh to get correct scrolled position: 
6852         wxScrolledWindow::Refresh(eraseb
, rect
); 
6856             int rect_x
, rect_y
, rectWidth
, rectHeight
; 
6857             int width_label
, width_cell
, height_label
, height_cell
; 
6860             // Copy rectangle can get scroll offsets.. 
6861             rect_x 
= rect
->GetX(); 
6862             rect_y 
= rect
->GetY(); 
6863             rectWidth 
= rect
->GetWidth(); 
6864             rectHeight 
= rect
->GetHeight(); 
6866             width_label 
= m_rowLabelWidth 
- rect_x
; 
6867             if (width_label 
> rectWidth
) 
6868                 width_label 
= rectWidth
; 
6870             height_label 
= m_colLabelHeight 
- rect_y
; 
6871             if (height_label 
> rectHeight
) 
6872                 height_label 
= rectHeight
; 
6874             if (rect_x 
> m_rowLabelWidth
) 
6876                 x 
= rect_x 
- m_rowLabelWidth
; 
6877                 width_cell 
= rectWidth
; 
6882                 width_cell 
= rectWidth 
- (m_rowLabelWidth 
- rect_x
); 
6885             if (rect_y 
> m_colLabelHeight
) 
6887                 y 
= rect_y 
- m_colLabelHeight
; 
6888                 height_cell 
= rectHeight
; 
6893                 height_cell 
= rectHeight 
- (m_colLabelHeight 
- rect_y
); 
6896             // Paint corner label part intersecting rect. 
6897             if ( width_label 
> 0 && height_label 
> 0 ) 
6899                 wxRect 
anotherrect(rect_x
, rect_y
, width_label
, height_label
); 
6900                 m_cornerLabelWin
->Refresh(eraseb
, &anotherrect
); 
6903             // Paint col labels part intersecting rect. 
6904             if ( width_cell 
> 0 && height_label 
> 0 ) 
6906                 wxRect 
anotherrect(x
, rect_y
, width_cell
, height_label
); 
6907                 m_colLabelWin
->Refresh(eraseb
, &anotherrect
); 
6910             // Paint row labels part intersecting rect. 
6911             if ( width_label 
> 0 && height_cell 
> 0 ) 
6913                 wxRect 
anotherrect(rect_x
, y
, width_label
, height_cell
); 
6914                 m_rowLabelWin
->Refresh(eraseb
, &anotherrect
); 
6917             // Paint cell area part intersecting rect. 
6918             if ( width_cell 
> 0 && height_cell 
> 0 ) 
6920                 wxRect 
anotherrect(x
, y
, width_cell
, height_cell
); 
6921                 m_gridWin
->Refresh(eraseb
, &anotherrect
); 
6926             m_cornerLabelWin
->Refresh(eraseb
, NULL
); 
6927             m_colLabelWin
->Refresh(eraseb
, NULL
); 
6928             m_rowLabelWin
->Refresh(eraseb
, NULL
); 
6929             m_gridWin
->Refresh(eraseb
, NULL
); 
6934 void wxGrid::OnSize(wxSizeEvent
& WXUNUSED(event
)) 
6936     if (m_targetWindow 
!= this) // check whether initialisation has been done 
6938         // update our children window positions and scrollbars 
6943 void wxGrid::OnKeyDown( wxKeyEvent
& event 
) 
6945     if ( m_inOnKeyDown 
) 
6947         // shouldn't be here - we are going round in circles... 
6949         wxFAIL_MSG( wxT("wxGrid::OnKeyDown called while already active") ); 
6952     m_inOnKeyDown 
= true; 
6954     // propagate the event up and see if it gets processed 
6955     wxWindow 
*parent 
= GetParent(); 
6956     wxKeyEvent 
keyEvt( event 
); 
6957     keyEvt
.SetEventObject( parent 
); 
6959     if ( !parent
->GetEventHandler()->ProcessEvent( keyEvt 
) ) 
6961         if (GetLayoutDirection() == wxLayout_RightToLeft
) 
6963             if (event
.GetKeyCode() == WXK_RIGHT
) 
6964                 event
.m_keyCode 
= WXK_LEFT
; 
6965             else if (event
.GetKeyCode() == WXK_LEFT
) 
6966                 event
.m_keyCode 
= WXK_RIGHT
; 
6969         // try local handlers 
6970         switch ( event
.GetKeyCode() ) 
6973                 if ( event
.ControlDown() ) 
6974                     MoveCursorUpBlock( event
.ShiftDown() ); 
6976                     MoveCursorUp( event
.ShiftDown() ); 
6980                 if ( event
.ControlDown() ) 
6981                     MoveCursorDownBlock( event
.ShiftDown() ); 
6983                     MoveCursorDown( event
.ShiftDown() ); 
6987                 if ( event
.ControlDown() ) 
6988                     MoveCursorLeftBlock( event
.ShiftDown() ); 
6990                     MoveCursorLeft( event
.ShiftDown() ); 
6994                 if ( event
.ControlDown() ) 
6995                     MoveCursorRightBlock( event
.ShiftDown() ); 
6997                     MoveCursorRight( event
.ShiftDown() ); 
7001             case WXK_NUMPAD_ENTER
: 
7002                 if ( event
.ControlDown() ) 
7004                     event
.Skip();  // to let the edit control have the return 
7008                     if ( GetGridCursorRow() < GetNumberRows()-1 ) 
7010                         MoveCursorDown( event
.ShiftDown() ); 
7014                         // at the bottom of a column 
7015                         DisableCellEditControl(); 
7025                 if (event
.ShiftDown()) 
7027                     if ( GetGridCursorCol() > 0 ) 
7029                         MoveCursorLeft( false ); 
7034                         DisableCellEditControl(); 
7039                     if ( GetGridCursorCol() < GetNumberCols() - 1 ) 
7041                         MoveCursorRight( false ); 
7046                         DisableCellEditControl(); 
7052                 if ( event
.ControlDown() ) 
7054                     MakeCellVisible( 0, 0 ); 
7055                     SetCurrentCell( 0, 0 ); 
7064                 if ( event
.ControlDown() ) 
7066                     MakeCellVisible( m_numRows 
- 1, m_numCols 
- 1 ); 
7067                     SetCurrentCell( m_numRows 
- 1, m_numCols 
- 1 ); 
7084                 if ( event
.ControlDown() ) 
7088                         m_selection
->ToggleCellSelection( 
7089                             m_currentCellCoords
.GetRow(), 
7090                             m_currentCellCoords
.GetCol(), 
7091                             event
.ControlDown(), 
7099                 if ( !IsEditable() ) 
7100                     MoveCursorRight( false ); 
7111     m_inOnKeyDown 
= false; 
7114 void wxGrid::OnKeyUp( wxKeyEvent
& event 
) 
7116     // try local handlers 
7118     if ( event
.GetKeyCode() == WXK_SHIFT 
) 
7120         if ( m_selectingTopLeft 
!= wxGridNoCellCoords 
&& 
7121              m_selectingBottomRight 
!= wxGridNoCellCoords 
) 
7125                 m_selection
->SelectBlock( 
7126                     m_selectingTopLeft
.GetRow(), 
7127                     m_selectingTopLeft
.GetCol(), 
7128                     m_selectingBottomRight
.GetRow(), 
7129                     m_selectingBottomRight
.GetCol(), 
7130                     event
.ControlDown(), 
7137         m_selectingTopLeft 
= wxGridNoCellCoords
; 
7138         m_selectingBottomRight 
= wxGridNoCellCoords
; 
7139         m_selectingKeyboard 
= wxGridNoCellCoords
; 
7143 void wxGrid::OnChar( wxKeyEvent
& event 
) 
7145     // is it possible to edit the current cell at all? 
7146     if ( !IsCellEditControlEnabled() && CanEnableCellControl() ) 
7148         // yes, now check whether the cells editor accepts the key 
7149         int row 
= m_currentCellCoords
.GetRow(); 
7150         int col 
= m_currentCellCoords
.GetCol(); 
7151         wxGridCellAttr 
*attr 
= GetCellAttr(row
, col
); 
7152         wxGridCellEditor 
*editor 
= attr
->GetEditor(this, row
, col
); 
7154         // <F2> is special and will always start editing, for 
7155         // other keys - ask the editor itself 
7156         if ( (event
.GetKeyCode() == WXK_F2 
&& !event
.HasModifiers()) 
7157              || editor
->IsAcceptedKey(event
) ) 
7159             // ensure cell is visble 
7160             MakeCellVisible(row
, col
); 
7161             EnableCellEditControl(); 
7163             // a problem can arise if the cell is not completely 
7164             // visible (even after calling MakeCellVisible the 
7165             // control is not created and calling StartingKey will 
7167             if ( event
.GetKeyCode() != WXK_F2 
&& editor
->IsCreated() && m_cellEditCtrlEnabled 
) 
7168                 editor
->StartingKey(event
); 
7184 void wxGrid::OnEraseBackground(wxEraseEvent
&) 
7188 void wxGrid::SetCurrentCell( const wxGridCellCoords
& coords 
) 
7190     if ( SendEvent( wxEVT_GRID_SELECT_CELL
, coords
.GetRow(), coords
.GetCol() ) ) 
7192         // the event has been intercepted - do nothing 
7196 #if !defined(__WXMAC__) 
7197     wxClientDC 
dc( m_gridWin 
); 
7201     if ( m_currentCellCoords 
!= wxGridNoCellCoords 
) 
7203         DisableCellEditControl(); 
7205         if ( IsVisible( m_currentCellCoords
, false ) ) 
7208             r 
= BlockToDeviceRect( m_currentCellCoords
, m_currentCellCoords 
); 
7209             if ( !m_gridLinesEnabled 
) 
7217             wxGridCellCoordsArray cells 
= CalcCellsExposed( r 
); 
7219             // Otherwise refresh redraws the highlight! 
7220             m_currentCellCoords 
= coords
; 
7222 #if defined(__WXMAC__) 
7223             m_gridWin
->Refresh(true /*, & r */); 
7225             DrawGridCellArea( dc
, cells 
); 
7226             DrawAllGridLines( dc
, r 
); 
7231     m_currentCellCoords 
= coords
; 
7233     wxGridCellAttr 
*attr 
= GetCellAttr( coords 
); 
7234 #if !defined(__WXMAC__) 
7235     DrawCellHighlight( dc
, attr 
); 
7240 void wxGrid::HighlightBlock( int topRow
, int leftCol
, int bottomRow
, int rightCol 
) 
7243     wxGridCellCoords updateTopLeft
, updateBottomRight
; 
7247         if ( m_selection
->GetSelectionMode() == wxGrid::wxGridSelectRows 
) 
7250             rightCol 
= GetNumberCols() - 1; 
7252         else if ( m_selection
->GetSelectionMode() == wxGrid::wxGridSelectColumns 
) 
7255             bottomRow 
= GetNumberRows() - 1; 
7259     if ( topRow 
> bottomRow 
) 
7266     if ( leftCol 
> rightCol 
) 
7273     updateTopLeft 
= wxGridCellCoords( topRow
, leftCol 
); 
7274     updateBottomRight 
= wxGridCellCoords( bottomRow
, rightCol 
); 
7276     // First the case that we selected a completely new area 
7277     if ( m_selectingTopLeft 
== wxGridNoCellCoords 
|| 
7278          m_selectingBottomRight 
== wxGridNoCellCoords 
) 
7281         rect 
= BlockToDeviceRect( wxGridCellCoords ( topRow
, leftCol 
), 
7282                                   wxGridCellCoords ( bottomRow
, rightCol 
) ); 
7283         m_gridWin
->Refresh( false, &rect 
); 
7286     // Now handle changing an existing selection area. 
7287     else if ( m_selectingTopLeft 
!= updateTopLeft 
|| 
7288               m_selectingBottomRight 
!= updateBottomRight 
) 
7290         // Compute two optimal update rectangles: 
7291         // Either one rectangle is a real subset of the 
7292         // other, or they are (almost) disjoint! 
7294         bool    need_refresh
[4]; 
7298         need_refresh
[3] = false; 
7301         // Store intermediate values 
7302         wxCoord oldLeft 
= m_selectingTopLeft
.GetCol(); 
7303         wxCoord oldTop 
= m_selectingTopLeft
.GetRow(); 
7304         wxCoord oldRight 
= m_selectingBottomRight
.GetCol(); 
7305         wxCoord oldBottom 
= m_selectingBottomRight
.GetRow(); 
7307         // Determine the outer/inner coordinates. 
7308         if (oldLeft 
> leftCol
) 
7314         if (oldTop 
> topRow 
) 
7320         if (oldRight 
< rightCol 
) 
7323             oldRight 
= rightCol
; 
7326         if (oldBottom 
< bottomRow
) 
7329             oldBottom 
= bottomRow
; 
7333         // Now, either the stuff marked old is the outer 
7334         // rectangle or we don't have a situation where one 
7335         // is contained in the other. 
7337         if ( oldLeft 
< leftCol 
) 
7339             // Refresh the newly selected or deselected 
7340             // area to the left of the old or new selection. 
7341             need_refresh
[0] = true; 
7342             rect
[0] = BlockToDeviceRect( 
7343                 wxGridCellCoords( oldTop
,  oldLeft 
), 
7344                 wxGridCellCoords( oldBottom
, leftCol 
- 1 ) ); 
7347         if ( oldTop 
< topRow 
) 
7349             // Refresh the newly selected or deselected 
7350             // area above the old or new selection. 
7351             need_refresh
[1] = true; 
7352             rect
[1] = BlockToDeviceRect( 
7353                 wxGridCellCoords( oldTop
, leftCol 
), 
7354                 wxGridCellCoords( topRow 
- 1, rightCol 
) ); 
7357         if ( oldRight 
> rightCol 
) 
7359             // Refresh the newly selected or deselected 
7360             // area to the right of the old or new selection. 
7361             need_refresh
[2] = true; 
7362             rect
[2] = BlockToDeviceRect( 
7363                 wxGridCellCoords( oldTop
, rightCol 
+ 1 ), 
7364                 wxGridCellCoords( oldBottom
, oldRight 
) ); 
7367         if ( oldBottom 
> bottomRow 
) 
7369             // Refresh the newly selected or deselected 
7370             // area below the old or new selection. 
7371             need_refresh
[3] = true; 
7372             rect
[3] = BlockToDeviceRect( 
7373                 wxGridCellCoords( bottomRow 
+ 1, leftCol 
), 
7374                 wxGridCellCoords( oldBottom
, rightCol 
) ); 
7377         // various Refresh() calls 
7378         for (i 
= 0; i 
< 4; i
++ ) 
7379             if ( need_refresh
[i
] && rect
[i
] != wxGridNoCellRect 
) 
7380                 m_gridWin
->Refresh( false, &(rect
[i
]) ); 
7384     m_selectingTopLeft 
= updateTopLeft
; 
7385     m_selectingBottomRight 
= updateBottomRight
; 
7389 // ------ functions to get/send data (see also public functions) 
7392 bool wxGrid::GetModelValues() 
7394     // Hide the editor, so it won't hide a changed value. 
7395     HideCellEditControl(); 
7399         // all we need to do is repaint the grid 
7401         m_gridWin
->Refresh(); 
7408 bool wxGrid::SetModelValues() 
7412     // Disable the editor, so it won't hide a changed value. 
7413     // Do we also want to save the current value of the editor first? 
7415     DisableCellEditControl(); 
7419         for ( row 
= 0; row 
< m_numRows
; row
++ ) 
7421             for ( col 
= 0; col 
< m_numCols
; col
++ ) 
7423                 m_table
->SetValue( row
, col
, GetCellValue(row
, col
) ); 
7433 // Note - this function only draws cells that are in the list of 
7434 // exposed cells (usually set from the update region by 
7435 // CalcExposedCells) 
7437 void wxGrid::DrawGridCellArea( wxDC
& dc
, const wxGridCellCoordsArray
& cells 
) 
7439     if ( !m_numRows 
|| !m_numCols 
) 
7442     int i
, numCells 
= cells
.GetCount(); 
7443     int row
, col
, cell_rows
, cell_cols
; 
7444     wxGridCellCoordsArray redrawCells
; 
7446     for ( i 
= numCells 
- 1; i 
>= 0; i
-- ) 
7448         row 
= cells
[i
].GetRow(); 
7449         col 
= cells
[i
].GetCol(); 
7450         GetCellSize( row
, col
, &cell_rows
, &cell_cols 
); 
7452         // If this cell is part of a multicell block, find owner for repaint 
7453         if ( cell_rows 
<= 0 || cell_cols 
<= 0 ) 
7455             wxGridCellCoords 
cell( row 
+ cell_rows
, col 
+ cell_cols 
); 
7456             bool marked 
= false; 
7457             for ( int j 
= 0; j 
< numCells
; j
++ ) 
7459                 if ( cell 
== cells
[j
] ) 
7468                 int count 
= redrawCells
.GetCount(); 
7469                 for (int j 
= 0; j 
< count
; j
++) 
7471                     if ( cell 
== redrawCells
[j
] ) 
7479                     redrawCells
.Add( cell 
); 
7482             // don't bother drawing this cell 
7486         // If this cell is empty, find cell to left that might want to overflow 
7487         if (m_table 
&& m_table
->IsEmptyCell(row
, col
)) 
7489             for ( int l 
= 0; l 
< cell_rows
; l
++ ) 
7491                 // find a cell in this row to leave already marked for repaint 
7493                 for (int k 
= 0; k 
< int(redrawCells
.GetCount()); k
++) 
7494                     if ((redrawCells
[k
].GetCol() < left
) && 
7495                         (redrawCells
[k
].GetRow() == row
)) 
7497                         left 
= redrawCells
[k
].GetCol(); 
7501                     left 
= 0; // oh well 
7503                 for (int j 
= col 
- 1; j 
>= left
; j
--) 
7505                     if (!m_table
->IsEmptyCell(row 
+ l
, j
)) 
7507                         if (GetCellOverflow(row 
+ l
, j
)) 
7509                             wxGridCellCoords 
cell(row 
+ l
, j
); 
7510                             bool marked 
= false; 
7512                             for (int k 
= 0; k 
< numCells
; k
++) 
7514                                 if ( cell 
== cells
[k
] ) 
7523                                 int count 
= redrawCells
.GetCount(); 
7524                                 for (int k 
= 0; k 
< count
; k
++) 
7526                                     if ( cell 
== redrawCells
[k
] ) 
7533                                     redrawCells
.Add( cell 
); 
7542         DrawCell( dc
, cells
[i
] ); 
7545     numCells 
= redrawCells
.GetCount(); 
7547     for ( i 
= numCells 
- 1; i 
>= 0; i
-- ) 
7549         DrawCell( dc
, redrawCells
[i
] ); 
7553 void wxGrid::DrawGridSpace( wxDC
& dc 
) 
7556   m_gridWin
->GetClientSize( &cw
, &ch 
); 
7559   CalcUnscrolledPosition( cw
, ch
, &right
, &bottom 
); 
7561   int rightCol 
= m_numCols 
> 0 ? GetColRight(GetColAt( m_numCols 
- 1 )) : 0; 
7562   int bottomRow 
= m_numRows 
> 0 ? GetRowBottom(m_numRows 
- 1) : 0; 
7564   if ( right 
> rightCol 
|| bottom 
> bottomRow 
) 
7567       CalcUnscrolledPosition( 0, 0, &left
, &top 
); 
7569       dc
.SetBrush( wxBrush(GetDefaultCellBackgroundColour(), wxBRUSHSTYLE_SOLID
) ); 
7570       dc
.SetPen( *wxTRANSPARENT_PEN 
); 
7572       if ( right 
> rightCol 
) 
7574           dc
.DrawRectangle( rightCol
, top
, right 
- rightCol
, ch 
); 
7577       if ( bottom 
> bottomRow 
) 
7579           dc
.DrawRectangle( left
, bottomRow
, cw
, bottom 
- bottomRow 
); 
7584 void wxGrid::DrawCell( wxDC
& dc
, const wxGridCellCoords
& coords 
) 
7586     int row 
= coords
.GetRow(); 
7587     int col 
= coords
.GetCol(); 
7589     if ( GetColWidth(col
) <= 0 || GetRowHeight(row
) <= 0 ) 
7592     // we draw the cell border ourselves 
7593 #if !WXGRID_DRAW_LINES 
7594     if ( m_gridLinesEnabled 
) 
7595         DrawCellBorder( dc
, coords 
); 
7598     wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
7600     bool isCurrent 
= coords 
== m_currentCellCoords
; 
7602     wxRect rect 
= CellToRect( row
, col 
); 
7604     // if the editor is shown, we should use it and not the renderer 
7605     // Note: However, only if it is really _shown_, i.e. not hidden! 
7606     if ( isCurrent 
&& IsCellEditControlShown() ) 
7608         // NB: this "#if..." is temporary and fixes a problem where the 
7609         // edit control is erased by this code after being rendered. 
7610         // On wxMac (QD build only), the cell editor is a wxTextCntl and is rendered 
7611         // implicitly, causing this out-of order render. 
7612 #if !defined(__WXMAC__) 
7613         wxGridCellEditor 
*editor 
= attr
->GetEditor(this, row
, col
); 
7614         editor
->PaintBackground(rect
, attr
); 
7620         // but all the rest is drawn by the cell renderer and hence may be customized 
7621         wxGridCellRenderer 
*renderer 
= attr
->GetRenderer(this, row
, col
); 
7622         renderer
->Draw(*this, *attr
, dc
, rect
, row
, col
, IsInSelection(coords
)); 
7629 void wxGrid::DrawCellHighlight( wxDC
& dc
, const wxGridCellAttr 
*attr 
) 
7631     // don't show highlight when the grid doesn't have focus 
7635     int row 
= m_currentCellCoords
.GetRow(); 
7636     int col 
= m_currentCellCoords
.GetCol(); 
7638     if ( GetColWidth(col
) <= 0 || GetRowHeight(row
) <= 0 ) 
7641     wxRect rect 
= CellToRect(row
, col
); 
7643     // hmmm... what could we do here to show that the cell is disabled? 
7644     // for now, I just draw a thinner border than for the other ones, but 
7645     // it doesn't look really good 
7647     int penWidth 
= attr
->IsReadOnly() ? m_cellHighlightROPenWidth 
: m_cellHighlightPenWidth
; 
7651         // The center of the drawn line is where the position/width/height of 
7652         // the rectangle is actually at (on wxMSW at least), so the 
7653         // size of the rectangle is reduced to compensate for the thickness of 
7654         // the line. If this is too strange on non-wxMSW platforms then 
7655         // please #ifdef this appropriately. 
7656         rect
.x 
+= penWidth 
/ 2; 
7657         rect
.y 
+= penWidth 
/ 2; 
7658         rect
.width 
-= penWidth 
- 1; 
7659         rect
.height 
-= penWidth 
- 1; 
7661         // Now draw the rectangle 
7662         // use the cellHighlightColour if the cell is inside a selection, this 
7663         // will ensure the cell is always visible. 
7664         dc
.SetPen(wxPen(IsInSelection(row
,col
) ? m_selectionForeground 
: m_cellHighlightColour
, penWidth
, wxPENSTYLE_SOLID
)); 
7665         dc
.SetBrush(*wxTRANSPARENT_BRUSH
); 
7666         dc
.DrawRectangle(rect
); 
7670         // VZ: my experiments with 3D borders... 
7672         // how to properly set colours for arbitrary bg? 
7673         wxCoord x1 
= rect
.x
, 
7675                 x2 
= rect
.x 
+ rect
.width 
- 1, 
7676                 y2 
= rect
.y 
+ rect
.height 
- 1; 
7678         dc
.SetPen(*wxWHITE_PEN
); 
7679         dc
.DrawLine(x1
, y1
, x2
, y1
); 
7680         dc
.DrawLine(x1
, y1
, x1
, y2
); 
7682         dc
.DrawLine(x1 
+ 1, y2 
- 1, x2 
- 1, y2 
- 1); 
7683         dc
.DrawLine(x2 
- 1, y1 
+ 1, x2 
- 1, y2
); 
7685         dc
.SetPen(*wxBLACK_PEN
); 
7686         dc
.DrawLine(x1
, y2
, x2
, y2
); 
7687         dc
.DrawLine(x2
, y1
, x2
, y2 
+ 1); 
7691 wxPen 
wxGrid::GetDefaultGridLinePen() 
7693     return wxPen(GetGridLineColour(), 1, wxPENSTYLE_SOLID
); 
7696 wxPen 
wxGrid::GetRowGridLinePen(int WXUNUSED(row
)) 
7698     return GetDefaultGridLinePen(); 
7701 wxPen 
wxGrid::GetColGridLinePen(int WXUNUSED(col
)) 
7703     return GetDefaultGridLinePen(); 
7706 void wxGrid::DrawCellBorder( wxDC
& dc
, const wxGridCellCoords
& coords 
) 
7708     int row 
= coords
.GetRow(); 
7709     int col 
= coords
.GetCol(); 
7710     if ( GetColWidth(col
) <= 0 || GetRowHeight(row
) <= 0 ) 
7714     wxRect rect 
= CellToRect( row
, col 
); 
7716     // right hand border 
7717     dc
.SetPen( GetColGridLinePen(col
) ); 
7718     dc
.DrawLine( rect
.x 
+ rect
.width
, rect
.y
, 
7719                  rect
.x 
+ rect
.width
, rect
.y 
+ rect
.height 
+ 1 ); 
7722     dc
.SetPen( GetRowGridLinePen(row
) ); 
7723     dc
.DrawLine( rect
.x
, rect
.y 
+ rect
.height
, 
7724                  rect
.x 
+ rect
.width
, rect
.y 
+ rect
.height
); 
7727 void wxGrid::DrawHighlight(wxDC
& dc
, const wxGridCellCoordsArray
& cells
) 
7729     // This if block was previously in wxGrid::OnPaint but that doesn't 
7730     // seem to get called under wxGTK - MB 
7732     if ( m_currentCellCoords 
== wxGridNoCellCoords 
&& 
7733          m_numRows 
&& m_numCols 
) 
7735         m_currentCellCoords
.Set(0, 0); 
7738     if ( IsCellEditControlShown() ) 
7740         // don't show highlight when the edit control is shown 
7744     // if the active cell was repainted, repaint its highlight too because it 
7745     // might have been damaged by the grid lines 
7746     size_t count 
= cells
.GetCount(); 
7747     for ( size_t n 
= 0; n 
< count
; n
++ ) 
7749         if ( cells
[n
] == m_currentCellCoords 
) 
7751             wxGridCellAttr
* attr 
= GetCellAttr(m_currentCellCoords
); 
7752             DrawCellHighlight(dc
, attr
); 
7760 // TODO: remove this ??? 
7761 // This is used to redraw all grid lines e.g. when the grid line colour 
7764 void wxGrid::DrawAllGridLines( wxDC
& dc
, const wxRegion 
& WXUNUSED(reg
) ) 
7766 #if !WXGRID_DRAW_LINES 
7770     if ( !m_gridLinesEnabled 
|| !m_numRows 
|| !m_numCols 
) 
7773     int top
, bottom
, left
, right
; 
7775 #if 0  //#ifndef __WXGTK__ 
7779       m_gridWin
->GetClientSize(&cw
, &ch
); 
7781       // virtual coords of visible area 
7783       CalcUnscrolledPosition( 0, 0, &left
, &top 
); 
7784       CalcUnscrolledPosition( cw
, ch
, &right
, &bottom 
); 
7789       reg
.GetBox(x
, y
, w
, h
); 
7790       CalcUnscrolledPosition( x
, y
, &left
, &top 
); 
7791       CalcUnscrolledPosition( x 
+ w
, y 
+ h
, &right
, &bottom 
); 
7795       m_gridWin
->GetClientSize(&cw
, &ch
); 
7796       CalcUnscrolledPosition( 0, 0, &left
, &top 
); 
7797       CalcUnscrolledPosition( cw
, ch
, &right
, &bottom 
); 
7800     // avoid drawing grid lines past the last row and col 
7802     right 
= wxMin( right
, GetColRight(GetColAt( m_numCols 
- 1 )) ); 
7803     bottom 
= wxMin( bottom
, GetRowBottom(m_numRows 
- 1) ); 
7805     // no gridlines inside multicells, clip them out 
7806     int leftCol 
= GetColPos( internalXToCol(left
) ); 
7807     int topRow 
= internalYToRow(top
); 
7808     int rightCol 
= GetColPos( internalXToCol(right
) ); 
7809     int bottomRow 
= internalYToRow(bottom
); 
7811     wxRegion 
clippedcells(0, 0, cw
, ch
); 
7813     int i
, j
, cell_rows
, cell_cols
; 
7816     for (j
=topRow
; j
<=bottomRow
; j
++) 
7819         for (colPos
=leftCol
; colPos
<=rightCol
; colPos
++) 
7821             i 
= GetColAt( colPos 
); 
7823             GetCellSize( j
, i
, &cell_rows
, &cell_cols 
); 
7824             if ((cell_rows 
> 1) || (cell_cols 
> 1)) 
7826                 rect 
= CellToRect(j
,i
); 
7827                 CalcScrolledPosition( rect
.x
, rect
.y
, &rect
.x
, &rect
.y 
); 
7828                 clippedcells
.Subtract(rect
); 
7830             else if ((cell_rows 
< 0) || (cell_cols 
< 0)) 
7832                 rect 
= CellToRect(j 
+ cell_rows
, i 
+ cell_cols
); 
7833                 CalcScrolledPosition( rect
.x
, rect
.y
, &rect
.x
, &rect
.y 
); 
7834                 clippedcells
.Subtract(rect
); 
7839     dc
.SetDeviceClippingRegion( clippedcells 
); 
7842     // horizontal grid lines 
7844     // already declared above - int i; 
7845     for ( i 
= internalYToRow(top
); i 
< m_numRows
; i
++ ) 
7847         int bot 
= GetRowBottom(i
) - 1; 
7856             dc
.SetPen( GetRowGridLinePen(i
) ); 
7857             dc
.DrawLine( left
, bot
, right
, bot 
); 
7861     // vertical grid lines 
7864     for ( colPos 
= leftCol
; colPos 
< m_numCols
; colPos
++ ) 
7866         i 
= GetColAt( colPos 
); 
7868         int colRight 
= GetColRight(i
); 
7870         if (GetLayoutDirection() != wxLayout_RightToLeft
) 
7874         if ( colRight 
> right 
) 
7879         if ( colRight 
>= left 
) 
7881             dc
.SetPen( GetColGridLinePen(i
) ); 
7882             dc
.DrawLine( colRight
, top
, colRight
, bottom 
); 
7886     dc
.DestroyClippingRegion(); 
7889 void wxGrid::DrawRowLabels( wxDC
& dc
, const wxArrayInt
& rows
) 
7895     size_t numLabels 
= rows
.GetCount(); 
7897     for ( i 
= 0; i 
< numLabels
; i
++ ) 
7899         DrawRowLabel( dc
, rows
[i
] ); 
7903 void wxGrid::DrawRowLabel( wxDC
& dc
, int row 
) 
7905     if ( GetRowHeight(row
) <= 0 || m_rowLabelWidth 
<= 0 ) 
7910     int rowTop 
= GetRowTop(row
), 
7911         rowBottom 
= GetRowBottom(row
) - 1; 
7913     dc
.SetPen( wxPen(wxSystemSettings::GetColour(wxSYS_COLOUR_3DSHADOW
), 1, wxPENSTYLE_SOLID
) ); 
7914     dc
.DrawLine( m_rowLabelWidth 
- 1, rowTop
, m_rowLabelWidth 
- 1, rowBottom 
); 
7915     dc
.DrawLine( 0, rowTop
, 0, rowBottom 
); 
7916     dc
.DrawLine( 0, rowBottom
, m_rowLabelWidth
, rowBottom 
); 
7918     dc
.SetPen( *wxWHITE_PEN 
); 
7919     dc
.DrawLine( 1, rowTop
, 1, rowBottom 
); 
7920     dc
.DrawLine( 1, rowTop
, m_rowLabelWidth 
- 1, rowTop 
); 
7922     dc
.SetBackgroundMode( wxBRUSHSTYLE_TRANSPARENT 
); 
7923     dc
.SetTextForeground( GetLabelTextColour() ); 
7924     dc
.SetFont( GetLabelFont() ); 
7927     GetRowLabelAlignment( &hAlign
, &vAlign 
); 
7930     rect
.SetY( GetRowTop(row
) + 2 ); 
7931     rect
.SetWidth( m_rowLabelWidth 
- 4 ); 
7932     rect
.SetHeight( GetRowHeight(row
) - 4 ); 
7933     DrawTextRectangle( dc
, GetRowLabelValue( row 
), rect
, hAlign
, vAlign 
); 
7936 void wxGrid::SetUseNativeColLabels( bool native 
) 
7938     m_nativeColumnLabels 
= native
; 
7941         int height 
= wxRendererNative::Get().GetHeaderButtonHeight( this ); 
7942         SetColLabelSize( height 
); 
7945     m_colLabelWin
->Refresh(); 
7948 void wxGrid::DrawColLabels( wxDC
& dc
,const wxArrayInt
& cols 
) 
7954     size_t numLabels 
= cols
.GetCount(); 
7956     for ( i 
= 0; i 
< numLabels
; i
++ ) 
7958         DrawColLabel( dc
, cols
[i
] ); 
7962 void wxGrid::DrawColLabel( wxDC
& dc
, int col 
) 
7964     if ( GetColWidth(col
) <= 0 || m_colLabelHeight 
<= 0 ) 
7967     int colLeft 
= GetColLeft(col
); 
7971     if (m_nativeColumnLabels
) 
7973         rect
.SetX( colLeft
); 
7975         rect
.SetWidth( GetColWidth(col
)); 
7976         rect
.SetHeight( m_colLabelHeight 
); 
7978         wxWindowDC 
*win_dc 
= (wxWindowDC
*) &dc
; 
7979         wxRendererNative::Get().DrawHeaderButton( win_dc
->GetWindow(), dc
, rect
, 0 ); 
7983         int colRight 
= GetColRight(col
) - 1; 
7985         dc
.SetPen( wxPen(wxSystemSettings::GetColour(wxSYS_COLOUR_3DSHADOW
), 1, wxPENSTYLE_SOLID
) ); 
7986         dc
.DrawLine( colRight
, 0, colRight
, m_colLabelHeight 
- 1 ); 
7987         dc
.DrawLine( colLeft
, 0, colRight
, 0 ); 
7988         dc
.DrawLine( colLeft
, m_colLabelHeight 
- 1, 
7989                  colRight 
+ 1, m_colLabelHeight 
- 1 ); 
7991         dc
.SetPen( *wxWHITE_PEN 
); 
7992         dc
.DrawLine( colLeft
, 1, colLeft
, m_colLabelHeight 
- 1 ); 
7993         dc
.DrawLine( colLeft
, 1, colRight
, 1 ); 
7996     dc
.SetBackgroundMode( wxBRUSHSTYLE_TRANSPARENT 
); 
7997     dc
.SetTextForeground( GetLabelTextColour() ); 
7998     dc
.SetFont( GetLabelFont() ); 
8000     int hAlign
, vAlign
, orient
; 
8001     GetColLabelAlignment( &hAlign
, &vAlign 
); 
8002     orient 
= GetColLabelTextOrientation(); 
8004     rect
.SetX( colLeft 
+ 2 ); 
8006     rect
.SetWidth( GetColWidth(col
) - 4 ); 
8007     rect
.SetHeight( m_colLabelHeight 
- 4 ); 
8008     DrawTextRectangle( dc
, GetColLabelValue( col 
), rect
, hAlign
, vAlign
, orient 
); 
8011 void wxGrid::DrawTextRectangle( wxDC
& dc
, 
8012                                 const wxString
& value
, 
8016                                 int textOrientation 
) 
8018     wxArrayString lines
; 
8020     StringToLines( value
, lines 
); 
8022     // Forward to new API. 
8023     DrawTextRectangle( dc
, 
8031 // VZ: this should be replaced with wxDC::DrawLabel() to which we just have to 
8032 //     add textOrientation support 
8033 void wxGrid::DrawTextRectangle(wxDC
& dc
, 
8034                                const wxArrayString
& lines
, 
8038                                int textOrientation
) 
8040     if ( lines
.empty() ) 
8043     wxDCClipper 
clip(dc
, rect
); 
8048     if ( textOrientation 
== wxHORIZONTAL 
) 
8049         GetTextBoxSize( dc
, lines
, &textWidth
, &textHeight 
); 
8051         GetTextBoxSize( dc
, lines
, &textHeight
, &textWidth 
); 
8055     switch ( vertAlign 
) 
8057         case wxALIGN_BOTTOM
: 
8058             if ( textOrientation 
== wxHORIZONTAL 
) 
8059                 y 
= rect
.y 
+ (rect
.height 
- textHeight 
- 1); 
8061                 x 
= rect
.x 
+ rect
.width 
- textWidth
; 
8064         case wxALIGN_CENTRE
: 
8065             if ( textOrientation 
== wxHORIZONTAL 
) 
8066                 y 
= rect
.y 
+ ((rect
.height 
- textHeight
) / 2); 
8068                 x 
= rect
.x 
+ ((rect
.width 
- textWidth
) / 2); 
8073             if ( textOrientation 
== wxHORIZONTAL 
) 
8080     // Align each line of a multi-line label 
8081     size_t nLines 
= lines
.GetCount(); 
8082     for ( size_t l 
= 0; l 
< nLines
; l
++ ) 
8084         const wxString
& line 
= lines
[l
]; 
8088             *(textOrientation 
== wxHORIZONTAL 
? &y 
: &x
) += dc
.GetCharHeight(); 
8092         wxCoord lineWidth 
= 0, 
8094         dc
.GetTextExtent(line
, &lineWidth
, &lineHeight
); 
8096         switch ( horizAlign 
) 
8099                 if ( textOrientation 
== wxHORIZONTAL 
) 
8100                     x 
= rect
.x 
+ (rect
.width 
- lineWidth 
- 1); 
8102                     y 
= rect
.y 
+ lineWidth 
+ 1; 
8105             case wxALIGN_CENTRE
: 
8106                 if ( textOrientation 
== wxHORIZONTAL 
) 
8107                     x 
= rect
.x 
+ ((rect
.width 
- lineWidth
) / 2); 
8109                     y 
= rect
.y 
+ rect
.height 
- ((rect
.height 
- lineWidth
) / 2); 
8114                 if ( textOrientation 
== wxHORIZONTAL 
) 
8117                     y 
= rect
.y 
+ rect
.height 
- 1; 
8121         if ( textOrientation 
== wxHORIZONTAL 
) 
8123             dc
.DrawText( line
, x
, y 
); 
8128             dc
.DrawRotatedText( line
, x
, y
, 90.0 ); 
8134 // Split multi-line text up into an array of strings. 
8135 // Any existing contents of the string array are preserved. 
8137 // TODO: refactor wxTextFile::Read() and reuse the same code from here 
8138 void wxGrid::StringToLines( const wxString
& value
, wxArrayString
& lines 
) const 
8142     wxString eol 
= wxTextFile::GetEOL( wxTextFileType_Unix 
); 
8143     wxString tVal 
= wxTextFile::Translate( value
, wxTextFileType_Unix 
); 
8145     while ( startPos 
< (int)tVal
.length() ) 
8147         pos 
= tVal
.Mid(startPos
).Find( eol 
); 
8152         else if ( pos 
== 0 ) 
8154             lines
.Add( wxEmptyString 
); 
8158             lines
.Add( tVal
.Mid(startPos
, pos
) ); 
8161         startPos 
+= pos 
+ 1; 
8164     if ( startPos 
< (int)tVal
.length() ) 
8166         lines
.Add( tVal
.Mid( startPos 
) ); 
8170 void wxGrid::GetTextBoxSize( const wxDC
& dc
, 
8171                              const wxArrayString
& lines
, 
8172                              long *width
, long *height 
) const 
8176     wxCoord lineW 
= 0, lineH 
= 0; 
8179     for ( i 
= 0; i 
< lines
.GetCount(); i
++ ) 
8181         dc
.GetTextExtent( lines
[i
], &lineW
, &lineH 
); 
8182         w 
= wxMax( w
, lineW 
); 
8191 // ------ Batch processing. 
8193 void wxGrid::EndBatch() 
8195     if ( m_batchCount 
> 0 ) 
8198         if ( !m_batchCount 
) 
8201             m_rowLabelWin
->Refresh(); 
8202             m_colLabelWin
->Refresh(); 
8203             m_cornerLabelWin
->Refresh(); 
8204             m_gridWin
->Refresh(); 
8209 // Use this, rather than wxWindow::Refresh(), to force an immediate 
8210 // repainting of the grid. Has no effect if you are already inside a 
8211 // BeginBatch / EndBatch block. 
8213 void wxGrid::ForceRefresh() 
8219 bool wxGrid::Enable(bool enable
) 
8221     if ( !wxScrolledWindow::Enable(enable
) ) 
8224     // redraw in the new state 
8225     m_gridWin
->Refresh(); 
8231 // ------ Edit control functions 
8234 void wxGrid::EnableEditing( bool edit 
) 
8236     // TODO: improve this ? 
8238     if ( edit 
!= m_editable 
) 
8241             EnableCellEditControl(edit
); 
8246 void wxGrid::EnableCellEditControl( bool enable 
) 
8251     if ( enable 
!= m_cellEditCtrlEnabled 
) 
8255             if (SendEvent( wxEVT_GRID_EDITOR_SHOWN
) <0) 
8258             // this should be checked by the caller! 
8259             wxASSERT_MSG( CanEnableCellControl(), _T("can't enable editing for this cell!") ); 
8261             // do it before ShowCellEditControl() 
8262             m_cellEditCtrlEnabled 
= enable
; 
8264             ShowCellEditControl(); 
8268             //FIXME:add veto support 
8269             SendEvent( wxEVT_GRID_EDITOR_HIDDEN 
); 
8271             HideCellEditControl(); 
8272             SaveEditControlValue(); 
8274             // do it after HideCellEditControl() 
8275             m_cellEditCtrlEnabled 
= enable
; 
8280 bool wxGrid::IsCurrentCellReadOnly() const 
8283     wxGridCellAttr
* attr 
= ((wxGrid 
*)this)->GetCellAttr(m_currentCellCoords
); 
8284     bool readonly 
= attr
->IsReadOnly(); 
8290 bool wxGrid::CanEnableCellControl() const 
8292     return m_editable 
&& (m_currentCellCoords 
!= wxGridNoCellCoords
) && 
8293         !IsCurrentCellReadOnly(); 
8296 bool wxGrid::IsCellEditControlEnabled() const 
8298     // the cell edit control might be disable for all cells or just for the 
8299     // current one if it's read only 
8300     return m_cellEditCtrlEnabled 
? !IsCurrentCellReadOnly() : false; 
8303 bool wxGrid::IsCellEditControlShown() const 
8305     bool isShown 
= false; 
8307     if ( m_cellEditCtrlEnabled 
) 
8309         int row 
= m_currentCellCoords
.GetRow(); 
8310         int col 
= m_currentCellCoords
.GetCol(); 
8311         wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
8312         wxGridCellEditor
* editor 
= attr
->GetEditor((wxGrid
*) this, row
, col
); 
8317             if ( editor
->IsCreated() ) 
8319                 isShown 
= editor
->GetControl()->IsShown(); 
8329 void wxGrid::ShowCellEditControl() 
8331     if ( IsCellEditControlEnabled() ) 
8333         if ( !IsVisible( m_currentCellCoords
, false ) ) 
8335             m_cellEditCtrlEnabled 
= false; 
8340             wxRect rect 
= CellToRect( m_currentCellCoords 
); 
8341             int row 
= m_currentCellCoords
.GetRow(); 
8342             int col 
= m_currentCellCoords
.GetCol(); 
8344             // if this is part of a multicell, find owner (topleft) 
8345             int cell_rows
, cell_cols
; 
8346             GetCellSize( row
, col
, &cell_rows
, &cell_cols 
); 
8347             if ( cell_rows 
<= 0 || cell_cols 
<= 0 ) 
8351                 m_currentCellCoords
.SetRow( row 
); 
8352                 m_currentCellCoords
.SetCol( col 
); 
8355             // erase the highlight and the cell contents because the editor 
8356             // might not cover the entire cell 
8357             wxClientDC 
dc( m_gridWin 
); 
8359             wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
8360             dc
.SetBrush(wxBrush(attr
->GetBackgroundColour(), wxBRUSHSTYLE_SOLID
)); 
8361             dc
.SetPen(*wxTRANSPARENT_PEN
); 
8362             dc
.DrawRectangle(rect
); 
8364             // convert to scrolled coords 
8365             CalcScrolledPosition( rect
.x
, rect
.y
, &rect
.x
, &rect
.y 
); 
8371             // cell is shifted by one pixel 
8372             // However, don't allow x or y to become negative 
8373             // since the SetSize() method interprets that as 
8380             wxGridCellEditor
* editor 
= attr
->GetEditor(this, row
, col
); 
8381             if ( !editor
->IsCreated() ) 
8383                 editor
->Create(m_gridWin
, wxID_ANY
, 
8384                                new wxGridCellEditorEvtHandler(this, editor
)); 
8386                 wxGridEditorCreatedEvent 
evt(GetId(), 
8387                                              wxEVT_GRID_EDITOR_CREATED
, 
8391                                              editor
->GetControl()); 
8392                 GetEventHandler()->ProcessEvent(evt
); 
8395             // resize editor to overflow into righthand cells if allowed 
8396             int maxWidth 
= rect
.width
; 
8397             wxString value 
= GetCellValue(row
, col
); 
8398             if ( (value 
!= wxEmptyString
) && (attr
->GetOverflow()) ) 
8401                 GetTextExtent(value
, &maxWidth
, &y
, NULL
, NULL
, &attr
->GetFont()); 
8402                 if (maxWidth 
< rect
.width
) 
8403                     maxWidth 
= rect
.width
; 
8406             int client_right 
= m_gridWin
->GetClientSize().GetWidth(); 
8407             if (rect
.x 
+ maxWidth 
> client_right
) 
8408                 maxWidth 
= client_right 
- rect
.x
; 
8410             if ((maxWidth 
> rect
.width
) && (col 
< m_numCols
) && m_table
) 
8412                 GetCellSize( row
, col
, &cell_rows
, &cell_cols 
); 
8413                 // may have changed earlier 
8414                 for (int i 
= col 
+ cell_cols
; i 
< m_numCols
; i
++) 
8417                     GetCellSize( row
, i
, &c_rows
, &c_cols 
); 
8419                     // looks weird going over a multicell 
8420                     if (m_table
->IsEmptyCell( row
, i 
) && 
8421                             (rect
.width 
< maxWidth
) && (c_rows 
== 1)) 
8423                         rect
.width 
+= GetColWidth( i 
); 
8429                 if (rect
.GetRight() > client_right
) 
8430                     rect
.SetRight( client_right 
- 1 ); 
8433             editor
->SetCellAttr( attr 
); 
8434             editor
->SetSize( rect 
); 
8436                 editor
->GetControl()->Move( 
8437                     editor
->GetControl()->GetPosition().x 
+ nXMove
, 
8438                     editor
->GetControl()->GetPosition().y 
); 
8439             editor
->Show( true, attr 
); 
8441             // recalc dimensions in case we need to 
8442             // expand the scrolled window to account for editor 
8445             editor
->BeginEdit(row
, col
, this); 
8446             editor
->SetCellAttr(NULL
); 
8454 void wxGrid::HideCellEditControl() 
8456     if ( IsCellEditControlEnabled() ) 
8458         int row 
= m_currentCellCoords
.GetRow(); 
8459         int col 
= m_currentCellCoords
.GetCol(); 
8461         wxGridCellAttr 
*attr 
= GetCellAttr(row
, col
); 
8462         wxGridCellEditor 
*editor 
= attr
->GetEditor(this, row
, col
); 
8463         editor
->Show( false ); 
8467         m_gridWin
->SetFocus(); 
8469         // refresh whole row to the right 
8470         wxRect 
rect( CellToRect(row
, col
) ); 
8471         CalcScrolledPosition(rect
.x
, rect
.y
, &rect
.x
, &rect
.y 
); 
8472         rect
.width 
= m_gridWin
->GetClientSize().GetWidth() - rect
.x
; 
8475         // ensure that the pixels under the focus ring get refreshed as well 
8476         rect
.Inflate(10, 10); 
8479         m_gridWin
->Refresh( false, &rect 
); 
8483 void wxGrid::SaveEditControlValue() 
8485     if ( IsCellEditControlEnabled() ) 
8487         int row 
= m_currentCellCoords
.GetRow(); 
8488         int col 
= m_currentCellCoords
.GetCol(); 
8490         wxString oldval 
= GetCellValue(row
, col
); 
8492         wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
8493         wxGridCellEditor
* editor 
= attr
->GetEditor(this, row
, col
); 
8494         bool changed 
= editor
->EndEdit(row
, col
, this); 
8501             if ( SendEvent( wxEVT_GRID_CELL_CHANGE
, 
8502                        m_currentCellCoords
.GetRow(), 
8503                        m_currentCellCoords
.GetCol() ) < 0 ) 
8505                 // Event has been vetoed, set the data back. 
8506                 SetCellValue(row
, col
, oldval
); 
8513 // ------ Grid location functions 
8514 //  Note that all of these functions work with the logical coordinates of 
8515 //  grid cells and labels so you will need to convert from device 
8516 //  coordinates for mouse events etc. 
8519 void wxGrid::XYToCell( int x
, int y
, wxGridCellCoords
& coords 
) const 
8521     int row 
= YToRow(y
); 
8522     int col 
= XToCol(x
); 
8524     if ( row 
== -1 || col 
== -1 ) 
8526         coords 
= wxGridNoCellCoords
; 
8530         coords
.Set( row
, col 
); 
8534 // Internal Helper function for computing row or column from some 
8535 // (unscrolled) coordinate value, using either 
8536 // m_defaultRowHeight/m_defaultColWidth or binary search on array 
8537 // of m_rowBottoms/m_ColRights to speed up the search! 
8539 static int CoordToRowOrCol(int coord
, int defaultDist
, int minDist
, 
8540                            const wxArrayInt
& BorderArray
, int nMax
, 
8544         return clipToMinMax 
&& (nMax 
> 0) ? 0 : -1; 
8549     size_t i_max 
= coord 
/ defaultDist
, 
8552     if (BorderArray
.IsEmpty()) 
8554         if ((int) i_max 
< nMax
) 
8556         return clipToMinMax 
? nMax 
- 1 : -1; 
8559     if ( i_max 
>= BorderArray
.GetCount()) 
8561         i_max 
= BorderArray
.GetCount() - 1; 
8565         if ( coord 
>= BorderArray
[i_max
]) 
8569                 i_max 
= coord 
/ minDist
; 
8571                 i_max 
=  BorderArray
.GetCount() - 1; 
8574         if ( i_max 
>= BorderArray
.GetCount()) 
8575             i_max 
= BorderArray
.GetCount() - 1; 
8578     if ( coord 
>= BorderArray
[i_max
]) 
8579         return clipToMinMax 
? (int)i_max 
: -1; 
8580     if ( coord 
< BorderArray
[0] ) 
8583     while ( i_max 
- i_min 
> 0 ) 
8585         wxCHECK_MSG(BorderArray
[i_min
] <= coord 
&& coord 
< BorderArray
[i_max
], 
8586                     0, _T("wxGrid: internal error in CoordToRowOrCol")); 
8587         if (coord 
>=  BorderArray
[ i_max 
- 1]) 
8591         int median 
= i_min 
+ (i_max 
- i_min 
+ 1) / 2; 
8592         if (coord 
< BorderArray
[median
]) 
8601 int wxGrid::YToRow( int y 
) const 
8603     return CoordToRowOrCol(y
, m_defaultRowHeight
, 
8604                            m_minAcceptableRowHeight
, m_rowBottoms
, m_numRows
, false); 
8607 int wxGrid::XToCol( int x
, bool clipToMinMax 
) const 
8610         return clipToMinMax 
&& (m_numCols 
> 0) ? GetColAt( 0 ) : -1; 
8612     wxASSERT_MSG(m_defaultColWidth 
> 0, wxT("Default column width can not be zero")); 
8614     int maxPos 
= x 
/ m_defaultColWidth
; 
8617     if (m_colRights
.IsEmpty()) 
8619         if(maxPos 
< m_numCols
) 
8620             return GetColAt( maxPos 
); 
8621         return clipToMinMax 
? GetColAt( m_numCols 
- 1 ) : -1; 
8624     if ( maxPos 
>= m_numCols
) 
8625         maxPos 
= m_numCols 
- 1; 
8628         if ( x 
>= m_colRights
[GetColAt( maxPos 
)]) 
8631             if (m_minAcceptableColWidth
) 
8632                 maxPos 
= x 
/ m_minAcceptableColWidth
; 
8634                 maxPos 
=  m_numCols 
- 1; 
8636         if ( maxPos 
>= m_numCols
) 
8637             maxPos 
= m_numCols 
- 1; 
8640     //X is beyond the last column 
8641     if ( x 
>= m_colRights
[GetColAt( maxPos 
)]) 
8642         return clipToMinMax 
? GetColAt( maxPos 
) : -1; 
8644     //X is before the first column 
8645     if ( x 
< m_colRights
[GetColAt( 0 )] ) 
8646         return GetColAt( 0 ); 
8648     //Perform a binary search 
8649     while ( maxPos 
- minPos 
> 0 ) 
8651         wxCHECK_MSG(m_colRights
[GetColAt( minPos 
)] <= x 
&& x 
< m_colRights
[GetColAt( maxPos 
)], 
8652                     0, _T("wxGrid: internal error in XToCol")); 
8654         if (x 
>=  m_colRights
[GetColAt( maxPos 
- 1 )]) 
8655             return GetColAt( maxPos 
); 
8658         int median 
= minPos 
+ (maxPos 
- minPos 
+ 1) / 2; 
8659         if (x 
< m_colRights
[GetColAt( median 
)]) 
8664     return GetColAt( maxPos 
); 
8667 // return the row number that that the y coord is near 
8668 //  the edge of, or -1 if not near an edge. 
8669 // coords can only possibly be near an edge if 
8670 //    (a) the row/column is large enough to still allow for an "inner" area 
8671 //        that is _not_ nead the edge (i.e., if the height/width is smaller 
8672 //        than WXGRID_LABEL_EDGE_ZONE, coords are _never_ considered to be 
8675 //    (b) resizing rows/columns (the thing for which edge detection is 
8676 //        relevant at all) is enabled. 
8678 int wxGrid::YToEdgeOfRow( int y 
) const 
8681     i 
= internalYToRow(y
); 
8683     if ( GetRowHeight(i
) > WXGRID_LABEL_EDGE_ZONE 
&& CanDragRowSize() ) 
8685         // We know that we are in row i, test whether we are 
8686         // close enough to lower or upper border, respectively. 
8687         if ( abs(GetRowBottom(i
) - y
) < WXGRID_LABEL_EDGE_ZONE 
) 
8689         else if ( i 
> 0 && y 
- GetRowTop(i
) < WXGRID_LABEL_EDGE_ZONE 
) 
8696 // return the col number that that the x coord is near the edge of, or 
8697 // -1 if not near an edge 
8698 // See comment at YToEdgeOfRow for conditions on edge detection. 
8700 int wxGrid::XToEdgeOfCol( int x 
) const 
8703     i 
= internalXToCol(x
); 
8705     if ( GetColWidth(i
) > WXGRID_LABEL_EDGE_ZONE 
&& CanDragColSize() ) 
8707         // We know that we are in column i; test whether we are 
8708         // close enough to right or left border, respectively. 
8709         if ( abs(GetColRight(i
) - x
) < WXGRID_LABEL_EDGE_ZONE 
) 
8711         else if ( i 
> 0 && x 
- GetColLeft(i
) < WXGRID_LABEL_EDGE_ZONE 
) 
8718 wxRect 
wxGrid::CellToRect( int row
, int col 
) const 
8720     wxRect 
rect( -1, -1, -1, -1 ); 
8722     if ( row 
>= 0 && row 
< m_numRows 
&& 
8723          col 
>= 0 && col 
< m_numCols 
) 
8725         int i
, cell_rows
, cell_cols
; 
8726         rect
.width 
= rect
.height 
= 0; 
8727         GetCellSize( row
, col
, &cell_rows
, &cell_cols 
); 
8728         // if negative then find multicell owner 
8733         GetCellSize( row
, col
, &cell_rows
, &cell_cols 
); 
8735         rect
.x 
= GetColLeft(col
); 
8736         rect
.y 
= GetRowTop(row
); 
8737         for (i
=col
; i 
< col 
+ cell_cols
; i
++) 
8738             rect
.width 
+= GetColWidth(i
); 
8739         for (i
=row
; i 
< row 
+ cell_rows
; i
++) 
8740             rect
.height 
+= GetRowHeight(i
); 
8743     // if grid lines are enabled, then the area of the cell is a bit smaller 
8744     if (m_gridLinesEnabled
) 
8753 bool wxGrid::IsVisible( int row
, int col
, bool wholeCellVisible 
) const 
8755     // get the cell rectangle in logical coords 
8757     wxRect 
r( CellToRect( row
, col 
) ); 
8759     // convert to device coords 
8761     int left
, top
, right
, bottom
; 
8762     CalcScrolledPosition( r
.GetLeft(), r
.GetTop(), &left
, &top 
); 
8763     CalcScrolledPosition( r
.GetRight(), r
.GetBottom(), &right
, &bottom 
); 
8765     // check against the client area of the grid window 
8767     m_gridWin
->GetClientSize( &cw
, &ch 
); 
8769     if ( wholeCellVisible 
) 
8771         // is the cell wholly visible ? 
8772         return ( left 
>= 0 && right 
<= cw 
&& 
8773                  top 
>= 0 && bottom 
<= ch 
); 
8777         // is the cell partly visible ? 
8779         return ( ((left 
>= 0 && left 
< cw
) || (right 
> 0 && right 
<= cw
)) && 
8780                  ((top 
>= 0 && top 
< ch
) || (bottom 
> 0 && bottom 
<= ch
)) ); 
8784 // make the specified cell location visible by doing a minimal amount 
8787 void wxGrid::MakeCellVisible( int row
, int col 
) 
8790     int xpos 
= -1, ypos 
= -1; 
8792     if ( row 
>= 0 && row 
< m_numRows 
&& 
8793          col 
>= 0 && col 
< m_numCols 
) 
8795         // get the cell rectangle in logical coords 
8796         wxRect 
r( CellToRect( row
, col 
) ); 
8798         // convert to device coords 
8799         int left
, top
, right
, bottom
; 
8800         CalcScrolledPosition( r
.GetLeft(), r
.GetTop(), &left
, &top 
); 
8801         CalcScrolledPosition( r
.GetRight(), r
.GetBottom(), &right
, &bottom 
); 
8804         m_gridWin
->GetClientSize( &cw
, &ch 
); 
8810         else if ( bottom 
> ch 
) 
8812             int h 
= r
.GetHeight(); 
8814             for ( i 
= row 
- 1; i 
>= 0; i
-- ) 
8816                 int rowHeight 
= GetRowHeight(i
); 
8817                 if ( h 
+ rowHeight 
> ch 
) 
8824             // we divide it later by GRID_SCROLL_LINE, make sure that we don't 
8825             // have rounding errors (this is important, because if we do, 
8826             // we might not scroll at all and some cells won't be redrawn) 
8828             // Sometimes GRID_SCROLL_LINE / 2 is not enough, 
8829             // so just add a full scroll unit... 
8830             ypos 
+= m_scrollLineY
; 
8833         // special handling for wide cells - show always left part of the cell! 
8834         // Otherwise, e.g. when stepping from row to row, it would jump between 
8835         // left and right part of the cell on every step! 
8837         if ( left 
< 0 || (right 
- left
) >= cw 
) 
8841         else if ( right 
> cw 
) 
8843             // position the view so that the cell is on the right 
8845             CalcUnscrolledPosition(0, 0, &x0
, &y0
); 
8846             xpos 
= x0 
+ (right 
- cw
); 
8848             // see comment for ypos above 
8849             xpos 
+= m_scrollLineX
; 
8852         if ( xpos 
!= -1 || ypos 
!= -1 ) 
8855                 xpos 
/= m_scrollLineX
; 
8857                 ypos 
/= m_scrollLineY
; 
8858             Scroll( xpos
, ypos 
); 
8865 // ------ Grid cursor movement functions 
8868 bool wxGrid::MoveCursorUp( bool expandSelection 
) 
8870     if ( m_currentCellCoords 
!= wxGridNoCellCoords 
&& 
8871          m_currentCellCoords
.GetRow() >= 0 ) 
8873         if ( expandSelection 
) 
8875             if ( m_selectingKeyboard 
== wxGridNoCellCoords 
) 
8876                 m_selectingKeyboard 
= m_currentCellCoords
; 
8877             if ( m_selectingKeyboard
.GetRow() > 0 ) 
8879                 m_selectingKeyboard
.SetRow( m_selectingKeyboard
.GetRow() - 1 ); 
8880                 MakeCellVisible( m_selectingKeyboard
.GetRow(), 
8881                                  m_selectingKeyboard
.GetCol() ); 
8882                 HighlightBlock( m_currentCellCoords
, m_selectingKeyboard 
); 
8885         else if ( m_currentCellCoords
.GetRow() > 0 ) 
8887             int row 
= m_currentCellCoords
.GetRow() - 1; 
8888             int col 
= m_currentCellCoords
.GetCol(); 
8890             MakeCellVisible( row
, col 
); 
8891             SetCurrentCell( row
, col 
); 
8902 bool wxGrid::MoveCursorDown( bool expandSelection 
) 
8904     if ( m_currentCellCoords 
!= wxGridNoCellCoords 
&& 
8905          m_currentCellCoords
.GetRow() < m_numRows 
) 
8907         if ( expandSelection 
) 
8909             if ( m_selectingKeyboard 
== wxGridNoCellCoords 
) 
8910                 m_selectingKeyboard 
= m_currentCellCoords
; 
8911             if ( m_selectingKeyboard
.GetRow() < m_numRows 
- 1 ) 
8913                 m_selectingKeyboard
.SetRow( m_selectingKeyboard
.GetRow() + 1 ); 
8914                 MakeCellVisible( m_selectingKeyboard
.GetRow(), 
8915                         m_selectingKeyboard
.GetCol() ); 
8916                 HighlightBlock( m_currentCellCoords
, m_selectingKeyboard 
); 
8919         else if ( m_currentCellCoords
.GetRow() < m_numRows 
- 1 ) 
8921             int row 
= m_currentCellCoords
.GetRow() + 1; 
8922             int col 
= m_currentCellCoords
.GetCol(); 
8924             MakeCellVisible( row
, col 
); 
8925             SetCurrentCell( row
, col 
); 
8936 bool wxGrid::MoveCursorLeft( bool expandSelection 
) 
8938     if ( m_currentCellCoords 
!= wxGridNoCellCoords 
&& 
8939          m_currentCellCoords
.GetCol() >= 0 ) 
8941         if ( expandSelection 
) 
8943             if ( m_selectingKeyboard 
== wxGridNoCellCoords 
) 
8944                 m_selectingKeyboard 
= m_currentCellCoords
; 
8945             if ( m_selectingKeyboard
.GetCol() > 0 ) 
8947                 m_selectingKeyboard
.SetCol( m_selectingKeyboard
.GetCol() - 1 ); 
8948                 MakeCellVisible( m_selectingKeyboard
.GetRow(), 
8949                         m_selectingKeyboard
.GetCol() ); 
8950                 HighlightBlock( m_currentCellCoords
, m_selectingKeyboard 
); 
8953         else if ( GetColPos( m_currentCellCoords
.GetCol() ) > 0 ) 
8955             int row 
= m_currentCellCoords
.GetRow(); 
8956             int col 
= GetColAt( GetColPos( m_currentCellCoords
.GetCol() ) - 1 ); 
8959             MakeCellVisible( row
, col 
); 
8960             SetCurrentCell( row
, col 
); 
8971 bool wxGrid::MoveCursorRight( bool expandSelection 
) 
8973     if ( m_currentCellCoords 
!= wxGridNoCellCoords 
&& 
8974          m_currentCellCoords
.GetCol() < m_numCols 
) 
8976         if ( expandSelection 
) 
8978             if ( m_selectingKeyboard 
== wxGridNoCellCoords 
) 
8979                 m_selectingKeyboard 
= m_currentCellCoords
; 
8980             if ( m_selectingKeyboard
.GetCol() < m_numCols 
- 1 ) 
8982                 m_selectingKeyboard
.SetCol( m_selectingKeyboard
.GetCol() + 1 ); 
8983                 MakeCellVisible( m_selectingKeyboard
.GetRow(), 
8984                         m_selectingKeyboard
.GetCol() ); 
8985                 HighlightBlock( m_currentCellCoords
, m_selectingKeyboard 
); 
8988         else if ( GetColPos( m_currentCellCoords
.GetCol() ) < m_numCols 
- 1 ) 
8990             int row 
= m_currentCellCoords
.GetRow(); 
8991             int col 
= GetColAt( GetColPos( m_currentCellCoords
.GetCol() ) + 1 ); 
8994             MakeCellVisible( row
, col 
); 
8995             SetCurrentCell( row
, col 
); 
9006 bool wxGrid::MovePageUp() 
9008     if ( m_currentCellCoords 
== wxGridNoCellCoords 
) 
9011     int row 
= m_currentCellCoords
.GetRow(); 
9015         m_gridWin
->GetClientSize( &cw
, &ch 
); 
9017         int y 
= GetRowTop(row
); 
9018         int newRow 
= internalYToRow( y 
- ch 
+ 1 ); 
9020         if ( newRow 
== row 
) 
9022             // row > 0, so newRow can never be less than 0 here. 
9026         MakeCellVisible( newRow
, m_currentCellCoords
.GetCol() ); 
9027         SetCurrentCell( newRow
, m_currentCellCoords
.GetCol() ); 
9035 bool wxGrid::MovePageDown() 
9037     if ( m_currentCellCoords 
== wxGridNoCellCoords 
) 
9040     int row 
= m_currentCellCoords
.GetRow(); 
9041     if ( (row 
+ 1) < m_numRows 
) 
9044         m_gridWin
->GetClientSize( &cw
, &ch 
); 
9046         int y 
= GetRowTop(row
); 
9047         int newRow 
= internalYToRow( y 
+ ch 
); 
9048         if ( newRow 
== row 
) 
9050             // row < m_numRows, so newRow can't overflow here. 
9054         MakeCellVisible( newRow
, m_currentCellCoords
.GetCol() ); 
9055         SetCurrentCell( newRow
, m_currentCellCoords
.GetCol() ); 
9063 bool wxGrid::MoveCursorUpBlock( bool expandSelection 
) 
9066          m_currentCellCoords 
!= wxGridNoCellCoords 
&& 
9067          m_currentCellCoords
.GetRow() > 0 ) 
9069         int row 
= m_currentCellCoords
.GetRow(); 
9070         int col 
= m_currentCellCoords
.GetCol(); 
9072         if ( m_table
->IsEmptyCell(row
, col
) ) 
9074             // starting in an empty cell: find the next block of 
9080                 if ( !(m_table
->IsEmptyCell(row
, col
)) ) 
9084         else if ( m_table
->IsEmptyCell(row 
- 1, col
) ) 
9086             // starting at the top of a block: find the next block 
9092                 if ( !(m_table
->IsEmptyCell(row
, col
)) ) 
9098             // starting within a block: find the top of the block 
9103                 if ( m_table
->IsEmptyCell(row
, col
) ) 
9111         MakeCellVisible( row
, col 
); 
9112         if ( expandSelection 
) 
9114             m_selectingKeyboard 
= wxGridCellCoords( row
, col 
); 
9115             HighlightBlock( m_currentCellCoords
, m_selectingKeyboard 
); 
9120             SetCurrentCell( row
, col 
); 
9129 bool wxGrid::MoveCursorDownBlock( bool expandSelection 
) 
9132          m_currentCellCoords 
!= wxGridNoCellCoords 
&& 
9133          m_currentCellCoords
.GetRow() < m_numRows 
- 1 ) 
9135         int row 
= m_currentCellCoords
.GetRow(); 
9136         int col 
= m_currentCellCoords
.GetCol(); 
9138         if ( m_table
->IsEmptyCell(row
, col
) ) 
9140             // starting in an empty cell: find the next block of 
9143             while ( row 
< m_numRows 
- 1 ) 
9146                 if ( !(m_table
->IsEmptyCell(row
, col
)) ) 
9150         else if ( m_table
->IsEmptyCell(row 
+ 1, col
) ) 
9152             // starting at the bottom of a block: find the next block 
9155             while ( row 
< m_numRows 
- 1 ) 
9158                 if ( !(m_table
->IsEmptyCell(row
, col
)) ) 
9164             // starting within a block: find the bottom of the block 
9166             while ( row 
< m_numRows 
- 1 ) 
9169                 if ( m_table
->IsEmptyCell(row
, col
) ) 
9177         MakeCellVisible( row
, col 
); 
9178         if ( expandSelection 
) 
9180             m_selectingKeyboard 
= wxGridCellCoords( row
, col 
); 
9181             HighlightBlock( m_currentCellCoords
, m_selectingKeyboard 
); 
9186             SetCurrentCell( row
, col 
); 
9195 bool wxGrid::MoveCursorLeftBlock( bool expandSelection 
) 
9198          m_currentCellCoords 
!= wxGridNoCellCoords 
&& 
9199          m_currentCellCoords
.GetCol() > 0 ) 
9201         int row 
= m_currentCellCoords
.GetRow(); 
9202         int col 
= m_currentCellCoords
.GetCol(); 
9204         if ( m_table
->IsEmptyCell(row
, col
) ) 
9206             // starting in an empty cell: find the next block of 
9212                 if ( !(m_table
->IsEmptyCell(row
, col
)) ) 
9216         else if ( m_table
->IsEmptyCell(row
, col 
- 1) ) 
9218             // starting at the left of a block: find the next block 
9224                 if ( !(m_table
->IsEmptyCell(row
, col
)) ) 
9230             // starting within a block: find the left of the block 
9235                 if ( m_table
->IsEmptyCell(row
, col
) ) 
9243         MakeCellVisible( row
, col 
); 
9244         if ( expandSelection 
) 
9246             m_selectingKeyboard 
= wxGridCellCoords( row
, col 
); 
9247             HighlightBlock( m_currentCellCoords
, m_selectingKeyboard 
); 
9252             SetCurrentCell( row
, col 
); 
9261 bool wxGrid::MoveCursorRightBlock( bool expandSelection 
) 
9264          m_currentCellCoords 
!= wxGridNoCellCoords 
&& 
9265          m_currentCellCoords
.GetCol() < m_numCols 
- 1 ) 
9267         int row 
= m_currentCellCoords
.GetRow(); 
9268         int col 
= m_currentCellCoords
.GetCol(); 
9270         if ( m_table
->IsEmptyCell(row
, col
) ) 
9272             // starting in an empty cell: find the next block of 
9275             while ( col 
< m_numCols 
- 1 ) 
9278                 if ( !(m_table
->IsEmptyCell(row
, col
)) ) 
9282         else if ( m_table
->IsEmptyCell(row
, col 
+ 1) ) 
9284             // starting at the right of a block: find the next block 
9287             while ( col 
< m_numCols 
- 1 ) 
9290                 if ( !(m_table
->IsEmptyCell(row
, col
)) ) 
9296             // starting within a block: find the right of the block 
9298             while ( col 
< m_numCols 
- 1 ) 
9301                 if ( m_table
->IsEmptyCell(row
, col
) ) 
9309         MakeCellVisible( row
, col 
); 
9310         if ( expandSelection 
) 
9312             m_selectingKeyboard 
= wxGridCellCoords( row
, col 
); 
9313             HighlightBlock( m_currentCellCoords
, m_selectingKeyboard 
); 
9318             SetCurrentCell( row
, col 
); 
9328 // ------ Label values and formatting 
9331 void wxGrid::GetRowLabelAlignment( int *horiz
, int *vert 
) const 
9334         *horiz 
= m_rowLabelHorizAlign
; 
9336         *vert  
= m_rowLabelVertAlign
; 
9339 void wxGrid::GetColLabelAlignment( int *horiz
, int *vert 
) const 
9342         *horiz 
= m_colLabelHorizAlign
; 
9344         *vert  
= m_colLabelVertAlign
; 
9347 int wxGrid::GetColLabelTextOrientation() const 
9349     return m_colLabelTextOrientation
; 
9352 wxString 
wxGrid::GetRowLabelValue( int row 
) const 
9356         return m_table
->GetRowLabelValue( row 
); 
9366 wxString 
wxGrid::GetColLabelValue( int col 
) const 
9370         return m_table
->GetColLabelValue( col 
); 
9380 void wxGrid::SetRowLabelSize( int width 
) 
9382     wxASSERT( width 
>= 0 || width 
== wxGRID_AUTOSIZE 
); 
9384     if ( width 
== wxGRID_AUTOSIZE 
) 
9386         width 
= CalcColOrRowLabelAreaMinSize(wxGRID_ROW
); 
9389     if ( width 
!= m_rowLabelWidth 
) 
9393             m_rowLabelWin
->Show( false ); 
9394             m_cornerLabelWin
->Show( false ); 
9396         else if ( m_rowLabelWidth 
== 0 ) 
9398             m_rowLabelWin
->Show( true ); 
9399             if ( m_colLabelHeight 
> 0 ) 
9400                 m_cornerLabelWin
->Show( true ); 
9403         m_rowLabelWidth 
= width
; 
9405         wxScrolledWindow::Refresh( true ); 
9409 void wxGrid::SetColLabelSize( int height 
) 
9411     wxASSERT( height 
>=0 || height 
== wxGRID_AUTOSIZE 
); 
9413     if ( height 
== wxGRID_AUTOSIZE 
) 
9415         height 
= CalcColOrRowLabelAreaMinSize(wxGRID_COLUMN
); 
9418     if ( height 
!= m_colLabelHeight 
) 
9422             m_colLabelWin
->Show( false ); 
9423             m_cornerLabelWin
->Show( false ); 
9425         else if ( m_colLabelHeight 
== 0 ) 
9427             m_colLabelWin
->Show( true ); 
9428             if ( m_rowLabelWidth 
> 0 ) 
9429                 m_cornerLabelWin
->Show( true ); 
9432         m_colLabelHeight 
= height
; 
9434         wxScrolledWindow::Refresh( true ); 
9438 void wxGrid::SetLabelBackgroundColour( const wxColour
& colour 
) 
9440     if ( m_labelBackgroundColour 
!= colour 
) 
9442         m_labelBackgroundColour 
= colour
; 
9443         m_rowLabelWin
->SetBackgroundColour( colour 
); 
9444         m_colLabelWin
->SetBackgroundColour( colour 
); 
9445         m_cornerLabelWin
->SetBackgroundColour( colour 
); 
9447         if ( !GetBatchCount() ) 
9449             m_rowLabelWin
->Refresh(); 
9450             m_colLabelWin
->Refresh(); 
9451             m_cornerLabelWin
->Refresh(); 
9456 void wxGrid::SetLabelTextColour( const wxColour
& colour 
) 
9458     if ( m_labelTextColour 
!= colour 
) 
9460         m_labelTextColour 
= colour
; 
9461         if ( !GetBatchCount() ) 
9463             m_rowLabelWin
->Refresh(); 
9464             m_colLabelWin
->Refresh(); 
9469 void wxGrid::SetLabelFont( const wxFont
& font 
) 
9472     if ( !GetBatchCount() ) 
9474         m_rowLabelWin
->Refresh(); 
9475         m_colLabelWin
->Refresh(); 
9479 void wxGrid::SetRowLabelAlignment( int horiz
, int vert 
) 
9481     // allow old (incorrect) defs to be used 
9484         case wxLEFT
:   horiz 
= wxALIGN_LEFT
; break; 
9485         case wxRIGHT
:  horiz 
= wxALIGN_RIGHT
; break; 
9486         case wxCENTRE
: horiz 
= wxALIGN_CENTRE
; break; 
9491         case wxTOP
:    vert 
= wxALIGN_TOP
;    break; 
9492         case wxBOTTOM
: vert 
= wxALIGN_BOTTOM
; break; 
9493         case wxCENTRE
: vert 
= wxALIGN_CENTRE
; break; 
9496     if ( horiz 
== wxALIGN_LEFT 
|| horiz 
== wxALIGN_CENTRE 
|| horiz 
== wxALIGN_RIGHT 
) 
9498         m_rowLabelHorizAlign 
= horiz
; 
9501     if ( vert 
== wxALIGN_TOP 
|| vert 
== wxALIGN_CENTRE 
|| vert 
== wxALIGN_BOTTOM 
) 
9503         m_rowLabelVertAlign 
= vert
; 
9506     if ( !GetBatchCount() ) 
9508         m_rowLabelWin
->Refresh(); 
9512 void wxGrid::SetColLabelAlignment( int horiz
, int vert 
) 
9514     // allow old (incorrect) defs to be used 
9517         case wxLEFT
:   horiz 
= wxALIGN_LEFT
; break; 
9518         case wxRIGHT
:  horiz 
= wxALIGN_RIGHT
; break; 
9519         case wxCENTRE
: horiz 
= wxALIGN_CENTRE
; break; 
9524         case wxTOP
:    vert 
= wxALIGN_TOP
;    break; 
9525         case wxBOTTOM
: vert 
= wxALIGN_BOTTOM
; break; 
9526         case wxCENTRE
: vert 
= wxALIGN_CENTRE
; break; 
9529     if ( horiz 
== wxALIGN_LEFT 
|| horiz 
== wxALIGN_CENTRE 
|| horiz 
== wxALIGN_RIGHT 
) 
9531         m_colLabelHorizAlign 
= horiz
; 
9534     if ( vert 
== wxALIGN_TOP 
|| vert 
== wxALIGN_CENTRE 
|| vert 
== wxALIGN_BOTTOM 
) 
9536         m_colLabelVertAlign 
= vert
; 
9539     if ( !GetBatchCount() ) 
9541         m_colLabelWin
->Refresh(); 
9545 // Note: under MSW, the default column label font must be changed because it 
9546 //       does not support vertical printing 
9548 // Example: wxFont font(9, wxSWISS, wxNORMAL, wxBOLD); 
9549 //                      pGrid->SetLabelFont(font); 
9550 //                      pGrid->SetColLabelTextOrientation(wxVERTICAL); 
9552 void wxGrid::SetColLabelTextOrientation( int textOrientation 
) 
9554     if ( textOrientation 
== wxHORIZONTAL 
|| textOrientation 
== wxVERTICAL 
) 
9555         m_colLabelTextOrientation 
= textOrientation
; 
9557     if ( !GetBatchCount() ) 
9558         m_colLabelWin
->Refresh(); 
9561 void wxGrid::SetRowLabelValue( int row
, const wxString
& s 
) 
9565         m_table
->SetRowLabelValue( row
, s 
); 
9566         if ( !GetBatchCount() ) 
9568             wxRect rect 
= CellToRect( row
, 0 ); 
9569             if ( rect
.height 
> 0 ) 
9571                 CalcScrolledPosition(0, rect
.y
, &rect
.x
, &rect
.y
); 
9573                 rect
.width 
= m_rowLabelWidth
; 
9574                 m_rowLabelWin
->Refresh( true, &rect 
); 
9580 void wxGrid::SetColLabelValue( int col
, const wxString
& s 
) 
9584         m_table
->SetColLabelValue( col
, s 
); 
9585         if ( !GetBatchCount() ) 
9587             wxRect rect 
= CellToRect( 0, col 
); 
9588             if ( rect
.width 
> 0 ) 
9590                 CalcScrolledPosition(rect
.x
, 0, &rect
.x
, &rect
.y
); 
9592                 rect
.height 
= m_colLabelHeight
; 
9593                 m_colLabelWin
->Refresh( true, &rect 
); 
9599 void wxGrid::SetGridLineColour( const wxColour
& colour 
) 
9601     if ( m_gridLineColour 
!= colour 
) 
9603         m_gridLineColour 
= colour
; 
9605         wxClientDC 
dc( m_gridWin 
); 
9607         DrawAllGridLines( dc
, wxRegion() ); 
9611 void wxGrid::SetCellHighlightColour( const wxColour
& colour 
) 
9613     if ( m_cellHighlightColour 
!= colour 
) 
9615         m_cellHighlightColour 
= colour
; 
9617         wxClientDC 
dc( m_gridWin 
); 
9619         wxGridCellAttr
* attr 
= GetCellAttr(m_currentCellCoords
); 
9620         DrawCellHighlight(dc
, attr
); 
9625 void wxGrid::SetCellHighlightPenWidth(int width
) 
9627     if (m_cellHighlightPenWidth 
!= width
) 
9629         m_cellHighlightPenWidth 
= width
; 
9631         // Just redrawing the cell highlight is not enough since that won't 
9632         // make any visible change if the the thickness is getting smaller. 
9633         int row 
= m_currentCellCoords
.GetRow(); 
9634         int col 
= m_currentCellCoords
.GetCol(); 
9635         if ( row 
== -1 || col 
== -1 || GetColWidth(col
) <= 0 || GetRowHeight(row
) <= 0 ) 
9638         wxRect rect 
= CellToRect(row
, col
); 
9639         m_gridWin
->Refresh(true, &rect
); 
9643 void wxGrid::SetCellHighlightROPenWidth(int width
) 
9645     if (m_cellHighlightROPenWidth 
!= width
) 
9647         m_cellHighlightROPenWidth 
= width
; 
9649         // Just redrawing the cell highlight is not enough since that won't 
9650         // make any visible change if the the thickness is getting smaller. 
9651         int row 
= m_currentCellCoords
.GetRow(); 
9652         int col 
= m_currentCellCoords
.GetCol(); 
9653         if ( row 
== -1 || col 
== -1 || 
9654                 GetColWidth(col
) <= 0 || GetRowHeight(row
) <= 0 ) 
9657         wxRect rect 
= CellToRect(row
, col
); 
9658         m_gridWin
->Refresh(true, &rect
); 
9662 void wxGrid::EnableGridLines( bool enable 
) 
9664     if ( enable 
!= m_gridLinesEnabled 
) 
9666         m_gridLinesEnabled 
= enable
; 
9668         if ( !GetBatchCount() ) 
9672                 wxClientDC 
dc( m_gridWin 
); 
9674                 DrawAllGridLines( dc
, wxRegion() ); 
9678                 m_gridWin
->Refresh(); 
9684 int wxGrid::GetDefaultRowSize() const 
9686     return m_defaultRowHeight
; 
9689 int wxGrid::GetRowSize( int row 
) const 
9691     wxCHECK_MSG( row 
>= 0 && row 
< m_numRows
, 0, _T("invalid row index") ); 
9693     return GetRowHeight(row
); 
9696 int wxGrid::GetDefaultColSize() const 
9698     return m_defaultColWidth
; 
9701 int wxGrid::GetColSize( int col 
) const 
9703     wxCHECK_MSG( col 
>= 0 && col 
< m_numCols
, 0, _T("invalid column index") ); 
9705     return GetColWidth(col
); 
9708 // ============================================================================ 
9709 // access to the grid attributes: each of them has a default value in the grid 
9710 // itself and may be overidden on a per-cell basis 
9711 // ============================================================================ 
9713 // ---------------------------------------------------------------------------- 
9714 // setting default attributes 
9715 // ---------------------------------------------------------------------------- 
9717 void wxGrid::SetDefaultCellBackgroundColour( const wxColour
& col 
) 
9719     m_defaultCellAttr
->SetBackgroundColour(col
); 
9721     m_gridWin
->SetBackgroundColour(col
); 
9725 void wxGrid::SetDefaultCellTextColour( const wxColour
& col 
) 
9727     m_defaultCellAttr
->SetTextColour(col
); 
9730 void wxGrid::SetDefaultCellAlignment( int horiz
, int vert 
) 
9732     m_defaultCellAttr
->SetAlignment(horiz
, vert
); 
9735 void wxGrid::SetDefaultCellOverflow( bool allow 
) 
9737     m_defaultCellAttr
->SetOverflow(allow
); 
9740 void wxGrid::SetDefaultCellFont( const wxFont
& font 
) 
9742     m_defaultCellAttr
->SetFont(font
); 
9745 // For editors and renderers the type registry takes precedence over the 
9746 // default attr, so we need to register the new editor/renderer for the string 
9747 // data type in order to make setting a default editor/renderer appear to 
9750 void wxGrid::SetDefaultRenderer(wxGridCellRenderer 
*renderer
) 
9752     RegisterDataType(wxGRID_VALUE_STRING
, 
9754                      GetDefaultEditorForType(wxGRID_VALUE_STRING
)); 
9757 void wxGrid::SetDefaultEditor(wxGridCellEditor 
*editor
) 
9759     RegisterDataType(wxGRID_VALUE_STRING
, 
9760                      GetDefaultRendererForType(wxGRID_VALUE_STRING
), 
9764 // ---------------------------------------------------------------------------- 
9765 // access to the default attributes 
9766 // ---------------------------------------------------------------------------- 
9768 wxColour 
wxGrid::GetDefaultCellBackgroundColour() const 
9770     return m_defaultCellAttr
->GetBackgroundColour(); 
9773 wxColour 
wxGrid::GetDefaultCellTextColour() const 
9775     return m_defaultCellAttr
->GetTextColour(); 
9778 wxFont 
wxGrid::GetDefaultCellFont() const 
9780     return m_defaultCellAttr
->GetFont(); 
9783 void wxGrid::GetDefaultCellAlignment( int *horiz
, int *vert 
) const 
9785     m_defaultCellAttr
->GetAlignment(horiz
, vert
); 
9788 bool wxGrid::GetDefaultCellOverflow() const 
9790     return m_defaultCellAttr
->GetOverflow(); 
9793 wxGridCellRenderer 
*wxGrid::GetDefaultRenderer() const 
9795     return m_defaultCellAttr
->GetRenderer(NULL
, 0, 0); 
9798 wxGridCellEditor 
*wxGrid::GetDefaultEditor() const 
9800     return m_defaultCellAttr
->GetEditor(NULL
, 0, 0); 
9803 // ---------------------------------------------------------------------------- 
9804 // access to cell attributes 
9805 // ---------------------------------------------------------------------------- 
9807 wxColour 
wxGrid::GetCellBackgroundColour(int row
, int col
) const 
9809     wxGridCellAttr 
*attr 
= GetCellAttr(row
, col
); 
9810     wxColour colour 
= attr
->GetBackgroundColour(); 
9816 wxColour 
wxGrid::GetCellTextColour( int row
, int col 
) const 
9818     wxGridCellAttr 
*attr 
= GetCellAttr(row
, col
); 
9819     wxColour colour 
= attr
->GetTextColour(); 
9825 wxFont 
wxGrid::GetCellFont( int row
, int col 
) const 
9827     wxGridCellAttr 
*attr 
= GetCellAttr(row
, col
); 
9828     wxFont font 
= attr
->GetFont(); 
9834 void wxGrid::GetCellAlignment( int row
, int col
, int *horiz
, int *vert 
) const 
9836     wxGridCellAttr 
*attr 
= GetCellAttr(row
, col
); 
9837     attr
->GetAlignment(horiz
, vert
); 
9841 bool wxGrid::GetCellOverflow( int row
, int col 
) const 
9843     wxGridCellAttr 
*attr 
= GetCellAttr(row
, col
); 
9844     bool allow 
= attr
->GetOverflow(); 
9850 void wxGrid::GetCellSize( int row
, int col
, int *num_rows
, int *num_cols 
) const 
9852     wxGridCellAttr 
*attr 
= GetCellAttr(row
, col
); 
9853     attr
->GetSize( num_rows
, num_cols 
); 
9857 wxGridCellRenderer
* wxGrid::GetCellRenderer(int row
, int col
) const 
9859     wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
9860     wxGridCellRenderer
* renderer 
= attr
->GetRenderer(this, row
, col
); 
9866 wxGridCellEditor
* wxGrid::GetCellEditor(int row
, int col
) const 
9868     wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
9869     wxGridCellEditor
* editor 
= attr
->GetEditor(this, row
, col
); 
9875 bool wxGrid::IsReadOnly(int row
, int col
) const 
9877     wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
9878     bool isReadOnly 
= attr
->IsReadOnly(); 
9884 // ---------------------------------------------------------------------------- 
9885 // attribute support: cache, automatic provider creation, ... 
9886 // ---------------------------------------------------------------------------- 
9888 bool wxGrid::CanHaveAttributes() const 
9895     return m_table
->CanHaveAttributes(); 
9898 void wxGrid::ClearAttrCache() 
9900     if ( m_attrCache
.row 
!= -1 ) 
9902         wxSafeDecRef(m_attrCache
.attr
); 
9903         m_attrCache
.attr 
= NULL
; 
9904         m_attrCache
.row 
= -1; 
9908 void wxGrid::CacheAttr(int row
, int col
, wxGridCellAttr 
*attr
) const 
9912         wxGrid 
*self 
= (wxGrid 
*)this;  // const_cast 
9914         self
->ClearAttrCache(); 
9915         self
->m_attrCache
.row 
= row
; 
9916         self
->m_attrCache
.col 
= col
; 
9917         self
->m_attrCache
.attr 
= attr
; 
9922 bool wxGrid::LookupAttr(int row
, int col
, wxGridCellAttr 
**attr
) const 
9924     if ( row 
== m_attrCache
.row 
&& col 
== m_attrCache
.col 
) 
9926         *attr 
= m_attrCache
.attr
; 
9927         wxSafeIncRef(m_attrCache
.attr
); 
9929 #ifdef DEBUG_ATTR_CACHE 
9930         gs_nAttrCacheHits
++; 
9937 #ifdef DEBUG_ATTR_CACHE 
9938         gs_nAttrCacheMisses
++; 
9945 wxGridCellAttr 
*wxGrid::GetCellAttr(int row
, int col
) const 
9947     wxGridCellAttr 
*attr 
= NULL
; 
9948     // Additional test to avoid looking at the cache e.g. for 
9949     // wxNoCellCoords, as this will confuse memory management. 
9952         if ( !LookupAttr(row
, col
, &attr
) ) 
9954             attr 
= m_table 
? m_table
->GetAttr(row
, col
, wxGridCellAttr::Any
) 
9955                            : (wxGridCellAttr 
*)NULL
; 
9956             CacheAttr(row
, col
, attr
); 
9962         attr
->SetDefAttr(m_defaultCellAttr
); 
9966         attr 
= m_defaultCellAttr
; 
9973 wxGridCellAttr 
*wxGrid::GetOrCreateCellAttr(int row
, int col
) const 
9975     wxGridCellAttr 
*attr 
= (wxGridCellAttr 
*)NULL
; 
9976     bool canHave 
= ((wxGrid
*)this)->CanHaveAttributes(); 
9978     wxCHECK_MSG( canHave
, attr
, _T("Cell attributes not allowed")); 
9979     wxCHECK_MSG( m_table
, attr
, _T("must have a table") ); 
9981     attr 
= m_table
->GetAttr(row
, col
, wxGridCellAttr::Cell
); 
9984         attr 
= new wxGridCellAttr(m_defaultCellAttr
); 
9986         // artificially inc the ref count to match DecRef() in caller 
9988         m_table
->SetAttr(attr
, row
, col
); 
9994 // ---------------------------------------------------------------------------- 
9995 // setting column attributes (wrappers around SetColAttr) 
9996 // ---------------------------------------------------------------------------- 
9998 void wxGrid::SetColFormatBool(int col
) 
10000     SetColFormatCustom(col
, wxGRID_VALUE_BOOL
); 
10003 void wxGrid::SetColFormatNumber(int col
) 
10005     SetColFormatCustom(col
, wxGRID_VALUE_NUMBER
); 
10008 void wxGrid::SetColFormatFloat(int col
, int width
, int precision
) 
10010     wxString typeName 
= wxGRID_VALUE_FLOAT
; 
10011     if ( (width 
!= -1) || (precision 
!= -1) ) 
10013         typeName 
<< _T(':') << width 
<< _T(',') << precision
; 
10016     SetColFormatCustom(col
, typeName
); 
10019 void wxGrid::SetColFormatCustom(int col
, const wxString
& typeName
) 
10021     wxGridCellAttr 
*attr 
= m_table
->GetAttr(-1, col
, wxGridCellAttr::Col 
); 
10023         attr 
= new wxGridCellAttr
; 
10024     wxGridCellRenderer 
*renderer 
= GetDefaultRendererForType(typeName
); 
10025     attr
->SetRenderer(renderer
); 
10026     wxGridCellEditor 
*editor 
= GetDefaultEditorForType(typeName
);  
10027     attr
->SetEditor(editor
);  
10029     SetColAttr(col
, attr
); 
10033 // ---------------------------------------------------------------------------- 
10034 // setting cell attributes: this is forwarded to the table 
10035 // ---------------------------------------------------------------------------- 
10037 void wxGrid::SetAttr(int row
, int col
, wxGridCellAttr 
*attr
) 
10039     if ( CanHaveAttributes() ) 
10041         m_table
->SetAttr(attr
, row
, col
); 
10046         wxSafeDecRef(attr
); 
10050 void wxGrid::SetRowAttr(int row
, wxGridCellAttr 
*attr
) 
10052     if ( CanHaveAttributes() ) 
10054         m_table
->SetRowAttr(attr
, row
); 
10059         wxSafeDecRef(attr
); 
10063 void wxGrid::SetColAttr(int col
, wxGridCellAttr 
*attr
) 
10065     if ( CanHaveAttributes() ) 
10067         m_table
->SetColAttr(attr
, col
); 
10072         wxSafeDecRef(attr
); 
10076 void wxGrid::SetCellBackgroundColour( int row
, int col
, const wxColour
& colour 
) 
10078     if ( CanHaveAttributes() ) 
10080         wxGridCellAttr 
*attr 
= GetOrCreateCellAttr(row
, col
); 
10081         attr
->SetBackgroundColour(colour
); 
10086 void wxGrid::SetCellTextColour( int row
, int col
, const wxColour
& colour 
) 
10088     if ( CanHaveAttributes() ) 
10090         wxGridCellAttr 
*attr 
= GetOrCreateCellAttr(row
, col
); 
10091         attr
->SetTextColour(colour
); 
10096 void wxGrid::SetCellFont( int row
, int col
, const wxFont
& font 
) 
10098     if ( CanHaveAttributes() ) 
10100         wxGridCellAttr 
*attr 
= GetOrCreateCellAttr(row
, col
); 
10101         attr
->SetFont(font
); 
10106 void wxGrid::SetCellAlignment( int row
, int col
, int horiz
, int vert 
) 
10108     if ( CanHaveAttributes() ) 
10110         wxGridCellAttr 
*attr 
= GetOrCreateCellAttr(row
, col
); 
10111         attr
->SetAlignment(horiz
, vert
); 
10116 void wxGrid::SetCellOverflow( int row
, int col
, bool allow 
) 
10118     if ( CanHaveAttributes() ) 
10120         wxGridCellAttr 
*attr 
= GetOrCreateCellAttr(row
, col
); 
10121         attr
->SetOverflow(allow
); 
10126 void wxGrid::SetCellSize( int row
, int col
, int num_rows
, int num_cols 
) 
10128     if ( CanHaveAttributes() ) 
10130         int cell_rows
, cell_cols
; 
10132         wxGridCellAttr 
*attr 
= GetOrCreateCellAttr(row
, col
); 
10133         attr
->GetSize(&cell_rows
, &cell_cols
); 
10134         attr
->SetSize(num_rows
, num_cols
); 
10137         // Cannot set the size of a cell to 0 or negative values 
10138         // While it is perfectly legal to do that, this function cannot 
10139         // handle all the possibilies, do it by hand by getting the CellAttr. 
10140         // You can only set the size of a cell to 1,1 or greater with this fn 
10141         wxASSERT_MSG( !((cell_rows 
< 1) || (cell_cols 
< 1)), 
10142                       wxT("wxGrid::SetCellSize setting cell size that is already part of another cell")); 
10143         wxASSERT_MSG( !((num_rows 
< 1) || (num_cols 
< 1)), 
10144                       wxT("wxGrid::SetCellSize setting cell size to < 1")); 
10146         // if this was already a multicell then "turn off" the other cells first 
10147         if ((cell_rows 
> 1) || (cell_rows 
> 1)) 
10150             for (j
=row
; j 
< row 
+ cell_rows
; j
++) 
10152                 for (i
=col
; i 
< col 
+ cell_cols
; i
++) 
10154                     if ((i 
!= col
) || (j 
!= row
)) 
10156                         wxGridCellAttr 
*attr_stub 
= GetOrCreateCellAttr(j
, i
); 
10157                         attr_stub
->SetSize( 1, 1 ); 
10158                         attr_stub
->DecRef(); 
10164         // mark the cells that will be covered by this cell to 
10165         // negative or zero values to point back at this cell 
10166         if (((num_rows 
> 1) || (num_cols 
> 1)) && (num_rows 
>= 1) && (num_cols 
>= 1)) 
10169             for (j
=row
; j 
< row 
+ num_rows
; j
++) 
10171                 for (i
=col
; i 
< col 
+ num_cols
; i
++) 
10173                     if ((i 
!= col
) || (j 
!= row
)) 
10175                         wxGridCellAttr 
*attr_stub 
= GetOrCreateCellAttr(j
, i
); 
10176                         attr_stub
->SetSize( row 
- j
, col 
- i 
); 
10177                         attr_stub
->DecRef(); 
10185 void wxGrid::SetCellRenderer(int row
, int col
, wxGridCellRenderer 
*renderer
) 
10187     if ( CanHaveAttributes() ) 
10189         wxGridCellAttr 
*attr 
= GetOrCreateCellAttr(row
, col
); 
10190         attr
->SetRenderer(renderer
); 
10195 void wxGrid::SetCellEditor(int row
, int col
, wxGridCellEditor
* editor
) 
10197     if ( CanHaveAttributes() ) 
10199         wxGridCellAttr 
*attr 
= GetOrCreateCellAttr(row
, col
); 
10200         attr
->SetEditor(editor
); 
10205 void wxGrid::SetReadOnly(int row
, int col
, bool isReadOnly
) 
10207     if ( CanHaveAttributes() ) 
10209         wxGridCellAttr 
*attr 
= GetOrCreateCellAttr(row
, col
); 
10210         attr
->SetReadOnly(isReadOnly
); 
10215 // ---------------------------------------------------------------------------- 
10216 // Data type registration 
10217 // ---------------------------------------------------------------------------- 
10219 void wxGrid::RegisterDataType(const wxString
& typeName
, 
10220                               wxGridCellRenderer
* renderer
, 
10221                               wxGridCellEditor
* editor
) 
10223     m_typeRegistry
->RegisterDataType(typeName
, renderer
, editor
); 
10227 wxGridCellEditor 
* wxGrid::GetDefaultEditorForCell(int row
, int col
) const 
10229     wxString typeName 
= m_table
->GetTypeName(row
, col
); 
10230     return GetDefaultEditorForType(typeName
); 
10233 wxGridCellRenderer 
* wxGrid::GetDefaultRendererForCell(int row
, int col
) const 
10235     wxString typeName 
= m_table
->GetTypeName(row
, col
); 
10236     return GetDefaultRendererForType(typeName
); 
10239 wxGridCellEditor 
* wxGrid::GetDefaultEditorForType(const wxString
& typeName
) const 
10241     int index 
= m_typeRegistry
->FindOrCloneDataType(typeName
); 
10242     if ( index 
== wxNOT_FOUND 
) 
10244         wxFAIL_MSG(wxString::Format(wxT("Unknown data type name [%s]"), typeName
.c_str())); 
10249     return m_typeRegistry
->GetEditor(index
); 
10252 wxGridCellRenderer 
* wxGrid::GetDefaultRendererForType(const wxString
& typeName
) const 
10254     int index 
= m_typeRegistry
->FindOrCloneDataType(typeName
); 
10255     if ( index 
== wxNOT_FOUND 
) 
10257         wxFAIL_MSG(wxString::Format(wxT("Unknown data type name [%s]"), typeName
.c_str())); 
10262     return m_typeRegistry
->GetRenderer(index
); 
10265 // ---------------------------------------------------------------------------- 
10267 // ---------------------------------------------------------------------------- 
10269 void wxGrid::EnableDragRowSize( bool enable 
) 
10271     m_canDragRowSize 
= enable
; 
10274 void wxGrid::EnableDragColSize( bool enable 
) 
10276     m_canDragColSize 
= enable
; 
10279 void wxGrid::EnableDragGridSize( bool enable 
) 
10281     m_canDragGridSize 
= enable
; 
10284 void wxGrid::EnableDragCell( bool enable 
) 
10286     m_canDragCell 
= enable
; 
10289 void wxGrid::SetDefaultRowSize( int height
, bool resizeExistingRows 
) 
10291     m_defaultRowHeight 
= wxMax( height
, m_minAcceptableRowHeight 
); 
10293     if ( resizeExistingRows 
) 
10295         // since we are resizing all rows to the default row size, 
10296         // we can simply clear the row heights and row bottoms 
10297         // arrays (which also allows us to take advantage of 
10298         // some speed optimisations) 
10299         m_rowHeights
.Empty(); 
10300         m_rowBottoms
.Empty(); 
10301         if ( !GetBatchCount() ) 
10306 void wxGrid::SetRowSize( int row
, int height 
) 
10308     wxCHECK_RET( row 
>= 0 && row 
< m_numRows
, _T("invalid row index") ); 
10310     // See comment in SetColSize 
10311     if ( height 
< GetRowMinimalAcceptableHeight()) 
10314     if ( m_rowHeights
.IsEmpty() ) 
10316         // need to really create the array 
10320     int h 
= wxMax( 0, height 
); 
10321     int diff 
= h 
- m_rowHeights
[row
]; 
10323     m_rowHeights
[row
] = h
; 
10324     for ( int i 
= row
; i 
< m_numRows
; i
++ ) 
10326         m_rowBottoms
[i
] += diff
; 
10329     if ( !GetBatchCount() ) 
10333 void wxGrid::SetDefaultColSize( int width
, bool resizeExistingCols 
) 
10335     // we dont allow zero default column width 
10336     m_defaultColWidth 
= wxMax( wxMax( width
, m_minAcceptableColWidth 
), 1 ); 
10338     if ( resizeExistingCols 
) 
10340         // since we are resizing all columns to the default column size, 
10341         // we can simply clear the col widths and col rights 
10342         // arrays (which also allows us to take advantage of 
10343         // some speed optimisations) 
10344         m_colWidths
.Empty(); 
10345         m_colRights
.Empty(); 
10346         if ( !GetBatchCount() ) 
10351 void wxGrid::SetColSize( int col
, int width 
) 
10353     wxCHECK_RET( col 
>= 0 && col 
< m_numCols
, _T("invalid column index") ); 
10355     // should we check that it's bigger than GetColMinimalWidth(col) here? 
10357     // No, because it is reasonable to assume the library user know's 
10358     // what he is doing. However we should test against the weaker 
10359     // constraint of minimalAcceptableWidth, as this breaks rendering 
10361     // This test then fixes sf.net bug #645734 
10363     if ( width 
< GetColMinimalAcceptableWidth() ) 
10366     if ( m_colWidths
.IsEmpty() ) 
10368         // need to really create the array 
10372     // if < 0 then calculate new width from label 
10376         wxArrayString lines
; 
10377         wxClientDC 
dc(m_colLabelWin
); 
10378         dc
.SetFont(GetLabelFont()); 
10379         StringToLines(GetColLabelValue(col
), lines
); 
10380         GetTextBoxSize(dc
, lines
, &w
, &h
); 
10384     int w 
= wxMax( 0, width 
); 
10385     int diff 
= w 
- m_colWidths
[col
]; 
10386     m_colWidths
[col
] = w
; 
10388     for ( int colPos 
= GetColPos(col
); colPos 
< m_numCols
; colPos
++ ) 
10390         m_colRights
[GetColAt(colPos
)] += diff
; 
10393     if ( !GetBatchCount() ) 
10397 void wxGrid::SetColMinimalWidth( int col
, int width 
) 
10399     if (width 
> GetColMinimalAcceptableWidth()) 
10401         wxLongToLongHashMap::key_type key 
= (wxLongToLongHashMap::key_type
)col
; 
10402         m_colMinWidths
[key
] = width
; 
10406 void wxGrid::SetRowMinimalHeight( int row
, int width 
) 
10408     if (width 
> GetRowMinimalAcceptableHeight()) 
10410         wxLongToLongHashMap::key_type key 
= (wxLongToLongHashMap::key_type
)row
; 
10411         m_rowMinHeights
[key
] = width
; 
10415 int wxGrid::GetColMinimalWidth(int col
) const 
10417     wxLongToLongHashMap::key_type key 
= (wxLongToLongHashMap::key_type
)col
; 
10418     wxLongToLongHashMap::const_iterator it 
= m_colMinWidths
.find(key
); 
10420     return it 
!= m_colMinWidths
.end() ? (int)it
->second 
: m_minAcceptableColWidth
; 
10423 int wxGrid::GetRowMinimalHeight(int row
) const 
10425     wxLongToLongHashMap::key_type key 
= (wxLongToLongHashMap::key_type
)row
; 
10426     wxLongToLongHashMap::const_iterator it 
= m_rowMinHeights
.find(key
); 
10428     return it 
!= m_rowMinHeights
.end() ? (int)it
->second 
: m_minAcceptableRowHeight
; 
10431 void wxGrid::SetColMinimalAcceptableWidth( int width 
) 
10433     // We do allow a width of 0 since this gives us 
10434     // an easy way to temporarily hiding columns. 
10436         m_minAcceptableColWidth 
= width
; 
10439 void wxGrid::SetRowMinimalAcceptableHeight( int height 
) 
10441     // We do allow a height of 0 since this gives us 
10442     // an easy way to temporarily hiding rows. 
10444         m_minAcceptableRowHeight 
= height
; 
10447 int  wxGrid::GetColMinimalAcceptableWidth() const 
10449     return m_minAcceptableColWidth
; 
10452 int  wxGrid::GetRowMinimalAcceptableHeight() const 
10454     return m_minAcceptableRowHeight
; 
10457 // ---------------------------------------------------------------------------- 
10459 // ---------------------------------------------------------------------------- 
10462 wxGrid::AutoSizeColOrRow(int colOrRow
, bool setAsMin
, wxGridDirection direction
) 
10464     const bool column 
= direction 
== wxGRID_COLUMN
; 
10466     wxClientDC 
dc(m_gridWin
); 
10468     // cancel editing of cell 
10469     HideCellEditControl(); 
10470     SaveEditControlValue(); 
10472     // init both of them to avoid compiler warnings, even if we only need one 
10480     wxCoord extent
, extentMax 
= 0; 
10481     int max 
= column 
? m_numRows 
: m_numCols
; 
10482     for ( int rowOrCol 
= 0; rowOrCol 
< max
; rowOrCol
++ ) 
10489         wxGridCellAttr 
*attr 
= GetCellAttr(row
, col
); 
10490         wxGridCellRenderer 
*renderer 
= attr
->GetRenderer(this, row
, col
); 
10493             wxSize size 
= renderer
->GetBestSize(*this, *attr
, dc
, row
, col
); 
10494             extent 
= column 
? size
.x 
: size
.y
; 
10495             if ( extent 
> extentMax 
) 
10496                 extentMax 
= extent
; 
10498             renderer
->DecRef(); 
10504     // now also compare with the column label extent 
10506     dc
.SetFont( GetLabelFont() ); 
10510         dc
.GetMultiLineTextExtent( GetColLabelValue(col
), &w
, &h 
); 
10511         if ( GetColLabelTextOrientation() == wxVERTICAL 
) 
10515         dc
.GetMultiLineTextExtent( GetRowLabelValue(row
), &w
, &h 
); 
10517     extent 
= column 
? w 
: h
; 
10518     if ( extent 
> extentMax 
) 
10519         extentMax 
= extent
; 
10523         // empty column - give default extent (notice that if extentMax is less 
10524         // than default extent but != 0, it's OK) 
10525         extentMax 
= column 
? m_defaultColWidth 
: m_defaultRowHeight
; 
10530             // leave some space around text 
10538         // Ensure automatic width is not less than minimal width. See the 
10539         // comment in SetColSize() for explanation of why this isn't done 
10540         // in SetColSize(). 
10542             extentMax 
= wxMax(extentMax
, GetColMinimalWidth(col
)); 
10544         SetColSize( col
, extentMax 
); 
10545         if ( !GetBatchCount() ) 
10548             m_gridWin
->GetClientSize( &cw
, &ch 
); 
10549             wxRect 
rect ( CellToRect( 0, col 
) ); 
10551             CalcScrolledPosition(rect
.x
, 0, &rect
.x
, &dummy
); 
10552             rect
.width 
= cw 
- rect
.x
; 
10553             rect
.height 
= m_colLabelHeight
; 
10554             m_colLabelWin
->Refresh( true, &rect 
); 
10559         // Ensure automatic width is not less than minimal height. See the 
10560         // comment in SetColSize() for explanation of why this isn't done 
10561         // in SetRowSize(). 
10563             extentMax 
= wxMax(extentMax
, GetRowMinimalHeight(row
)); 
10565         SetRowSize(row
, extentMax
); 
10566         if ( !GetBatchCount() ) 
10569             m_gridWin
->GetClientSize( &cw
, &ch 
); 
10570             wxRect 
rect( CellToRect( row
, 0 ) ); 
10572             CalcScrolledPosition(0, rect
.y
, &dummy
, &rect
.y
); 
10573             rect
.width 
= m_rowLabelWidth
; 
10574             rect
.height 
= ch 
- rect
.y
; 
10575             m_rowLabelWin
->Refresh( true, &rect 
); 
10582             SetColMinimalWidth(col
, extentMax
); 
10584             SetRowMinimalHeight(row
, extentMax
); 
10588 wxCoord 
wxGrid::CalcColOrRowLabelAreaMinSize(wxGridDirection direction
) 
10590     // calculate size for the rows or columns? 
10591     const bool calcRows 
= direction 
== wxGRID_ROW
; 
10593     wxClientDC 
dc(calcRows 
? GetGridRowLabelWindow() 
10594                            : GetGridColLabelWindow()); 
10595     dc
.SetFont(GetLabelFont()); 
10597     // which dimension should we take into account for calculations? 
10599     // for columns, the text can be only horizontal so it's easy but for rows 
10600     // we also have to take into account the text orientation 
10602         useWidth 
= calcRows 
|| (GetColLabelTextOrientation() == wxVERTICAL
); 
10604     wxArrayString lines
; 
10605     wxCoord extentMax 
= 0; 
10607     const int numRowsOrCols 
= calcRows 
? m_numRows 
: m_numCols
; 
10608     for ( int rowOrCol 
= 0; rowOrCol 
< numRowsOrCols
; rowOrCol
++ ) 
10612         wxString label 
= calcRows 
? GetRowLabelValue(rowOrCol
) 
10613                                   : GetColLabelValue(rowOrCol
); 
10614         StringToLines(label
, lines
); 
10617         GetTextBoxSize(dc
, lines
, &w
, &h
); 
10619         const wxCoord extent 
= useWidth 
? w 
: h
; 
10620         if ( extent 
> extentMax 
) 
10621             extentMax 
= extent
; 
10626         // empty column - give default extent (notice that if extentMax is less 
10627         // than default extent but != 0, it's OK) 
10628         extentMax 
= calcRows 
? GetDefaultRowLabelSize() 
10629                              : GetDefaultColLabelSize(); 
10632     // leave some space around text (taken from AutoSizeColOrRow) 
10641 int wxGrid::SetOrCalcColumnSizes(bool calcOnly
, bool setAsMin
) 
10643     int width 
= m_rowLabelWidth
; 
10645     wxGridUpdateLocker locker
; 
10647         locker
.Create(this); 
10649     for ( int col 
= 0; col 
< m_numCols
; col
++ ) 
10652             AutoSizeColumn(col
, setAsMin
); 
10654         width 
+= GetColWidth(col
); 
10660 int wxGrid::SetOrCalcRowSizes(bool calcOnly
, bool setAsMin
) 
10662     int height 
= m_colLabelHeight
; 
10664     wxGridUpdateLocker locker
; 
10666         locker
.Create(this); 
10668     for ( int row 
= 0; row 
< m_numRows
; row
++ ) 
10671             AutoSizeRow(row
, setAsMin
); 
10673         height 
+= GetRowHeight(row
); 
10679 void wxGrid::AutoSize() 
10681     wxGridUpdateLocker 
locker(this); 
10683     // we need to round up the size of the scrollable area to a multiple of 
10684     // scroll step to ensure that we don't get the scrollbars when we're sized 
10685     // exactly to fit our contents 
10686     wxSize 
size(SetOrCalcColumnSizes(false) - m_rowLabelWidth 
+ m_extraWidth
, 
10687                 SetOrCalcRowSizes(false) - m_colLabelHeight 
+ m_extraHeight
); 
10688     wxSize 
sizeFit(GetScrollX(size
.x
) * GetScrollLineX(), 
10689                    GetScrollY(size
.y
) * GetScrollLineY()); 
10691     // distribute the extra space between the columns/rows to avoid having 
10692     // extra white space 
10693     wxCoord diff 
= sizeFit
.x 
- size
.x
; 
10694     if ( diff 
&& m_numCols 
) 
10696         // try to resize the columns uniformly 
10697         wxCoord diffPerCol 
= diff 
/ m_numCols
; 
10700             for ( int col 
= 0; col 
< m_numCols
; col
++ ) 
10702                 SetColSize(col
, GetColWidth(col
) + diffPerCol
); 
10706         // add remaining amount to the last columns 
10707         diff 
-= diffPerCol 
* m_numCols
; 
10710             for ( int col 
= m_numCols 
- 1; col 
>= m_numCols 
- diff
; col
-- ) 
10712                 SetColSize(col
, GetColWidth(col
) + 1); 
10718     diff 
= sizeFit
.y 
- size
.y
; 
10719     if ( diff 
&& m_numRows 
) 
10721         // try to resize the columns uniformly 
10722         wxCoord diffPerRow 
= diff 
/ m_numRows
; 
10725             for ( int row 
= 0; row 
< m_numRows
; row
++ ) 
10727                 SetRowSize(row
, GetRowHeight(row
) + diffPerRow
); 
10731         // add remaining amount to the last rows 
10732         diff 
-= diffPerRow 
* m_numRows
; 
10735             for ( int row 
= m_numRows 
- 1; row 
>= m_numRows 
- diff
; row
-- ) 
10737                 SetRowSize(row
, GetRowHeight(row
) + 1); 
10742     // we know that we're not going to have scrollbars so disable them now to 
10743     // avoid trouble in SetClientSize() which can otherwise set the correct 
10744     // client size but also leave space for (not needed any more) scrollbars 
10745     SetScrollbars(0, 0, 0, 0, 0, 0, true); 
10746     SetClientSize(sizeFit
.x 
+ m_rowLabelWidth
, sizeFit
.y 
+ m_colLabelHeight
); 
10749 void wxGrid::AutoSizeRowLabelSize( int row 
) 
10751     wxArrayString lines
; 
10754     // Hide the edit control, so it 
10755     // won't interfere with drag-shrinking. 
10756     if ( IsCellEditControlShown() ) 
10758         HideCellEditControl(); 
10759         SaveEditControlValue(); 
10762     // autosize row height depending on label text 
10763     StringToLines( GetRowLabelValue( row 
), lines 
); 
10764     wxClientDC 
dc( m_rowLabelWin 
); 
10765     GetTextBoxSize( dc
, lines
, &w
, &h 
); 
10766     if ( h 
< m_defaultRowHeight 
) 
10767         h 
= m_defaultRowHeight
; 
10768     SetRowSize(row
, h
); 
10772 void wxGrid::AutoSizeColLabelSize( int col 
) 
10774     wxArrayString lines
; 
10777     // Hide the edit control, so it 
10778     // won't interfere with drag-shrinking. 
10779     if ( IsCellEditControlShown() ) 
10781         HideCellEditControl(); 
10782         SaveEditControlValue(); 
10785     // autosize column width depending on label text 
10786     StringToLines( GetColLabelValue( col 
), lines 
); 
10787     wxClientDC 
dc( m_colLabelWin 
); 
10788     if ( GetColLabelTextOrientation() == wxHORIZONTAL 
) 
10789         GetTextBoxSize( dc
, lines
, &w
, &h 
); 
10791         GetTextBoxSize( dc
, lines
, &h
, &w 
); 
10792     if ( w 
< m_defaultColWidth 
) 
10793         w 
= m_defaultColWidth
; 
10794     SetColSize(col
, w
); 
10798 wxSize 
wxGrid::DoGetBestSize() const 
10800     wxGrid 
*self 
= (wxGrid 
*)this;  // const_cast 
10802     // we do the same as in AutoSize() here with the exception that we don't 
10803     // change the column/row sizes, only calculate them 
10804     wxSize 
size(self
->SetOrCalcColumnSizes(true) - m_rowLabelWidth 
+ m_extraWidth
, 
10805                 self
->SetOrCalcRowSizes(true) - m_colLabelHeight 
+ m_extraHeight
); 
10806     wxSize 
sizeFit(GetScrollX(size
.x
) * GetScrollLineX(), 
10807                    GetScrollY(size
.y
) * GetScrollLineY()); 
10809     // NOTE: This size should be cached, but first we need to add calls to 
10810     // InvalidateBestSize everywhere that could change the results of this 
10812     // CacheBestSize(size); 
10814     return wxSize(sizeFit
.x 
+ m_rowLabelWidth
, sizeFit
.y 
+ m_colLabelHeight
) 
10815             + GetWindowBorderSize(); 
10823 wxPen
& wxGrid::GetDividerPen() const 
10828 // ---------------------------------------------------------------------------- 
10829 // cell value accessor functions 
10830 // ---------------------------------------------------------------------------- 
10832 void wxGrid::SetCellValue( int row
, int col
, const wxString
& s 
) 
10836         m_table
->SetValue( row
, col
, s 
); 
10837         if ( !GetBatchCount() ) 
10840             wxRect 
rect( CellToRect( row
, col 
) ); 
10842             rect
.width 
= m_gridWin
->GetClientSize().GetWidth(); 
10843             CalcScrolledPosition(0, rect
.y
, &dummy
, &rect
.y
); 
10844             m_gridWin
->Refresh( false, &rect 
); 
10847         if ( m_currentCellCoords
.GetRow() == row 
&& 
10848              m_currentCellCoords
.GetCol() == col 
&& 
10849              IsCellEditControlShown()) 
10850              // Note: If we are using IsCellEditControlEnabled, 
10851              // this interacts badly with calling SetCellValue from 
10852              // an EVT_GRID_CELL_CHANGE handler. 
10854             HideCellEditControl(); 
10855             ShowCellEditControl(); // will reread data from table 
10860 // ---------------------------------------------------------------------------- 
10861 // block, row and column selection 
10862 // ---------------------------------------------------------------------------- 
10864 void wxGrid::SelectRow( int row
, bool addToSelected 
) 
10866     if ( IsSelection() && !addToSelected 
) 
10870         m_selection
->SelectRow( row
, false, addToSelected 
); 
10873 void wxGrid::SelectCol( int col
, bool addToSelected 
) 
10875     if ( IsSelection() && !addToSelected 
) 
10879         m_selection
->SelectCol( col
, false, addToSelected 
); 
10882 void wxGrid::SelectBlock( int topRow
, int leftCol
, int bottomRow
, int rightCol
, 
10883                           bool addToSelected 
) 
10885     if ( IsSelection() && !addToSelected 
) 
10889         m_selection
->SelectBlock( topRow
, leftCol
, bottomRow
, rightCol
, 
10890                                   false, addToSelected 
); 
10893 void wxGrid::SelectAll() 
10895     if ( m_numRows 
> 0 && m_numCols 
> 0 ) 
10898             m_selection
->SelectBlock( 0, 0, m_numRows 
- 1, m_numCols 
- 1 ); 
10902 // ---------------------------------------------------------------------------- 
10903 // cell, row and col deselection 
10904 // ---------------------------------------------------------------------------- 
10906 void wxGrid::DeselectRow( int row 
) 
10908     if ( !m_selection 
) 
10911     if ( m_selection
->GetSelectionMode() == wxGrid::wxGridSelectRows 
) 
10913         if ( m_selection
->IsInSelection(row
, 0 ) ) 
10914             m_selection
->ToggleCellSelection(row
, 0); 
10918         int nCols 
= GetNumberCols(); 
10919         for ( int i 
= 0; i 
< nCols
; i
++ ) 
10921             if ( m_selection
->IsInSelection(row
, i 
) ) 
10922                 m_selection
->ToggleCellSelection(row
, i
); 
10927 void wxGrid::DeselectCol( int col 
) 
10929     if ( !m_selection 
) 
10932     if ( m_selection
->GetSelectionMode() == wxGrid::wxGridSelectColumns 
) 
10934         if ( m_selection
->IsInSelection(0, col 
) ) 
10935             m_selection
->ToggleCellSelection(0, col
); 
10939         int nRows 
= GetNumberRows(); 
10940         for ( int i 
= 0; i 
< nRows
; i
++ ) 
10942             if ( m_selection
->IsInSelection(i
, col 
) ) 
10943                 m_selection
->ToggleCellSelection(i
, col
); 
10948 void wxGrid::DeselectCell( int row
, int col 
) 
10950     if ( m_selection 
&& m_selection
->IsInSelection(row
, col
) ) 
10951         m_selection
->ToggleCellSelection(row
, col
); 
10954 bool wxGrid::IsSelection() const 
10956     return ( m_selection 
&& (m_selection
->IsSelection() || 
10957              ( m_selectingTopLeft 
!= wxGridNoCellCoords 
&& 
10958                m_selectingBottomRight 
!= wxGridNoCellCoords
) ) ); 
10961 bool wxGrid::IsInSelection( int row
, int col 
) const 
10963     return ( m_selection 
&& (m_selection
->IsInSelection( row
, col 
) || 
10964              ( row 
>= m_selectingTopLeft
.GetRow() && 
10965                col 
>= m_selectingTopLeft
.GetCol() && 
10966                row 
<= m_selectingBottomRight
.GetRow() && 
10967                col 
<= m_selectingBottomRight
.GetCol() )) ); 
10970 wxGridCellCoordsArray 
wxGrid::GetSelectedCells() const 
10974         wxGridCellCoordsArray a
; 
10978     return m_selection
->m_cellSelection
; 
10981 wxGridCellCoordsArray 
wxGrid::GetSelectionBlockTopLeft() const 
10985         wxGridCellCoordsArray a
; 
10989     return m_selection
->m_blockSelectionTopLeft
; 
10992 wxGridCellCoordsArray 
wxGrid::GetSelectionBlockBottomRight() const 
10996         wxGridCellCoordsArray a
; 
11000     return m_selection
->m_blockSelectionBottomRight
; 
11003 wxArrayInt 
wxGrid::GetSelectedRows() const 
11011     return m_selection
->m_rowSelection
; 
11014 wxArrayInt 
wxGrid::GetSelectedCols() const 
11022     return m_selection
->m_colSelection
; 
11025 void wxGrid::ClearSelection() 
11027     wxRect r1 
= BlockToDeviceRect( m_selectingTopLeft
, m_selectingBottomRight
); 
11028     wxRect r2 
= BlockToDeviceRect( m_currentCellCoords
, m_selectingKeyboard 
); 
11029     m_selectingTopLeft 
= 
11030     m_selectingBottomRight 
= 
11031     m_selectingKeyboard 
= wxGridNoCellCoords
; 
11032     Refresh( false, &r1 
); 
11033     Refresh( false, &r2 
); 
11035         m_selection
->ClearSelection(); 
11038 // This function returns the rectangle that encloses the given block 
11039 // in device coords clipped to the client size of the grid window. 
11041 wxRect 
wxGrid::BlockToDeviceRect( const wxGridCellCoords
& topLeft
, 
11042                                   const wxGridCellCoords
& bottomRight 
) const 
11045     wxRect tempCellRect 
= CellToRect(topLeft
); 
11046     if ( tempCellRect 
!= wxGridNoCellRect 
) 
11048         resultRect 
= tempCellRect
; 
11052         resultRect 
= wxRect(0, 0, 0, 0); 
11055     tempCellRect 
= CellToRect(bottomRight
); 
11056     if ( tempCellRect 
!= wxGridNoCellRect 
) 
11058         resultRect 
+= tempCellRect
; 
11062         // If both inputs were "wxGridNoCellRect," then there's nothing to do. 
11063         return wxGridNoCellRect
; 
11066     // Ensure that left/right and top/bottom pairs are in order. 
11067     int left 
= resultRect
.GetLeft(); 
11068     int top 
= resultRect
.GetTop(); 
11069     int right 
= resultRect
.GetRight(); 
11070     int bottom 
= resultRect
.GetBottom(); 
11072     int leftCol 
= topLeft
.GetCol(); 
11073     int topRow 
= topLeft
.GetRow(); 
11074     int rightCol 
= bottomRight
.GetCol(); 
11075     int bottomRow 
= bottomRight
.GetRow(); 
11084         leftCol 
= rightCol
; 
11095         topRow 
= bottomRow
; 
11099     // The following loop is ONLY necessary to detect and handle merged cells. 
11101     m_gridWin
->GetClientSize( &cw
, &ch 
); 
11103     // Get the origin coordinates: notice that they will be negative if the 
11104     // grid is scrolled downwards/to the right. 
11105     int gridOriginX 
= 0; 
11106     int gridOriginY 
= 0; 
11107     CalcScrolledPosition(gridOriginX
, gridOriginY
, &gridOriginX
, &gridOriginY
); 
11109     int onScreenLeftmostCol 
= internalXToCol(-gridOriginX
); 
11110     int onScreenUppermostRow 
= internalYToRow(-gridOriginY
); 
11112     int onScreenRightmostCol 
= internalXToCol(-gridOriginX 
+ cw
); 
11113     int onScreenBottommostRow 
= internalYToRow(-gridOriginY 
+ ch
); 
11115     // Bound our loop so that we only examine the portion of the selected block 
11116     // that is shown on screen. Therefore, we compare the Top-Left block values 
11117     // to the Top-Left screen values, and the Bottom-Right block values to the 
11118     // Bottom-Right screen values, choosing appropriately. 
11119     const int visibleTopRow 
= wxMax(topRow
, onScreenUppermostRow
); 
11120     const int visibleBottomRow 
= wxMin(bottomRow
, onScreenBottommostRow
); 
11121     const int visibleLeftCol 
= wxMax(leftCol
, onScreenLeftmostCol
); 
11122     const int visibleRightCol 
= wxMin(rightCol
, onScreenRightmostCol
); 
11124     for ( int j 
= visibleTopRow
; j 
<= visibleBottomRow
; j
++ ) 
11126         for ( int i 
= visibleLeftCol
; i 
<= visibleRightCol
; i
++ ) 
11128             if ( (j 
== visibleTopRow
) || (j 
== visibleBottomRow
) || 
11129                     (i 
== visibleLeftCol
) || (i 
== visibleRightCol
) ) 
11131                 tempCellRect 
= CellToRect( j
, i 
); 
11133                 if (tempCellRect
.x 
< left
) 
11134                     left 
= tempCellRect
.x
; 
11135                 if (tempCellRect
.y 
< top
) 
11136                     top 
= tempCellRect
.y
; 
11137                 if (tempCellRect
.x 
+ tempCellRect
.width 
> right
) 
11138                     right 
= tempCellRect
.x 
+ tempCellRect
.width
; 
11139                 if (tempCellRect
.y 
+ tempCellRect
.height 
> bottom
) 
11140                     bottom 
= tempCellRect
.y 
+ tempCellRect
.height
; 
11144                 i 
= visibleRightCol
; // jump over inner cells. 
11149     // Convert to scrolled coords 
11150     CalcScrolledPosition( left
, top
, &left
, &top 
); 
11151     CalcScrolledPosition( right
, bottom
, &right
, &bottom 
); 
11153     if (right 
< 0 || bottom 
< 0 || left 
> cw 
|| top 
> ch
) 
11154         return wxRect(0,0,0,0); 
11156     resultRect
.SetLeft( wxMax(0, left
) ); 
11157     resultRect
.SetTop( wxMax(0, top
) ); 
11158     resultRect
.SetRight( wxMin(cw
, right
) ); 
11159     resultRect
.SetBottom( wxMin(ch
, bottom
) ); 
11164 // ---------------------------------------------------------------------------- 
11166 // ---------------------------------------------------------------------------- 
11168 #if wxUSE_DRAG_AND_DROP 
11170 // this allow setting drop target directly on wxGrid 
11171 void wxGrid::SetDropTarget(wxDropTarget 
*dropTarget
) 
11173     GetGridWindow()->SetDropTarget(dropTarget
); 
11176 #endif // wxUSE_DRAG_AND_DROP 
11178 // ---------------------------------------------------------------------------- 
11179 // grid event classes 
11180 // ---------------------------------------------------------------------------- 
11182 IMPLEMENT_DYNAMIC_CLASS( wxGridEvent
, wxNotifyEvent 
) 
11184 wxGridEvent::wxGridEvent( int id
, wxEventType type
, wxObject
* obj
, 
11185                           int row
, int col
, int x
, int y
, bool sel
, 
11186                           bool control
, bool shift
, bool alt
, bool meta 
) 
11187         : wxNotifyEvent( type
, id 
) 
11194     m_control 
= control
; 
11199     SetEventObject(obj
); 
11203 IMPLEMENT_DYNAMIC_CLASS( wxGridSizeEvent
, wxNotifyEvent 
) 
11205 wxGridSizeEvent::wxGridSizeEvent( int id
, wxEventType type
, wxObject
* obj
, 
11206                                   int rowOrCol
, int x
, int y
, 
11207                                   bool control
, bool shift
, bool alt
, bool meta 
) 
11208         : wxNotifyEvent( type
, id 
) 
11210     m_rowOrCol 
= rowOrCol
; 
11213     m_control 
= control
; 
11218     SetEventObject(obj
); 
11222 IMPLEMENT_DYNAMIC_CLASS( wxGridRangeSelectEvent
, wxNotifyEvent 
) 
11224 wxGridRangeSelectEvent::wxGridRangeSelectEvent(int id
, wxEventType type
, wxObject
* obj
, 
11225                                                const wxGridCellCoords
& topLeft
, 
11226                                                const wxGridCellCoords
& bottomRight
, 
11227                                                bool sel
, bool control
, 
11228                                                bool shift
, bool alt
, bool meta 
) 
11229         : wxNotifyEvent( type
, id 
) 
11231     m_topLeft 
= topLeft
; 
11232     m_bottomRight 
= bottomRight
; 
11234     m_control 
= control
; 
11239     SetEventObject(obj
); 
11243 IMPLEMENT_DYNAMIC_CLASS(wxGridEditorCreatedEvent
, wxCommandEvent
) 
11245 wxGridEditorCreatedEvent::wxGridEditorCreatedEvent(int id
, wxEventType type
, 
11246                                                    wxObject
* obj
, int row
, 
11247                                                    int col
, wxControl
* ctrl
) 
11248     : wxCommandEvent(type
, id
) 
11250     SetEventObject(obj
); 
11256 #endif // wxUSE_GRID