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
) 
  95     void ChangeAttr(wxGridCellAttr
* new_attr
) 
  99             // "Delete" (i.e. DecRef) the old attribute. 
 102             // Take ownership of the new attribute, i.e. no IncRef. 
 106     ~wxGridCellWithAttr() 
 111     wxGridCellCoords coords
; 
 112     wxGridCellAttr  
*attr
; 
 115 WX_DECLARE_OBJARRAY_WITH_DECL(wxGridCellWithAttr
, wxGridCellWithAttrArray
, 
 116                               class WXDLLIMPEXP_ADV
); 
 118 #include "wx/arrimpl.cpp" 
 120 WX_DEFINE_OBJARRAY(wxGridCellCoordsArray
) 
 121 WX_DEFINE_OBJARRAY(wxGridCellWithAttrArray
) 
 123 // ---------------------------------------------------------------------------- 
 125 // ---------------------------------------------------------------------------- 
 127 DEFINE_EVENT_TYPE(wxEVT_GRID_CELL_LEFT_CLICK
) 
 128 DEFINE_EVENT_TYPE(wxEVT_GRID_CELL_RIGHT_CLICK
) 
 129 DEFINE_EVENT_TYPE(wxEVT_GRID_CELL_LEFT_DCLICK
) 
 130 DEFINE_EVENT_TYPE(wxEVT_GRID_CELL_RIGHT_DCLICK
) 
 131 DEFINE_EVENT_TYPE(wxEVT_GRID_CELL_BEGIN_DRAG
) 
 132 DEFINE_EVENT_TYPE(wxEVT_GRID_LABEL_LEFT_CLICK
) 
 133 DEFINE_EVENT_TYPE(wxEVT_GRID_LABEL_RIGHT_CLICK
) 
 134 DEFINE_EVENT_TYPE(wxEVT_GRID_LABEL_LEFT_DCLICK
) 
 135 DEFINE_EVENT_TYPE(wxEVT_GRID_LABEL_RIGHT_DCLICK
) 
 136 DEFINE_EVENT_TYPE(wxEVT_GRID_ROW_SIZE
) 
 137 DEFINE_EVENT_TYPE(wxEVT_GRID_COL_SIZE
) 
 138 DEFINE_EVENT_TYPE(wxEVT_GRID_COL_MOVE
) 
 139 DEFINE_EVENT_TYPE(wxEVT_GRID_RANGE_SELECT
) 
 140 DEFINE_EVENT_TYPE(wxEVT_GRID_CELL_CHANGE
) 
 141 DEFINE_EVENT_TYPE(wxEVT_GRID_SELECT_CELL
) 
 142 DEFINE_EVENT_TYPE(wxEVT_GRID_EDITOR_SHOWN
) 
 143 DEFINE_EVENT_TYPE(wxEVT_GRID_EDITOR_HIDDEN
) 
 144 DEFINE_EVENT_TYPE(wxEVT_GRID_EDITOR_CREATED
) 
 146 // ---------------------------------------------------------------------------- 
 148 // ---------------------------------------------------------------------------- 
 150 // common base class for various grid subwindows 
 151 class WXDLLIMPEXP_ADV wxGridSubwindow 
: public wxWindow
 
 154     wxGridSubwindow() { m_owner 
= NULL
; } 
 155     wxGridSubwindow(wxGrid 
*owner
, 
 159                     int additionalStyle 
= 0, 
 160                     const wxString
& name 
= wxPanelNameStr
) 
 161         : wxWindow(owner
, id
, pos
, size
, 
 162                    wxBORDER_NONE 
| additionalStyle
, 
 168     virtual bool AcceptsFocus() const { return false; } 
 170     wxGrid 
*GetOwner() { return m_owner
; } 
 173     void OnMouseCaptureLost(wxMouseCaptureLostEvent
& event
); 
 177     DECLARE_EVENT_TABLE() 
 178     DECLARE_NO_COPY_CLASS(wxGridSubwindow
) 
 181 class WXDLLIMPEXP_ADV wxGridRowLabelWindow 
: public wxGridSubwindow
 
 184     wxGridRowLabelWindow() { } 
 185     wxGridRowLabelWindow( wxGrid 
*parent
, wxWindowID id
, 
 186                           const wxPoint 
&pos
, const wxSize 
&size 
); 
 189     void OnPaint( wxPaintEvent
& event 
); 
 190     void OnMouseEvent( wxMouseEvent
& event 
); 
 191     void OnMouseWheel( wxMouseEvent
& event 
); 
 193     DECLARE_DYNAMIC_CLASS(wxGridRowLabelWindow
) 
 194     DECLARE_EVENT_TABLE() 
 195     DECLARE_NO_COPY_CLASS(wxGridRowLabelWindow
) 
 199 class WXDLLIMPEXP_ADV wxGridColLabelWindow 
: public wxGridSubwindow
 
 202     wxGridColLabelWindow() { } 
 203     wxGridColLabelWindow( wxGrid 
*parent
, wxWindowID id
, 
 204                           const wxPoint 
&pos
, const wxSize 
&size 
); 
 207     void OnPaint( wxPaintEvent
& event 
); 
 208     void OnMouseEvent( wxMouseEvent
& event 
); 
 209     void OnMouseWheel( wxMouseEvent
& event 
); 
 211     DECLARE_DYNAMIC_CLASS(wxGridColLabelWindow
) 
 212     DECLARE_EVENT_TABLE() 
 213     DECLARE_NO_COPY_CLASS(wxGridColLabelWindow
) 
 217 class WXDLLIMPEXP_ADV wxGridCornerLabelWindow 
: public wxGridSubwindow
 
 220     wxGridCornerLabelWindow() { } 
 221     wxGridCornerLabelWindow( wxGrid 
*parent
, wxWindowID id
, 
 222                              const wxPoint 
&pos
, const wxSize 
&size 
); 
 225     void OnMouseEvent( wxMouseEvent
& event 
); 
 226     void OnMouseWheel( wxMouseEvent
& event 
); 
 227     void OnPaint( wxPaintEvent
& event 
); 
 229     DECLARE_DYNAMIC_CLASS(wxGridCornerLabelWindow
) 
 230     DECLARE_EVENT_TABLE() 
 231     DECLARE_NO_COPY_CLASS(wxGridCornerLabelWindow
) 
 234 class WXDLLIMPEXP_ADV wxGridWindow 
: public wxGridSubwindow
 
 239         m_rowLabelWin 
= NULL
; 
 240         m_colLabelWin 
= NULL
; 
 243     wxGridWindow( wxGrid 
*parent
, 
 244                   wxGridRowLabelWindow 
*rowLblWin
, 
 245                   wxGridColLabelWindow 
*colLblWin
, 
 246                   wxWindowID id
, const wxPoint 
&pos
, const wxSize 
&size 
); 
 248     void ScrollWindow( int dx
, int dy
, const wxRect 
*rect 
); 
 250     virtual bool AcceptsFocus() const { return true; } 
 253     wxGridRowLabelWindow     
*m_rowLabelWin
; 
 254     wxGridColLabelWindow     
*m_colLabelWin
; 
 256     void OnPaint( wxPaintEvent 
&event 
); 
 257     void OnMouseWheel( wxMouseEvent
& event 
); 
 258     void OnMouseEvent( wxMouseEvent
& event 
); 
 259     void OnKeyDown( wxKeyEvent
& ); 
 260     void OnKeyUp( wxKeyEvent
& ); 
 261     void OnChar( wxKeyEvent
& ); 
 262     void OnEraseBackground( wxEraseEvent
& ); 
 263     void OnFocus( wxFocusEvent
& ); 
 265     DECLARE_DYNAMIC_CLASS(wxGridWindow
) 
 266     DECLARE_EVENT_TABLE() 
 267     DECLARE_NO_COPY_CLASS(wxGridWindow
) 
 271 class wxGridCellEditorEvtHandler 
: public wxEvtHandler
 
 274     wxGridCellEditorEvtHandler(wxGrid
* grid
, wxGridCellEditor
* editor
) 
 281     void OnKillFocus(wxFocusEvent
& event
); 
 282     void OnKeyDown(wxKeyEvent
& event
); 
 283     void OnChar(wxKeyEvent
& event
); 
 285     void SetInSetFocus(bool inSetFocus
) { m_inSetFocus 
= inSetFocus
; } 
 289     wxGridCellEditor   
*m_editor
; 
 291     // Work around the fact that a focus kill event can be sent to 
 292     // a combobox within a set focus event. 
 295     DECLARE_EVENT_TABLE() 
 296     DECLARE_DYNAMIC_CLASS(wxGridCellEditorEvtHandler
) 
 297     DECLARE_NO_COPY_CLASS(wxGridCellEditorEvtHandler
) 
 301 IMPLEMENT_ABSTRACT_CLASS(wxGridCellEditorEvtHandler
, wxEvtHandler
) 
 303 BEGIN_EVENT_TABLE( wxGridCellEditorEvtHandler
, wxEvtHandler 
) 
 304     EVT_KILL_FOCUS( wxGridCellEditorEvtHandler::OnKillFocus 
) 
 305     EVT_KEY_DOWN( wxGridCellEditorEvtHandler::OnKeyDown 
) 
 306     EVT_CHAR( wxGridCellEditorEvtHandler::OnChar 
) 
 310 // ---------------------------------------------------------------------------- 
 311 // the internal data representation used by wxGridCellAttrProvider 
 312 // ---------------------------------------------------------------------------- 
 314 // this class stores attributes set for cells 
 315 class WXDLLIMPEXP_ADV wxGridCellAttrData
 
 318     void SetAttr(wxGridCellAttr 
*attr
, int row
, int col
); 
 319     wxGridCellAttr 
*GetAttr(int row
, int col
) const; 
 320     void UpdateAttrRows( size_t pos
, int numRows 
); 
 321     void UpdateAttrCols( size_t pos
, int numCols 
); 
 324     // searches for the attr for given cell, returns wxNOT_FOUND if not found 
 325     int FindIndex(int row
, int col
) const; 
 327     wxGridCellWithAttrArray m_attrs
; 
 330 // this class stores attributes set for rows or columns 
 331 class WXDLLIMPEXP_ADV wxGridRowOrColAttrData
 
 334     // empty ctor to suppress warnings 
 335     wxGridRowOrColAttrData() {} 
 336     ~wxGridRowOrColAttrData(); 
 338     void SetAttr(wxGridCellAttr 
*attr
, int rowOrCol
); 
 339     wxGridCellAttr 
*GetAttr(int rowOrCol
) const; 
 340     void UpdateAttrRowsOrCols( size_t pos
, int numRowsOrCols 
); 
 343     wxArrayInt m_rowsOrCols
; 
 344     wxArrayAttrs m_attrs
; 
 347 // NB: this is just a wrapper around 3 objects: one which stores cell 
 348 //     attributes, and 2 others for row/col ones 
 349 class WXDLLIMPEXP_ADV wxGridCellAttrProviderData
 
 352     wxGridCellAttrData m_cellAttrs
; 
 353     wxGridRowOrColAttrData m_rowAttrs
, 
 358 // ---------------------------------------------------------------------------- 
 359 // data structures used for the data type registry 
 360 // ---------------------------------------------------------------------------- 
 362 struct wxGridDataTypeInfo
 
 364     wxGridDataTypeInfo(const wxString
& typeName
, 
 365                        wxGridCellRenderer
* renderer
, 
 366                        wxGridCellEditor
* editor
) 
 367         : m_typeName(typeName
), m_renderer(renderer
), m_editor(editor
) 
 370     ~wxGridDataTypeInfo() 
 372         wxSafeDecRef(m_renderer
); 
 373         wxSafeDecRef(m_editor
); 
 377     wxGridCellRenderer
* m_renderer
; 
 378     wxGridCellEditor
*   m_editor
; 
 380     DECLARE_NO_COPY_CLASS(wxGridDataTypeInfo
) 
 384 WX_DEFINE_ARRAY_WITH_DECL_PTR(wxGridDataTypeInfo
*, wxGridDataTypeInfoArray
, 
 385                                  class WXDLLIMPEXP_ADV
); 
 388 class WXDLLIMPEXP_ADV wxGridTypeRegistry
 
 391   wxGridTypeRegistry() {} 
 392     ~wxGridTypeRegistry(); 
 394     void RegisterDataType(const wxString
& typeName
, 
 395                      wxGridCellRenderer
* renderer
, 
 396                      wxGridCellEditor
* editor
); 
 398     // find one of already registered data types 
 399     int FindRegisteredDataType(const wxString
& typeName
); 
 401     // try to FindRegisteredDataType(), if this fails and typeName is one of 
 402     // standard typenames, register it and return its index 
 403     int FindDataType(const wxString
& typeName
); 
 405     // try to FindDataType(), if it fails see if it is not one of already 
 406     // registered data types with some params in which case clone the 
 407     // registered data type and set params for it 
 408     int FindOrCloneDataType(const wxString
& typeName
); 
 410     wxGridCellRenderer
* GetRenderer(int index
); 
 411     wxGridCellEditor
*   GetEditor(int index
); 
 414     wxGridDataTypeInfoArray m_typeinfo
; 
 418 // ---------------------------------------------------------------------------- 
 419 // conditional compilation 
 420 // ---------------------------------------------------------------------------- 
 422 #ifndef WXGRID_DRAW_LINES 
 423 #define WXGRID_DRAW_LINES 1 
 426 // ---------------------------------------------------------------------------- 
 428 // ---------------------------------------------------------------------------- 
 430 //#define DEBUG_ATTR_CACHE 
 431 #ifdef DEBUG_ATTR_CACHE 
 432     static size_t gs_nAttrCacheHits 
= 0; 
 433     static size_t gs_nAttrCacheMisses 
= 0; 
 436 // ---------------------------------------------------------------------------- 
 438 // ---------------------------------------------------------------------------- 
 440 wxGridCellCoords 
wxGridNoCellCoords( -1, -1 ); 
 441 wxRect 
wxGridNoCellRect( -1, -1, -1, -1 ); 
 444 // TODO: this doesn't work at all, grid cells have different sizes and approx 
 445 //       calculations don't work as because of the size mismatch scrollbars 
 446 //       sometimes fail to be shown when they should be or vice versa 
 448 //       The scroll bars may be a little flakey once in a while, but that is 
 449 //       surely much less horrible than having scroll lines of only 1!!! 
 452 //       Well, it's still seriously broken so it might be better but needs 
 455 static const size_t GRID_SCROLL_LINE_X 
= 15;  // 1; 
 456 static const size_t GRID_SCROLL_LINE_Y 
= GRID_SCROLL_LINE_X
; 
 458 // the size of hash tables used a bit everywhere (the max number of elements 
 459 // in these hash tables is the number of rows/columns) 
 460 static const int GRID_HASH_SIZE 
= 100; 
 463 // ---------------------------------------------------------------------------- 
 465 // ---------------------------------------------------------------------------- 
 467 static inline int GetScrollX(int x
) 
 469     return (x 
+ GRID_SCROLL_LINE_X 
- 1) / GRID_SCROLL_LINE_X
; 
 472 static inline int GetScrollY(int y
) 
 474     return (y 
+ GRID_SCROLL_LINE_Y 
- 1) / GRID_SCROLL_LINE_Y
; 
 478 // ============================================================================ 
 480 // ============================================================================ 
 482 // ---------------------------------------------------------------------------- 
 484 // ---------------------------------------------------------------------------- 
 486 wxGridCellEditor::wxGridCellEditor() 
 492 wxGridCellEditor::~wxGridCellEditor() 
 497 void wxGridCellEditor::Create(wxWindow
* WXUNUSED(parent
), 
 498                               wxWindowID 
WXUNUSED(id
), 
 499                               wxEvtHandler
* evtHandler
) 
 502         m_control
->PushEventHandler(evtHandler
); 
 505 void wxGridCellEditor::PaintBackground(const wxRect
& rectCell
, 
 506                                        wxGridCellAttr 
*attr
) 
 508     // erase the background because we might not fill the cell 
 509     wxClientDC 
dc(m_control
->GetParent()); 
 510     wxGridWindow
* gridWindow 
= wxDynamicCast(m_control
->GetParent(), wxGridWindow
); 
 512         gridWindow
->GetOwner()->PrepareDC(dc
); 
 514     dc
.SetPen(*wxTRANSPARENT_PEN
); 
 515     dc
.SetBrush(wxBrush(attr
->GetBackgroundColour(), wxBRUSHSTYLE_SOLID
)); 
 516     dc
.DrawRectangle(rectCell
); 
 518     // redraw the control we just painted over 
 519     m_control
->Refresh(); 
 522 void wxGridCellEditor::Destroy() 
 526         m_control
->PopEventHandler( true /* delete it*/ ); 
 528         m_control
->Destroy(); 
 533 void wxGridCellEditor::Show(bool show
, wxGridCellAttr 
*attr
) 
 535     wxASSERT_MSG(m_control
, wxT("The wxGridCellEditor must be created first!")); 
 537     m_control
->Show(show
); 
 541         // set the colours/fonts if we have any 
 544             m_colFgOld 
= m_control
->GetForegroundColour(); 
 545             m_control
->SetForegroundColour(attr
->GetTextColour()); 
 547             m_colBgOld 
= m_control
->GetBackgroundColour(); 
 548             m_control
->SetBackgroundColour(attr
->GetBackgroundColour()); 
 550 // Workaround for GTK+1 font setting problem on some platforms 
 551 #if !defined(__WXGTK__) || defined(__WXGTK20__) 
 552             m_fontOld 
= m_control
->GetFont(); 
 553             m_control
->SetFont(attr
->GetFont()); 
 556             // can't do anything more in the base class version, the other 
 557             // attributes may only be used by the derived classes 
 562         // restore the standard colours fonts 
 563         if ( m_colFgOld
.Ok() ) 
 565             m_control
->SetForegroundColour(m_colFgOld
); 
 566             m_colFgOld 
= wxNullColour
; 
 569         if ( m_colBgOld
.Ok() ) 
 571             m_control
->SetBackgroundColour(m_colBgOld
); 
 572             m_colBgOld 
= wxNullColour
; 
 575 // Workaround for GTK+1 font setting problem on some platforms 
 576 #if !defined(__WXGTK__) || defined(__WXGTK20__) 
 577         if ( m_fontOld
.Ok() ) 
 579             m_control
->SetFont(m_fontOld
); 
 580             m_fontOld 
= wxNullFont
; 
 586 void wxGridCellEditor::SetSize(const wxRect
& rect
) 
 588     wxASSERT_MSG(m_control
, wxT("The wxGridCellEditor must be created first!")); 
 590     m_control
->SetSize(rect
, wxSIZE_ALLOW_MINUS_ONE
); 
 593 void wxGridCellEditor::HandleReturn(wxKeyEvent
& event
) 
 598 bool wxGridCellEditor::IsAcceptedKey(wxKeyEvent
& event
) 
 600     bool ctrl 
= event
.ControlDown(); 
 601     bool alt  
= event
.AltDown(); 
 604     // On the Mac the Alt key is more like shift and is used for entry of 
 605     // valid characters, so check for Ctrl and Meta instead. 
 606     alt 
= event
.MetaDown(); 
 609     // Assume it's not a valid char if ctrl or alt is down, but if both are 
 610     // down then it may be because of an AltGr key combination, so let them 
 611     // through in that case. 
 612     if ((ctrl 
|| alt
) && !(ctrl 
&& alt
)) 
 619     // If it's a F-Key or other special key then it shouldn't start the 
 621     if (event
.GetKeyCode() >= WXK_START
) 
 625     // if the unicode key code is not really a unicode character (it may 
 626     // be a function key or etc., the platforms appear to always give us a 
 627     // small value in this case) then fallback to the ASCII key code but 
 628     // don't do anything for function keys or etc. 
 629     key 
= event
.GetUnicodeKey(); 
 632         key 
= event
.GetKeyCode(); 
 633         keyOk 
= (key 
<= 127); 
 636     key 
= event
.GetKeyCode(); 
 637     keyOk 
= (key 
<= 255); 
 643 void wxGridCellEditor::StartingKey(wxKeyEvent
& event
) 
 648 void wxGridCellEditor::StartingClick() 
 654 // ---------------------------------------------------------------------------- 
 655 // wxGridCellTextEditor 
 656 // ---------------------------------------------------------------------------- 
 658 wxGridCellTextEditor::wxGridCellTextEditor() 
 663 void wxGridCellTextEditor::Create(wxWindow
* parent
, 
 665                                   wxEvtHandler
* evtHandler
) 
 667     DoCreate(parent
, id
, evtHandler
); 
 670 void wxGridCellTextEditor::DoCreate(wxWindow
* parent
, 
 672                                     wxEvtHandler
* evtHandler
, 
 675     style 
|= wxTE_PROCESS_ENTER 
| wxTE_PROCESS_TAB 
| wxNO_BORDER
; 
 677     m_control 
= new wxTextCtrl(parent
, id
, wxEmptyString
, 
 678                                wxDefaultPosition
, wxDefaultSize
, 
 681     // set max length allowed in the textctrl, if the parameter was set 
 682     if ( m_maxChars 
!= 0 ) 
 684         Text()->SetMaxLength(m_maxChars
); 
 687     wxGridCellEditor::Create(parent
, id
, evtHandler
); 
 690 void wxGridCellTextEditor::PaintBackground(const wxRect
& WXUNUSED(rectCell
), 
 691                                            wxGridCellAttr 
* WXUNUSED(attr
)) 
 693     // as we fill the entire client area, 
 694     // don't do anything here to minimize flicker 
 697 void wxGridCellTextEditor::SetSize(const wxRect
& rectOrig
) 
 699     wxRect 
rect(rectOrig
); 
 701     // Make the edit control large enough to allow for internal margins 
 703     // TODO: remove this if the text ctrl sizing is improved esp. for unix 
 705 #if defined(__WXGTK__) 
 713 #elif defined(__WXMSW__) 
 727     int extra_x 
= ( rect
.x 
> 2 ) ? 2 : 1; 
 728     int extra_y 
= ( rect
.y 
> 2 ) ? 2 : 1; 
 730     #if defined(__WXMOTIF__) 
 735     rect
.SetLeft( wxMax(0, rect
.x 
- extra_x
) ); 
 736     rect
.SetTop( wxMax(0, rect
.y 
- extra_y
) ); 
 737     rect
.SetRight( rect
.GetRight() + 2 * extra_x 
); 
 738     rect
.SetBottom( rect
.GetBottom() + 2 * extra_y 
); 
 741     wxGridCellEditor::SetSize(rect
); 
 744 void wxGridCellTextEditor::BeginEdit(int row
, int col
, wxGrid
* grid
) 
 746     wxASSERT_MSG(m_control
, wxT("The wxGridCellEditor must be created first!")); 
 748     m_startValue 
= grid
->GetTable()->GetValue(row
, col
); 
 750     DoBeginEdit(m_startValue
); 
 753 void wxGridCellTextEditor::DoBeginEdit(const wxString
& startValue
) 
 755     Text()->SetValue(startValue
); 
 756     Text()->SetInsertionPointEnd(); 
 757     Text()->SetSelection(-1, -1); 
 761 bool wxGridCellTextEditor::EndEdit(int row
, int col
, wxGrid
* grid
) 
 763     wxASSERT_MSG(m_control
, wxT("The wxGridCellEditor must be created first!")); 
 765     bool changed 
= false; 
 766     wxString value 
= Text()->GetValue(); 
 767     if (value 
!= m_startValue
) 
 771         grid
->GetTable()->SetValue(row
, col
, value
); 
 773     m_startValue 
= wxEmptyString
; 
 775     // No point in setting the text of the hidden control 
 776     //Text()->SetValue(m_startValue); 
 781 void wxGridCellTextEditor::Reset() 
 783     wxASSERT_MSG(m_control
, wxT("The wxGridCellEditor must be created first!")); 
 785     DoReset(m_startValue
); 
 788 void wxGridCellTextEditor::DoReset(const wxString
& startValue
) 
 790     Text()->SetValue(startValue
); 
 791     Text()->SetInsertionPointEnd(); 
 794 bool wxGridCellTextEditor::IsAcceptedKey(wxKeyEvent
& event
) 
 796     return wxGridCellEditor::IsAcceptedKey(event
); 
 799 void wxGridCellTextEditor::StartingKey(wxKeyEvent
& event
) 
 801     // Since this is now happening in the EVT_CHAR event EmulateKeyPress is no 
 802     // longer an appropriate way to get the character into the text control. 
 803     // Do it ourselves instead.  We know that if we get this far that we have 
 804     // a valid character, so not a whole lot of testing needs to be done. 
 806     wxTextCtrl
* tc 
= Text(); 
 811     ch 
= event
.GetUnicodeKey(); 
 813         ch 
= (wxChar
)event
.GetKeyCode(); 
 815     ch 
= (wxChar
)event
.GetKeyCode(); 
 821             // delete the character at the cursor 
 822             pos 
= tc
->GetInsertionPoint(); 
 823             if (pos 
< tc
->GetLastPosition()) 
 824                 tc
->Remove(pos
, pos 
+ 1); 
 828             // delete the character before the cursor 
 829             pos 
= tc
->GetInsertionPoint(); 
 831                 tc
->Remove(pos 
- 1, pos
); 
 840 void wxGridCellTextEditor::HandleReturn( wxKeyEvent
& 
 841                                          WXUNUSED_GTK(WXUNUSED_MOTIF(event
)) ) 
 843 #if defined(__WXMOTIF__) || defined(__WXGTK__) 
 844     // wxMotif needs a little extra help... 
 845     size_t pos 
= (size_t)( Text()->GetInsertionPoint() ); 
 846     wxString 
s( Text()->GetValue() ); 
 847     s 
= s
.Left(pos
) + wxT("\n") + s
.Mid(pos
); 
 849     Text()->SetInsertionPoint( pos 
); 
 851     // the other ports can handle a Return key press 
 857 void wxGridCellTextEditor::SetParameters(const wxString
& params
) 
 867         if ( params
.ToLong(&tmp
) ) 
 869             m_maxChars 
= (size_t)tmp
; 
 873             wxLogDebug( _T("Invalid wxGridCellTextEditor parameter string '%s' ignored"), params
.c_str() ); 
 878 // return the value in the text control 
 879 wxString 
wxGridCellTextEditor::GetValue() const 
 881     return Text()->GetValue(); 
 884 // ---------------------------------------------------------------------------- 
 885 // wxGridCellNumberEditor 
 886 // ---------------------------------------------------------------------------- 
 888 wxGridCellNumberEditor::wxGridCellNumberEditor(int min
, int max
) 
 894 void wxGridCellNumberEditor::Create(wxWindow
* parent
, 
 896                                     wxEvtHandler
* evtHandler
) 
 901         // create a spin ctrl 
 902         m_control 
= new wxSpinCtrl(parent
, wxID_ANY
, wxEmptyString
, 
 903                                    wxDefaultPosition
, wxDefaultSize
, 
 907         wxGridCellEditor::Create(parent
, id
, evtHandler
); 
 912         // just a text control 
 913         wxGridCellTextEditor::Create(parent
, id
, evtHandler
); 
 916         Text()->SetValidator(wxTextValidator(wxFILTER_NUMERIC
)); 
 921 void wxGridCellNumberEditor::BeginEdit(int row
, int col
, wxGrid
* grid
) 
 923     // first get the value 
 924     wxGridTableBase 
*table 
= grid
->GetTable(); 
 925     if ( table
->CanGetValueAs(row
, col
, wxGRID_VALUE_NUMBER
) ) 
 927         m_valueOld 
= table
->GetValueAsLong(row
, col
); 
 932         wxString sValue 
= table
->GetValue(row
, col
); 
 933         if (! sValue
.ToLong(&m_valueOld
) && ! sValue
.empty()) 
 935             wxFAIL_MSG( _T("this cell doesn't have numeric value") ); 
 943         Spin()->SetValue((int)m_valueOld
); 
 949         DoBeginEdit(GetString()); 
 953 bool wxGridCellNumberEditor::EndEdit(int row
, int col
, 
 962         value 
= Spin()->GetValue(); 
 963         if ( value 
== m_valueOld 
) 
 966         text
.Printf(wxT("%ld"), value
); 
 968     else // using unconstrained input 
 969 #endif // wxUSE_SPINCTRL 
 971         const wxString 
textOld(grid
->GetCellValue(row
, col
)); 
 972         text 
= Text()->GetValue(); 
 975             if ( textOld
.empty() ) 
 978         else // non-empty text now (maybe 0) 
 980             if ( !text
.ToLong(&value
) ) 
 983             // if value == m_valueOld == 0 but old text was "" and new one is 
 984             // "0" something still did change 
 985             if ( value 
== m_valueOld 
&& (value 
|| !textOld
.empty()) ) 
 990     wxGridTableBase 
* const table 
= grid
->GetTable(); 
 991     if ( table
->CanSetValueAs(row
, col
, wxGRID_VALUE_NUMBER
) ) 
 992         table
->SetValueAsLong(row
, col
, value
); 
 994         table
->SetValue(row
, col
, text
); 
 999 void wxGridCellNumberEditor::Reset() 
1004         Spin()->SetValue((int)m_valueOld
); 
1009         DoReset(GetString()); 
1013 bool wxGridCellNumberEditor::IsAcceptedKey(wxKeyEvent
& event
) 
1015     if ( wxGridCellEditor::IsAcceptedKey(event
) ) 
1017         int keycode 
= event
.GetKeyCode(); 
1018         if ( (keycode 
< 128) && 
1019              (wxIsdigit(keycode
) || keycode 
== '+' || keycode 
== '-')) 
1028 void wxGridCellNumberEditor::StartingKey(wxKeyEvent
& event
) 
1030     int keycode 
= event
.GetKeyCode(); 
1033         if ( wxIsdigit(keycode
) || keycode 
== '+' || keycode 
== '-') 
1035             wxGridCellTextEditor::StartingKey(event
); 
1037             // skip Skip() below 
1044         if ( wxIsdigit(keycode
) ) 
1046             wxSpinCtrl
* spin 
= (wxSpinCtrl
*)m_control
; 
1047             spin
->SetValue(keycode 
- '0'); 
1048             spin
->SetSelection(1,1); 
1057 void wxGridCellNumberEditor::SetParameters(const wxString
& params
) 
1068         if ( params
.BeforeFirst(_T(',')).ToLong(&tmp
) ) 
1072             if ( params
.AfterFirst(_T(',')).ToLong(&tmp
) ) 
1076                 // skip the error message below 
1081         wxLogDebug(_T("Invalid wxGridCellNumberEditor parameter string '%s' ignored"), params
.c_str()); 
1085 // return the value in the spin control if it is there (the text control otherwise) 
1086 wxString 
wxGridCellNumberEditor::GetValue() const 
1093         long value 
= Spin()->GetValue(); 
1094         s
.Printf(wxT("%ld"), value
); 
1099         s 
= Text()->GetValue(); 
1105 // ---------------------------------------------------------------------------- 
1106 // wxGridCellFloatEditor 
1107 // ---------------------------------------------------------------------------- 
1109 wxGridCellFloatEditor::wxGridCellFloatEditor(int width
, int precision
) 
1112     m_precision 
= precision
; 
1115 void wxGridCellFloatEditor::Create(wxWindow
* parent
, 
1117                                    wxEvtHandler
* evtHandler
) 
1119     wxGridCellTextEditor::Create(parent
, id
, evtHandler
); 
1121 #if wxUSE_VALIDATORS 
1122     Text()->SetValidator(wxTextValidator(wxFILTER_NUMERIC
)); 
1126 void wxGridCellFloatEditor::BeginEdit(int row
, int col
, wxGrid
* grid
) 
1128     // first get the value 
1129     wxGridTableBase 
* const table 
= grid
->GetTable(); 
1130     if ( table
->CanGetValueAs(row
, col
, wxGRID_VALUE_FLOAT
) ) 
1132         m_valueOld 
= table
->GetValueAsDouble(row
, col
); 
1138         const wxString value 
= table
->GetValue(row
, col
); 
1139         if ( !value
.empty() ) 
1141             if ( !value
.ToDouble(&m_valueOld
) ) 
1143                 wxFAIL_MSG( _T("this cell doesn't have float value") ); 
1149     DoBeginEdit(GetString()); 
1152 bool wxGridCellFloatEditor::EndEdit(int row
, int col
, wxGrid
* grid
) 
1154     const wxString 
text(Text()->GetValue()), 
1155                    textOld(grid
->GetCellValue(row
, col
)); 
1158     if ( !text
.empty() ) 
1160         if ( !text
.ToDouble(&value
) ) 
1163     else // new value is empty string 
1165         if ( textOld
.empty() ) 
1166             return false;           // nothing changed 
1171     // the test for empty strings ensures that we don't skip the value setting 
1172     // when "" is replaced by "0" or vice versa as "" numeric value is also 0. 
1173     if ( wxIsSameDouble(value
, m_valueOld
) && !text
.empty() && !textOld
.empty() ) 
1174         return false;           // nothing changed 
1176     wxGridTableBase 
* const table 
= grid
->GetTable(); 
1178     if ( table
->CanSetValueAs(row
, col
, wxGRID_VALUE_FLOAT
) ) 
1179         table
->SetValueAsDouble(row
, col
, value
); 
1181         table
->SetValue(row
, col
, text
); 
1186 void wxGridCellFloatEditor::Reset() 
1188     DoReset(GetString()); 
1191 void wxGridCellFloatEditor::StartingKey(wxKeyEvent
& event
) 
1193     int keycode 
= event
.GetKeyCode(); 
1195     tmpbuf
[0] = (char) keycode
; 
1197     wxString 
strbuf(tmpbuf
, *wxConvCurrent
); 
1200     bool is_decimal_point 
= ( strbuf 
== 
1201        wxLocale::GetInfo(wxLOCALE_DECIMAL_POINT
, wxLOCALE_CAT_NUMBER
) ); 
1203     bool is_decimal_point 
= ( strbuf 
== _T(".") ); 
1206     if ( wxIsdigit(keycode
) || keycode 
== '+' || keycode 
== '-' 
1207          || is_decimal_point 
) 
1209         wxGridCellTextEditor::StartingKey(event
); 
1211         // skip Skip() below 
1218 void wxGridCellFloatEditor::SetParameters(const wxString
& params
) 
1229         if ( params
.BeforeFirst(_T(',')).ToLong(&tmp
) ) 
1233             if ( params
.AfterFirst(_T(',')).ToLong(&tmp
) ) 
1235                 m_precision 
= (int)tmp
; 
1237                 // skip the error message below 
1242         wxLogDebug(_T("Invalid wxGridCellFloatEditor parameter string '%s' ignored"), params
.c_str()); 
1246 wxString 
wxGridCellFloatEditor::GetString() const 
1249     if ( m_precision 
== -1 && m_width 
!= -1) 
1251         // default precision 
1252         fmt
.Printf(_T("%%%d.f"), m_width
); 
1254     else if ( m_precision 
!= -1 && m_width 
== -1) 
1257         fmt
.Printf(_T("%%.%df"), m_precision
); 
1259     else if ( m_precision 
!= -1 && m_width 
!= -1 ) 
1261         fmt
.Printf(_T("%%%d.%df"), m_width
, m_precision
); 
1265         // default width/precision 
1269     return wxString::Format(fmt
, m_valueOld
); 
1272 bool wxGridCellFloatEditor::IsAcceptedKey(wxKeyEvent
& event
) 
1274     if ( wxGridCellEditor::IsAcceptedKey(event
) ) 
1276         const int keycode 
= event
.GetKeyCode(); 
1277         if ( isascii(keycode
) ) 
1280             tmpbuf
[0] = (char) keycode
; 
1282             wxString 
strbuf(tmpbuf
, *wxConvCurrent
); 
1285             const wxString decimalPoint 
= 
1286                 wxLocale::GetInfo(wxLOCALE_DECIMAL_POINT
, wxLOCALE_CAT_NUMBER
); 
1288             const wxString 
decimalPoint(_T('.')); 
1291             // accept digits, 'e' as in '1e+6', also '-', '+', and '.' 
1292             if ( wxIsdigit(keycode
) || 
1293                     tolower(keycode
) == 'e' || 
1294                         keycode 
== decimalPoint 
|| 
1306 #endif // wxUSE_TEXTCTRL 
1310 // ---------------------------------------------------------------------------- 
1311 // wxGridCellBoolEditor 
1312 // ---------------------------------------------------------------------------- 
1314 // the default values for GetValue() 
1315 wxString 
wxGridCellBoolEditor::ms_stringValues
[2] = { _T(""), _T("1") }; 
1317 void wxGridCellBoolEditor::Create(wxWindow
* parent
, 
1319                                   wxEvtHandler
* evtHandler
) 
1321     m_control 
= new wxCheckBox(parent
, id
, wxEmptyString
, 
1322                                wxDefaultPosition
, wxDefaultSize
, 
1325     wxGridCellEditor::Create(parent
, id
, evtHandler
); 
1328 void wxGridCellBoolEditor::SetSize(const wxRect
& r
) 
1330     bool resize 
= false; 
1331     wxSize size 
= m_control
->GetSize(); 
1332     wxCoord minSize 
= wxMin(r
.width
, r
.height
); 
1334     // check if the checkbox is not too big/small for this cell 
1335     wxSize sizeBest 
= m_control
->GetBestSize(); 
1336     if ( !(size 
== sizeBest
) ) 
1338         // reset to default size if it had been made smaller 
1344     if ( size
.x 
>= minSize 
|| size
.y 
>= minSize 
) 
1346         // leave 1 pixel margin 
1347         size
.x 
= size
.y 
= minSize 
- 2; 
1354         m_control
->SetSize(size
); 
1357     // position it in the centre of the rectangle (TODO: support alignment?) 
1359 #if defined(__WXGTK__) || defined (__WXMOTIF__) 
1360     // the checkbox without label still has some space to the right in wxGTK, 
1361     // so shift it to the right 
1363 #elif defined(__WXMSW__) 
1364     // here too, but in other way 
1369     int hAlign 
= wxALIGN_CENTRE
; 
1370     int vAlign 
= wxALIGN_CENTRE
; 
1372         GetCellAttr()->GetAlignment(& hAlign
, & vAlign
); 
1375     if (hAlign 
== wxALIGN_LEFT
) 
1383         y 
= r
.y 
+ r
.height 
/ 2 - size
.y 
/ 2; 
1385     else if (hAlign 
== wxALIGN_RIGHT
) 
1387         x 
= r
.x 
+ r
.width 
- size
.x 
- 2; 
1388         y 
= r
.y 
+ r
.height 
/ 2 - size
.y 
/ 2; 
1390     else if (hAlign 
== wxALIGN_CENTRE
) 
1392         x 
= r
.x 
+ r
.width 
/ 2 - size
.x 
/ 2; 
1393         y 
= r
.y 
+ r
.height 
/ 2 - size
.y 
/ 2; 
1396     m_control
->Move(x
, y
); 
1399 void wxGridCellBoolEditor::Show(bool show
, wxGridCellAttr 
*attr
) 
1401     m_control
->Show(show
); 
1405         wxColour colBg 
= attr 
? attr
->GetBackgroundColour() : *wxLIGHT_GREY
; 
1406         CBox()->SetBackgroundColour(colBg
); 
1410 void wxGridCellBoolEditor::BeginEdit(int row
, int col
, wxGrid
* grid
) 
1412     wxASSERT_MSG(m_control
, 
1413                  wxT("The wxGridCellEditor must be created first!")); 
1415     if (grid
->GetTable()->CanGetValueAs(row
, col
, wxGRID_VALUE_BOOL
)) 
1417         m_startValue 
= grid
->GetTable()->GetValueAsBool(row
, col
); 
1421         wxString 
cellval( grid
->GetTable()->GetValue(row
, col
) ); 
1423         if ( cellval 
== ms_stringValues
[false] ) 
1424             m_startValue 
= false; 
1425         else if ( cellval 
== ms_stringValues
[true] ) 
1426             m_startValue 
= true; 
1429             // do not try to be smart here and convert it to true or false 
1430             // because we'll still overwrite it with something different and 
1431             // this risks to be very surprising for the user code, let them 
1433             wxFAIL_MSG( _T("invalid value for a cell with bool editor!") ); 
1437     CBox()->SetValue(m_startValue
); 
1441 bool wxGridCellBoolEditor::EndEdit(int row
, int col
, 
1444     wxASSERT_MSG(m_control
, 
1445                  wxT("The wxGridCellEditor must be created first!")); 
1447     bool changed 
= false; 
1448     bool value 
= CBox()->GetValue(); 
1449     if ( value 
!= m_startValue 
) 
1454         wxGridTableBase 
* const table 
= grid
->GetTable(); 
1455         if ( table
->CanGetValueAs(row
, col
, wxGRID_VALUE_BOOL
) ) 
1456             table
->SetValueAsBool(row
, col
, value
); 
1458             table
->SetValue(row
, col
, GetValue()); 
1464 void wxGridCellBoolEditor::Reset() 
1466     wxASSERT_MSG(m_control
, 
1467                  wxT("The wxGridCellEditor must be created first!")); 
1469     CBox()->SetValue(m_startValue
); 
1472 void wxGridCellBoolEditor::StartingClick() 
1474     CBox()->SetValue(!CBox()->GetValue()); 
1477 bool wxGridCellBoolEditor::IsAcceptedKey(wxKeyEvent
& event
) 
1479     if ( wxGridCellEditor::IsAcceptedKey(event
) ) 
1481         int keycode 
= event
.GetKeyCode(); 
1494 void wxGridCellBoolEditor::StartingKey(wxKeyEvent
& event
) 
1496     int keycode 
= event
.GetKeyCode(); 
1500             CBox()->SetValue(!CBox()->GetValue()); 
1504             CBox()->SetValue(true); 
1508             CBox()->SetValue(false); 
1513 wxString 
wxGridCellBoolEditor::GetValue() const 
1515   return ms_stringValues
[CBox()->GetValue()]; 
1519 wxGridCellBoolEditor::UseStringValues(const wxString
& valueTrue
, 
1520                                       const wxString
& valueFalse
) 
1522     ms_stringValues
[false] = valueFalse
; 
1523     ms_stringValues
[true] = valueTrue
; 
1527 wxGridCellBoolEditor::IsTrueValue(const wxString
& value
) 
1529     return value 
== ms_stringValues
[true]; 
1532 #endif // wxUSE_CHECKBOX 
1536 // ---------------------------------------------------------------------------- 
1537 // wxGridCellChoiceEditor 
1538 // ---------------------------------------------------------------------------- 
1540 wxGridCellChoiceEditor::wxGridCellChoiceEditor(const wxArrayString
& choices
, 
1542     : m_choices(choices
), 
1543       m_allowOthers(allowOthers
) { } 
1545 wxGridCellChoiceEditor::wxGridCellChoiceEditor(size_t count
, 
1546                                                const wxString choices
[], 
1548                       : m_allowOthers(allowOthers
) 
1552         m_choices
.Alloc(count
); 
1553         for ( size_t n 
= 0; n 
< count
; n
++ ) 
1555             m_choices
.Add(choices
[n
]); 
1560 wxGridCellEditor 
*wxGridCellChoiceEditor::Clone() const 
1562     wxGridCellChoiceEditor 
*editor 
= new wxGridCellChoiceEditor
; 
1563     editor
->m_allowOthers 
= m_allowOthers
; 
1564     editor
->m_choices 
= m_choices
; 
1569 void wxGridCellChoiceEditor::Create(wxWindow
* parent
, 
1571                                     wxEvtHandler
* evtHandler
) 
1573     int style 
= wxTE_PROCESS_ENTER 
| 
1577     if ( !m_allowOthers 
) 
1578         style 
|= wxCB_READONLY
; 
1579     m_control 
= new wxComboBox(parent
, id
, wxEmptyString
, 
1580                                wxDefaultPosition
, wxDefaultSize
, 
1584     wxGridCellEditor::Create(parent
, id
, evtHandler
); 
1587 void wxGridCellChoiceEditor::PaintBackground(const wxRect
& rectCell
, 
1588                                              wxGridCellAttr 
* attr
) 
1590     // as we fill the entire client area, don't do anything here to minimize 
1593     // TODO: It doesn't actually fill the client area since the height of a 
1594     // combo always defaults to the standard.  Until someone has time to 
1595     // figure out the right rectangle to paint, just do it the normal way. 
1596     wxGridCellEditor::PaintBackground(rectCell
, attr
); 
1599 void wxGridCellChoiceEditor::BeginEdit(int row
, int col
, wxGrid
* grid
) 
1601     wxASSERT_MSG(m_control
, 
1602                  wxT("The wxGridCellEditor must be created first!")); 
1604     wxGridCellEditorEvtHandler
* evtHandler 
= NULL
; 
1606         evtHandler 
= wxDynamicCast(m_control
->GetEventHandler(), wxGridCellEditorEvtHandler
); 
1608     // Don't immediately end if we get a kill focus event within BeginEdit 
1610         evtHandler
->SetInSetFocus(true); 
1612     m_startValue 
= grid
->GetTable()->GetValue(row
, col
); 
1614     Reset(); // this updates combo box to correspond to m_startValue 
1616     Combo()->SetFocus(); 
1620         // When dropping down the menu, a kill focus event 
1621         // happens after this point, so we can't reset the flag yet. 
1622 #if !defined(__WXGTK20__) 
1623         evtHandler
->SetInSetFocus(false); 
1628 bool wxGridCellChoiceEditor::EndEdit(int row
, int col
, 
1631     wxString value 
= Combo()->GetValue(); 
1632     if ( value 
== m_startValue 
) 
1635     grid
->GetTable()->SetValue(row
, col
, value
); 
1640 void wxGridCellChoiceEditor::Reset() 
1644         Combo()->SetValue(m_startValue
); 
1645         Combo()->SetInsertionPointEnd(); 
1647     else // the combobox is read-only 
1649         // find the right position, or default to the first if not found 
1650         int pos 
= Combo()->FindString(m_startValue
); 
1651         if (pos 
== wxNOT_FOUND
) 
1653         Combo()->SetSelection(pos
); 
1657 void wxGridCellChoiceEditor::SetParameters(const wxString
& params
) 
1667     wxStringTokenizer 
tk(params
, _T(',')); 
1668     while ( tk
.HasMoreTokens() ) 
1670         m_choices
.Add(tk
.GetNextToken()); 
1674 // return the value in the text control 
1675 wxString 
wxGridCellChoiceEditor::GetValue() const 
1677   return Combo()->GetValue(); 
1680 #endif // wxUSE_COMBOBOX 
1682 // ---------------------------------------------------------------------------- 
1683 // wxGridCellEditorEvtHandler 
1684 // ---------------------------------------------------------------------------- 
1686 void wxGridCellEditorEvtHandler::OnKillFocus(wxFocusEvent
& event
) 
1688     // Don't disable the cell if we're just starting to edit it 
1693     m_grid
->DisableCellEditControl(); 
1698 void wxGridCellEditorEvtHandler::OnKeyDown(wxKeyEvent
& event
) 
1700     switch ( event
.GetKeyCode() ) 
1704             m_grid
->DisableCellEditControl(); 
1708             m_grid
->GetEventHandler()->ProcessEvent( event 
); 
1712         case WXK_NUMPAD_ENTER
: 
1713             if (!m_grid
->GetEventHandler()->ProcessEvent(event
)) 
1714                 m_editor
->HandleReturn(event
); 
1723 void wxGridCellEditorEvtHandler::OnChar(wxKeyEvent
& event
) 
1725     int row 
= m_grid
->GetGridCursorRow(); 
1726     int col 
= m_grid
->GetGridCursorCol(); 
1727     wxRect rect 
= m_grid
->CellToRect( row
, col 
); 
1729     m_grid
->GetGridWindow()->GetClientSize( &cw
, &ch 
); 
1731     // if cell width is smaller than grid client area, cell is wholly visible 
1732     bool wholeCellVisible 
= (rect
.GetWidth() < cw
); 
1734     switch ( event
.GetKeyCode() ) 
1739         case WXK_NUMPAD_ENTER
: 
1744             if ( wholeCellVisible 
) 
1746                 // no special processing needed... 
1751             // do special processing for partly visible cell... 
1753             // get the widths of all cells previous to this one 
1755             for ( int i 
= 0; i 
< col
; i
++ ) 
1757                 colXPos 
+= m_grid
->GetColSize(i
); 
1760             int xUnit 
= 1, yUnit 
= 1; 
1761             m_grid
->GetScrollPixelsPerUnit(&xUnit
, &yUnit
); 
1764                 m_grid
->Scroll(colXPos 
/ xUnit 
- 1, m_grid
->GetScrollPos(wxVERTICAL
)); 
1768                 m_grid
->Scroll(colXPos 
/ xUnit
, m_grid
->GetScrollPos(wxVERTICAL
)); 
1776             if ( wholeCellVisible 
) 
1778                 // no special processing needed... 
1783             // do special processing for partly visible cell... 
1786             wxString value 
= m_grid
->GetCellValue(row
, col
); 
1787             if ( wxEmptyString 
!= value 
) 
1789                 // get width of cell CONTENTS (text) 
1791                 wxFont font 
= m_grid
->GetCellFont(row
, col
); 
1792                 m_grid
->GetTextExtent(value
, &textWidth
, &y
, NULL
, NULL
, &font
); 
1794                 // try to RIGHT align the text by scrolling 
1795                 int client_right 
= m_grid
->GetGridWindow()->GetClientSize().GetWidth(); 
1797                 // (m_grid->GetScrollLineX()*2) is a factor for not scrolling to far, 
1798                 // otherwise the last part of the cell content might be hidden below the scroll bar 
1799                 // FIXME: maybe there is a more suitable correction? 
1800                 textWidth 
-= (client_right 
- (m_grid
->GetScrollLineX() * 2)); 
1801                 if ( textWidth 
< 0 ) 
1807             // get the widths of all cells previous to this one 
1809             for ( int i 
= 0; i 
< col
; i
++ ) 
1811                 colXPos 
+= m_grid
->GetColSize(i
); 
1814             // and add the (modified) text width of the cell contents 
1815             // as we'd like to see the last part of the cell contents 
1816             colXPos 
+= textWidth
; 
1818             int xUnit 
= 1, yUnit 
= 1; 
1819             m_grid
->GetScrollPixelsPerUnit(&xUnit
, &yUnit
); 
1820             m_grid
->Scroll(colXPos 
/ xUnit 
- 1, m_grid
->GetScrollPos(wxVERTICAL
)); 
1831 // ---------------------------------------------------------------------------- 
1832 // wxGridCellWorker is an (almost) empty common base class for 
1833 // wxGridCellRenderer and wxGridCellEditor managing ref counting 
1834 // ---------------------------------------------------------------------------- 
1836 void wxGridCellWorker::SetParameters(const wxString
& WXUNUSED(params
)) 
1841 wxGridCellWorker::~wxGridCellWorker() 
1845 // ============================================================================ 
1847 // ============================================================================ 
1849 // ---------------------------------------------------------------------------- 
1850 // wxGridCellRenderer 
1851 // ---------------------------------------------------------------------------- 
1853 void wxGridCellRenderer::Draw(wxGrid
& grid
, 
1854                               wxGridCellAttr
& attr
, 
1857                               int WXUNUSED(row
), int WXUNUSED(col
), 
1860     dc
.SetBackgroundMode( wxBRUSHSTYLE_SOLID 
); 
1862     // grey out fields if the grid is disabled 
1863     if ( grid
.IsEnabled() ) 
1868             if ( grid
.HasFocus() ) 
1869                 clr 
= grid
.GetSelectionBackground(); 
1871                 clr 
= wxSystemSettings::GetColour(wxSYS_COLOUR_BTNSHADOW
); 
1872             dc
.SetBrush( wxBrush(clr
, wxBRUSHSTYLE_SOLID
) ); 
1876             dc
.SetBrush( wxBrush(attr
.GetBackgroundColour(), wxBRUSHSTYLE_SOLID
) ); 
1881         dc
.SetBrush(wxBrush(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE
), wxBRUSHSTYLE_SOLID
)); 
1884     dc
.SetPen( *wxTRANSPARENT_PEN 
); 
1885     dc
.DrawRectangle(rect
); 
1888 // ---------------------------------------------------------------------------- 
1889 // wxGridCellStringRenderer 
1890 // ---------------------------------------------------------------------------- 
1892 void wxGridCellStringRenderer::SetTextColoursAndFont(const wxGrid
& grid
, 
1893                                                      const wxGridCellAttr
& attr
, 
1897     dc
.SetBackgroundMode( wxBRUSHSTYLE_TRANSPARENT 
); 
1899     // TODO some special colours for attr.IsReadOnly() case? 
1901     // different coloured text when the grid is disabled 
1902     if ( grid
.IsEnabled() ) 
1907             if ( grid
.HasFocus() ) 
1908                 clr 
= grid
.GetSelectionBackground(); 
1910                 clr 
= wxSystemSettings::GetColour(wxSYS_COLOUR_BTNSHADOW
); 
1911             dc
.SetTextBackground( clr 
); 
1912             dc
.SetTextForeground( grid
.GetSelectionForeground() ); 
1916             dc
.SetTextBackground( attr
.GetBackgroundColour() ); 
1917             dc
.SetTextForeground( attr
.GetTextColour() ); 
1922         dc
.SetTextBackground(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE
)); 
1923         dc
.SetTextForeground(wxSystemSettings::GetColour(wxSYS_COLOUR_GRAYTEXT
)); 
1926     dc
.SetFont( attr
.GetFont() ); 
1929 wxSize 
wxGridCellStringRenderer::DoGetBestSize(const wxGridCellAttr
& attr
, 
1931                                                const wxString
& text
) 
1933     wxCoord x 
= 0, y 
= 0, max_x 
= 0; 
1934     dc
.SetFont(attr
.GetFont()); 
1935     wxStringTokenizer 
tk(text
, _T('\n')); 
1936     while ( tk
.HasMoreTokens() ) 
1938         dc
.GetTextExtent(tk
.GetNextToken(), &x
, &y
); 
1939         max_x 
= wxMax(max_x
, x
); 
1942     y 
*= 1 + text
.Freq(wxT('\n')); // multiply by the number of lines. 
1944     return wxSize(max_x
, y
); 
1947 wxSize 
wxGridCellStringRenderer::GetBestSize(wxGrid
& grid
, 
1948                                              wxGridCellAttr
& attr
, 
1952     return DoGetBestSize(attr
, dc
, grid
.GetCellValue(row
, col
)); 
1955 void wxGridCellStringRenderer::Draw(wxGrid
& grid
, 
1956                                     wxGridCellAttr
& attr
, 
1958                                     const wxRect
& rectCell
, 
1962     wxRect rect 
= rectCell
; 
1965     // erase only this cells background, overflow cells should have been erased 
1966     wxGridCellRenderer::Draw(grid
, attr
, dc
, rectCell
, row
, col
, isSelected
); 
1969     attr
.GetAlignment(&hAlign
, &vAlign
); 
1971     int overflowCols 
= 0; 
1973     if (attr
.GetOverflow()) 
1975         int cols 
= grid
.GetNumberCols(); 
1976         int best_width 
= GetBestSize(grid
,attr
,dc
,row
,col
).GetWidth(); 
1977         int cell_rows
, cell_cols
; 
1978         attr
.GetSize( &cell_rows
, &cell_cols 
); // shouldn't get here if <= 0 
1979         if ((best_width 
> rectCell
.width
) && (col 
< cols
) && grid
.GetTable()) 
1981             int i
, c_cols
, c_rows
; 
1982             for (i 
= col
+cell_cols
; i 
< cols
; i
++) 
1984                 bool is_empty 
= true; 
1985                 for (int j
=row
; j 
< row 
+ cell_rows
; j
++) 
1987                     // check w/ anchor cell for multicell block 
1988                     grid
.GetCellSize(j
, i
, &c_rows
, &c_cols
); 
1991                     if (!grid
.GetTable()->IsEmptyCell(j 
+ c_rows
, i
)) 
2000                     rect
.width 
+= grid
.GetColSize(i
); 
2008                 if (rect
.width 
>= best_width
) 
2012             overflowCols 
= i 
- col 
- cell_cols 
+ 1; 
2013             if (overflowCols 
>= cols
) 
2014                 overflowCols 
= cols 
- 1; 
2017         if (overflowCols 
> 0) // redraw overflow cells w/ proper hilight 
2019             hAlign 
= wxALIGN_LEFT
; // if oveflowed then it's left aligned 
2021             clip
.x 
+= rectCell
.width
; 
2022             // draw each overflow cell individually 
2023             int col_end 
= col 
+ cell_cols 
+ overflowCols
; 
2024             if (col_end 
>= grid
.GetNumberCols()) 
2025                 col_end 
= grid
.GetNumberCols() - 1; 
2026             for (int i 
= col 
+ cell_cols
; i 
<= col_end
; i
++) 
2028                 clip
.width 
= grid
.GetColSize(i
) - 1; 
2029                 dc
.DestroyClippingRegion(); 
2030                 dc
.SetClippingRegion(clip
); 
2032                 SetTextColoursAndFont(grid
, attr
, dc
, 
2033                         grid
.IsInSelection(row
,i
)); 
2035                 grid
.DrawTextRectangle(dc
, grid
.GetCellValue(row
, col
), 
2036                         rect
, hAlign
, vAlign
); 
2037                 clip
.x 
+= grid
.GetColSize(i
) - 1; 
2043             dc
.DestroyClippingRegion(); 
2047     // now we only have to draw the text 
2048     SetTextColoursAndFont(grid
, attr
, dc
, isSelected
); 
2050     grid
.DrawTextRectangle(dc
, grid
.GetCellValue(row
, col
), 
2051                            rect
, hAlign
, vAlign
); 
2054 // ---------------------------------------------------------------------------- 
2055 // wxGridCellNumberRenderer 
2056 // ---------------------------------------------------------------------------- 
2058 wxString 
wxGridCellNumberRenderer::GetString(const wxGrid
& grid
, int row
, int col
) 
2060     wxGridTableBase 
*table 
= grid
.GetTable(); 
2062     if ( table
->CanGetValueAs(row
, col
, wxGRID_VALUE_NUMBER
) ) 
2064         text
.Printf(_T("%ld"), table
->GetValueAsLong(row
, col
)); 
2068         text 
= table
->GetValue(row
, col
); 
2074 void wxGridCellNumberRenderer::Draw(wxGrid
& grid
, 
2075                                     wxGridCellAttr
& attr
, 
2077                                     const wxRect
& rectCell
, 
2081     wxGridCellRenderer::Draw(grid
, attr
, dc
, rectCell
, row
, col
, isSelected
); 
2083     SetTextColoursAndFont(grid
, attr
, dc
, isSelected
); 
2085     // draw the text right aligned by default 
2087     attr
.GetAlignment(&hAlign
, &vAlign
); 
2088     hAlign 
= wxALIGN_RIGHT
; 
2090     wxRect rect 
= rectCell
; 
2093     grid
.DrawTextRectangle(dc
, GetString(grid
, row
, col
), rect
, hAlign
, vAlign
); 
2096 wxSize 
wxGridCellNumberRenderer::GetBestSize(wxGrid
& grid
, 
2097                                              wxGridCellAttr
& attr
, 
2101     return DoGetBestSize(attr
, dc
, GetString(grid
, row
, col
)); 
2104 // ---------------------------------------------------------------------------- 
2105 // wxGridCellFloatRenderer 
2106 // ---------------------------------------------------------------------------- 
2108 wxGridCellFloatRenderer::wxGridCellFloatRenderer(int width
, int precision
) 
2111     SetPrecision(precision
); 
2114 wxGridCellRenderer 
*wxGridCellFloatRenderer::Clone() const 
2116     wxGridCellFloatRenderer 
*renderer 
= new wxGridCellFloatRenderer
; 
2117     renderer
->m_width 
= m_width
; 
2118     renderer
->m_precision 
= m_precision
; 
2119     renderer
->m_format 
= m_format
; 
2124 wxString 
wxGridCellFloatRenderer::GetString(const wxGrid
& grid
, int row
, int col
) 
2126     wxGridTableBase 
*table 
= grid
.GetTable(); 
2131     if ( table
->CanGetValueAs(row
, col
, wxGRID_VALUE_FLOAT
) ) 
2133         val 
= table
->GetValueAsDouble(row
, col
); 
2138         text 
= table
->GetValue(row
, col
); 
2139         hasDouble 
= text
.ToDouble(&val
); 
2146             if ( m_width 
== -1 ) 
2148                 if ( m_precision 
== -1 ) 
2150                     // default width/precision 
2151                     m_format 
= _T("%f"); 
2155                     m_format
.Printf(_T("%%.%df"), m_precision
); 
2158             else if ( m_precision 
== -1 ) 
2160                 // default precision 
2161                 m_format
.Printf(_T("%%%d.f"), m_width
); 
2165                 m_format
.Printf(_T("%%%d.%df"), m_width
, m_precision
); 
2169         text
.Printf(m_format
, val
); 
2172     //else: text already contains the string 
2177 void wxGridCellFloatRenderer::Draw(wxGrid
& grid
, 
2178                                    wxGridCellAttr
& attr
, 
2180                                    const wxRect
& rectCell
, 
2184     wxGridCellRenderer::Draw(grid
, attr
, dc
, rectCell
, row
, col
, isSelected
); 
2186     SetTextColoursAndFont(grid
, attr
, dc
, isSelected
); 
2188     // draw the text right aligned by default 
2190     attr
.GetAlignment(&hAlign
, &vAlign
); 
2191     hAlign 
= wxALIGN_RIGHT
; 
2193     wxRect rect 
= rectCell
; 
2196     grid
.DrawTextRectangle(dc
, GetString(grid
, row
, col
), rect
, hAlign
, vAlign
); 
2199 wxSize 
wxGridCellFloatRenderer::GetBestSize(wxGrid
& grid
, 
2200                                             wxGridCellAttr
& attr
, 
2204     return DoGetBestSize(attr
, dc
, GetString(grid
, row
, col
)); 
2207 void wxGridCellFloatRenderer::SetParameters(const wxString
& params
) 
2211         // reset to defaults 
2217         wxString tmp 
= params
.BeforeFirst(_T(',')); 
2221             if ( tmp
.ToLong(&width
) ) 
2223                 SetWidth((int)width
); 
2227                 wxLogDebug(_T("Invalid wxGridCellFloatRenderer width parameter string '%s ignored"), params
.c_str()); 
2231         tmp 
= params
.AfterFirst(_T(',')); 
2235             if ( tmp
.ToLong(&precision
) ) 
2237                 SetPrecision((int)precision
); 
2241                 wxLogDebug(_T("Invalid wxGridCellFloatRenderer precision parameter string '%s ignored"), params
.c_str()); 
2247 // ---------------------------------------------------------------------------- 
2248 // wxGridCellBoolRenderer 
2249 // ---------------------------------------------------------------------------- 
2251 wxSize 
wxGridCellBoolRenderer::ms_sizeCheckMark
; 
2253 // FIXME these checkbox size calculations are really ugly... 
2255 // between checkmark and box 
2256 static const wxCoord wxGRID_CHECKMARK_MARGIN 
= 2; 
2258 wxSize 
wxGridCellBoolRenderer::GetBestSize(wxGrid
& grid
, 
2259                                            wxGridCellAttr
& WXUNUSED(attr
), 
2264     // compute it only once (no locks for MT safeness in GUI thread...) 
2265     if ( !ms_sizeCheckMark
.x 
) 
2267         // get checkbox size 
2268         wxCheckBox 
*checkbox 
= new wxCheckBox(&grid
, wxID_ANY
, wxEmptyString
); 
2269         wxSize size 
= checkbox
->GetBestSize(); 
2270         wxCoord checkSize 
= size
.y 
+ 2 * wxGRID_CHECKMARK_MARGIN
; 
2272 #if defined(__WXMOTIF__) 
2273         checkSize 
-= size
.y 
/ 2; 
2278         ms_sizeCheckMark
.x 
= ms_sizeCheckMark
.y 
= checkSize
; 
2281     return ms_sizeCheckMark
; 
2284 void wxGridCellBoolRenderer::Draw(wxGrid
& grid
, 
2285                                   wxGridCellAttr
& attr
, 
2291     wxGridCellRenderer::Draw(grid
, attr
, dc
, rect
, row
, col
, isSelected
); 
2293     // draw a check mark in the centre (ignoring alignment - TODO) 
2294     wxSize size 
= GetBestSize(grid
, attr
, dc
, row
, col
); 
2296     // don't draw outside the cell 
2297     wxCoord minSize 
= wxMin(rect
.width
, rect
.height
); 
2298     if ( size
.x 
>= minSize 
|| size
.y 
>= minSize 
) 
2300         // and even leave (at least) 1 pixel margin 
2301         size
.x 
= size
.y 
= minSize
; 
2304     // draw a border around checkmark 
2306     attr
.GetAlignment(&hAlign
, &vAlign
); 
2309     if (hAlign 
== wxALIGN_CENTRE
) 
2311         rectBorder
.x 
= rect
.x 
+ rect
.width 
/ 2 - size
.x 
/ 2; 
2312         rectBorder
.y 
= rect
.y 
+ rect
.height 
/ 2 - size
.y 
/ 2; 
2313         rectBorder
.width 
= size
.x
; 
2314         rectBorder
.height 
= size
.y
; 
2316     else if (hAlign 
== wxALIGN_LEFT
) 
2318         rectBorder
.x 
= rect
.x 
+ 2; 
2319         rectBorder
.y 
= rect
.y 
+ rect
.height 
/ 2 - size
.y 
/ 2; 
2320         rectBorder
.width 
= size
.x
; 
2321         rectBorder
.height 
= size
.y
; 
2323     else if (hAlign 
== wxALIGN_RIGHT
) 
2325         rectBorder
.x 
= rect
.x 
+ rect
.width 
- size
.x 
- 2; 
2326         rectBorder
.y 
= rect
.y 
+ rect
.height 
/ 2 - size
.y 
/ 2; 
2327         rectBorder
.width 
= size
.x
; 
2328         rectBorder
.height 
= size
.y
; 
2332     if ( grid
.GetTable()->CanGetValueAs(row
, col
, wxGRID_VALUE_BOOL
) ) 
2334         value 
= grid
.GetTable()->GetValueAsBool(row
, col
); 
2338         wxString 
cellval( grid
.GetTable()->GetValue(row
, col
) ); 
2339         value 
= wxGridCellBoolEditor::IsTrueValue(cellval
); 
2344         flags 
|= wxCONTROL_CHECKED
; 
2346     wxRendererNative::Get().DrawCheckBox( &grid
, dc
, rectBorder
, flags 
); 
2349 // ---------------------------------------------------------------------------- 
2351 // ---------------------------------------------------------------------------- 
2353 void wxGridCellAttr::Init(wxGridCellAttr 
*attrDefault
) 
2357     m_isReadOnly 
= Unset
; 
2362     m_attrkind 
= wxGridCellAttr::Cell
; 
2364     m_sizeRows 
= m_sizeCols 
= 1; 
2365     m_overflow 
= UnsetOverflow
; 
2367     SetDefAttr(attrDefault
); 
2370 wxGridCellAttr 
*wxGridCellAttr::Clone() const 
2372     wxGridCellAttr 
*attr 
= new wxGridCellAttr(m_defGridAttr
); 
2374     if ( HasTextColour() ) 
2375         attr
->SetTextColour(GetTextColour()); 
2376     if ( HasBackgroundColour() ) 
2377         attr
->SetBackgroundColour(GetBackgroundColour()); 
2379         attr
->SetFont(GetFont()); 
2380     if ( HasAlignment() ) 
2381         attr
->SetAlignment(m_hAlign
, m_vAlign
); 
2383     attr
->SetSize( m_sizeRows
, m_sizeCols 
); 
2387         attr
->SetRenderer(m_renderer
); 
2388         m_renderer
->IncRef(); 
2392         attr
->SetEditor(m_editor
); 
2397         attr
->SetReadOnly(); 
2399     attr
->SetOverflow( m_overflow 
== Overflow 
); 
2400     attr
->SetKind( m_attrkind 
); 
2405 void wxGridCellAttr::MergeWith(wxGridCellAttr 
*mergefrom
) 
2407     if ( !HasTextColour() && mergefrom
->HasTextColour() ) 
2408         SetTextColour(mergefrom
->GetTextColour()); 
2409     if ( !HasBackgroundColour() && mergefrom
->HasBackgroundColour() ) 
2410         SetBackgroundColour(mergefrom
->GetBackgroundColour()); 
2411     if ( !HasFont() && mergefrom
->HasFont() ) 
2412         SetFont(mergefrom
->GetFont()); 
2413     if ( !HasAlignment() && mergefrom
->HasAlignment() ) 
2416         mergefrom
->GetAlignment( &hAlign
, &vAlign
); 
2417         SetAlignment(hAlign
, vAlign
); 
2419     if ( !HasSize() && mergefrom
->HasSize() ) 
2420         mergefrom
->GetSize( &m_sizeRows
, &m_sizeCols 
); 
2422     // Directly access member functions as GetRender/Editor don't just return 
2423     // m_renderer/m_editor 
2425     // Maybe add support for merge of Render and Editor? 
2426     if (!HasRenderer() && mergefrom
->HasRenderer() ) 
2428         m_renderer 
= mergefrom
->m_renderer
; 
2429         m_renderer
->IncRef(); 
2431     if ( !HasEditor() && mergefrom
->HasEditor() ) 
2433         m_editor 
=  mergefrom
->m_editor
; 
2436     if ( !HasReadWriteMode() && mergefrom
->HasReadWriteMode() ) 
2437         SetReadOnly(mergefrom
->IsReadOnly()); 
2439     if (!HasOverflowMode() && mergefrom
->HasOverflowMode() ) 
2440         SetOverflow(mergefrom
->GetOverflow()); 
2442     SetDefAttr(mergefrom
->m_defGridAttr
); 
2445 void wxGridCellAttr::SetSize(int num_rows
, int num_cols
) 
2447     // The size of a cell is normally 1,1 
2449     // If this cell is larger (2,2) then this is the top left cell 
2450     // the other cells that will be covered (lower right cells) must be 
2451     // set to negative or zero values such that 
2452     // row + num_rows of the covered cell points to the larger cell (this cell) 
2453     // same goes for the col + num_cols. 
2455     // Size of 0,0 is NOT valid, neither is <=0 and any positive value 
2457     wxASSERT_MSG( (!((num_rows 
> 0) && (num_cols 
<= 0)) || 
2458                   !((num_rows 
<= 0) && (num_cols 
> 0)) || 
2459                   !((num_rows 
== 0) && (num_cols 
== 0))), 
2460                   wxT("wxGridCellAttr::SetSize only takes two postive values or negative/zero values")); 
2462     m_sizeRows 
= num_rows
; 
2463     m_sizeCols 
= num_cols
; 
2466 const wxColour
& wxGridCellAttr::GetTextColour() const 
2468     if (HasTextColour()) 
2472     else if (m_defGridAttr 
&& m_defGridAttr 
!= this) 
2474         return m_defGridAttr
->GetTextColour(); 
2478         wxFAIL_MSG(wxT("Missing default cell attribute")); 
2479         return wxNullColour
; 
2483 const wxColour
& wxGridCellAttr::GetBackgroundColour() const 
2485     if (HasBackgroundColour()) 
2489     else if (m_defGridAttr 
&& m_defGridAttr 
!= this) 
2491         return m_defGridAttr
->GetBackgroundColour(); 
2495         wxFAIL_MSG(wxT("Missing default cell attribute")); 
2496         return wxNullColour
; 
2500 const wxFont
& wxGridCellAttr::GetFont() const 
2506     else if (m_defGridAttr 
&& m_defGridAttr 
!= this) 
2508         return m_defGridAttr
->GetFont(); 
2512         wxFAIL_MSG(wxT("Missing default cell attribute")); 
2517 void wxGridCellAttr::GetAlignment(int *hAlign
, int *vAlign
) const 
2526     else if (m_defGridAttr 
&& m_defGridAttr 
!= this) 
2528         m_defGridAttr
->GetAlignment(hAlign
, vAlign
); 
2532         wxFAIL_MSG(wxT("Missing default cell attribute")); 
2536 void wxGridCellAttr::GetSize( int *num_rows
, int *num_cols 
) const 
2539         *num_rows 
= m_sizeRows
; 
2541         *num_cols 
= m_sizeCols
; 
2544 // GetRenderer and GetEditor use a slightly different decision path about 
2545 // which attribute to use.  If a non-default attr object has one then it is 
2546 // used, otherwise the default editor or renderer is fetched from the grid and 
2547 // used.  It should be the default for the data type of the cell.  If it is 
2548 // NULL (because the table has a type that the grid does not have in its 
2549 // registry), then the grid's default editor or renderer is used. 
2551 wxGridCellRenderer
* wxGridCellAttr::GetRenderer(const wxGrid
* grid
, int row
, int col
) const 
2553     wxGridCellRenderer 
*renderer 
= NULL
; 
2555     if ( m_renderer 
&& this != m_defGridAttr 
) 
2557         // use the cells renderer if it has one 
2558         renderer 
= m_renderer
; 
2561     else // no non-default cell renderer 
2563         // get default renderer for the data type 
2566             // GetDefaultRendererForCell() will do IncRef() for us 
2567             renderer 
= grid
->GetDefaultRendererForCell(row
, col
); 
2570         if ( renderer 
== NULL 
) 
2572             if ( (m_defGridAttr 
!= NULL
) && (m_defGridAttr 
!= this) ) 
2574                 // if we still don't have one then use the grid default 
2575                 // (no need for IncRef() here neither) 
2576                 renderer 
= m_defGridAttr
->GetRenderer(NULL
, 0, 0); 
2578             else // default grid attr 
2580                 // use m_renderer which we had decided not to use initially 
2581                 renderer 
= m_renderer
; 
2588     // we're supposed to always find something 
2589     wxASSERT_MSG(renderer
, wxT("Missing default cell renderer")); 
2594 // same as above, except for s/renderer/editor/g 
2595 wxGridCellEditor
* wxGridCellAttr::GetEditor(const wxGrid
* grid
, int row
, int col
) const 
2597     wxGridCellEditor 
*editor 
= NULL
; 
2599     if ( m_editor 
&& this != m_defGridAttr 
) 
2601         // use the cells editor if it has one 
2605     else // no non default cell editor 
2607         // get default editor for the data type 
2610             // GetDefaultEditorForCell() will do IncRef() for us 
2611             editor 
= grid
->GetDefaultEditorForCell(row
, col
); 
2614         if ( editor 
== NULL 
) 
2616             if ( (m_defGridAttr 
!= NULL
) && (m_defGridAttr 
!= this) ) 
2618                 // if we still don't have one then use the grid default 
2619                 // (no need for IncRef() here neither) 
2620                 editor 
= m_defGridAttr
->GetEditor(NULL
, 0, 0); 
2622             else // default grid attr 
2624                 // use m_editor which we had decided not to use initially 
2632     // we're supposed to always find something 
2633     wxASSERT_MSG(editor
, wxT("Missing default cell editor")); 
2638 // ---------------------------------------------------------------------------- 
2639 // wxGridCellAttrData 
2640 // ---------------------------------------------------------------------------- 
2642 void wxGridCellAttrData::SetAttr(wxGridCellAttr 
*attr
, int row
, int col
) 
2644     // Note: contrary to wxGridRowOrColAttrData::SetAttr, we must not 
2645     //       touch attribute's reference counting explicitly, since this 
2646     //       is managed by class wxGridCellWithAttr 
2647     int n 
= FindIndex(row
, col
); 
2648     if ( n 
== wxNOT_FOUND 
) 
2652             // add the attribute 
2653             m_attrs
.Add(new wxGridCellWithAttr(row
, col
, attr
)); 
2655         //else: nothing to do 
2657     else // we already have an attribute for this cell 
2661             // change the attribute 
2662             m_attrs
[(size_t)n
].ChangeAttr(attr
); 
2666             // remove this attribute 
2667             m_attrs
.RemoveAt((size_t)n
); 
2672 wxGridCellAttr 
*wxGridCellAttrData::GetAttr(int row
, int col
) const 
2674     wxGridCellAttr 
*attr 
= (wxGridCellAttr 
*)NULL
; 
2676     int n 
= FindIndex(row
, col
); 
2677     if ( n 
!= wxNOT_FOUND 
) 
2679         attr 
= m_attrs
[(size_t)n
].attr
; 
2686 void wxGridCellAttrData::UpdateAttrRows( size_t pos
, int numRows 
) 
2688     size_t count 
= m_attrs
.GetCount(); 
2689     for ( size_t n 
= 0; n 
< count
; n
++ ) 
2691         wxGridCellCoords
& coords 
= m_attrs
[n
].coords
; 
2692         wxCoord row 
= coords
.GetRow(); 
2693         if ((size_t)row 
>= pos
) 
2697                 // If rows inserted, include row counter where necessary 
2698                 coords
.SetRow(row 
+ numRows
); 
2700             else if (numRows 
< 0) 
2702                 // If rows deleted ... 
2703                 if ((size_t)row 
>= pos 
- numRows
) 
2705                     // ...either decrement row counter (if row still exists)... 
2706                     coords
.SetRow(row 
+ numRows
); 
2710                     // ...or remove the attribute 
2711                     m_attrs
.RemoveAt(n
); 
2720 void wxGridCellAttrData::UpdateAttrCols( size_t pos
, int numCols 
) 
2722     size_t count 
= m_attrs
.GetCount(); 
2723     for ( size_t n 
= 0; n 
< count
; n
++ ) 
2725         wxGridCellCoords
& coords 
= m_attrs
[n
].coords
; 
2726         wxCoord col 
= coords
.GetCol(); 
2727         if ( (size_t)col 
>= pos 
) 
2731                 // If rows inserted, include row counter where necessary 
2732                 coords
.SetCol(col 
+ numCols
); 
2734             else if (numCols 
< 0) 
2736                 // If rows deleted ... 
2737                 if ((size_t)col 
>= pos 
- numCols
) 
2739                     // ...either decrement row counter (if row still exists)... 
2740                     coords
.SetCol(col 
+ numCols
); 
2744                     // ...or remove the attribute 
2745                     m_attrs
.RemoveAt(n
); 
2754 int wxGridCellAttrData::FindIndex(int row
, int col
) const 
2756     size_t count 
= m_attrs
.GetCount(); 
2757     for ( size_t n 
= 0; n 
< count
; n
++ ) 
2759         const wxGridCellCoords
& coords 
= m_attrs
[n
].coords
; 
2760         if ( (coords
.GetRow() == row
) && (coords
.GetCol() == col
) ) 
2769 // ---------------------------------------------------------------------------- 
2770 // wxGridRowOrColAttrData 
2771 // ---------------------------------------------------------------------------- 
2773 wxGridRowOrColAttrData::~wxGridRowOrColAttrData() 
2775     size_t count 
= m_attrs
.GetCount(); 
2776     for ( size_t n 
= 0; n 
< count
; n
++ ) 
2778         m_attrs
[n
]->DecRef(); 
2782 wxGridCellAttr 
*wxGridRowOrColAttrData::GetAttr(int rowOrCol
) const 
2784     wxGridCellAttr 
*attr 
= (wxGridCellAttr 
*)NULL
; 
2786     int n 
= m_rowsOrCols
.Index(rowOrCol
); 
2787     if ( n 
!= wxNOT_FOUND 
) 
2789         attr 
= m_attrs
[(size_t)n
]; 
2796 void wxGridRowOrColAttrData::SetAttr(wxGridCellAttr 
*attr
, int rowOrCol
) 
2798     int i 
= m_rowsOrCols
.Index(rowOrCol
); 
2799     if ( i 
== wxNOT_FOUND 
) 
2803             // add the attribute - no need to do anything to reference count 
2804             //                     since we take ownership of the attribute. 
2805             m_rowsOrCols
.Add(rowOrCol
); 
2808         // nothing to remove 
2812         size_t n 
= (size_t)i
; 
2813         if ( m_attrs
[n
] == attr 
) 
2818             // change the attribute, handling reference count manually, 
2819             //                       taking ownership of the new attribute. 
2820             m_attrs
[n
]->DecRef(); 
2825             // remove this attribute, handling reference count manually 
2826             m_attrs
[n
]->DecRef(); 
2827             m_rowsOrCols
.RemoveAt(n
); 
2828             m_attrs
.RemoveAt(n
); 
2833 void wxGridRowOrColAttrData::UpdateAttrRowsOrCols( size_t pos
, int numRowsOrCols 
) 
2835     size_t count 
= m_attrs
.GetCount(); 
2836     for ( size_t n 
= 0; n 
< count
; n
++ ) 
2838         int & rowOrCol 
= m_rowsOrCols
[n
]; 
2839         if ( (size_t)rowOrCol 
>= pos 
) 
2841             if ( numRowsOrCols 
> 0 ) 
2843                 // If rows inserted, include row counter where necessary 
2844                 rowOrCol 
+= numRowsOrCols
; 
2846             else if ( numRowsOrCols 
< 0) 
2848                 // If rows deleted, either decrement row counter (if row still exists) 
2849                 if ((size_t)rowOrCol 
>= pos 
- numRowsOrCols
) 
2850                     rowOrCol 
+= numRowsOrCols
; 
2853                     m_rowsOrCols
.RemoveAt(n
); 
2854                     m_attrs
[n
]->DecRef(); 
2855                     m_attrs
.RemoveAt(n
); 
2864 // ---------------------------------------------------------------------------- 
2865 // wxGridCellAttrProvider 
2866 // ---------------------------------------------------------------------------- 
2868 wxGridCellAttrProvider::wxGridCellAttrProvider() 
2870     m_data 
= (wxGridCellAttrProviderData 
*)NULL
; 
2873 wxGridCellAttrProvider::~wxGridCellAttrProvider() 
2878 void wxGridCellAttrProvider::InitData() 
2880     m_data 
= new wxGridCellAttrProviderData
; 
2883 wxGridCellAttr 
*wxGridCellAttrProvider::GetAttr(int row
, int col
, 
2884                                                 wxGridCellAttr::wxAttrKind  kind 
) const 
2886     wxGridCellAttr 
*attr 
= (wxGridCellAttr 
*)NULL
; 
2891             case (wxGridCellAttr::Any
): 
2892                 // Get cached merge attributes. 
2893                 // Currently not used as no cache implemented as not mutable 
2894                 // attr = m_data->m_mergeAttr.GetAttr(row, col); 
2897                     // Basically implement old version. 
2898                     // Also check merge cache, so we don't have to re-merge every time.. 
2899                     wxGridCellAttr 
*attrcell 
= m_data
->m_cellAttrs
.GetAttr(row
, col
); 
2900                     wxGridCellAttr 
*attrrow 
= m_data
->m_rowAttrs
.GetAttr(row
); 
2901                     wxGridCellAttr 
*attrcol 
= m_data
->m_colAttrs
.GetAttr(col
); 
2903                     if ((attrcell 
!= attrrow
) && (attrrow 
!= attrcol
) && (attrcell 
!= attrcol
)) 
2905                         // Two or more are non NULL 
2906                         attr 
= new wxGridCellAttr
; 
2907                         attr
->SetKind(wxGridCellAttr::Merged
); 
2909                         // Order is important.. 
2912                             attr
->MergeWith(attrcell
); 
2917                             attr
->MergeWith(attrcol
); 
2922                             attr
->MergeWith(attrrow
); 
2926                         // store merge attr if cache implemented 
2928                         //m_data->m_mergeAttr.SetAttr(attr, row, col); 
2932                         // one or none is non null return it or null. 
2951             case (wxGridCellAttr::Cell
): 
2952                 attr 
= m_data
->m_cellAttrs
.GetAttr(row
, col
); 
2955             case (wxGridCellAttr::Col
): 
2956                 attr 
= m_data
->m_colAttrs
.GetAttr(col
); 
2959             case (wxGridCellAttr::Row
): 
2960                 attr 
= m_data
->m_rowAttrs
.GetAttr(row
); 
2965                 // (wxGridCellAttr::Default): 
2966                 // (wxGridCellAttr::Merged): 
2974 void wxGridCellAttrProvider::SetAttr(wxGridCellAttr 
*attr
, 
2980     m_data
->m_cellAttrs
.SetAttr(attr
, row
, col
); 
2983 void wxGridCellAttrProvider::SetRowAttr(wxGridCellAttr 
*attr
, int row
) 
2988     m_data
->m_rowAttrs
.SetAttr(attr
, row
); 
2991 void wxGridCellAttrProvider::SetColAttr(wxGridCellAttr 
*attr
, int col
) 
2996     m_data
->m_colAttrs
.SetAttr(attr
, col
); 
2999 void wxGridCellAttrProvider::UpdateAttrRows( size_t pos
, int numRows 
) 
3003         m_data
->m_cellAttrs
.UpdateAttrRows( pos
, numRows 
); 
3005         m_data
->m_rowAttrs
.UpdateAttrRowsOrCols( pos
, numRows 
); 
3009 void wxGridCellAttrProvider::UpdateAttrCols( size_t pos
, int numCols 
) 
3013         m_data
->m_cellAttrs
.UpdateAttrCols( pos
, numCols 
); 
3015         m_data
->m_colAttrs
.UpdateAttrRowsOrCols( pos
, numCols 
); 
3019 // ---------------------------------------------------------------------------- 
3020 // wxGridTypeRegistry 
3021 // ---------------------------------------------------------------------------- 
3023 wxGridTypeRegistry::~wxGridTypeRegistry() 
3025     size_t count 
= m_typeinfo
.GetCount(); 
3026     for ( size_t i 
= 0; i 
< count
; i
++ ) 
3027         delete m_typeinfo
[i
]; 
3030 void wxGridTypeRegistry::RegisterDataType(const wxString
& typeName
, 
3031                                           wxGridCellRenderer
* renderer
, 
3032                                           wxGridCellEditor
* editor
) 
3034     wxGridDataTypeInfo
* info 
= new wxGridDataTypeInfo(typeName
, renderer
, editor
); 
3036     // is it already registered? 
3037     int loc 
= FindRegisteredDataType(typeName
); 
3038     if ( loc 
!= wxNOT_FOUND 
) 
3040         delete m_typeinfo
[loc
]; 
3041         m_typeinfo
[loc
] = info
; 
3045         m_typeinfo
.Add(info
); 
3049 int wxGridTypeRegistry::FindRegisteredDataType(const wxString
& typeName
) 
3051     size_t count 
= m_typeinfo
.GetCount(); 
3052     for ( size_t i 
= 0; i 
< count
; i
++ ) 
3054         if ( typeName 
== m_typeinfo
[i
]->m_typeName 
) 
3063 int wxGridTypeRegistry::FindDataType(const wxString
& typeName
) 
3065     int index 
= FindRegisteredDataType(typeName
); 
3066     if ( index 
== wxNOT_FOUND 
) 
3068         // check whether this is one of the standard ones, in which case 
3069         // register it "on the fly" 
3071         if ( typeName 
== wxGRID_VALUE_STRING 
) 
3073             RegisterDataType(wxGRID_VALUE_STRING
, 
3074                              new wxGridCellStringRenderer
, 
3075                              new wxGridCellTextEditor
); 
3078 #endif // wxUSE_TEXTCTRL 
3080         if ( typeName 
== wxGRID_VALUE_BOOL 
) 
3082             RegisterDataType(wxGRID_VALUE_BOOL
, 
3083                              new wxGridCellBoolRenderer
, 
3084                              new wxGridCellBoolEditor
); 
3087 #endif // wxUSE_CHECKBOX 
3089         if ( typeName 
== wxGRID_VALUE_NUMBER 
) 
3091             RegisterDataType(wxGRID_VALUE_NUMBER
, 
3092                              new wxGridCellNumberRenderer
, 
3093                              new wxGridCellNumberEditor
); 
3095         else if ( typeName 
== wxGRID_VALUE_FLOAT 
) 
3097             RegisterDataType(wxGRID_VALUE_FLOAT
, 
3098                              new wxGridCellFloatRenderer
, 
3099                              new wxGridCellFloatEditor
); 
3102 #endif // wxUSE_TEXTCTRL 
3104         if ( typeName 
== wxGRID_VALUE_CHOICE 
) 
3106             RegisterDataType(wxGRID_VALUE_CHOICE
, 
3107                              new wxGridCellStringRenderer
, 
3108                              new wxGridCellChoiceEditor
); 
3111 #endif // wxUSE_COMBOBOX 
3116         // we get here only if just added the entry for this type, so return 
3118         index 
= m_typeinfo
.GetCount() - 1; 
3124 int wxGridTypeRegistry::FindOrCloneDataType(const wxString
& typeName
) 
3126     int index 
= FindDataType(typeName
); 
3127     if ( index 
== wxNOT_FOUND 
) 
3129         // the first part of the typename is the "real" type, anything after ':' 
3130         // are the parameters for the renderer 
3131         index 
= FindDataType(typeName
.BeforeFirst(_T(':'))); 
3132         if ( index 
== wxNOT_FOUND 
) 
3137         wxGridCellRenderer 
*renderer 
= GetRenderer(index
); 
3138         wxGridCellRenderer 
*rendererOld 
= renderer
; 
3139         renderer 
= renderer
->Clone(); 
3140         rendererOld
->DecRef(); 
3142         wxGridCellEditor 
*editor 
= GetEditor(index
); 
3143         wxGridCellEditor 
*editorOld 
= editor
; 
3144         editor 
= editor
->Clone(); 
3145         editorOld
->DecRef(); 
3147         // do it even if there are no parameters to reset them to defaults 
3148         wxString params 
= typeName
.AfterFirst(_T(':')); 
3149         renderer
->SetParameters(params
); 
3150         editor
->SetParameters(params
); 
3152         // register the new typename 
3153         RegisterDataType(typeName
, renderer
, editor
); 
3155         // we just registered it, it's the last one 
3156         index 
= m_typeinfo
.GetCount() - 1; 
3162 wxGridCellRenderer
* wxGridTypeRegistry::GetRenderer(int index
) 
3164     wxGridCellRenderer
* renderer 
= m_typeinfo
[index
]->m_renderer
; 
3171 wxGridCellEditor
* wxGridTypeRegistry::GetEditor(int index
) 
3173     wxGridCellEditor
* editor 
= m_typeinfo
[index
]->m_editor
; 
3180 // ---------------------------------------------------------------------------- 
3182 // ---------------------------------------------------------------------------- 
3184 IMPLEMENT_ABSTRACT_CLASS( wxGridTableBase
, wxObject 
) 
3186 wxGridTableBase::wxGridTableBase() 
3188     m_view 
= (wxGrid 
*) NULL
; 
3189     m_attrProvider 
= (wxGridCellAttrProvider 
*) NULL
; 
3192 wxGridTableBase::~wxGridTableBase() 
3194     delete m_attrProvider
; 
3197 void wxGridTableBase::SetAttrProvider(wxGridCellAttrProvider 
*attrProvider
) 
3199     delete m_attrProvider
; 
3200     m_attrProvider 
= attrProvider
; 
3203 bool wxGridTableBase::CanHaveAttributes() 
3205     if ( ! GetAttrProvider() ) 
3207         // use the default attr provider by default 
3208         SetAttrProvider(new wxGridCellAttrProvider
); 
3214 wxGridCellAttr 
*wxGridTableBase::GetAttr(int row
, int col
, wxGridCellAttr::wxAttrKind  kind
) 
3216     if ( m_attrProvider 
) 
3217         return m_attrProvider
->GetAttr(row
, col
, kind
); 
3219         return (wxGridCellAttr 
*)NULL
; 
3222 void wxGridTableBase::SetAttr(wxGridCellAttr
* attr
, int row
, int col
) 
3224     if ( m_attrProvider 
) 
3227             attr
->SetKind(wxGridCellAttr::Cell
); 
3228         m_attrProvider
->SetAttr(attr
, row
, col
); 
3232         // as we take ownership of the pointer and don't store it, we must 
3238 void wxGridTableBase::SetRowAttr(wxGridCellAttr 
*attr
, int row
) 
3240     if ( m_attrProvider 
) 
3242         attr
->SetKind(wxGridCellAttr::Row
); 
3243         m_attrProvider
->SetRowAttr(attr
, row
); 
3247         // as we take ownership of the pointer and don't store it, we must 
3253 void wxGridTableBase::SetColAttr(wxGridCellAttr 
*attr
, int col
) 
3255     if ( m_attrProvider 
) 
3257         attr
->SetKind(wxGridCellAttr::Col
); 
3258         m_attrProvider
->SetColAttr(attr
, col
); 
3262         // as we take ownership of the pointer and don't store it, we must 
3268 bool wxGridTableBase::InsertRows( size_t WXUNUSED(pos
), 
3269                                   size_t WXUNUSED(numRows
) ) 
3271     wxFAIL_MSG( wxT("Called grid table class function InsertRows\nbut your derived table class does not override this function") ); 
3276 bool wxGridTableBase::AppendRows( size_t WXUNUSED(numRows
) ) 
3278     wxFAIL_MSG( wxT("Called grid table class function AppendRows\nbut your derived table class does not override this function")); 
3283 bool wxGridTableBase::DeleteRows( size_t WXUNUSED(pos
), 
3284                                   size_t WXUNUSED(numRows
) ) 
3286     wxFAIL_MSG( wxT("Called grid table class function DeleteRows\nbut your derived table class does not override this function")); 
3291 bool wxGridTableBase::InsertCols( size_t WXUNUSED(pos
), 
3292                                   size_t WXUNUSED(numCols
) ) 
3294     wxFAIL_MSG( wxT("Called grid table class function InsertCols\nbut your derived table class does not override this function")); 
3299 bool wxGridTableBase::AppendCols( size_t WXUNUSED(numCols
) ) 
3301     wxFAIL_MSG(wxT("Called grid table class function AppendCols\nbut your derived table class does not override this function")); 
3306 bool wxGridTableBase::DeleteCols( size_t WXUNUSED(pos
), 
3307                                   size_t WXUNUSED(numCols
) ) 
3309     wxFAIL_MSG( wxT("Called grid table class function DeleteCols\nbut your derived table class does not override this function")); 
3314 wxString 
wxGridTableBase::GetRowLabelValue( int row 
) 
3318     // RD: Starting the rows at zero confuses users, 
3319     // no matter how much it makes sense to us geeks. 
3325 wxString 
wxGridTableBase::GetColLabelValue( int col 
) 
3327     // default col labels are: 
3328     //   cols 0 to 25   : A-Z 
3329     //   cols 26 to 675 : AA-ZZ 
3334     for ( n 
= 1; ; n
++ ) 
3336         s 
+= (wxChar
) (_T('A') + (wxChar
)(col 
% 26)); 
3342     // reverse the string... 
3344     for ( i 
= 0; i 
< n
; i
++ ) 
3352 wxString 
wxGridTableBase::GetTypeName( int WXUNUSED(row
), int WXUNUSED(col
) ) 
3354     return wxGRID_VALUE_STRING
; 
3357 bool wxGridTableBase::CanGetValueAs( int WXUNUSED(row
), int WXUNUSED(col
), 
3358                                      const wxString
& typeName 
) 
3360     return typeName 
== wxGRID_VALUE_STRING
; 
3363 bool wxGridTableBase::CanSetValueAs( int row
, int col
, const wxString
& typeName 
) 
3365     return CanGetValueAs(row
, col
, typeName
); 
3368 long wxGridTableBase::GetValueAsLong( int WXUNUSED(row
), int WXUNUSED(col
) ) 
3373 double wxGridTableBase::GetValueAsDouble( int WXUNUSED(row
), int WXUNUSED(col
) ) 
3378 bool wxGridTableBase::GetValueAsBool( int WXUNUSED(row
), int WXUNUSED(col
) ) 
3383 void wxGridTableBase::SetValueAsLong( int WXUNUSED(row
), int WXUNUSED(col
), 
3384                                       long WXUNUSED(value
) ) 
3388 void wxGridTableBase::SetValueAsDouble( int WXUNUSED(row
), int WXUNUSED(col
), 
3389                                         double WXUNUSED(value
) ) 
3393 void wxGridTableBase::SetValueAsBool( int WXUNUSED(row
), int WXUNUSED(col
), 
3394                                       bool WXUNUSED(value
) ) 
3398 void* wxGridTableBase::GetValueAsCustom( int WXUNUSED(row
), int WXUNUSED(col
), 
3399                                          const wxString
& WXUNUSED(typeName
) ) 
3404 void  wxGridTableBase::SetValueAsCustom( int WXUNUSED(row
), int WXUNUSED(col
), 
3405                                          const wxString
& WXUNUSED(typeName
), 
3406                                          void* WXUNUSED(value
) ) 
3410 ////////////////////////////////////////////////////////////////////// 
3412 // Message class for the grid table to send requests and notifications 
3416 wxGridTableMessage::wxGridTableMessage() 
3418     m_table 
= (wxGridTableBase 
*) NULL
; 
3424 wxGridTableMessage::wxGridTableMessage( wxGridTableBase 
*table
, int id
, 
3425                                         int commandInt1
, int commandInt2 
) 
3429     m_comInt1 
= commandInt1
; 
3430     m_comInt2 
= commandInt2
; 
3433 ////////////////////////////////////////////////////////////////////// 
3435 // A basic grid table for string data. An object of this class will 
3436 // created by wxGrid if you don't specify an alternative table class. 
3439 WX_DEFINE_OBJARRAY(wxGridStringArray
) 
3441 IMPLEMENT_DYNAMIC_CLASS( wxGridStringTable
, wxGridTableBase 
) 
3443 wxGridStringTable::wxGridStringTable() 
3448 wxGridStringTable::wxGridStringTable( int numRows
, int numCols 
) 
3451     m_data
.Alloc( numRows 
); 
3454     sa
.Alloc( numCols 
); 
3455     sa
.Add( wxEmptyString
, numCols 
); 
3457     m_data
.Add( sa
, numRows 
); 
3460 wxGridStringTable::~wxGridStringTable() 
3464 int wxGridStringTable::GetNumberRows() 
3466     return m_data
.GetCount(); 
3469 int wxGridStringTable::GetNumberCols() 
3471     if ( m_data
.GetCount() > 0 ) 
3472         return m_data
[0].GetCount(); 
3477 wxString 
wxGridStringTable::GetValue( int row
, int col 
) 
3479     wxCHECK_MSG( (row 
< GetNumberRows()) && (col 
< GetNumberCols()), 
3481                  _T("invalid row or column index in wxGridStringTable") ); 
3483     return m_data
[row
][col
]; 
3486 void wxGridStringTable::SetValue( int row
, int col
, const wxString
& value 
) 
3488     wxCHECK_RET( (row 
< GetNumberRows()) && (col 
< GetNumberCols()), 
3489                  _T("invalid row or column index in wxGridStringTable") ); 
3491     m_data
[row
][col
] = value
; 
3494 bool wxGridStringTable::IsEmptyCell( int row
, int col 
) 
3496     wxCHECK_MSG( (row 
< GetNumberRows()) && (col 
< GetNumberCols()), 
3498                   _T("invalid row or column index in wxGridStringTable") ); 
3500     return (m_data
[row
][col
] == wxEmptyString
); 
3503 void wxGridStringTable::Clear() 
3506     int numRows
, numCols
; 
3508     numRows 
= m_data
.GetCount(); 
3511         numCols 
= m_data
[0].GetCount(); 
3513         for ( row 
= 0; row 
< numRows
; row
++ ) 
3515             for ( col 
= 0; col 
< numCols
; col
++ ) 
3517                 m_data
[row
][col
] = wxEmptyString
; 
3523 bool wxGridStringTable::InsertRows( size_t pos
, size_t numRows 
) 
3525     size_t curNumRows 
= m_data
.GetCount(); 
3526     size_t curNumCols 
= ( curNumRows 
> 0 ? m_data
[0].GetCount() : 
3527                           ( GetView() ? GetView()->GetNumberCols() : 0 ) ); 
3529     if ( pos 
>= curNumRows 
) 
3531         return AppendRows( numRows 
); 
3535     sa
.Alloc( curNumCols 
); 
3536     sa
.Add( wxEmptyString
, curNumCols 
); 
3537     m_data
.Insert( sa
, pos
, numRows 
); 
3541         wxGridTableMessage 
msg( this, 
3542                                 wxGRIDTABLE_NOTIFY_ROWS_INSERTED
, 
3546         GetView()->ProcessTableMessage( msg 
); 
3552 bool wxGridStringTable::AppendRows( size_t numRows 
) 
3554     size_t curNumRows 
= m_data
.GetCount(); 
3555     size_t curNumCols 
= ( curNumRows 
> 0 
3556                          ? m_data
[0].GetCount() 
3557                          : ( GetView() ? GetView()->GetNumberCols() : 0 ) ); 
3560     if ( curNumCols 
> 0 ) 
3562         sa
.Alloc( curNumCols 
); 
3563         sa
.Add( wxEmptyString
, curNumCols 
); 
3566     m_data
.Add( sa
, numRows 
); 
3570         wxGridTableMessage 
msg( this, 
3571                                 wxGRIDTABLE_NOTIFY_ROWS_APPENDED
, 
3574         GetView()->ProcessTableMessage( msg 
); 
3580 bool wxGridStringTable::DeleteRows( size_t pos
, size_t numRows 
) 
3582     size_t curNumRows 
= m_data
.GetCount(); 
3584     if ( pos 
>= curNumRows 
) 
3586         wxFAIL_MSG( wxString::Format
 
3588                         wxT("Called wxGridStringTable::DeleteRows(pos=%lu, N=%lu)\nPos value is invalid for present table with %lu rows"), 
3590                         (unsigned long)numRows
, 
3591                         (unsigned long)curNumRows
 
3597     if ( numRows 
> curNumRows 
- pos 
) 
3599         numRows 
= curNumRows 
- pos
; 
3602     if ( numRows 
>= curNumRows 
) 
3608         m_data
.RemoveAt( pos
, numRows 
); 
3613         wxGridTableMessage 
msg( this, 
3614                                 wxGRIDTABLE_NOTIFY_ROWS_DELETED
, 
3618         GetView()->ProcessTableMessage( msg 
); 
3624 bool wxGridStringTable::InsertCols( size_t pos
, size_t numCols 
) 
3628     size_t curNumRows 
= m_data
.GetCount(); 
3629     size_t curNumCols 
= ( curNumRows 
> 0 
3630                          ? m_data
[0].GetCount() 
3631                          : ( GetView() ? GetView()->GetNumberCols() : 0 ) ); 
3633     if ( pos 
>= curNumCols 
) 
3635         return AppendCols( numCols 
); 
3638     if ( !m_colLabels
.IsEmpty() ) 
3640         m_colLabels
.Insert( wxEmptyString
, pos
, numCols 
); 
3643         for ( i 
= pos
; i 
< pos 
+ numCols
; i
++ ) 
3644             m_colLabels
[i
] = wxGridTableBase::GetColLabelValue( i 
); 
3647     for ( row 
= 0; row 
< curNumRows
; row
++ ) 
3649         for ( col 
= pos
; col 
< pos 
+ numCols
; col
++ ) 
3651             m_data
[row
].Insert( wxEmptyString
, col 
); 
3657         wxGridTableMessage 
msg( this, 
3658                                 wxGRIDTABLE_NOTIFY_COLS_INSERTED
, 
3662         GetView()->ProcessTableMessage( msg 
); 
3668 bool wxGridStringTable::AppendCols( size_t numCols 
) 
3672     size_t curNumRows 
= m_data
.GetCount(); 
3677         // TODO: something better than this ? 
3679         wxFAIL_MSG( wxT("Unable to append cols to a grid table with no rows.\nCall AppendRows() first") ); 
3684     for ( row 
= 0; row 
< curNumRows
; row
++ ) 
3686         m_data
[row
].Add( wxEmptyString
, numCols 
); 
3691         wxGridTableMessage 
msg( this, 
3692                                 wxGRIDTABLE_NOTIFY_COLS_APPENDED
, 
3695         GetView()->ProcessTableMessage( msg 
); 
3701 bool wxGridStringTable::DeleteCols( size_t pos
, size_t numCols 
) 
3705     size_t curNumRows 
= m_data
.GetCount(); 
3706     size_t curNumCols 
= ( curNumRows 
> 0 ? m_data
[0].GetCount() : 
3707                           ( GetView() ? GetView()->GetNumberCols() : 0 ) ); 
3709     if ( pos 
>= curNumCols 
) 
3711         wxFAIL_MSG( wxString::Format
 
3713                         wxT("Called wxGridStringTable::DeleteCols(pos=%lu, N=%lu)\nPos value is invalid for present table with %lu cols"), 
3715                         (unsigned long)numCols
, 
3716                         (unsigned long)curNumCols
 
3723         colID 
= GetView()->GetColAt( pos 
); 
3727     if ( numCols 
> curNumCols 
- colID 
) 
3729         numCols 
= curNumCols 
- colID
; 
3732     if ( !m_colLabels
.IsEmpty() ) 
3734         // m_colLabels stores just as many elements as it needs, e.g. if only 
3735         // the label of the first column had been set it would have only one 
3736         // element and not numCols, so account for it 
3737         int nToRm 
= m_colLabels
.size() - colID
; 
3739             m_colLabels
.RemoveAt( colID
, nToRm 
); 
3742     for ( row 
= 0; row 
< curNumRows
; row
++ ) 
3744         if ( numCols 
>= curNumCols 
) 
3746             m_data
[row
].Clear(); 
3750             m_data
[row
].RemoveAt( colID
, numCols 
); 
3756         wxGridTableMessage 
msg( this, 
3757                                 wxGRIDTABLE_NOTIFY_COLS_DELETED
, 
3761         GetView()->ProcessTableMessage( msg 
); 
3767 wxString 
wxGridStringTable::GetRowLabelValue( int row 
) 
3769     if ( row 
> (int)(m_rowLabels
.GetCount()) - 1 ) 
3771         // using default label 
3773         return wxGridTableBase::GetRowLabelValue( row 
); 
3777         return m_rowLabels
[row
]; 
3781 wxString 
wxGridStringTable::GetColLabelValue( int col 
) 
3783     if ( col 
> (int)(m_colLabels
.GetCount()) - 1 ) 
3785         // using default label 
3787         return wxGridTableBase::GetColLabelValue( col 
); 
3791         return m_colLabels
[col
]; 
3795 void wxGridStringTable::SetRowLabelValue( int row
, const wxString
& value 
) 
3797     if ( row 
> (int)(m_rowLabels
.GetCount()) - 1 ) 
3799         int n 
= m_rowLabels
.GetCount(); 
3802         for ( i 
= n
; i 
<= row
; i
++ ) 
3804             m_rowLabels
.Add( wxGridTableBase::GetRowLabelValue(i
) ); 
3808     m_rowLabels
[row
] = value
; 
3811 void wxGridStringTable::SetColLabelValue( int col
, const wxString
& value 
) 
3813     if ( col 
> (int)(m_colLabels
.GetCount()) - 1 ) 
3815         int n 
= m_colLabels
.GetCount(); 
3818         for ( i 
= n
; i 
<= col
; i
++ ) 
3820             m_colLabels
.Add( wxGridTableBase::GetColLabelValue(i
) ); 
3824     m_colLabels
[col
] = value
; 
3828 ////////////////////////////////////////////////////////////////////// 
3829 ////////////////////////////////////////////////////////////////////// 
3831 BEGIN_EVENT_TABLE(wxGridSubwindow
, wxWindow
) 
3832     EVT_MOUSE_CAPTURE_LOST(wxGridSubwindow::OnMouseCaptureLost
) 
3835 void wxGridSubwindow::OnMouseCaptureLost(wxMouseCaptureLostEvent
& WXUNUSED(event
)) 
3837     m_owner
->CancelMouseCapture(); 
3840 IMPLEMENT_DYNAMIC_CLASS( wxGridRowLabelWindow
, wxWindow 
) 
3842 BEGIN_EVENT_TABLE( wxGridRowLabelWindow
, wxGridSubwindow 
) 
3843     EVT_PAINT( wxGridRowLabelWindow::OnPaint 
) 
3844     EVT_MOUSEWHEEL( wxGridRowLabelWindow::OnMouseWheel 
) 
3845     EVT_MOUSE_EVENTS( wxGridRowLabelWindow::OnMouseEvent 
) 
3848 wxGridRowLabelWindow::wxGridRowLabelWindow( wxGrid 
*parent
, 
3850                                             const wxPoint 
&pos
, const wxSize 
&size 
) 
3851   : wxGridSubwindow(parent
, id
, pos
, size
) 
3856 void wxGridRowLabelWindow::OnPaint( wxPaintEvent
& WXUNUSED(event
) ) 
3860     // NO - don't do this because it will set both the x and y origin 
3861     // coords to match the parent scrolled window and we just want to 
3862     // set the y coord  - MB 
3864     // m_owner->PrepareDC( dc ); 
3867     m_owner
->CalcUnscrolledPosition( 0, 0, &x
, &y 
); 
3868     wxPoint pt 
= dc
.GetDeviceOrigin(); 
3869     dc
.SetDeviceOrigin( pt
.x
, pt
.y
-y 
); 
3871     wxArrayInt rows 
= m_owner
->CalcRowLabelsExposed( GetUpdateRegion() ); 
3872     m_owner
->DrawRowLabels( dc
, rows 
); 
3875 void wxGridRowLabelWindow::OnMouseEvent( wxMouseEvent
& event 
) 
3877     m_owner
->ProcessRowLabelMouseEvent( event 
); 
3880 void wxGridRowLabelWindow::OnMouseWheel( wxMouseEvent
& event 
) 
3882     m_owner
->GetEventHandler()->ProcessEvent( event 
); 
3885 ////////////////////////////////////////////////////////////////////// 
3887 IMPLEMENT_DYNAMIC_CLASS( wxGridColLabelWindow
, wxWindow 
) 
3889 BEGIN_EVENT_TABLE( wxGridColLabelWindow
, wxGridSubwindow 
) 
3890     EVT_PAINT( wxGridColLabelWindow::OnPaint 
) 
3891     EVT_MOUSEWHEEL( wxGridColLabelWindow::OnMouseWheel 
) 
3892     EVT_MOUSE_EVENTS( wxGridColLabelWindow::OnMouseEvent 
) 
3895 wxGridColLabelWindow::wxGridColLabelWindow( wxGrid 
*parent
, 
3897                                             const wxPoint 
&pos
, const wxSize 
&size 
) 
3898   : wxGridSubwindow(parent
, id
, pos
, size
) 
3903 void wxGridColLabelWindow::OnPaint( wxPaintEvent
& WXUNUSED(event
) ) 
3907     // NO - don't do this because it will set both the x and y origin 
3908     // coords to match the parent scrolled window and we just want to 
3909     // set the x coord  - MB 
3911     // m_owner->PrepareDC( dc ); 
3914     m_owner
->CalcUnscrolledPosition( 0, 0, &x
, &y 
); 
3915     wxPoint pt 
= dc
.GetDeviceOrigin(); 
3916     if (GetLayoutDirection() == wxLayout_RightToLeft
) 
3917         dc
.SetDeviceOrigin( pt
.x
+x
, pt
.y 
); 
3919         dc
.SetDeviceOrigin( pt
.x
-x
, pt
.y 
); 
3921     wxArrayInt cols 
= m_owner
->CalcColLabelsExposed( GetUpdateRegion() ); 
3922     m_owner
->DrawColLabels( dc
, cols 
); 
3925 void wxGridColLabelWindow::OnMouseEvent( wxMouseEvent
& event 
) 
3927     m_owner
->ProcessColLabelMouseEvent( event 
); 
3930 void wxGridColLabelWindow::OnMouseWheel( wxMouseEvent
& event 
) 
3932     m_owner
->GetEventHandler()->ProcessEvent( event 
); 
3935 ////////////////////////////////////////////////////////////////////// 
3937 IMPLEMENT_DYNAMIC_CLASS( wxGridCornerLabelWindow
, wxWindow 
) 
3939 BEGIN_EVENT_TABLE( wxGridCornerLabelWindow
, wxGridSubwindow 
) 
3940     EVT_MOUSEWHEEL( wxGridCornerLabelWindow::OnMouseWheel 
) 
3941     EVT_MOUSE_EVENTS( wxGridCornerLabelWindow::OnMouseEvent 
) 
3942     EVT_PAINT( wxGridCornerLabelWindow::OnPaint 
) 
3945 wxGridCornerLabelWindow::wxGridCornerLabelWindow( wxGrid 
*parent
, 
3947                                                   const wxPoint 
&pos
, const wxSize 
&size 
) 
3948   : wxGridSubwindow(parent
, id
, pos
, size
) 
3953 void wxGridCornerLabelWindow::OnPaint( wxPaintEvent
& WXUNUSED(event
) ) 
3957     int client_height 
= 0; 
3958     int client_width 
= 0; 
3959     GetClientSize( &client_width
, &client_height 
); 
3961     // VZ: any reason for this ifdef? (FIXME) 
3967     rect
.SetWidth( client_width 
- 2 ); 
3968     rect
.SetHeight( client_height 
- 2 ); 
3970     wxRendererNative::Get().DrawHeaderButton( this, dc
, rect
, 0 ); 
3972     dc
.SetPen( wxPen(wxSystemSettings::GetColour(wxSYS_COLOUR_3DSHADOW
), 1, wxPENSTYLE_SOLID
) ); 
3973     dc
.DrawLine( client_width 
- 1, client_height 
- 1, client_width 
- 1, 0 ); 
3974     dc
.DrawLine( client_width 
- 1, client_height 
- 1, 0, client_height 
- 1 ); 
3975     dc
.DrawLine( 0, 0, client_width
, 0 ); 
3976     dc
.DrawLine( 0, 0, 0, client_height 
); 
3978     dc
.SetPen( *wxWHITE_PEN 
); 
3979     dc
.DrawLine( 1, 1, client_width 
- 1, 1 ); 
3980     dc
.DrawLine( 1, 1, 1, client_height 
- 1 ); 
3984 void wxGridCornerLabelWindow::OnMouseEvent( wxMouseEvent
& event 
) 
3986     m_owner
->ProcessCornerLabelMouseEvent( event 
); 
3989 void wxGridCornerLabelWindow::OnMouseWheel( wxMouseEvent
& event 
) 
3991     m_owner
->GetEventHandler()->ProcessEvent(event
); 
3994 ////////////////////////////////////////////////////////////////////// 
3996 IMPLEMENT_DYNAMIC_CLASS( wxGridWindow
, wxWindow 
) 
3998 BEGIN_EVENT_TABLE( wxGridWindow
, wxGridSubwindow 
) 
3999     EVT_PAINT( wxGridWindow::OnPaint 
) 
4000     EVT_MOUSEWHEEL( wxGridWindow::OnMouseWheel 
) 
4001     EVT_MOUSE_EVENTS( wxGridWindow::OnMouseEvent 
) 
4002     EVT_KEY_DOWN( wxGridWindow::OnKeyDown 
) 
4003     EVT_KEY_UP( wxGridWindow::OnKeyUp 
) 
4004     EVT_CHAR( wxGridWindow::OnChar 
) 
4005     EVT_SET_FOCUS( wxGridWindow::OnFocus 
) 
4006     EVT_KILL_FOCUS( wxGridWindow::OnFocus 
) 
4007     EVT_ERASE_BACKGROUND( wxGridWindow::OnEraseBackground 
) 
4010 wxGridWindow::wxGridWindow( wxGrid 
*parent
, 
4011                             wxGridRowLabelWindow 
*rowLblWin
, 
4012                             wxGridColLabelWindow 
*colLblWin
, 
4015                             const wxSize 
&size 
) 
4016             : wxGridSubwindow(parent
, id
, pos
, size
, 
4017                               wxWANTS_CHARS 
| wxCLIP_CHILDREN
, 
4018                               wxT("grid window") ) 
4021     m_rowLabelWin 
= rowLblWin
; 
4022     m_colLabelWin 
= colLblWin
; 
4025 void wxGridWindow::OnPaint( wxPaintEvent 
&WXUNUSED(event
) ) 
4027     wxPaintDC 
dc( this ); 
4028     m_owner
->PrepareDC( dc 
); 
4029     wxRegion reg 
= GetUpdateRegion(); 
4030     wxGridCellCoordsArray dirtyCells 
= m_owner
->CalcCellsExposed( reg 
); 
4031     m_owner
->DrawGridCellArea( dc
, dirtyCells 
); 
4033 #if WXGRID_DRAW_LINES 
4034     m_owner
->DrawAllGridLines( dc
, reg 
); 
4037     m_owner
->DrawGridSpace( dc 
); 
4038     m_owner
->DrawHighlight( dc
, dirtyCells 
); 
4041 void wxGridWindow::ScrollWindow( int dx
, int dy
, const wxRect 
*rect 
) 
4043     wxWindow::ScrollWindow( dx
, dy
, rect 
); 
4044     m_rowLabelWin
->ScrollWindow( 0, dy
, rect 
); 
4045     m_colLabelWin
->ScrollWindow( dx
, 0, rect 
); 
4048 void wxGridWindow::OnMouseEvent( wxMouseEvent
& event 
) 
4050     if (event
.ButtonDown(wxMOUSE_BTN_LEFT
) && FindFocus() != this) 
4053     m_owner
->ProcessGridCellMouseEvent( event 
); 
4056 void wxGridWindow::OnMouseWheel( wxMouseEvent
& event 
) 
4058     m_owner
->GetEventHandler()->ProcessEvent( event 
); 
4061 // This seems to be required for wxMotif/wxGTK otherwise the mouse 
4062 // cursor must be in the cell edit control to get key events 
4064 void wxGridWindow::OnKeyDown( wxKeyEvent
& event 
) 
4066     if ( !m_owner
->GetEventHandler()->ProcessEvent( event 
) ) 
4070 void wxGridWindow::OnKeyUp( wxKeyEvent
& event 
) 
4072     if ( !m_owner
->GetEventHandler()->ProcessEvent( event 
) ) 
4076 void wxGridWindow::OnChar( wxKeyEvent
& event 
) 
4078     if ( !m_owner
->GetEventHandler()->ProcessEvent( event 
) ) 
4082 void wxGridWindow::OnEraseBackground( wxEraseEvent
& WXUNUSED(event
) ) 
4086 void wxGridWindow::OnFocus(wxFocusEvent
& event
) 
4088     // and if we have any selection, it has to be repainted, because it 
4089     // uses different colour when the grid is not focused: 
4090     if ( m_owner
->IsSelection() ) 
4096         // NB: Note that this code is in "else" branch only because the other 
4097         //     branch refreshes everything and so there's no point in calling 
4098         //     Refresh() again, *not* because it should only be done if 
4099         //     !IsSelection(). If the above code is ever optimized to refresh 
4100         //     only selected area, this needs to be moved out of the "else" 
4101         //     branch so that it's always executed. 
4103         // current cell cursor {dis,re}appears on focus change: 
4104         const wxGridCellCoords 
cursorCoords(m_owner
->GetGridCursorRow(), 
4105                                             m_owner
->GetGridCursorCol()); 
4106         const wxRect cursor 
= 
4107             m_owner
->BlockToDeviceRect(cursorCoords
, cursorCoords
); 
4108         Refresh(true, &cursor
); 
4111     if ( !m_owner
->GetEventHandler()->ProcessEvent( event 
) ) 
4115 ////////////////////////////////////////////////////////////////////// 
4117 // Internal Helper function for computing row or column from some 
4118 // (unscrolled) coordinate value, using either 
4119 // m_defaultRowHeight/m_defaultColWidth or binary search on array 
4120 // of m_rowBottoms/m_ColRights to speed up the search! 
4122 // Internal helper macros for simpler use of that function 
4124 static int CoordToRowOrCol(int coord
, int defaultDist
, int minDist
, 
4125                            const wxArrayInt
& BorderArray
, int nMax
, 
4128 #define internalXToCol(x) XToCol(x, true) 
4129 #define internalYToRow(y) CoordToRowOrCol(y, m_defaultRowHeight, \ 
4130                                           m_minAcceptableRowHeight, \ 
4131                                           m_rowBottoms, m_numRows, true) 
4133 ///////////////////////////////////////////////////////////////////// 
4135 #if wxUSE_EXTENDED_RTTI 
4136 WX_DEFINE_FLAGS( wxGridStyle 
) 
4138 wxBEGIN_FLAGS( wxGridStyle 
) 
4139     // new style border flags, we put them first to 
4140     // use them for streaming out 
4141     wxFLAGS_MEMBER(wxBORDER_SIMPLE
) 
4142     wxFLAGS_MEMBER(wxBORDER_SUNKEN
) 
4143     wxFLAGS_MEMBER(wxBORDER_DOUBLE
) 
4144     wxFLAGS_MEMBER(wxBORDER_RAISED
) 
4145     wxFLAGS_MEMBER(wxBORDER_STATIC
) 
4146     wxFLAGS_MEMBER(wxBORDER_NONE
) 
4148     // old style border flags 
4149     wxFLAGS_MEMBER(wxSIMPLE_BORDER
) 
4150     wxFLAGS_MEMBER(wxSUNKEN_BORDER
) 
4151     wxFLAGS_MEMBER(wxDOUBLE_BORDER
) 
4152     wxFLAGS_MEMBER(wxRAISED_BORDER
) 
4153     wxFLAGS_MEMBER(wxSTATIC_BORDER
) 
4154     wxFLAGS_MEMBER(wxBORDER
) 
4156     // standard window styles 
4157     wxFLAGS_MEMBER(wxTAB_TRAVERSAL
) 
4158     wxFLAGS_MEMBER(wxCLIP_CHILDREN
) 
4159     wxFLAGS_MEMBER(wxTRANSPARENT_WINDOW
) 
4160     wxFLAGS_MEMBER(wxWANTS_CHARS
) 
4161     wxFLAGS_MEMBER(wxFULL_REPAINT_ON_RESIZE
) 
4162     wxFLAGS_MEMBER(wxALWAYS_SHOW_SB
) 
4163     wxFLAGS_MEMBER(wxVSCROLL
) 
4164     wxFLAGS_MEMBER(wxHSCROLL
) 
4166 wxEND_FLAGS( wxGridStyle 
) 
4168 IMPLEMENT_DYNAMIC_CLASS_XTI(wxGrid
, wxScrolledWindow
,"wx/grid.h") 
4170 wxBEGIN_PROPERTIES_TABLE(wxGrid
) 
4171     wxHIDE_PROPERTY( Children 
) 
4172     wxPROPERTY_FLAGS( WindowStyle 
, wxGridStyle 
, long , SetWindowStyleFlag 
, GetWindowStyleFlag 
, EMPTY_MACROVALUE
, 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // style 
4173 wxEND_PROPERTIES_TABLE() 
4175 wxBEGIN_HANDLERS_TABLE(wxGrid
) 
4176 wxEND_HANDLERS_TABLE() 
4178 wxCONSTRUCTOR_5( wxGrid 
, wxWindow
* , Parent 
, wxWindowID 
, Id 
, wxPoint 
, Position 
, wxSize 
, Size 
, long , WindowStyle 
) 
4181  TODO : Expose more information of a list's layout, etc. via appropriate objects (e.g., NotebookPageInfo) 
4184 IMPLEMENT_DYNAMIC_CLASS( wxGrid
, wxScrolledWindow 
) 
4187 BEGIN_EVENT_TABLE( wxGrid
, wxScrolledWindow 
) 
4188     EVT_PAINT( wxGrid::OnPaint 
) 
4189     EVT_SIZE( wxGrid::OnSize 
) 
4190     EVT_KEY_DOWN( wxGrid::OnKeyDown 
) 
4191     EVT_KEY_UP( wxGrid::OnKeyUp 
) 
4192     EVT_CHAR ( wxGrid::OnChar 
) 
4193     EVT_ERASE_BACKGROUND( wxGrid::OnEraseBackground 
) 
4201 wxGrid::wxGrid( wxWindow 
*parent
, 
4206                  const wxString
& name 
) 
4209     Create(parent
, id
, pos
, size
, style
, name
); 
4212 bool wxGrid::Create(wxWindow 
*parent
, wxWindowID id
, 
4213                           const wxPoint
& pos
, const wxSize
& size
, 
4214                           long style
, const wxString
& name
) 
4216     if (!wxScrolledWindow::Create(parent
, id
, pos
, size
, 
4217                                   style 
| wxWANTS_CHARS
, name
)) 
4220     m_colMinWidths 
= wxLongToLongHashMap(GRID_HASH_SIZE
); 
4221     m_rowMinHeights 
= wxLongToLongHashMap(GRID_HASH_SIZE
); 
4224     SetInitialSize(size
); 
4225     SetScrollRate(m_scrollLineX
, m_scrollLineY
); 
4233     // Must do this or ~wxScrollHelper will pop the wrong event handler 
4234     SetTargetWindow(this); 
4236     wxSafeDecRef(m_defaultCellAttr
); 
4238 #ifdef DEBUG_ATTR_CACHE 
4239     size_t total 
= gs_nAttrCacheHits 
+ gs_nAttrCacheMisses
; 
4240     wxPrintf(_T("wxGrid attribute cache statistics: " 
4241                 "total: %u, hits: %u (%u%%)\n"), 
4242              total
, gs_nAttrCacheHits
, 
4243              total 
? (gs_nAttrCacheHits
*100) / total 
: 0); 
4246     // if we own the table, just delete it, otherwise at least don't leave it 
4247     // with dangling view pointer 
4250     else if ( m_table 
&& m_table
->GetView() == this ) 
4251         m_table
->SetView(NULL
); 
4253     delete m_typeRegistry
; 
4258 // ----- internal init and update functions 
4261 // NOTE: If using the default visual attributes works everywhere then this can 
4262 // be removed as well as the #else cases below. 
4263 #define _USE_VISATTR 0 
4265 void wxGrid::Create() 
4267     // create the type registry 
4268     m_typeRegistry 
= new wxGridTypeRegistry
; 
4270     m_cellEditCtrlEnabled 
= false; 
4272     m_defaultCellAttr 
= new wxGridCellAttr(); 
4274     // Set default cell attributes 
4275     m_defaultCellAttr
->SetDefAttr(m_defaultCellAttr
); 
4276     m_defaultCellAttr
->SetKind(wxGridCellAttr::Default
); 
4277     m_defaultCellAttr
->SetFont(GetFont()); 
4278     m_defaultCellAttr
->SetAlignment(wxALIGN_LEFT
, wxALIGN_TOP
); 
4279     m_defaultCellAttr
->SetRenderer(new wxGridCellStringRenderer
); 
4280     m_defaultCellAttr
->SetEditor(new wxGridCellTextEditor
); 
4283     wxVisualAttributes gva 
= wxListBox::GetClassDefaultAttributes(); 
4284     wxVisualAttributes lva 
= wxPanel::GetClassDefaultAttributes(); 
4286     m_defaultCellAttr
->SetTextColour(gva
.colFg
); 
4287     m_defaultCellAttr
->SetBackgroundColour(gva
.colBg
); 
4290     m_defaultCellAttr
->SetTextColour( 
4291         wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT
)); 
4292     m_defaultCellAttr
->SetBackgroundColour( 
4293         wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW
)); 
4298     m_currentCellCoords 
= wxGridNoCellCoords
; 
4300     m_rowLabelWidth 
= WXGRID_DEFAULT_ROW_LABEL_WIDTH
; 
4301     m_colLabelHeight 
= WXGRID_DEFAULT_COL_LABEL_HEIGHT
; 
4303     // subwindow components that make up the wxGrid 
4304     m_rowLabelWin 
= new wxGridRowLabelWindow( this, 
4309     m_colLabelWin 
= new wxGridColLabelWindow( this, 
4314     m_cornerLabelWin 
= new wxGridCornerLabelWindow( this, 
4319     m_gridWin 
= new wxGridWindow( this, 
4326     SetTargetWindow( m_gridWin 
); 
4329     wxColour gfg 
= gva
.colFg
; 
4330     wxColour gbg 
= gva
.colBg
; 
4331     wxColour lfg 
= lva
.colFg
; 
4332     wxColour lbg 
= lva
.colBg
; 
4334     wxColour gfg 
= wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOWTEXT 
); 
4335     wxColour gbg 
= wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW 
); 
4336     wxColour lfg 
= wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOWTEXT 
); 
4337     wxColour lbg 
= wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE 
); 
4340     m_cornerLabelWin
->SetOwnForegroundColour(lfg
); 
4341     m_cornerLabelWin
->SetOwnBackgroundColour(lbg
); 
4342     m_rowLabelWin
->SetOwnForegroundColour(lfg
); 
4343     m_rowLabelWin
->SetOwnBackgroundColour(lbg
); 
4344     m_colLabelWin
->SetOwnForegroundColour(lfg
); 
4345     m_colLabelWin
->SetOwnBackgroundColour(lbg
); 
4347     m_gridWin
->SetOwnForegroundColour(gfg
); 
4348     m_gridWin
->SetOwnBackgroundColour(gbg
); 
4353 bool wxGrid::CreateGrid( int numRows
, int numCols
, 
4354                          wxGrid::wxGridSelectionModes selmode 
) 
4356     wxCHECK_MSG( !m_created
, 
4358                  wxT("wxGrid::CreateGrid or wxGrid::SetTable called more than once") ); 
4360     m_numRows 
= numRows
; 
4361     m_numCols 
= numCols
; 
4363     m_table 
= new wxGridStringTable( m_numRows
, m_numCols 
); 
4364     m_table
->SetView( this ); 
4366     m_selection 
= new wxGridSelection( this, selmode 
); 
4375 void wxGrid::SetSelectionMode(wxGrid::wxGridSelectionModes selmode
) 
4377     wxCHECK_RET( m_created
, 
4378                  wxT("Called wxGrid::SetSelectionMode() before calling CreateGrid()") ); 
4380     m_selection
->SetSelectionMode( selmode 
); 
4383 wxGrid::wxGridSelectionModes 
wxGrid::GetSelectionMode() const 
4385     wxCHECK_MSG( m_created
, wxGrid::wxGridSelectCells
, 
4386                  wxT("Called wxGrid::GetSelectionMode() before calling CreateGrid()") ); 
4388     return m_selection
->GetSelectionMode(); 
4391 bool wxGrid::SetTable( wxGridTableBase 
*table
, bool takeOwnership
, 
4392                        wxGrid::wxGridSelectionModes selmode 
) 
4394     bool checkSelection 
= false; 
4397         // stop all processing 
4402             m_table
->SetView(0); 
4414         checkSelection 
= true; 
4416         // kill row and column size arrays 
4417         m_colWidths
.Empty(); 
4418         m_colRights
.Empty(); 
4419         m_rowHeights
.Empty(); 
4420         m_rowBottoms
.Empty(); 
4425         m_numRows 
= table
->GetNumberRows(); 
4426         m_numCols 
= table
->GetNumberCols(); 
4429         m_table
->SetView( this ); 
4430         m_ownTable 
= takeOwnership
; 
4431         m_selection 
= new wxGridSelection( this, selmode 
); 
4434             // If the newly set table is smaller than the 
4435             // original one current cell and selection regions 
4436             // might be invalid, 
4437             m_selectingKeyboard 
= wxGridNoCellCoords
; 
4438             m_currentCellCoords 
= 
4439               wxGridCellCoords(wxMin(m_numRows
, m_currentCellCoords
.GetRow()), 
4440                                wxMin(m_numCols
, m_currentCellCoords
.GetCol())); 
4441             if (m_selectingTopLeft
.GetRow() >= m_numRows 
|| 
4442                 m_selectingTopLeft
.GetCol() >= m_numCols
) 
4444                 m_selectingTopLeft 
= wxGridNoCellCoords
; 
4445                 m_selectingBottomRight 
= wxGridNoCellCoords
; 
4448                 m_selectingBottomRight 
= 
4449                   wxGridCellCoords(wxMin(m_numRows
, 
4450                                          m_selectingBottomRight
.GetRow()), 
4452                                          m_selectingBottomRight
.GetCol())); 
4462 void wxGrid::InitVars() 
4466     m_cornerLabelWin 
= NULL
; 
4467     m_rowLabelWin 
= NULL
; 
4468     m_colLabelWin 
= NULL
; 
4475     m_defaultCellAttr 
= NULL
; 
4476     m_typeRegistry 
= NULL
; 
4477     m_winCapture 
= NULL
; 
4482     m_rowLabelWidth  
= WXGRID_DEFAULT_ROW_LABEL_WIDTH
; 
4483     m_colLabelHeight 
= WXGRID_DEFAULT_COL_LABEL_HEIGHT
; 
4485     if ( m_rowLabelWin 
) 
4487         m_labelBackgroundColour 
= m_rowLabelWin
->GetBackgroundColour(); 
4491         m_labelBackgroundColour 
= *wxWHITE
; 
4494     m_labelTextColour 
= *wxBLACK
; 
4497     m_attrCache
.row 
= -1; 
4498     m_attrCache
.col 
= -1; 
4499     m_attrCache
.attr 
= NULL
; 
4501     // TODO: something better than this ? 
4503     m_labelFont 
= this->GetFont(); 
4504     m_labelFont
.SetWeight( wxBOLD 
); 
4506     m_rowLabelHorizAlign 
= wxALIGN_CENTRE
; 
4507     m_rowLabelVertAlign  
= wxALIGN_CENTRE
; 
4509     m_colLabelHorizAlign 
= wxALIGN_CENTRE
; 
4510     m_colLabelVertAlign  
= wxALIGN_CENTRE
; 
4511     m_colLabelTextOrientation 
= wxHORIZONTAL
; 
4513     m_defaultColWidth  
= WXGRID_DEFAULT_COL_WIDTH
; 
4514     m_defaultRowHeight 
= m_gridWin
->GetCharHeight(); 
4516     m_minAcceptableColWidth  
= WXGRID_MIN_COL_WIDTH
; 
4517     m_minAcceptableRowHeight 
= WXGRID_MIN_ROW_HEIGHT
; 
4519 #if defined(__WXMOTIF__) || defined(__WXGTK__)  // see also text ctrl sizing in ShowCellEditControl() 
4520     m_defaultRowHeight 
+= 8; 
4522     m_defaultRowHeight 
+= 4; 
4525     m_gridLineColour 
= wxColour( 192,192,192 ); 
4526     m_gridLinesEnabled 
= true; 
4527     m_cellHighlightColour 
= *wxBLACK
; 
4528     m_cellHighlightPenWidth 
= 2; 
4529     m_cellHighlightROPenWidth 
= 1; 
4531     m_canDragColMove 
= false; 
4533     m_cursorMode  
= WXGRID_CURSOR_SELECT_CELL
; 
4534     m_winCapture 
= (wxWindow 
*)NULL
; 
4535     m_canDragRowSize 
= true; 
4536     m_canDragColSize 
= true; 
4537     m_canDragGridSize 
= true; 
4538     m_canDragCell 
= false; 
4540     m_dragRowOrCol 
= -1; 
4541     m_isDragging 
= false; 
4542     m_startDragPos 
= wxDefaultPosition
; 
4543     m_nativeColumnLabels 
= false; 
4545     m_waitForSlowClick 
= false; 
4547     m_rowResizeCursor 
= wxCursor( wxCURSOR_SIZENS 
); 
4548     m_colResizeCursor 
= wxCursor( wxCURSOR_SIZEWE 
); 
4550     m_currentCellCoords 
= wxGridNoCellCoords
; 
4554     m_selectionBackground 
= wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT
); 
4555     m_selectionForeground 
= wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHTTEXT
); 
4557     m_editable 
= true;  // default for whole grid 
4559     m_inOnKeyDown 
= false; 
4565     m_scrollLineX 
= GRID_SCROLL_LINE_X
; 
4566     m_scrollLineY 
= GRID_SCROLL_LINE_Y
; 
4569 // ---------------------------------------------------------------------------- 
4570 // the idea is to call these functions only when necessary because they create 
4571 // quite big arrays which eat memory mostly unnecessary - in particular, if 
4572 // default widths/heights are used for all rows/columns, we may not use these 
4575 // with some extra code, it should be possible to only store the widths/heights 
4576 // different from default ones (resulting in space savings for huge grids) but 
4577 // this is not done currently 
4578 // ---------------------------------------------------------------------------- 
4580 void wxGrid::InitRowHeights() 
4582     m_rowHeights
.Empty(); 
4583     m_rowBottoms
.Empty(); 
4585     m_rowHeights
.Alloc( m_numRows 
); 
4586     m_rowBottoms
.Alloc( m_numRows 
); 
4588     m_rowHeights
.Add( m_defaultRowHeight
, m_numRows 
); 
4591     for ( int i 
= 0; i 
< m_numRows
; i
++ ) 
4593         rowBottom 
+= m_defaultRowHeight
; 
4594         m_rowBottoms
.Add( rowBottom 
); 
4598 void wxGrid::InitColWidths() 
4600     m_colWidths
.Empty(); 
4601     m_colRights
.Empty(); 
4603     m_colWidths
.Alloc( m_numCols 
); 
4604     m_colRights
.Alloc( m_numCols 
); 
4606     m_colWidths
.Add( m_defaultColWidth
, m_numCols 
); 
4609     for ( int i 
= 0; i 
< m_numCols
; i
++ ) 
4611         colRight 
= ( GetColPos( i 
) + 1 ) * m_defaultColWidth
; 
4612         m_colRights
.Add( colRight 
); 
4616 int wxGrid::GetColWidth(int col
) const 
4618     return m_colWidths
.IsEmpty() ? m_defaultColWidth 
: m_colWidths
[col
]; 
4621 int wxGrid::GetColLeft(int col
) const 
4623     return m_colRights
.IsEmpty() ? GetColPos( col 
) * m_defaultColWidth
 
4624                                  : m_colRights
[col
] - m_colWidths
[col
]; 
4627 int wxGrid::GetColRight(int col
) const 
4629     return m_colRights
.IsEmpty() ? (GetColPos( col 
) + 1) * m_defaultColWidth
 
4633 int wxGrid::GetRowHeight(int row
) const 
4635     return m_rowHeights
.IsEmpty() ? m_defaultRowHeight 
: m_rowHeights
[row
]; 
4638 int wxGrid::GetRowTop(int row
) const 
4640     return m_rowBottoms
.IsEmpty() ? row 
* m_defaultRowHeight
 
4641                                   : m_rowBottoms
[row
] - m_rowHeights
[row
]; 
4644 int wxGrid::GetRowBottom(int row
) const 
4646     return m_rowBottoms
.IsEmpty() ? (row 
+ 1) * m_defaultRowHeight
 
4647                                   : m_rowBottoms
[row
]; 
4650 void wxGrid::CalcDimensions() 
4652     // compute the size of the scrollable area 
4653     int w 
= m_numCols 
> 0 ? GetColRight(GetColAt(m_numCols 
- 1)) : 0; 
4654     int h 
= m_numRows 
> 0 ? GetRowBottom(m_numRows 
- 1) : 0; 
4659     // take into account editor if shown 
4660     if ( IsCellEditControlShown() ) 
4663         int r 
= m_currentCellCoords
.GetRow(); 
4664         int c 
= m_currentCellCoords
.GetCol(); 
4665         int x 
= GetColLeft(c
); 
4666         int y 
= GetRowTop(r
); 
4668         // how big is the editor 
4669         wxGridCellAttr
* attr 
= GetCellAttr(r
, c
); 
4670         wxGridCellEditor
* editor 
= attr
->GetEditor(this, r
, c
); 
4671         editor
->GetControl()->GetSize(&w2
, &h2
); 
4682     // preserve (more or less) the previous position 
4684     GetViewStart( &x
, &y 
); 
4686     // ensure the position is valid for the new scroll ranges 
4688         x 
= wxMax( w 
- 1, 0 ); 
4690         y 
= wxMax( h 
- 1, 0 ); 
4692     // update the virtual size and refresh the scrollbars to reflect it 
4693     m_gridWin
->SetVirtualSize(w
, h
); 
4697     // if our OnSize() hadn't been called (it would if we have scrollbars), we 
4698     // still must reposition the children 
4702 wxSize 
wxGrid::GetSizeAvailableForScrollTarget(const wxSize
& size
) 
4704     wxSize 
sizeGridWin(size
); 
4705     sizeGridWin
.x 
-= m_rowLabelWidth
; 
4706     sizeGridWin
.y 
-= m_colLabelHeight
; 
4711 void wxGrid::CalcWindowSizes() 
4713     // escape if the window is has not been fully created yet 
4715     if ( m_cornerLabelWin 
== NULL 
) 
4719     GetClientSize( &cw
, &ch 
); 
4721     // the grid may be too small to have enough space for the labels yet, don't 
4722     // size the windows to negative sizes in this case 
4723     int gw 
= cw 
- m_rowLabelWidth
; 
4724     int gh 
= ch 
- m_colLabelHeight
; 
4730     if ( m_cornerLabelWin 
&& m_cornerLabelWin
->IsShown() ) 
4731         m_cornerLabelWin
->SetSize( 0, 0, m_rowLabelWidth
, m_colLabelHeight 
); 
4733     if ( m_colLabelWin 
&& m_colLabelWin
->IsShown() ) 
4734         m_colLabelWin
->SetSize( m_rowLabelWidth
, 0, gw
, m_colLabelHeight 
); 
4736     if ( m_rowLabelWin 
&& m_rowLabelWin
->IsShown() ) 
4737         m_rowLabelWin
->SetSize( 0, m_colLabelHeight
, m_rowLabelWidth
, gh 
); 
4739     if ( m_gridWin 
&& m_gridWin
->IsShown() ) 
4740         m_gridWin
->SetSize( m_rowLabelWidth
, m_colLabelHeight
, gw
, gh 
); 
4743 // this is called when the grid table sends a message 
4744 // to indicate that it has been redimensioned 
4746 bool wxGrid::Redimension( wxGridTableMessage
& msg 
) 
4749     bool result 
= false; 
4751     // Clear the attribute cache as the attribute might refer to a different 
4752     // cell than stored in the cache after adding/removing rows/columns. 
4755     // By the same reasoning, the editor should be dismissed if columns are 
4756     // added or removed. And for consistency, it should IMHO always be 
4757     // removed, not only if the cell "underneath" it actually changes. 
4758     // For now, I intentionally do not save the editor's content as the 
4759     // cell it might want to save that stuff to might no longer exist. 
4760     HideCellEditControl(); 
4763     // if we were using the default widths/heights so far, we must change them 
4765     if ( m_colWidths
.IsEmpty() ) 
4770     if ( m_rowHeights
.IsEmpty() ) 
4776     switch ( msg
.GetId() ) 
4778         case wxGRIDTABLE_NOTIFY_ROWS_INSERTED
: 
4780             size_t pos 
= msg
.GetCommandInt(); 
4781             int numRows 
= msg
.GetCommandInt2(); 
4783             m_numRows 
+= numRows
; 
4785             if ( !m_rowHeights
.IsEmpty() ) 
4787                 m_rowHeights
.Insert( m_defaultRowHeight
, pos
, numRows 
); 
4788                 m_rowBottoms
.Insert( 0, pos
, numRows 
); 
4792                     bottom 
= m_rowBottoms
[pos 
- 1]; 
4794                 for ( i 
= pos
; i 
< m_numRows
; i
++ ) 
4796                     bottom 
+= m_rowHeights
[i
]; 
4797                     m_rowBottoms
[i
] = bottom
; 
4801             if ( m_currentCellCoords 
== wxGridNoCellCoords 
) 
4803                 // if we have just inserted cols into an empty grid the current 
4804                 // cell will be undefined... 
4806                 SetCurrentCell( 0, 0 ); 
4810                 m_selection
->UpdateRows( pos
, numRows 
); 
4811             wxGridCellAttrProvider 
* attrProvider 
= m_table
->GetAttrProvider(); 
4813                 attrProvider
->UpdateAttrRows( pos
, numRows 
); 
4815             if ( !GetBatchCount() ) 
4818                 m_rowLabelWin
->Refresh(); 
4824         case wxGRIDTABLE_NOTIFY_ROWS_APPENDED
: 
4826             int numRows 
= msg
.GetCommandInt(); 
4827             int oldNumRows 
= m_numRows
; 
4828             m_numRows 
+= numRows
; 
4830             if ( !m_rowHeights
.IsEmpty() ) 
4832                 m_rowHeights
.Add( m_defaultRowHeight
, numRows 
); 
4833                 m_rowBottoms
.Add( 0, numRows 
); 
4836                 if ( oldNumRows 
> 0 ) 
4837                     bottom 
= m_rowBottoms
[oldNumRows 
- 1]; 
4839                 for ( i 
= oldNumRows
; i 
< m_numRows
; i
++ ) 
4841                     bottom 
+= m_rowHeights
[i
]; 
4842                     m_rowBottoms
[i
] = bottom
; 
4846             if ( m_currentCellCoords 
== wxGridNoCellCoords 
) 
4848                 // if we have just inserted cols into an empty grid the current 
4849                 // cell will be undefined... 
4851                 SetCurrentCell( 0, 0 ); 
4854             if ( !GetBatchCount() ) 
4857                 m_rowLabelWin
->Refresh(); 
4863         case wxGRIDTABLE_NOTIFY_ROWS_DELETED
: 
4865             size_t pos 
= msg
.GetCommandInt(); 
4866             int numRows 
= msg
.GetCommandInt2(); 
4867             m_numRows 
-= numRows
; 
4869             if ( !m_rowHeights
.IsEmpty() ) 
4871                 m_rowHeights
.RemoveAt( pos
, numRows 
); 
4872                 m_rowBottoms
.RemoveAt( pos
, numRows 
); 
4875                 for ( i 
= 0; i 
< m_numRows
; i
++ ) 
4877                     h 
+= m_rowHeights
[i
]; 
4878                     m_rowBottoms
[i
] = h
; 
4884                 m_currentCellCoords 
= wxGridNoCellCoords
; 
4888                 if ( m_currentCellCoords
.GetRow() >= m_numRows 
) 
4889                     m_currentCellCoords
.Set( 0, 0 ); 
4893                 m_selection
->UpdateRows( pos
, -((int)numRows
) ); 
4894             wxGridCellAttrProvider 
* attrProvider 
= m_table
->GetAttrProvider(); 
4897                 attrProvider
->UpdateAttrRows( pos
, -((int)numRows
) ); 
4899 // ifdef'd out following patch from Paul Gammans 
4901                 // No need to touch column attributes, unless we 
4902                 // removed _all_ rows, in this case, we remove 
4903                 // all column attributes. 
4904                 // I hate to do this here, but the 
4905                 // needed data is not available inside UpdateAttrRows. 
4906                 if ( !GetNumberRows() ) 
4907                     attrProvider
->UpdateAttrCols( 0, -GetNumberCols() ); 
4911             if ( !GetBatchCount() ) 
4914                 m_rowLabelWin
->Refresh(); 
4920         case wxGRIDTABLE_NOTIFY_COLS_INSERTED
: 
4922             size_t pos 
= msg
.GetCommandInt(); 
4923             int numCols 
= msg
.GetCommandInt2(); 
4924             m_numCols 
+= numCols
; 
4926             if ( !m_colAt
.IsEmpty() ) 
4928                 //Shift the column IDs 
4930                 for ( i 
= 0; i 
< m_numCols 
- numCols
; i
++ ) 
4932                     if ( m_colAt
[i
] >= (int)pos 
) 
4933                         m_colAt
[i
] += numCols
; 
4936                 m_colAt
.Insert( pos
, pos
, numCols 
); 
4938                 //Set the new columns' positions 
4939                 for ( i 
= pos 
+ 1; i 
< (int)pos 
+ numCols
; i
++ ) 
4945             if ( !m_colWidths
.IsEmpty() ) 
4947                 m_colWidths
.Insert( m_defaultColWidth
, pos
, numCols 
); 
4948                 m_colRights
.Insert( 0, pos
, numCols 
); 
4952                     right 
= m_colRights
[GetColAt( pos 
- 1 )]; 
4955                 for ( colPos 
= pos
; colPos 
< m_numCols
; colPos
++ ) 
4957                     i 
= GetColAt( colPos 
); 
4959                     right 
+= m_colWidths
[i
]; 
4960                     m_colRights
[i
] = right
; 
4964             if ( m_currentCellCoords 
== wxGridNoCellCoords 
) 
4966                 // if we have just inserted cols into an empty grid the current 
4967                 // cell will be undefined... 
4969                 SetCurrentCell( 0, 0 ); 
4973                 m_selection
->UpdateCols( pos
, numCols 
); 
4974             wxGridCellAttrProvider 
* attrProvider 
= m_table
->GetAttrProvider(); 
4976                 attrProvider
->UpdateAttrCols( pos
, numCols 
); 
4977             if ( !GetBatchCount() ) 
4980                 m_colLabelWin
->Refresh(); 
4986         case wxGRIDTABLE_NOTIFY_COLS_APPENDED
: 
4988             int numCols 
= msg
.GetCommandInt(); 
4989             int oldNumCols 
= m_numCols
; 
4990             m_numCols 
+= numCols
; 
4992             if ( !m_colAt
.IsEmpty() ) 
4994                 m_colAt
.Add( 0, numCols 
); 
4996                 //Set the new columns' positions 
4998                 for ( i 
= oldNumCols
; i 
< m_numCols
; i
++ ) 
5004             if ( !m_colWidths
.IsEmpty() ) 
5006                 m_colWidths
.Add( m_defaultColWidth
, numCols 
); 
5007                 m_colRights
.Add( 0, numCols 
); 
5010                 if ( oldNumCols 
> 0 ) 
5011                     right 
= m_colRights
[GetColAt( oldNumCols 
- 1 )]; 
5014                 for ( colPos 
= oldNumCols
; colPos 
< m_numCols
; colPos
++ ) 
5016                     i 
= GetColAt( colPos 
); 
5018                     right 
+= m_colWidths
[i
]; 
5019                     m_colRights
[i
] = right
; 
5023             if ( m_currentCellCoords 
== wxGridNoCellCoords 
) 
5025                 // if we have just inserted cols into an empty grid the current 
5026                 // cell will be undefined... 
5028                 SetCurrentCell( 0, 0 ); 
5030             if ( !GetBatchCount() ) 
5033                 m_colLabelWin
->Refresh(); 
5039         case wxGRIDTABLE_NOTIFY_COLS_DELETED
: 
5041             size_t pos 
= msg
.GetCommandInt(); 
5042             int numCols 
= msg
.GetCommandInt2(); 
5043             m_numCols 
-= numCols
; 
5045             if ( !m_colAt
.IsEmpty() ) 
5047                 int colID 
= GetColAt( pos 
); 
5049                 m_colAt
.RemoveAt( pos
, numCols 
); 
5051                 //Shift the column IDs 
5053                 for ( colPos 
= 0; colPos 
< m_numCols
; colPos
++ ) 
5055                     if ( m_colAt
[colPos
] > colID 
) 
5056                         m_colAt
[colPos
] -= numCols
; 
5060             if ( !m_colWidths
.IsEmpty() ) 
5062                 m_colWidths
.RemoveAt( pos
, numCols 
); 
5063                 m_colRights
.RemoveAt( pos
, numCols 
); 
5067                 for ( colPos 
= 0; colPos 
< m_numCols
; colPos
++ ) 
5069                     i 
= GetColAt( colPos 
); 
5071                     w 
+= m_colWidths
[i
]; 
5078                 m_currentCellCoords 
= wxGridNoCellCoords
; 
5082                 if ( m_currentCellCoords
.GetCol() >= m_numCols 
) 
5083                   m_currentCellCoords
.Set( 0, 0 ); 
5087                 m_selection
->UpdateCols( pos
, -((int)numCols
) ); 
5088             wxGridCellAttrProvider 
* attrProvider 
= m_table
->GetAttrProvider(); 
5091                 attrProvider
->UpdateAttrCols( pos
, -((int)numCols
) ); 
5093 // ifdef'd out following patch from Paul Gammans 
5095                 // No need to touch row attributes, unless we 
5096                 // removed _all_ columns, in this case, we remove 
5097                 // all row attributes. 
5098                 // I hate to do this here, but the 
5099                 // needed data is not available inside UpdateAttrCols. 
5100                 if ( !GetNumberCols() ) 
5101                     attrProvider
->UpdateAttrRows( 0, -GetNumberRows() ); 
5105             if ( !GetBatchCount() ) 
5108                 m_colLabelWin
->Refresh(); 
5115     if (result 
&& !GetBatchCount() ) 
5116         m_gridWin
->Refresh(); 
5121 wxArrayInt 
wxGrid::CalcRowLabelsExposed( const wxRegion
& reg 
) const 
5123     wxRegionIterator 
iter( reg 
); 
5126     wxArrayInt  rowlabels
; 
5133         // TODO: remove this when we can... 
5134         // There is a bug in wxMotif that gives garbage update 
5135         // rectangles if you jump-scroll a long way by clicking the 
5136         // scrollbar with middle button.  This is a work-around 
5138 #if defined(__WXMOTIF__) 
5140         m_gridWin
->GetClientSize( &cw
, &ch 
); 
5141         if ( r
.GetTop() > ch 
) 
5143         r
.SetBottom( wxMin( r
.GetBottom(), ch 
) ); 
5146         // logical bounds of update region 
5149         CalcUnscrolledPosition( 0, r
.GetTop(), &dummy
, &top 
); 
5150         CalcUnscrolledPosition( 0, r
.GetBottom(), &dummy
, &bottom 
); 
5152         // find the row labels within these bounds 
5155         for ( row 
= internalYToRow(top
); row 
< m_numRows
; row
++ ) 
5157             if ( GetRowBottom(row
) < top 
) 
5160             if ( GetRowTop(row
) > bottom 
) 
5163             rowlabels
.Add( row 
); 
5172 wxArrayInt 
wxGrid::CalcColLabelsExposed( const wxRegion
& reg 
) const 
5174     wxRegionIterator 
iter( reg 
); 
5177     wxArrayInt colLabels
; 
5184         // TODO: remove this when we can... 
5185         // There is a bug in wxMotif that gives garbage update 
5186         // rectangles if you jump-scroll a long way by clicking the 
5187         // scrollbar with middle button.  This is a work-around 
5189 #if defined(__WXMOTIF__) 
5191         m_gridWin
->GetClientSize( &cw
, &ch 
); 
5192         if ( r
.GetLeft() > cw 
) 
5194         r
.SetRight( wxMin( r
.GetRight(), cw 
) ); 
5197         // logical bounds of update region 
5200         CalcUnscrolledPosition( r
.GetLeft(), 0, &left
, &dummy 
); 
5201         CalcUnscrolledPosition( r
.GetRight(), 0, &right
, &dummy 
); 
5203         // find the cells within these bounds 
5207         for ( colPos 
= GetColPos( internalXToCol(left
) ); colPos 
< m_numCols
; colPos
++ ) 
5209             col 
= GetColAt( colPos 
); 
5211             if ( GetColRight(col
) < left 
) 
5214             if ( GetColLeft(col
) > right 
) 
5217             colLabels
.Add( col 
); 
5226 wxGridCellCoordsArray 
wxGrid::CalcCellsExposed( const wxRegion
& reg 
) const 
5228     wxRegionIterator 
iter( reg 
); 
5231     wxGridCellCoordsArray  cellsExposed
; 
5233     int left
, top
, right
, bottom
; 
5238         // TODO: remove this when we can... 
5239         // There is a bug in wxMotif that gives garbage update 
5240         // rectangles if you jump-scroll a long way by clicking the 
5241         // scrollbar with middle button.  This is a work-around 
5243 #if defined(__WXMOTIF__) 
5245         m_gridWin
->GetClientSize( &cw
, &ch 
); 
5246         if ( r
.GetTop() > ch 
) r
.SetTop( 0 ); 
5247         if ( r
.GetLeft() > cw 
) r
.SetLeft( 0 ); 
5248         r
.SetRight( wxMin( r
.GetRight(), cw 
) ); 
5249         r
.SetBottom( wxMin( r
.GetBottom(), ch 
) ); 
5252         // logical bounds of update region 
5254         CalcUnscrolledPosition( r
.GetLeft(), r
.GetTop(), &left
, &top 
); 
5255         CalcUnscrolledPosition( r
.GetRight(), r
.GetBottom(), &right
, &bottom 
); 
5257         // find the cells within these bounds 
5260         for ( row 
= internalYToRow(top
); row 
< m_numRows
; row
++ ) 
5262             if ( GetRowBottom(row
) <= top 
) 
5265             if ( GetRowTop(row
) > bottom 
) 
5269             for ( colPos 
= GetColPos( internalXToCol(left
) ); colPos 
< m_numCols
; colPos
++ ) 
5271                 col 
= GetColAt( colPos 
); 
5273                 if ( GetColRight(col
) <= left 
) 
5276                 if ( GetColLeft(col
) > right 
) 
5279                 cellsExposed
.Add( wxGridCellCoords( row
, col 
) ); 
5286     return cellsExposed
; 
5290 void wxGrid::ProcessRowLabelMouseEvent( wxMouseEvent
& event 
) 
5293     wxPoint 
pos( event
.GetPosition() ); 
5294     CalcUnscrolledPosition( pos
.x
, pos
.y
, &x
, &y 
); 
5296     if ( event
.Dragging() ) 
5300             m_isDragging 
= true; 
5301             m_rowLabelWin
->CaptureMouse(); 
5304         if ( event
.LeftIsDown() ) 
5306             switch ( m_cursorMode 
) 
5308                 case WXGRID_CURSOR_RESIZE_ROW
: 
5310                     int cw
, ch
, left
, dummy
; 
5311                     m_gridWin
->GetClientSize( &cw
, &ch 
); 
5312                     CalcUnscrolledPosition( 0, 0, &left
, &dummy 
); 
5314                     wxClientDC 
dc( m_gridWin 
); 
5317                                GetRowTop(m_dragRowOrCol
) + 
5318                                GetRowMinimalHeight(m_dragRowOrCol
) ); 
5319                     dc
.SetLogicalFunction(wxINVERT
); 
5320                     if ( m_dragLastPos 
>= 0 ) 
5322                         dc
.DrawLine( left
, m_dragLastPos
, left
+cw
, m_dragLastPos 
); 
5324                     dc
.DrawLine( left
, y
, left
+cw
, y 
); 
5329                 case WXGRID_CURSOR_SELECT_ROW
: 
5331                     if ( (row 
= YToRow( y 
)) >= 0 ) 
5335                             m_selection
->SelectRow( row
, 
5336                                                     event
.ControlDown(), 
5345                 // default label to suppress warnings about "enumeration value 
5346                 // 'xxx' not handled in switch 
5354     if ( m_isDragging 
&& (event
.Entering() || event
.Leaving()) ) 
5359         if (m_rowLabelWin
->HasCapture()) 
5360             m_rowLabelWin
->ReleaseMouse(); 
5361         m_isDragging 
= false; 
5364     // ------------ Entering or leaving the window 
5366     if ( event
.Entering() || event
.Leaving() ) 
5368         ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
, m_rowLabelWin
); 
5371     // ------------ Left button pressed 
5373     else if ( event
.LeftDown() ) 
5375         // don't send a label click event for a hit on the 
5376         // edge of the row label - this is probably the user 
5377         // wanting to resize the row 
5379         if ( YToEdgeOfRow(y
) < 0 ) 
5383                  !SendEvent( wxEVT_GRID_LABEL_LEFT_CLICK
, row
, -1, event 
) ) 
5385                 if ( !event
.ShiftDown() && !event
.CmdDown() ) 
5389                     if ( event
.ShiftDown() ) 
5391                         m_selection
->SelectBlock( m_currentCellCoords
.GetRow(), 
5394                                                   GetNumberCols() - 1, 
5395                                                   event
.ControlDown(), 
5402                         m_selection
->SelectRow( row
, 
5403                                                 event
.ControlDown(), 
5410                 ChangeCursorMode(WXGRID_CURSOR_SELECT_ROW
, m_rowLabelWin
); 
5415             // starting to drag-resize a row 
5416             if ( CanDragRowSize() ) 
5417                 ChangeCursorMode(WXGRID_CURSOR_RESIZE_ROW
, m_rowLabelWin
); 
5421     // ------------ Left double click 
5423     else if (event
.LeftDClick() ) 
5425         row 
= YToEdgeOfRow(y
); 
5430                  !SendEvent( wxEVT_GRID_LABEL_LEFT_DCLICK
, row
, -1, event 
) ) 
5432                 // no default action at the moment 
5437             // adjust row height depending on label text 
5438             AutoSizeRowLabelSize( row 
); 
5440             ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
, m_colLabelWin
); 
5445     // ------------ Left button released 
5447     else if ( event
.LeftUp() ) 
5449         if ( m_cursorMode 
== WXGRID_CURSOR_RESIZE_ROW 
) 
5451             DoEndDragResizeRow(); 
5453             // Note: we are ending the event *after* doing 
5454             // default processing in this case 
5456             SendEvent( wxEVT_GRID_ROW_SIZE
, m_dragRowOrCol
, -1, event 
); 
5459         ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
, m_rowLabelWin
); 
5463     // ------------ Right button down 
5465     else if ( event
.RightDown() ) 
5469              !SendEvent( wxEVT_GRID_LABEL_RIGHT_CLICK
, row
, -1, event 
) ) 
5471             // no default action at the moment 
5475     // ------------ Right double click 
5477     else if ( event
.RightDClick() ) 
5481              !SendEvent( wxEVT_GRID_LABEL_RIGHT_DCLICK
, row
, -1, event 
) ) 
5483             // no default action at the moment 
5487     // ------------ No buttons down and mouse moving 
5489     else if ( event
.Moving() ) 
5491         m_dragRowOrCol 
= YToEdgeOfRow( y 
); 
5492         if ( m_dragRowOrCol 
>= 0 ) 
5494             if ( m_cursorMode 
== WXGRID_CURSOR_SELECT_CELL 
) 
5496                 // don't capture the mouse yet 
5497                 if ( CanDragRowSize() ) 
5498                     ChangeCursorMode(WXGRID_CURSOR_RESIZE_ROW
, m_rowLabelWin
, false); 
5501         else if ( m_cursorMode 
!= WXGRID_CURSOR_SELECT_CELL 
) 
5503             ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
, m_rowLabelWin
, false); 
5508 void wxGrid::ProcessColLabelMouseEvent( wxMouseEvent
& event 
) 
5511     wxPoint 
pos( event
.GetPosition() ); 
5512     CalcUnscrolledPosition( pos
.x
, pos
.y
, &x
, &y 
); 
5514     if ( event
.Dragging() ) 
5518             m_isDragging 
= true; 
5519             m_colLabelWin
->CaptureMouse(); 
5521             if ( m_cursorMode 
== WXGRID_CURSOR_MOVE_COL 
) 
5522                 m_dragRowOrCol 
= XToCol( x 
); 
5525         if ( event
.LeftIsDown() ) 
5527             switch ( m_cursorMode 
) 
5529                 case WXGRID_CURSOR_RESIZE_COL
: 
5531                     int cw
, ch
, dummy
, top
; 
5532                     m_gridWin
->GetClientSize( &cw
, &ch 
); 
5533                     CalcUnscrolledPosition( 0, 0, &dummy
, &top 
); 
5535                     wxClientDC 
dc( m_gridWin 
); 
5538                     x 
= wxMax( x
, GetColLeft(m_dragRowOrCol
) + 
5539                                   GetColMinimalWidth(m_dragRowOrCol
)); 
5540                     dc
.SetLogicalFunction(wxINVERT
); 
5541                     if ( m_dragLastPos 
>= 0 ) 
5543                         dc
.DrawLine( m_dragLastPos
, top
, m_dragLastPos
, top 
+ ch 
); 
5545                     dc
.DrawLine( x
, top
, x
, top 
+ ch 
); 
5550                 case WXGRID_CURSOR_SELECT_COL
: 
5552                     if ( (col 
= XToCol( x 
)) >= 0 ) 
5556                             m_selection
->SelectCol( col
, 
5557                                                     event
.ControlDown(), 
5566                 case WXGRID_CURSOR_MOVE_COL
: 
5569                         m_moveToCol 
= GetColAt( 0 ); 
5571                         m_moveToCol 
= XToCol( x 
); 
5575                     if ( m_moveToCol 
< 0 ) 
5576                         markerX 
= GetColRight( GetColAt( m_numCols 
- 1 ) ); 
5577                     else if ( x 
>= (GetColLeft( m_moveToCol 
) + (GetColWidth(m_moveToCol
) / 2)) ) 
5579                         m_moveToCol 
= GetColAt( GetColPos( m_moveToCol 
) + 1 ); 
5580                         if ( m_moveToCol 
< 0 ) 
5581                             markerX 
= GetColRight( GetColAt( m_numCols 
- 1 ) ); 
5583                             markerX 
= GetColLeft( m_moveToCol 
); 
5586                         markerX 
= GetColLeft( m_moveToCol 
); 
5588                     if ( markerX 
!= m_dragLastPos 
) 
5590                         wxClientDC 
dc( m_colLabelWin 
); 
5594                         m_colLabelWin
->GetClientSize( &cw
, &ch 
); 
5598                         //Clean up the last indicator 
5599                         if ( m_dragLastPos 
>= 0 ) 
5601                             wxPen 
pen( m_colLabelWin
->GetBackgroundColour(), 2 ); 
5603                             dc
.DrawLine( m_dragLastPos 
+ 1, 0, m_dragLastPos 
+ 1, ch 
); 
5604                             dc
.SetPen(wxNullPen
); 
5606                             if ( XToCol( m_dragLastPos 
) != -1 ) 
5607                                 DrawColLabel( dc
, XToCol( m_dragLastPos 
) ); 
5610                         const wxColour 
*color
; 
5611                         //Moving to the same place? Don't draw a marker 
5612                         if ( (m_moveToCol 
== m_dragRowOrCol
) 
5613                           || (GetColPos( m_moveToCol 
) == GetColPos( m_dragRowOrCol 
) + 1) 
5614                           || (m_moveToCol 
< 0 && m_dragRowOrCol 
== GetColAt( m_numCols 
- 1 ))) 
5615                             color 
= wxLIGHT_GREY
; 
5620                         wxPen 
pen( *color
, 2 ); 
5623                         dc
.DrawLine( markerX
, 0, markerX
, ch 
); 
5625                         dc
.SetPen(wxNullPen
); 
5627                         m_dragLastPos 
= markerX 
- 1; 
5632                 // default label to suppress warnings about "enumeration value 
5633                 // 'xxx' not handled in switch 
5641     if ( m_isDragging 
&& (event
.Entering() || event
.Leaving()) ) 
5646         if (m_colLabelWin
->HasCapture()) 
5647             m_colLabelWin
->ReleaseMouse(); 
5648         m_isDragging 
= false; 
5651     // ------------ Entering or leaving the window 
5653     if ( event
.Entering() || event
.Leaving() ) 
5655         ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
, m_colLabelWin
); 
5658     // ------------ Left button pressed 
5660     else if ( event
.LeftDown() ) 
5662         // don't send a label click event for a hit on the 
5663         // edge of the col label - this is probably the user 
5664         // wanting to resize the col 
5666         if ( XToEdgeOfCol(x
) < 0 ) 
5670                  !SendEvent( wxEVT_GRID_LABEL_LEFT_CLICK
, -1, col
, event 
) ) 
5672                 if ( m_canDragColMove 
) 
5674                     //Show button as pressed 
5675                     wxClientDC 
dc( m_colLabelWin 
); 
5676                     int colLeft 
= GetColLeft( col 
); 
5677                     int colRight 
= GetColRight( col 
) - 1; 
5678                     dc
.SetPen( wxPen( m_colLabelWin
->GetBackgroundColour(), 1 ) ); 
5679                     dc
.DrawLine( colLeft
, 1, colLeft
, m_colLabelHeight
-1 ); 
5680                     dc
.DrawLine( colLeft
, 1, colRight
, 1 ); 
5682                     ChangeCursorMode(WXGRID_CURSOR_MOVE_COL
, m_colLabelWin
); 
5686                     if ( !event
.ShiftDown() && !event
.CmdDown() ) 
5690                         if ( event
.ShiftDown() ) 
5692                             m_selection
->SelectBlock( 0, 
5693                                                       m_currentCellCoords
.GetCol(), 
5694                                                       GetNumberRows() - 1, col
, 
5695                                                       event
.ControlDown(), 
5702                             m_selection
->SelectCol( col
, 
5703                                                     event
.ControlDown(), 
5710                     ChangeCursorMode(WXGRID_CURSOR_SELECT_COL
, m_colLabelWin
); 
5716             // starting to drag-resize a col 
5718             if ( CanDragColSize() ) 
5719                 ChangeCursorMode(WXGRID_CURSOR_RESIZE_COL
, m_colLabelWin
); 
5723     // ------------ Left double click 
5725     if ( event
.LeftDClick() ) 
5727         col 
= XToEdgeOfCol(x
); 
5732                  ! SendEvent( wxEVT_GRID_LABEL_LEFT_DCLICK
, -1, col
, event 
) ) 
5734                 // no default action at the moment 
5739             // adjust column width depending on label text 
5740             AutoSizeColLabelSize( col 
); 
5742             ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
, m_colLabelWin
); 
5747     // ------------ Left button released 
5749     else if ( event
.LeftUp() ) 
5751         switch ( m_cursorMode 
) 
5753             case WXGRID_CURSOR_RESIZE_COL
: 
5754                 DoEndDragResizeCol(); 
5756                 // Note: we are ending the event *after* doing 
5757                 // default processing in this case 
5759                 SendEvent( wxEVT_GRID_COL_SIZE
, -1, m_dragRowOrCol
, event 
); 
5762             case WXGRID_CURSOR_MOVE_COL
: 
5765                 SendEvent( wxEVT_GRID_COL_MOVE
, -1, m_dragRowOrCol
, event 
); 
5768             case WXGRID_CURSOR_SELECT_COL
: 
5769             case WXGRID_CURSOR_SELECT_CELL
: 
5770             case WXGRID_CURSOR_RESIZE_ROW
: 
5771             case WXGRID_CURSOR_SELECT_ROW
: 
5772                 // nothing to do (?) 
5776         ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
, m_colLabelWin
); 
5780     // ------------ Right button down 
5782     else if ( event
.RightDown() ) 
5786              !SendEvent( wxEVT_GRID_LABEL_RIGHT_CLICK
, -1, col
, event 
) ) 
5788             // no default action at the moment 
5792     // ------------ Right double click 
5794     else if ( event
.RightDClick() ) 
5798              !SendEvent( wxEVT_GRID_LABEL_RIGHT_DCLICK
, -1, col
, event 
) ) 
5800             // no default action at the moment 
5804     // ------------ No buttons down and mouse moving 
5806     else if ( event
.Moving() ) 
5808         m_dragRowOrCol 
= XToEdgeOfCol( x 
); 
5809         if ( m_dragRowOrCol 
>= 0 ) 
5811             if ( m_cursorMode 
== WXGRID_CURSOR_SELECT_CELL 
) 
5813                 // don't capture the cursor yet 
5814                 if ( CanDragColSize() ) 
5815                     ChangeCursorMode(WXGRID_CURSOR_RESIZE_COL
, m_colLabelWin
, false); 
5818         else if ( m_cursorMode 
!= WXGRID_CURSOR_SELECT_CELL 
) 
5820             ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
, m_colLabelWin
, false); 
5825 void wxGrid::ProcessCornerLabelMouseEvent( wxMouseEvent
& event 
) 
5827     if ( event
.LeftDown() ) 
5829         // indicate corner label by having both row and 
5832         if ( !SendEvent( wxEVT_GRID_LABEL_LEFT_CLICK
, -1, -1, event 
) ) 
5837     else if ( event
.LeftDClick() ) 
5839         SendEvent( wxEVT_GRID_LABEL_LEFT_DCLICK
, -1, -1, event 
); 
5841     else if ( event
.RightDown() ) 
5843         if ( !SendEvent( wxEVT_GRID_LABEL_RIGHT_CLICK
, -1, -1, event 
) ) 
5845             // no default action at the moment 
5848     else if ( event
.RightDClick() ) 
5850         if ( !SendEvent( wxEVT_GRID_LABEL_RIGHT_DCLICK
, -1, -1, event 
) ) 
5852             // no default action at the moment 
5857 void wxGrid::CancelMouseCapture() 
5859     // cancel operation currently in progress, whatever it is 
5862         m_isDragging 
= false; 
5863         m_cursorMode 
= WXGRID_CURSOR_SELECT_CELL
; 
5864         m_winCapture
->SetCursor( *wxSTANDARD_CURSOR 
); 
5865         m_winCapture 
= NULL
; 
5867         // remove traces of whatever we drew on screen 
5872 void wxGrid::ChangeCursorMode(CursorMode mode
, 
5877     static const wxChar 
*cursorModes
[] = 
5887     wxLogTrace(_T("grid"), 
5888                _T("wxGrid cursor mode (mouse capture for %s): %s -> %s"), 
5889                win 
== m_colLabelWin 
? _T("colLabelWin") 
5890                                     : win 
? _T("rowLabelWin") 
5892                cursorModes
[m_cursorMode
], cursorModes
[mode
]); 
5895     if ( mode 
== m_cursorMode 
&& 
5896          win 
== m_winCapture 
&& 
5897          captureMouse 
== (m_winCapture 
!= NULL
)) 
5902         // by default use the grid itself 
5908         if (m_winCapture
->HasCapture()) 
5909             m_winCapture
->ReleaseMouse(); 
5910         m_winCapture 
= (wxWindow 
*)NULL
; 
5913     m_cursorMode 
= mode
; 
5915     switch ( m_cursorMode 
) 
5917         case WXGRID_CURSOR_RESIZE_ROW
: 
5918             win
->SetCursor( m_rowResizeCursor 
); 
5921         case WXGRID_CURSOR_RESIZE_COL
: 
5922             win
->SetCursor( m_colResizeCursor 
); 
5925         case WXGRID_CURSOR_MOVE_COL
: 
5926             win
->SetCursor( wxCursor(wxCURSOR_HAND
) ); 
5930             win
->SetCursor( *wxSTANDARD_CURSOR 
); 
5934     // we need to capture mouse when resizing 
5935     bool resize 
= m_cursorMode 
== WXGRID_CURSOR_RESIZE_ROW 
|| 
5936                   m_cursorMode 
== WXGRID_CURSOR_RESIZE_COL
; 
5938     if ( captureMouse 
&& resize 
) 
5940         win
->CaptureMouse(); 
5945 void wxGrid::ProcessGridCellMouseEvent( wxMouseEvent
& event 
) 
5948     wxPoint 
pos( event
.GetPosition() ); 
5949     CalcUnscrolledPosition( pos
.x
, pos
.y
, &x
, &y 
); 
5951     wxGridCellCoords coords
; 
5952     XYToCell( x
, y
, coords 
); 
5954     int cell_rows
, cell_cols
; 
5955     bool isFirstDrag 
= !m_isDragging
; 
5956     GetCellSize( coords
.GetRow(), coords
.GetCol(), &cell_rows
, &cell_cols 
); 
5957     if ((cell_rows 
< 0) || (cell_cols 
< 0)) 
5959         coords
.SetRow(coords
.GetRow() + cell_rows
); 
5960         coords
.SetCol(coords
.GetCol() + cell_cols
); 
5963     if ( event
.Dragging() ) 
5965         //wxLogDebug("pos(%d, %d) coords(%d, %d)", pos.x, pos.y, coords.GetRow(), coords.GetCol()); 
5967         // Don't start doing anything until the mouse has been dragged at 
5968         // least 3 pixels in any direction... 
5971             if (m_startDragPos 
== wxDefaultPosition
) 
5973                 m_startDragPos 
= pos
; 
5976             if (abs(m_startDragPos
.x 
- pos
.x
) < 4 && abs(m_startDragPos
.y 
- pos
.y
) < 4) 
5980         m_isDragging 
= true; 
5981         if ( m_cursorMode 
== WXGRID_CURSOR_SELECT_CELL 
) 
5983             // Hide the edit control, so it 
5984             // won't interfere with drag-shrinking. 
5985             if ( IsCellEditControlShown() ) 
5987                 HideCellEditControl(); 
5988                 SaveEditControlValue(); 
5991             if ( coords 
!= wxGridNoCellCoords 
) 
5993                 if ( event
.CmdDown() ) 
5995                     if ( m_selectingKeyboard 
== wxGridNoCellCoords
) 
5996                         m_selectingKeyboard 
= coords
; 
5997                     HighlightBlock( m_selectingKeyboard
, coords 
); 
5999                 else if ( CanDragCell() ) 
6003                         if ( m_selectingKeyboard 
== wxGridNoCellCoords
) 
6004                             m_selectingKeyboard 
= coords
; 
6006                         SendEvent( wxEVT_GRID_CELL_BEGIN_DRAG
, 
6015                     if ( !IsSelection() ) 
6017                         HighlightBlock( coords
, coords 
); 
6021                         HighlightBlock( m_currentCellCoords
, coords 
); 
6025                 if (! IsVisible(coords
)) 
6027                     MakeCellVisible(coords
); 
6028                     // TODO: need to introduce a delay or something here.  The 
6029                     // scrolling is way to fast, at least on MSW - also on GTK. 
6032             // Have we captured the mouse yet? 
6035                 m_winCapture 
= m_gridWin
; 
6036                 m_winCapture
->CaptureMouse(); 
6041         else if ( event
.LeftIsDown() && 
6042                   m_cursorMode 
== WXGRID_CURSOR_RESIZE_ROW 
) 
6044             int cw
, ch
, left
, dummy
; 
6045             m_gridWin
->GetClientSize( &cw
, &ch 
); 
6046             CalcUnscrolledPosition( 0, 0, &left
, &dummy 
); 
6048             wxClientDC 
dc( m_gridWin 
); 
6050             y 
= wxMax( y
, GetRowTop(m_dragRowOrCol
) + 
6051                           GetRowMinimalHeight(m_dragRowOrCol
) ); 
6052             dc
.SetLogicalFunction(wxINVERT
); 
6053             if ( m_dragLastPos 
>= 0 ) 
6055                 dc
.DrawLine( left
, m_dragLastPos
, left
+cw
, m_dragLastPos 
); 
6057             dc
.DrawLine( left
, y
, left
+cw
, y 
); 
6060         else if ( event
.LeftIsDown() && 
6061                   m_cursorMode 
== WXGRID_CURSOR_RESIZE_COL 
) 
6063             int cw
, ch
, dummy
, top
; 
6064             m_gridWin
->GetClientSize( &cw
, &ch 
); 
6065             CalcUnscrolledPosition( 0, 0, &dummy
, &top 
); 
6067             wxClientDC 
dc( m_gridWin 
); 
6069             x 
= wxMax( x
, GetColLeft(m_dragRowOrCol
) + 
6070                           GetColMinimalWidth(m_dragRowOrCol
) ); 
6071             dc
.SetLogicalFunction(wxINVERT
); 
6072             if ( m_dragLastPos 
>= 0 ) 
6074                 dc
.DrawLine( m_dragLastPos
, top
, m_dragLastPos
, top 
+ ch 
); 
6076             dc
.DrawLine( x
, top
, x
, top 
+ ch 
); 
6083     m_isDragging 
= false; 
6084     m_startDragPos 
= wxDefaultPosition
; 
6086     // VZ: if we do this, the mode is reset to WXGRID_CURSOR_SELECT_CELL 
6087     //     immediately after it becomes WXGRID_CURSOR_RESIZE_ROW/COL under 
6090     if ( event
.Entering() || event
.Leaving() ) 
6092         ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
); 
6093         m_gridWin
->SetCursor( *wxSTANDARD_CURSOR 
); 
6098     // ------------ Left button pressed 
6100     if ( event
.LeftDown() && coords 
!= wxGridNoCellCoords 
) 
6102         if ( !SendEvent( wxEVT_GRID_CELL_LEFT_CLICK
, 
6107             if ( !event
.CmdDown() ) 
6109             if ( event
.ShiftDown() ) 
6113                     m_selection
->SelectBlock( m_currentCellCoords
.GetRow(), 
6114                                               m_currentCellCoords
.GetCol(), 
6117                                               event
.ControlDown(), 
6123             else if ( XToEdgeOfCol(x
) < 0 && 
6124                       YToEdgeOfRow(y
) < 0 ) 
6126                 DisableCellEditControl(); 
6127                 MakeCellVisible( coords 
); 
6129                 if ( event
.CmdDown() ) 
6133                         m_selection
->ToggleCellSelection( coords
.GetRow(), 
6135                                                           event
.ControlDown(), 
6140                     m_selectingTopLeft 
= wxGridNoCellCoords
; 
6141                     m_selectingBottomRight 
= wxGridNoCellCoords
; 
6142                     m_selectingKeyboard 
= coords
; 
6146                     m_waitForSlowClick 
= m_currentCellCoords 
== coords 
&& coords 
!= wxGridNoCellCoords
; 
6147                     SetCurrentCell( coords 
); 
6150                         if ( m_selection
->GetSelectionMode() != 
6151                                 wxGrid::wxGridSelectCells 
) 
6153                             HighlightBlock( coords
, coords 
); 
6161     // ------------ Left double click 
6163     else if ( event
.LeftDClick() && coords 
!= wxGridNoCellCoords 
) 
6165         DisableCellEditControl(); 
6167         if ( XToEdgeOfCol(x
) < 0 && YToEdgeOfRow(y
) < 0 ) 
6169             if ( !SendEvent( wxEVT_GRID_CELL_LEFT_DCLICK
, 
6174                 // we want double click to select a cell and start editing 
6175                 // (i.e. to behave in same way as sequence of two slow clicks): 
6176                 m_waitForSlowClick 
= true; 
6181     // ------------ Left button released 
6183     else if ( event
.LeftUp() ) 
6185         if ( m_cursorMode 
== WXGRID_CURSOR_SELECT_CELL 
) 
6189                 if (m_winCapture
->HasCapture()) 
6190                     m_winCapture
->ReleaseMouse(); 
6191                 m_winCapture 
= NULL
; 
6194             if ( coords 
== m_currentCellCoords 
&& m_waitForSlowClick 
&& CanEnableCellControl() ) 
6197                 EnableCellEditControl(); 
6199                 wxGridCellAttr 
*attr 
= GetCellAttr(coords
); 
6200                 wxGridCellEditor 
*editor 
= attr
->GetEditor(this, coords
.GetRow(), coords
.GetCol()); 
6201                 editor
->StartingClick(); 
6205                 m_waitForSlowClick 
= false; 
6207             else if ( m_selectingTopLeft 
!= wxGridNoCellCoords 
&& 
6208                  m_selectingBottomRight 
!= wxGridNoCellCoords 
) 
6212                     m_selection
->SelectBlock( m_selectingTopLeft
.GetRow(), 
6213                                               m_selectingTopLeft
.GetCol(), 
6214                                               m_selectingBottomRight
.GetRow(), 
6215                                               m_selectingBottomRight
.GetCol(), 
6216                                               event
.ControlDown(), 
6222                 m_selectingTopLeft 
= wxGridNoCellCoords
; 
6223                 m_selectingBottomRight 
= wxGridNoCellCoords
; 
6225                 // Show the edit control, if it has been hidden for 
6227                 ShowCellEditControl(); 
6230         else if ( m_cursorMode 
== WXGRID_CURSOR_RESIZE_ROW 
) 
6232             ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
); 
6233             DoEndDragResizeRow(); 
6235             // Note: we are ending the event *after* doing 
6236             // default processing in this case 
6238             SendEvent( wxEVT_GRID_ROW_SIZE
, m_dragRowOrCol
, -1, event 
); 
6240         else if ( m_cursorMode 
== WXGRID_CURSOR_RESIZE_COL 
) 
6242             ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
); 
6243             DoEndDragResizeCol(); 
6245             // Note: we are ending the event *after* doing 
6246             // default processing in this case 
6248             SendEvent( wxEVT_GRID_COL_SIZE
, -1, m_dragRowOrCol
, event 
); 
6254     // ------------ Right button down 
6256     else if ( event
.RightDown() && coords 
!= wxGridNoCellCoords 
) 
6258         DisableCellEditControl(); 
6259         if ( !SendEvent( wxEVT_GRID_CELL_RIGHT_CLICK
, 
6264             // no default action at the moment 
6268     // ------------ Right double click 
6270     else if ( event
.RightDClick() && coords 
!= wxGridNoCellCoords 
) 
6272         DisableCellEditControl(); 
6273         if ( !SendEvent( wxEVT_GRID_CELL_RIGHT_DCLICK
, 
6278             // no default action at the moment 
6282     // ------------ Moving and no button action 
6284     else if ( event
.Moving() && !event
.IsButton() ) 
6286         if ( coords
.GetRow() < 0 || coords
.GetCol() < 0 ) 
6288             // out of grid cell area 
6289             ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
); 
6293         int dragRow 
= YToEdgeOfRow( y 
); 
6294         int dragCol 
= XToEdgeOfCol( x 
); 
6296         // Dragging on the corner of a cell to resize in both 
6297         // directions is not implemented yet... 
6299         if ( dragRow 
>= 0 && dragCol 
>= 0 ) 
6301             ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
); 
6307             m_dragRowOrCol 
= dragRow
; 
6309             if ( m_cursorMode 
== WXGRID_CURSOR_SELECT_CELL 
) 
6311                 if ( CanDragRowSize() && CanDragGridSize() ) 
6312                     ChangeCursorMode(WXGRID_CURSOR_RESIZE_ROW
, NULL
, false); 
6315         else if ( dragCol 
>= 0 ) 
6317             m_dragRowOrCol 
= dragCol
; 
6319             if ( m_cursorMode 
== WXGRID_CURSOR_SELECT_CELL 
) 
6321                 if ( CanDragColSize() && CanDragGridSize() ) 
6322                     ChangeCursorMode(WXGRID_CURSOR_RESIZE_COL
, NULL
, false); 
6325         else // Neither on a row or col edge 
6327             if ( m_cursorMode 
!= WXGRID_CURSOR_SELECT_CELL 
) 
6329                 ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
); 
6335 void wxGrid::DoEndDragResizeRow() 
6337     if ( m_dragLastPos 
>= 0 ) 
6339         // erase the last line and resize the row 
6341         int cw
, ch
, left
, dummy
; 
6342         m_gridWin
->GetClientSize( &cw
, &ch 
); 
6343         CalcUnscrolledPosition( 0, 0, &left
, &dummy 
); 
6345         wxClientDC 
dc( m_gridWin 
); 
6347         dc
.SetLogicalFunction( wxINVERT 
); 
6348         dc
.DrawLine( left
, m_dragLastPos
, left 
+ cw
, m_dragLastPos 
); 
6349         HideCellEditControl(); 
6350         SaveEditControlValue(); 
6352         int rowTop 
= GetRowTop(m_dragRowOrCol
); 
6353         SetRowSize( m_dragRowOrCol
, 
6354                     wxMax( m_dragLastPos 
- rowTop
, m_minAcceptableRowHeight 
) ); 
6356         if ( !GetBatchCount() ) 
6358             // Only needed to get the correct rect.y: 
6359             wxRect 
rect ( CellToRect( m_dragRowOrCol
, 0 ) ); 
6361             CalcScrolledPosition(0, rect
.y
, &dummy
, &rect
.y
); 
6362             rect
.width 
= m_rowLabelWidth
; 
6363             rect
.height 
= ch 
- rect
.y
; 
6364             m_rowLabelWin
->Refresh( true, &rect 
); 
6367             // if there is a multicell block, paint all of it 
6370                 int i
, cell_rows
, cell_cols
, subtract_rows 
= 0; 
6371                 int leftCol 
= XToCol(left
); 
6372                 int rightCol 
= internalXToCol(left 
+ cw
); 
6375                     for (i
=leftCol
; i
<rightCol
; i
++) 
6377                         GetCellSize(m_dragRowOrCol
, i
, &cell_rows
, &cell_cols
); 
6378                         if (cell_rows 
< subtract_rows
) 
6379                             subtract_rows 
= cell_rows
; 
6381                     rect
.y 
= GetRowTop(m_dragRowOrCol 
+ subtract_rows
); 
6382                     CalcScrolledPosition(0, rect
.y
, &dummy
, &rect
.y
); 
6383                     rect
.height 
= ch 
- rect
.y
; 
6386             m_gridWin
->Refresh( false, &rect 
); 
6389         ShowCellEditControl(); 
6394 void wxGrid::DoEndDragResizeCol() 
6396     if ( m_dragLastPos 
>= 0 ) 
6398         // erase the last line and resize the col 
6400         int cw
, ch
, dummy
, top
; 
6401         m_gridWin
->GetClientSize( &cw
, &ch 
); 
6402         CalcUnscrolledPosition( 0, 0, &dummy
, &top 
); 
6404         wxClientDC 
dc( m_gridWin 
); 
6406         dc
.SetLogicalFunction( wxINVERT 
); 
6407         dc
.DrawLine( m_dragLastPos
, top
, m_dragLastPos
, top 
+ ch 
); 
6408         HideCellEditControl(); 
6409         SaveEditControlValue(); 
6411         int colLeft 
= GetColLeft(m_dragRowOrCol
); 
6412         SetColSize( m_dragRowOrCol
, 
6413                     wxMax( m_dragLastPos 
- colLeft
, 
6414                            GetColMinimalWidth(m_dragRowOrCol
) ) ); 
6416         if ( !GetBatchCount() ) 
6418             // Only needed to get the correct rect.x: 
6419             wxRect 
rect ( CellToRect( 0, m_dragRowOrCol 
) ); 
6421             CalcScrolledPosition(rect
.x
, 0, &rect
.x
, &dummy
); 
6422             rect
.width 
= cw 
- rect
.x
; 
6423             rect
.height 
= m_colLabelHeight
; 
6424             m_colLabelWin
->Refresh( true, &rect 
); 
6427             // if there is a multicell block, paint all of it 
6430                 int i
, cell_rows
, cell_cols
, subtract_cols 
= 0; 
6431                 int topRow 
= YToRow(top
); 
6432                 int bottomRow 
= internalYToRow(top 
+ cw
); 
6435                     for (i
=topRow
; i
<bottomRow
; i
++) 
6437                         GetCellSize(i
, m_dragRowOrCol
, &cell_rows
, &cell_cols
); 
6438                         if (cell_cols 
< subtract_cols
) 
6439                             subtract_cols 
= cell_cols
; 
6442                     rect
.x 
= GetColLeft(m_dragRowOrCol 
+ subtract_cols
); 
6443                     CalcScrolledPosition(rect
.x
, 0, &rect
.x
, &dummy
); 
6444                     rect
.width 
= cw 
- rect
.x
; 
6448             m_gridWin
->Refresh( false, &rect 
); 
6451         ShowCellEditControl(); 
6455 void wxGrid::DoEndDragMoveCol() 
6457     //The user clicked on the column but didn't actually drag 
6458     if ( m_dragLastPos 
< 0 ) 
6460         m_colLabelWin
->Refresh();   //Do this to "unpress" the column 
6465     if ( m_moveToCol 
== -1 ) 
6466         newPos 
= m_numCols 
- 1; 
6469         newPos 
= GetColPos( m_moveToCol 
); 
6470         if ( newPos 
> GetColPos( m_dragRowOrCol 
) ) 
6474     SetColPos( m_dragRowOrCol
, newPos 
); 
6477 void wxGrid::SetColPos( int colID
, int newPos 
) 
6479     if ( m_colAt
.IsEmpty() ) 
6481         m_colAt
.Alloc( m_numCols 
); 
6484         for ( i 
= 0; i 
< m_numCols
; i
++ ) 
6490     int oldPos 
= GetColPos( colID 
); 
6492     //Reshuffle the m_colAt array 
6493     if ( newPos 
> oldPos 
) 
6496         for ( i 
= oldPos
; i 
< newPos
; i
++ ) 
6498             m_colAt
[i
] = m_colAt
[i
+1]; 
6504         for ( i 
= oldPos
; i 
> newPos
; i
-- ) 
6506             m_colAt
[i
] = m_colAt
[i
-1]; 
6510     m_colAt
[newPos
] = colID
; 
6512     //Recalculate the column rights 
6513     if ( !m_colWidths
.IsEmpty() ) 
6517         for ( colPos 
= 0; colPos 
< m_numCols
; colPos
++ ) 
6519             int colID 
= GetColAt( colPos 
); 
6521             colRight 
+= m_colWidths
[colID
]; 
6522             m_colRights
[colID
] = colRight
; 
6526     m_colLabelWin
->Refresh(); 
6527     m_gridWin
->Refresh(); 
6532 void wxGrid::EnableDragColMove( bool enable 
) 
6534     if ( m_canDragColMove 
== enable 
) 
6537     m_canDragColMove 
= enable
; 
6539     if ( !m_canDragColMove 
) 
6543         //Recalculate the column rights 
6544         if ( !m_colWidths
.IsEmpty() ) 
6548             for ( colPos 
= 0; colPos 
< m_numCols
; colPos
++ ) 
6550                 colRight 
+= m_colWidths
[colPos
]; 
6551                 m_colRights
[colPos
] = colRight
; 
6555         m_colLabelWin
->Refresh(); 
6556         m_gridWin
->Refresh(); 
6562 // ------ interaction with data model 
6564 bool wxGrid::ProcessTableMessage( wxGridTableMessage
& msg 
) 
6566     switch ( msg
.GetId() ) 
6568         case wxGRIDTABLE_REQUEST_VIEW_GET_VALUES
: 
6569             return GetModelValues(); 
6571         case wxGRIDTABLE_REQUEST_VIEW_SEND_VALUES
: 
6572             return SetModelValues(); 
6574         case wxGRIDTABLE_NOTIFY_ROWS_INSERTED
: 
6575         case wxGRIDTABLE_NOTIFY_ROWS_APPENDED
: 
6576         case wxGRIDTABLE_NOTIFY_ROWS_DELETED
: 
6577         case wxGRIDTABLE_NOTIFY_COLS_INSERTED
: 
6578         case wxGRIDTABLE_NOTIFY_COLS_APPENDED
: 
6579         case wxGRIDTABLE_NOTIFY_COLS_DELETED
: 
6580             return Redimension( msg 
); 
6587 // The behaviour of this function depends on the grid table class 
6588 // Clear() function. For the default wxGridStringTable class the 
6589 // behavious is to replace all cell contents with wxEmptyString but 
6590 // not to change the number of rows or cols. 
6592 void wxGrid::ClearGrid() 
6596         if (IsCellEditControlEnabled()) 
6597             DisableCellEditControl(); 
6600         if (!GetBatchCount()) 
6601             m_gridWin
->Refresh(); 
6605 bool wxGrid::InsertRows( int pos
, int numRows
, bool WXUNUSED(updateLabels
) ) 
6607     // TODO: something with updateLabels flag 
6611         wxFAIL_MSG( wxT("Called wxGrid::InsertRows() before calling CreateGrid()") ); 
6617         if (IsCellEditControlEnabled()) 
6618             DisableCellEditControl(); 
6620         bool done 
= m_table
->InsertRows( pos
, numRows 
); 
6623         // the table will have sent the results of the insert row 
6624         // operation to this view object as a grid table message 
6630 bool wxGrid::AppendRows( int numRows
, bool WXUNUSED(updateLabels
) ) 
6632     // TODO: something with updateLabels flag 
6636         wxFAIL_MSG( wxT("Called wxGrid::AppendRows() before calling CreateGrid()") ); 
6642         bool done 
= m_table 
&& m_table
->AppendRows( numRows 
); 
6645         // the table will have sent the results of the append row 
6646         // operation to this view object as a grid table message 
6652 bool wxGrid::DeleteRows( int pos
, int numRows
, bool WXUNUSED(updateLabels
) ) 
6654     // TODO: something with updateLabels flag 
6658         wxFAIL_MSG( wxT("Called wxGrid::DeleteRows() before calling CreateGrid()") ); 
6664         if (IsCellEditControlEnabled()) 
6665             DisableCellEditControl(); 
6667         bool done 
= m_table
->DeleteRows( pos
, numRows 
); 
6669         // the table will have sent the results of the delete row 
6670         // operation to this view object as a grid table message 
6676 bool wxGrid::InsertCols( int pos
, int numCols
, bool WXUNUSED(updateLabels
) ) 
6678     // TODO: something with updateLabels flag 
6682         wxFAIL_MSG( wxT("Called wxGrid::InsertCols() before calling CreateGrid()") ); 
6688         if (IsCellEditControlEnabled()) 
6689             DisableCellEditControl(); 
6691         bool done 
= m_table
->InsertCols( pos
, numCols 
); 
6693         // the table will have sent the results of the insert col 
6694         // operation to this view object as a grid table message 
6700 bool wxGrid::AppendCols( int numCols
, bool WXUNUSED(updateLabels
) ) 
6702     // TODO: something with updateLabels flag 
6706         wxFAIL_MSG( wxT("Called wxGrid::AppendCols() before calling CreateGrid()") ); 
6712         bool done 
= m_table
->AppendCols( numCols 
); 
6714         // the table will have sent the results of the append col 
6715         // operation to this view object as a grid table message 
6721 bool wxGrid::DeleteCols( int pos
, int numCols
, bool WXUNUSED(updateLabels
) ) 
6723     // TODO: something with updateLabels flag 
6727         wxFAIL_MSG( wxT("Called wxGrid::DeleteCols() before calling CreateGrid()") ); 
6733         if (IsCellEditControlEnabled()) 
6734             DisableCellEditControl(); 
6736         bool done 
= m_table
->DeleteCols( pos
, numCols 
); 
6738         // the table will have sent the results of the delete col 
6739         // operation to this view object as a grid table message 
6746 // ----- event handlers 
6749 // Generate a grid event based on a mouse event and 
6750 // return the result of ProcessEvent() 
6752 int wxGrid::SendEvent( const wxEventType type
, 
6754                         wxMouseEvent
& mouseEv 
) 
6756    bool claimed
, vetoed
; 
6758    if ( type 
== wxEVT_GRID_ROW_SIZE 
|| type 
== wxEVT_GRID_COL_SIZE 
) 
6760        int rowOrCol 
= (row 
== -1 ? col 
: row
); 
6762        wxGridSizeEvent 
gridEvt( GetId(), 
6766                mouseEv
.GetX() + GetRowLabelSize(), 
6767                mouseEv
.GetY() + GetColLabelSize(), 
6768                mouseEv
.ControlDown(), 
6769                mouseEv
.ShiftDown(), 
6771                mouseEv
.MetaDown() ); 
6773        claimed 
= GetEventHandler()->ProcessEvent(gridEvt
); 
6774        vetoed 
= !gridEvt
.IsAllowed(); 
6776    else if ( type 
== wxEVT_GRID_RANGE_SELECT 
) 
6778        // Right now, it should _never_ end up here! 
6779        wxGridRangeSelectEvent 
gridEvt( GetId(), 
6783                m_selectingBottomRight
, 
6785                mouseEv
.ControlDown(), 
6786                mouseEv
.ShiftDown(), 
6788                mouseEv
.MetaDown() ); 
6790        claimed 
= GetEventHandler()->ProcessEvent(gridEvt
); 
6791        vetoed 
= !gridEvt
.IsAllowed(); 
6793    else if ( type 
== wxEVT_GRID_LABEL_LEFT_CLICK 
|| 
6794              type 
== wxEVT_GRID_LABEL_LEFT_DCLICK 
|| 
6795              type 
== wxEVT_GRID_LABEL_RIGHT_CLICK 
|| 
6796              type 
== wxEVT_GRID_LABEL_RIGHT_DCLICK 
) 
6798        wxPoint pos 
= mouseEv
.GetPosition(); 
6800        if ( mouseEv
.GetEventObject() == GetGridRowLabelWindow() ) 
6801            pos
.y 
+= GetColLabelSize(); 
6802        if ( mouseEv
.GetEventObject() == GetGridColLabelWindow() ) 
6803            pos
.x 
+= GetRowLabelSize(); 
6805        wxGridEvent 
gridEvt( GetId(), 
6812                mouseEv
.ControlDown(), 
6813                mouseEv
.ShiftDown(), 
6815                mouseEv
.MetaDown() ); 
6816        claimed 
= GetEventHandler()->ProcessEvent(gridEvt
); 
6817        vetoed 
= !gridEvt
.IsAllowed(); 
6821        wxGridEvent 
gridEvt( GetId(), 
6825                mouseEv
.GetX() + GetRowLabelSize(), 
6826                mouseEv
.GetY() + GetColLabelSize(), 
6828                mouseEv
.ControlDown(), 
6829                mouseEv
.ShiftDown(), 
6831                mouseEv
.MetaDown() ); 
6832        claimed 
= GetEventHandler()->ProcessEvent(gridEvt
); 
6833        vetoed 
= !gridEvt
.IsAllowed(); 
6836    // A Veto'd event may not be `claimed' so test this first 
6840    return claimed 
? 1 : 0; 
6843 // Generate a grid event of specified type and return the result 
6844 // of ProcessEvent(). 
6846 int wxGrid::SendEvent( const wxEventType type
, 
6849    bool claimed
, vetoed
; 
6851     if ( type 
== wxEVT_GRID_ROW_SIZE 
|| type 
== wxEVT_GRID_COL_SIZE 
) 
6853         int rowOrCol 
= (row 
== -1 ? col 
: row
); 
6855         wxGridSizeEvent 
gridEvt( GetId(), type
, this, rowOrCol 
); 
6857         claimed 
= GetEventHandler()->ProcessEvent(gridEvt
); 
6858         vetoed  
= !gridEvt
.IsAllowed(); 
6862         wxGridEvent 
gridEvt( GetId(), type
, this, row
, col 
); 
6864         claimed 
= GetEventHandler()->ProcessEvent(gridEvt
); 
6865         vetoed  
= !gridEvt
.IsAllowed(); 
6868     // A Veto'd event may not be `claimed' so test this first 
6872     return claimed 
? 1 : 0; 
6875 void wxGrid::OnPaint( wxPaintEvent
& WXUNUSED(event
) ) 
6877     // needed to prevent zillions of paint events on MSW 
6881 void wxGrid::Refresh(bool eraseb
, const wxRect
* rect
) 
6883     // Don't do anything if between Begin/EndBatch... 
6884     // EndBatch() will do all this on the last nested one anyway. 
6885     if ( m_created 
&& !GetBatchCount() ) 
6887         // Refresh to get correct scrolled position: 
6888         wxScrolledWindow::Refresh(eraseb
, rect
); 
6892             int rect_x
, rect_y
, rectWidth
, rectHeight
; 
6893             int width_label
, width_cell
, height_label
, height_cell
; 
6896             // Copy rectangle can get scroll offsets.. 
6897             rect_x 
= rect
->GetX(); 
6898             rect_y 
= rect
->GetY(); 
6899             rectWidth 
= rect
->GetWidth(); 
6900             rectHeight 
= rect
->GetHeight(); 
6902             width_label 
= m_rowLabelWidth 
- rect_x
; 
6903             if (width_label 
> rectWidth
) 
6904                 width_label 
= rectWidth
; 
6906             height_label 
= m_colLabelHeight 
- rect_y
; 
6907             if (height_label 
> rectHeight
) 
6908                 height_label 
= rectHeight
; 
6910             if (rect_x 
> m_rowLabelWidth
) 
6912                 x 
= rect_x 
- m_rowLabelWidth
; 
6913                 width_cell 
= rectWidth
; 
6918                 width_cell 
= rectWidth 
- (m_rowLabelWidth 
- rect_x
); 
6921             if (rect_y 
> m_colLabelHeight
) 
6923                 y 
= rect_y 
- m_colLabelHeight
; 
6924                 height_cell 
= rectHeight
; 
6929                 height_cell 
= rectHeight 
- (m_colLabelHeight 
- rect_y
); 
6932             // Paint corner label part intersecting rect. 
6933             if ( width_label 
> 0 && height_label 
> 0 ) 
6935                 wxRect 
anotherrect(rect_x
, rect_y
, width_label
, height_label
); 
6936                 m_cornerLabelWin
->Refresh(eraseb
, &anotherrect
); 
6939             // Paint col labels part intersecting rect. 
6940             if ( width_cell 
> 0 && height_label 
> 0 ) 
6942                 wxRect 
anotherrect(x
, rect_y
, width_cell
, height_label
); 
6943                 m_colLabelWin
->Refresh(eraseb
, &anotherrect
); 
6946             // Paint row labels part intersecting rect. 
6947             if ( width_label 
> 0 && height_cell 
> 0 ) 
6949                 wxRect 
anotherrect(rect_x
, y
, width_label
, height_cell
); 
6950                 m_rowLabelWin
->Refresh(eraseb
, &anotherrect
); 
6953             // Paint cell area part intersecting rect. 
6954             if ( width_cell 
> 0 && height_cell 
> 0 ) 
6956                 wxRect 
anotherrect(x
, y
, width_cell
, height_cell
); 
6957                 m_gridWin
->Refresh(eraseb
, &anotherrect
); 
6962             m_cornerLabelWin
->Refresh(eraseb
, NULL
); 
6963             m_colLabelWin
->Refresh(eraseb
, NULL
); 
6964             m_rowLabelWin
->Refresh(eraseb
, NULL
); 
6965             m_gridWin
->Refresh(eraseb
, NULL
); 
6970 void wxGrid::OnSize(wxSizeEvent
& WXUNUSED(event
)) 
6972     if (m_targetWindow 
!= this) // check whether initialisation has been done 
6974         // reposition our children windows 
6979 void wxGrid::OnKeyDown( wxKeyEvent
& event 
) 
6981     if ( m_inOnKeyDown 
) 
6983         // shouldn't be here - we are going round in circles... 
6985         wxFAIL_MSG( wxT("wxGrid::OnKeyDown called while already active") ); 
6988     m_inOnKeyDown 
= true; 
6990     // propagate the event up and see if it gets processed 
6991     wxWindow 
*parent 
= GetParent(); 
6992     wxKeyEvent 
keyEvt( event 
); 
6993     keyEvt
.SetEventObject( parent 
); 
6995     if ( !parent
->GetEventHandler()->ProcessEvent( keyEvt 
) ) 
6997         if (GetLayoutDirection() == wxLayout_RightToLeft
) 
6999             if (event
.GetKeyCode() == WXK_RIGHT
) 
7000                 event
.m_keyCode 
= WXK_LEFT
; 
7001             else if (event
.GetKeyCode() == WXK_LEFT
) 
7002                 event
.m_keyCode 
= WXK_RIGHT
; 
7005         // try local handlers 
7006         switch ( event
.GetKeyCode() ) 
7009                 if ( event
.ControlDown() ) 
7010                     MoveCursorUpBlock( event
.ShiftDown() ); 
7012                     MoveCursorUp( event
.ShiftDown() ); 
7016                 if ( event
.ControlDown() ) 
7017                     MoveCursorDownBlock( event
.ShiftDown() ); 
7019                     MoveCursorDown( event
.ShiftDown() ); 
7023                 if ( event
.ControlDown() ) 
7024                     MoveCursorLeftBlock( event
.ShiftDown() ); 
7026                     MoveCursorLeft( event
.ShiftDown() ); 
7030                 if ( event
.ControlDown() ) 
7031                     MoveCursorRightBlock( event
.ShiftDown() ); 
7033                     MoveCursorRight( event
.ShiftDown() ); 
7037             case WXK_NUMPAD_ENTER
: 
7038                 if ( event
.ControlDown() ) 
7040                     event
.Skip();  // to let the edit control have the return 
7044                     if ( GetGridCursorRow() < GetNumberRows()-1 ) 
7046                         MoveCursorDown( event
.ShiftDown() ); 
7050                         // at the bottom of a column 
7051                         DisableCellEditControl(); 
7061                 if (event
.ShiftDown()) 
7063                     if ( GetGridCursorCol() > 0 ) 
7065                         MoveCursorLeft( false ); 
7070                         DisableCellEditControl(); 
7075                     if ( GetGridCursorCol() < GetNumberCols() - 1 ) 
7077                         MoveCursorRight( false ); 
7082                         DisableCellEditControl(); 
7088                 if ( event
.ControlDown() ) 
7090                     MakeCellVisible( 0, 0 ); 
7091                     SetCurrentCell( 0, 0 ); 
7100                 if ( event
.ControlDown() ) 
7102                     MakeCellVisible( m_numRows 
- 1, m_numCols 
- 1 ); 
7103                     SetCurrentCell( m_numRows 
- 1, m_numCols 
- 1 ); 
7120                 // Ctrl-Space selects the current column, Shift-Space -- the 
7121                 // current row and Ctrl-Shift-Space -- everything 
7122                 switch ( m_selection 
? event
.GetModifiers() : wxMOD_NONE 
) 
7125                         m_selection
->SelectCol(m_currentCellCoords
.GetCol()); 
7129                         m_selection
->SelectRow(m_currentCellCoords
.GetRow()); 
7132                     case wxMOD_CONTROL 
| wxMOD_SHIFT
: 
7133                         m_selection
->SelectBlock(0, 0, 
7134                                                  m_numRows 
- 1, m_numCols 
- 1); 
7138                         if ( !IsEditable() ) 
7140                             MoveCursorRight(false); 
7143                         //else: fall through 
7156     m_inOnKeyDown 
= false; 
7159 void wxGrid::OnKeyUp( wxKeyEvent
& event 
) 
7161     // try local handlers 
7163     if ( event
.GetKeyCode() == WXK_SHIFT 
) 
7165         if ( m_selectingTopLeft 
!= wxGridNoCellCoords 
&& 
7166              m_selectingBottomRight 
!= wxGridNoCellCoords 
) 
7170                 m_selection
->SelectBlock( 
7171                     m_selectingTopLeft
.GetRow(), 
7172                     m_selectingTopLeft
.GetCol(), 
7173                     m_selectingBottomRight
.GetRow(), 
7174                     m_selectingBottomRight
.GetCol(), 
7175                     event
.ControlDown(), 
7182         m_selectingTopLeft 
= wxGridNoCellCoords
; 
7183         m_selectingBottomRight 
= wxGridNoCellCoords
; 
7184         m_selectingKeyboard 
= wxGridNoCellCoords
; 
7188 void wxGrid::OnChar( wxKeyEvent
& event 
) 
7190     // is it possible to edit the current cell at all? 
7191     if ( !IsCellEditControlEnabled() && CanEnableCellControl() ) 
7193         // yes, now check whether the cells editor accepts the key 
7194         int row 
= m_currentCellCoords
.GetRow(); 
7195         int col 
= m_currentCellCoords
.GetCol(); 
7196         wxGridCellAttr 
*attr 
= GetCellAttr(row
, col
); 
7197         wxGridCellEditor 
*editor 
= attr
->GetEditor(this, row
, col
); 
7199         // <F2> is special and will always start editing, for 
7200         // other keys - ask the editor itself 
7201         if ( (event
.GetKeyCode() == WXK_F2 
&& !event
.HasModifiers()) 
7202              || editor
->IsAcceptedKey(event
) ) 
7204             // ensure cell is visble 
7205             MakeCellVisible(row
, col
); 
7206             EnableCellEditControl(); 
7208             // a problem can arise if the cell is not completely 
7209             // visible (even after calling MakeCellVisible the 
7210             // control is not created and calling StartingKey will 
7212             if ( event
.GetKeyCode() != WXK_F2 
&& editor
->IsCreated() && m_cellEditCtrlEnabled 
) 
7213                 editor
->StartingKey(event
); 
7229 void wxGrid::OnEraseBackground(wxEraseEvent
&) 
7233 void wxGrid::SetCurrentCell( const wxGridCellCoords
& coords 
) 
7235     if ( SendEvent( wxEVT_GRID_SELECT_CELL
, coords
.GetRow(), coords
.GetCol() ) ) 
7237         // the event has been intercepted - do nothing 
7241 #if !defined(__WXMAC__) 
7242     wxClientDC 
dc( m_gridWin 
); 
7246     if ( m_currentCellCoords 
!= wxGridNoCellCoords 
) 
7248         DisableCellEditControl(); 
7250         if ( IsVisible( m_currentCellCoords
, false ) ) 
7253             r 
= BlockToDeviceRect( m_currentCellCoords
, m_currentCellCoords 
); 
7254             if ( !m_gridLinesEnabled 
) 
7262             wxGridCellCoordsArray cells 
= CalcCellsExposed( r 
); 
7264             // Otherwise refresh redraws the highlight! 
7265             m_currentCellCoords 
= coords
; 
7267 #if defined(__WXMAC__) 
7268             m_gridWin
->Refresh(true /*, & r */); 
7270             DrawGridCellArea( dc
, cells 
); 
7271             DrawAllGridLines( dc
, r 
); 
7276     m_currentCellCoords 
= coords
; 
7278     wxGridCellAttr 
*attr 
= GetCellAttr( coords 
); 
7279 #if !defined(__WXMAC__) 
7280     DrawCellHighlight( dc
, attr 
); 
7285 void wxGrid::HighlightBlock( int topRow
, int leftCol
, int bottomRow
, int rightCol 
) 
7288     wxGridCellCoords updateTopLeft
, updateBottomRight
; 
7292         if ( m_selection
->GetSelectionMode() == wxGrid::wxGridSelectRows 
) 
7295             rightCol 
= GetNumberCols() - 1; 
7297         else if ( m_selection
->GetSelectionMode() == wxGrid::wxGridSelectColumns 
) 
7300             bottomRow 
= GetNumberRows() - 1; 
7304     if ( topRow 
> bottomRow 
) 
7311     if ( leftCol 
> rightCol 
) 
7318     updateTopLeft 
= wxGridCellCoords( topRow
, leftCol 
); 
7319     updateBottomRight 
= wxGridCellCoords( bottomRow
, rightCol 
); 
7321     // First the case that we selected a completely new area 
7322     if ( m_selectingTopLeft 
== wxGridNoCellCoords 
|| 
7323          m_selectingBottomRight 
== wxGridNoCellCoords 
) 
7326         rect 
= BlockToDeviceRect( wxGridCellCoords ( topRow
, leftCol 
), 
7327                                   wxGridCellCoords ( bottomRow
, rightCol 
) ); 
7328         m_gridWin
->Refresh( false, &rect 
); 
7331     // Now handle changing an existing selection area. 
7332     else if ( m_selectingTopLeft 
!= updateTopLeft 
|| 
7333               m_selectingBottomRight 
!= updateBottomRight 
) 
7335         // Compute two optimal update rectangles: 
7336         // Either one rectangle is a real subset of the 
7337         // other, or they are (almost) disjoint! 
7339         bool    need_refresh
[4]; 
7343         need_refresh
[3] = false; 
7346         // Store intermediate values 
7347         wxCoord oldLeft 
= m_selectingTopLeft
.GetCol(); 
7348         wxCoord oldTop 
= m_selectingTopLeft
.GetRow(); 
7349         wxCoord oldRight 
= m_selectingBottomRight
.GetCol(); 
7350         wxCoord oldBottom 
= m_selectingBottomRight
.GetRow(); 
7352         // Determine the outer/inner coordinates. 
7353         if (oldLeft 
> leftCol
) 
7359         if (oldTop 
> topRow 
) 
7365         if (oldRight 
< rightCol 
) 
7368             oldRight 
= rightCol
; 
7371         if (oldBottom 
< bottomRow
) 
7374             oldBottom 
= bottomRow
; 
7378         // Now, either the stuff marked old is the outer 
7379         // rectangle or we don't have a situation where one 
7380         // is contained in the other. 
7382         if ( oldLeft 
< leftCol 
) 
7384             // Refresh the newly selected or deselected 
7385             // area to the left of the old or new selection. 
7386             need_refresh
[0] = true; 
7387             rect
[0] = BlockToDeviceRect( 
7388                 wxGridCellCoords( oldTop
,  oldLeft 
), 
7389                 wxGridCellCoords( oldBottom
, leftCol 
- 1 ) ); 
7392         if ( oldTop 
< topRow 
) 
7394             // Refresh the newly selected or deselected 
7395             // area above the old or new selection. 
7396             need_refresh
[1] = true; 
7397             rect
[1] = BlockToDeviceRect( 
7398                 wxGridCellCoords( oldTop
, leftCol 
), 
7399                 wxGridCellCoords( topRow 
- 1, rightCol 
) ); 
7402         if ( oldRight 
> rightCol 
) 
7404             // Refresh the newly selected or deselected 
7405             // area to the right of the old or new selection. 
7406             need_refresh
[2] = true; 
7407             rect
[2] = BlockToDeviceRect( 
7408                 wxGridCellCoords( oldTop
, rightCol 
+ 1 ), 
7409                 wxGridCellCoords( oldBottom
, oldRight 
) ); 
7412         if ( oldBottom 
> bottomRow 
) 
7414             // Refresh the newly selected or deselected 
7415             // area below the old or new selection. 
7416             need_refresh
[3] = true; 
7417             rect
[3] = BlockToDeviceRect( 
7418                 wxGridCellCoords( bottomRow 
+ 1, leftCol 
), 
7419                 wxGridCellCoords( oldBottom
, rightCol 
) ); 
7422         // various Refresh() calls 
7423         for (i 
= 0; i 
< 4; i
++ ) 
7424             if ( need_refresh
[i
] && rect
[i
] != wxGridNoCellRect 
) 
7425                 m_gridWin
->Refresh( false, &(rect
[i
]) ); 
7429     m_selectingTopLeft 
= updateTopLeft
; 
7430     m_selectingBottomRight 
= updateBottomRight
; 
7434 // ------ functions to get/send data (see also public functions) 
7437 bool wxGrid::GetModelValues() 
7439     // Hide the editor, so it won't hide a changed value. 
7440     HideCellEditControl(); 
7444         // all we need to do is repaint the grid 
7446         m_gridWin
->Refresh(); 
7453 bool wxGrid::SetModelValues() 
7457     // Disable the editor, so it won't hide a changed value. 
7458     // Do we also want to save the current value of the editor first? 
7460     DisableCellEditControl(); 
7464         for ( row 
= 0; row 
< m_numRows
; row
++ ) 
7466             for ( col 
= 0; col 
< m_numCols
; col
++ ) 
7468                 m_table
->SetValue( row
, col
, GetCellValue(row
, col
) ); 
7478 // Note - this function only draws cells that are in the list of 
7479 // exposed cells (usually set from the update region by 
7480 // CalcExposedCells) 
7482 void wxGrid::DrawGridCellArea( wxDC
& dc
, const wxGridCellCoordsArray
& cells 
) 
7484     if ( !m_numRows 
|| !m_numCols 
) 
7487     int i
, numCells 
= cells
.GetCount(); 
7488     int row
, col
, cell_rows
, cell_cols
; 
7489     wxGridCellCoordsArray redrawCells
; 
7491     for ( i 
= numCells 
- 1; i 
>= 0; i
-- ) 
7493         row 
= cells
[i
].GetRow(); 
7494         col 
= cells
[i
].GetCol(); 
7495         GetCellSize( row
, col
, &cell_rows
, &cell_cols 
); 
7497         // If this cell is part of a multicell block, find owner for repaint 
7498         if ( cell_rows 
<= 0 || cell_cols 
<= 0 ) 
7500             wxGridCellCoords 
cell( row 
+ cell_rows
, col 
+ cell_cols 
); 
7501             bool marked 
= false; 
7502             for ( int j 
= 0; j 
< numCells
; j
++ ) 
7504                 if ( cell 
== cells
[j
] ) 
7513                 int count 
= redrawCells
.GetCount(); 
7514                 for (int j 
= 0; j 
< count
; j
++) 
7516                     if ( cell 
== redrawCells
[j
] ) 
7524                     redrawCells
.Add( cell 
); 
7527             // don't bother drawing this cell 
7531         // If this cell is empty, find cell to left that might want to overflow 
7532         if (m_table 
&& m_table
->IsEmptyCell(row
, col
)) 
7534             for ( int l 
= 0; l 
< cell_rows
; l
++ ) 
7536                 // find a cell in this row to leave already marked for repaint 
7538                 for (int k 
= 0; k 
< int(redrawCells
.GetCount()); k
++) 
7539                     if ((redrawCells
[k
].GetCol() < left
) && 
7540                         (redrawCells
[k
].GetRow() == row
)) 
7542                         left 
= redrawCells
[k
].GetCol(); 
7546                     left 
= 0; // oh well 
7548                 for (int j 
= col 
- 1; j 
>= left
; j
--) 
7550                     if (!m_table
->IsEmptyCell(row 
+ l
, j
)) 
7552                         if (GetCellOverflow(row 
+ l
, j
)) 
7554                             wxGridCellCoords 
cell(row 
+ l
, j
); 
7555                             bool marked 
= false; 
7557                             for (int k 
= 0; k 
< numCells
; k
++) 
7559                                 if ( cell 
== cells
[k
] ) 
7568                                 int count 
= redrawCells
.GetCount(); 
7569                                 for (int k 
= 0; k 
< count
; k
++) 
7571                                     if ( cell 
== redrawCells
[k
] ) 
7578                                     redrawCells
.Add( cell 
); 
7587         DrawCell( dc
, cells
[i
] ); 
7590     numCells 
= redrawCells
.GetCount(); 
7592     for ( i 
= numCells 
- 1; i 
>= 0; i
-- ) 
7594         DrawCell( dc
, redrawCells
[i
] ); 
7598 void wxGrid::DrawGridSpace( wxDC
& dc 
) 
7601   m_gridWin
->GetClientSize( &cw
, &ch 
); 
7604   CalcUnscrolledPosition( cw
, ch
, &right
, &bottom 
); 
7606   int rightCol 
= m_numCols 
> 0 ? GetColRight(GetColAt( m_numCols 
- 1 )) : 0; 
7607   int bottomRow 
= m_numRows 
> 0 ? GetRowBottom(m_numRows 
- 1) : 0; 
7609   if ( right 
> rightCol 
|| bottom 
> bottomRow 
) 
7612       CalcUnscrolledPosition( 0, 0, &left
, &top 
); 
7614       dc
.SetBrush( wxBrush(GetDefaultCellBackgroundColour(), wxBRUSHSTYLE_SOLID
) ); 
7615       dc
.SetPen( *wxTRANSPARENT_PEN 
); 
7617       if ( right 
> rightCol 
) 
7619           dc
.DrawRectangle( rightCol
, top
, right 
- rightCol
, ch 
); 
7622       if ( bottom 
> bottomRow 
) 
7624           dc
.DrawRectangle( left
, bottomRow
, cw
, bottom 
- bottomRow 
); 
7629 void wxGrid::DrawCell( wxDC
& dc
, const wxGridCellCoords
& coords 
) 
7631     int row 
= coords
.GetRow(); 
7632     int col 
= coords
.GetCol(); 
7634     if ( GetColWidth(col
) <= 0 || GetRowHeight(row
) <= 0 ) 
7637     // we draw the cell border ourselves 
7638 #if !WXGRID_DRAW_LINES 
7639     if ( m_gridLinesEnabled 
) 
7640         DrawCellBorder( dc
, coords 
); 
7643     wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
7645     bool isCurrent 
= coords 
== m_currentCellCoords
; 
7647     wxRect rect 
= CellToRect( row
, col 
); 
7649     // if the editor is shown, we should use it and not the renderer 
7650     // Note: However, only if it is really _shown_, i.e. not hidden! 
7651     if ( isCurrent 
&& IsCellEditControlShown() ) 
7653         // NB: this "#if..." is temporary and fixes a problem where the 
7654         // edit control is erased by this code after being rendered. 
7655         // On wxMac (QD build only), the cell editor is a wxTextCntl and is rendered 
7656         // implicitly, causing this out-of order render. 
7657 #if !defined(__WXMAC__) 
7658         wxGridCellEditor 
*editor 
= attr
->GetEditor(this, row
, col
); 
7659         editor
->PaintBackground(rect
, attr
); 
7665         // but all the rest is drawn by the cell renderer and hence may be customized 
7666         wxGridCellRenderer 
*renderer 
= attr
->GetRenderer(this, row
, col
); 
7667         renderer
->Draw(*this, *attr
, dc
, rect
, row
, col
, IsInSelection(coords
)); 
7674 void wxGrid::DrawCellHighlight( wxDC
& dc
, const wxGridCellAttr 
*attr 
) 
7676     // don't show highlight when the grid doesn't have focus 
7680     int row 
= m_currentCellCoords
.GetRow(); 
7681     int col 
= m_currentCellCoords
.GetCol(); 
7683     if ( GetColWidth(col
) <= 0 || GetRowHeight(row
) <= 0 ) 
7686     wxRect rect 
= CellToRect(row
, col
); 
7688     // hmmm... what could we do here to show that the cell is disabled? 
7689     // for now, I just draw a thinner border than for the other ones, but 
7690     // it doesn't look really good 
7692     int penWidth 
= attr
->IsReadOnly() ? m_cellHighlightROPenWidth 
: m_cellHighlightPenWidth
; 
7696         // The center of the drawn line is where the position/width/height of 
7697         // the rectangle is actually at (on wxMSW at least), so the 
7698         // size of the rectangle is reduced to compensate for the thickness of 
7699         // the line. If this is too strange on non-wxMSW platforms then 
7700         // please #ifdef this appropriately. 
7701         rect
.x 
+= penWidth 
/ 2; 
7702         rect
.y 
+= penWidth 
/ 2; 
7703         rect
.width 
-= penWidth 
- 1; 
7704         rect
.height 
-= penWidth 
- 1; 
7706         // Now draw the rectangle 
7707         // use the cellHighlightColour if the cell is inside a selection, this 
7708         // will ensure the cell is always visible. 
7709         dc
.SetPen(wxPen(IsInSelection(row
,col
) ? m_selectionForeground 
: m_cellHighlightColour
, penWidth
, wxPENSTYLE_SOLID
)); 
7710         dc
.SetBrush(*wxTRANSPARENT_BRUSH
); 
7711         dc
.DrawRectangle(rect
); 
7715         // VZ: my experiments with 3D borders... 
7717         // how to properly set colours for arbitrary bg? 
7718         wxCoord x1 
= rect
.x
, 
7720                 x2 
= rect
.x 
+ rect
.width 
- 1, 
7721                 y2 
= rect
.y 
+ rect
.height 
- 1; 
7723         dc
.SetPen(*wxWHITE_PEN
); 
7724         dc
.DrawLine(x1
, y1
, x2
, y1
); 
7725         dc
.DrawLine(x1
, y1
, x1
, y2
); 
7727         dc
.DrawLine(x1 
+ 1, y2 
- 1, x2 
- 1, y2 
- 1); 
7728         dc
.DrawLine(x2 
- 1, y1 
+ 1, x2 
- 1, y2
); 
7730         dc
.SetPen(*wxBLACK_PEN
); 
7731         dc
.DrawLine(x1
, y2
, x2
, y2
); 
7732         dc
.DrawLine(x2
, y1
, x2
, y2 
+ 1); 
7736 wxPen 
wxGrid::GetDefaultGridLinePen() 
7738     return wxPen(GetGridLineColour(), 1, wxPENSTYLE_SOLID
); 
7741 wxPen 
wxGrid::GetRowGridLinePen(int WXUNUSED(row
)) 
7743     return GetDefaultGridLinePen(); 
7746 wxPen 
wxGrid::GetColGridLinePen(int WXUNUSED(col
)) 
7748     return GetDefaultGridLinePen(); 
7751 void wxGrid::DrawCellBorder( wxDC
& dc
, const wxGridCellCoords
& coords 
) 
7753     int row 
= coords
.GetRow(); 
7754     int col 
= coords
.GetCol(); 
7755     if ( GetColWidth(col
) <= 0 || GetRowHeight(row
) <= 0 ) 
7759     wxRect rect 
= CellToRect( row
, col 
); 
7761     // right hand border 
7762     dc
.SetPen( GetColGridLinePen(col
) ); 
7763     dc
.DrawLine( rect
.x 
+ rect
.width
, rect
.y
, 
7764                  rect
.x 
+ rect
.width
, rect
.y 
+ rect
.height 
+ 1 ); 
7767     dc
.SetPen( GetRowGridLinePen(row
) ); 
7768     dc
.DrawLine( rect
.x
, rect
.y 
+ rect
.height
, 
7769                  rect
.x 
+ rect
.width
, rect
.y 
+ rect
.height
); 
7772 void wxGrid::DrawHighlight(wxDC
& dc
, const wxGridCellCoordsArray
& cells
) 
7774     // This if block was previously in wxGrid::OnPaint but that doesn't 
7775     // seem to get called under wxGTK - MB 
7777     if ( m_currentCellCoords 
== wxGridNoCellCoords 
&& 
7778          m_numRows 
&& m_numCols 
) 
7780         m_currentCellCoords
.Set(0, 0); 
7783     if ( IsCellEditControlShown() ) 
7785         // don't show highlight when the edit control is shown 
7789     // if the active cell was repainted, repaint its highlight too because it 
7790     // might have been damaged by the grid lines 
7791     size_t count 
= cells
.GetCount(); 
7792     for ( size_t n 
= 0; n 
< count
; n
++ ) 
7794         wxGridCellCoords cell 
= cells
[n
]; 
7796         // If we are using attributes, then we may have just exposed another 
7797         // cell in a partially-visible merged cluster of cells. If the "anchor" 
7798         // (upper left) cell of this merged cluster is the cell indicated by 
7799         // m_currentCellCoords, then we need to refresh the cell highlight even 
7800         // though the "anchor" itself is not part of our update segment. 
7801         if ( CanHaveAttributes() ) 
7805             GetCellSize(cell
.GetRow(), cell
.GetCol(), &rows
, &cols
); 
7808                 cell
.SetRow(cell
.GetRow() + rows
); 
7811                 cell
.SetCol(cell
.GetCol() + cols
); 
7814         if ( cell 
== m_currentCellCoords 
) 
7816             wxGridCellAttr
* attr 
= GetCellAttr(m_currentCellCoords
); 
7817             DrawCellHighlight(dc
, attr
); 
7825 // TODO: remove this ??? 
7826 // This is used to redraw all grid lines e.g. when the grid line colour 
7829 void wxGrid::DrawAllGridLines( wxDC
& dc
, const wxRegion 
& WXUNUSED(reg
) ) 
7831 #if !WXGRID_DRAW_LINES 
7835     if ( !m_gridLinesEnabled 
|| !m_numRows 
|| !m_numCols 
) 
7838     int top
, bottom
, left
, right
; 
7840 #if 0  //#ifndef __WXGTK__ 
7844       m_gridWin
->GetClientSize(&cw
, &ch
); 
7846       // virtual coords of visible area 
7848       CalcUnscrolledPosition( 0, 0, &left
, &top 
); 
7849       CalcUnscrolledPosition( cw
, ch
, &right
, &bottom 
); 
7854       reg
.GetBox(x
, y
, w
, h
); 
7855       CalcUnscrolledPosition( x
, y
, &left
, &top 
); 
7856       CalcUnscrolledPosition( x 
+ w
, y 
+ h
, &right
, &bottom 
); 
7860       m_gridWin
->GetClientSize(&cw
, &ch
); 
7861       CalcUnscrolledPosition( 0, 0, &left
, &top 
); 
7862       CalcUnscrolledPosition( cw
, ch
, &right
, &bottom 
); 
7865     // avoid drawing grid lines past the last row and col 
7867     right 
= wxMin( right
, GetColRight(GetColAt( m_numCols 
- 1 )) ); 
7868     bottom 
= wxMin( bottom
, GetRowBottom(m_numRows 
- 1) ); 
7870     // no gridlines inside multicells, clip them out 
7871     int leftCol 
= GetColPos( internalXToCol(left
) ); 
7872     int topRow 
= internalYToRow(top
); 
7873     int rightCol 
= GetColPos( internalXToCol(right
) ); 
7874     int bottomRow 
= internalYToRow(bottom
); 
7876     wxRegion 
clippedcells(0, 0, cw
, ch
); 
7878     int i
, j
, cell_rows
, cell_cols
; 
7881     for (j
=topRow
; j
<=bottomRow
; j
++) 
7884         for (colPos
=leftCol
; colPos
<=rightCol
; colPos
++) 
7886             i 
= GetColAt( colPos 
); 
7888             GetCellSize( j
, i
, &cell_rows
, &cell_cols 
); 
7889             if ((cell_rows 
> 1) || (cell_cols 
> 1)) 
7891                 rect 
= CellToRect(j
,i
); 
7892                 CalcScrolledPosition( rect
.x
, rect
.y
, &rect
.x
, &rect
.y 
); 
7893                 clippedcells
.Subtract(rect
); 
7895             else if ((cell_rows 
< 0) || (cell_cols 
< 0)) 
7897                 rect 
= CellToRect(j 
+ cell_rows
, i 
+ cell_cols
); 
7898                 CalcScrolledPosition( rect
.x
, rect
.y
, &rect
.x
, &rect
.y 
); 
7899                 clippedcells
.Subtract(rect
); 
7904     dc
.SetDeviceClippingRegion( clippedcells 
); 
7907     // horizontal grid lines 
7909     // already declared above - int i; 
7910     for ( i 
= internalYToRow(top
); i 
< m_numRows
; i
++ ) 
7912         int bot 
= GetRowBottom(i
) - 1; 
7921             dc
.SetPen( GetRowGridLinePen(i
) ); 
7922             dc
.DrawLine( left
, bot
, right
, bot 
); 
7926     // vertical grid lines 
7929     for ( colPos 
= leftCol
; colPos 
< m_numCols
; colPos
++ ) 
7931         i 
= GetColAt( colPos 
); 
7933         int colRight 
= GetColRight(i
); 
7935         if (GetLayoutDirection() != wxLayout_RightToLeft
) 
7939         if ( colRight 
> right 
) 
7944         if ( colRight 
>= left 
) 
7946             dc
.SetPen( GetColGridLinePen(i
) ); 
7947             dc
.DrawLine( colRight
, top
, colRight
, bottom 
); 
7951     dc
.DestroyClippingRegion(); 
7954 void wxGrid::DrawRowLabels( wxDC
& dc
, const wxArrayInt
& rows
) 
7960     size_t numLabels 
= rows
.GetCount(); 
7962     for ( i 
= 0; i 
< numLabels
; i
++ ) 
7964         DrawRowLabel( dc
, rows
[i
] ); 
7968 void wxGrid::DrawRowLabel( wxDC
& dc
, int row 
) 
7970     if ( GetRowHeight(row
) <= 0 || m_rowLabelWidth 
<= 0 ) 
7975     int rowTop 
= GetRowTop(row
), 
7976         rowBottom 
= GetRowBottom(row
) - 1; 
7978     dc
.SetPen( wxPen(wxSystemSettings::GetColour(wxSYS_COLOUR_3DSHADOW
), 1, wxPENSTYLE_SOLID
) ); 
7979     dc
.DrawLine( m_rowLabelWidth 
- 1, rowTop
, m_rowLabelWidth 
- 1, rowBottom 
); 
7980     dc
.DrawLine( 0, rowTop
, 0, rowBottom 
); 
7981     dc
.DrawLine( 0, rowBottom
, m_rowLabelWidth
, rowBottom 
); 
7983     dc
.SetPen( *wxWHITE_PEN 
); 
7984     dc
.DrawLine( 1, rowTop
, 1, rowBottom 
); 
7985     dc
.DrawLine( 1, rowTop
, m_rowLabelWidth 
- 1, rowTop 
); 
7987     dc
.SetBackgroundMode( wxBRUSHSTYLE_TRANSPARENT 
); 
7988     dc
.SetTextForeground( GetLabelTextColour() ); 
7989     dc
.SetFont( GetLabelFont() ); 
7992     GetRowLabelAlignment( &hAlign
, &vAlign 
); 
7995     rect
.SetY( GetRowTop(row
) + 2 ); 
7996     rect
.SetWidth( m_rowLabelWidth 
- 4 ); 
7997     rect
.SetHeight( GetRowHeight(row
) - 4 ); 
7998     DrawTextRectangle( dc
, GetRowLabelValue( row 
), rect
, hAlign
, vAlign 
); 
8001 void wxGrid::SetUseNativeColLabels( bool native 
) 
8003     m_nativeColumnLabels 
= native
; 
8006         int height 
= wxRendererNative::Get().GetHeaderButtonHeight( this ); 
8007         SetColLabelSize( height 
); 
8010     m_colLabelWin
->Refresh(); 
8013 void wxGrid::DrawColLabels( wxDC
& dc
,const wxArrayInt
& cols 
) 
8019     size_t numLabels 
= cols
.GetCount(); 
8021     for ( i 
= 0; i 
< numLabels
; i
++ ) 
8023         DrawColLabel( dc
, cols
[i
] ); 
8027 void wxGrid::DrawColLabel( wxDC
& dc
, int col 
) 
8029     if ( GetColWidth(col
) <= 0 || m_colLabelHeight 
<= 0 ) 
8032     int colLeft 
= GetColLeft(col
); 
8036     if (m_nativeColumnLabels
) 
8038         rect
.SetX( colLeft
); 
8040         rect
.SetWidth( GetColWidth(col
)); 
8041         rect
.SetHeight( m_colLabelHeight 
); 
8043         wxWindowDC 
*win_dc 
= (wxWindowDC
*) &dc
; 
8044         wxRendererNative::Get().DrawHeaderButton( win_dc
->GetWindow(), dc
, rect
, 0 ); 
8048         int colRight 
= GetColRight(col
) - 1; 
8050         dc
.SetPen( wxPen(wxSystemSettings::GetColour(wxSYS_COLOUR_3DSHADOW
), 1, wxPENSTYLE_SOLID
) ); 
8051         dc
.DrawLine( colRight
, 0, colRight
, m_colLabelHeight 
- 1 ); 
8052         dc
.DrawLine( colLeft
, 0, colRight
, 0 ); 
8053         dc
.DrawLine( colLeft
, m_colLabelHeight 
- 1, 
8054                  colRight 
+ 1, m_colLabelHeight 
- 1 ); 
8056         dc
.SetPen( *wxWHITE_PEN 
); 
8057         dc
.DrawLine( colLeft
, 1, colLeft
, m_colLabelHeight 
- 1 ); 
8058         dc
.DrawLine( colLeft
, 1, colRight
, 1 ); 
8061     dc
.SetBackgroundMode( wxBRUSHSTYLE_TRANSPARENT 
); 
8062     dc
.SetTextForeground( GetLabelTextColour() ); 
8063     dc
.SetFont( GetLabelFont() ); 
8065     int hAlign
, vAlign
, orient
; 
8066     GetColLabelAlignment( &hAlign
, &vAlign 
); 
8067     orient 
= GetColLabelTextOrientation(); 
8069     rect
.SetX( colLeft 
+ 2 ); 
8071     rect
.SetWidth( GetColWidth(col
) - 4 ); 
8072     rect
.SetHeight( m_colLabelHeight 
- 4 ); 
8073     DrawTextRectangle( dc
, GetColLabelValue( col 
), rect
, hAlign
, vAlign
, orient 
); 
8076 void wxGrid::DrawTextRectangle( wxDC
& dc
, 
8077                                 const wxString
& value
, 
8081                                 int textOrientation 
) 
8083     wxArrayString lines
; 
8085     StringToLines( value
, lines 
); 
8087     // Forward to new API. 
8088     DrawTextRectangle( dc
, 
8096 // VZ: this should be replaced with wxDC::DrawLabel() to which we just have to 
8097 //     add textOrientation support 
8098 void wxGrid::DrawTextRectangle(wxDC
& dc
, 
8099                                const wxArrayString
& lines
, 
8103                                int textOrientation
) 
8105     if ( lines
.empty() ) 
8108     wxDCClipper 
clip(dc
, rect
); 
8113     if ( textOrientation 
== wxHORIZONTAL 
) 
8114         GetTextBoxSize( dc
, lines
, &textWidth
, &textHeight 
); 
8116         GetTextBoxSize( dc
, lines
, &textHeight
, &textWidth 
); 
8120     switch ( vertAlign 
) 
8122         case wxALIGN_BOTTOM
: 
8123             if ( textOrientation 
== wxHORIZONTAL 
) 
8124                 y 
= rect
.y 
+ (rect
.height 
- textHeight 
- 1); 
8126                 x 
= rect
.x 
+ rect
.width 
- textWidth
; 
8129         case wxALIGN_CENTRE
: 
8130             if ( textOrientation 
== wxHORIZONTAL 
) 
8131                 y 
= rect
.y 
+ ((rect
.height 
- textHeight
) / 2); 
8133                 x 
= rect
.x 
+ ((rect
.width 
- textWidth
) / 2); 
8138             if ( textOrientation 
== wxHORIZONTAL 
) 
8145     // Align each line of a multi-line label 
8146     size_t nLines 
= lines
.GetCount(); 
8147     for ( size_t l 
= 0; l 
< nLines
; l
++ ) 
8149         const wxString
& line 
= lines
[l
]; 
8153             *(textOrientation 
== wxHORIZONTAL 
? &y 
: &x
) += dc
.GetCharHeight(); 
8157         wxCoord lineWidth 
= 0, 
8159         dc
.GetTextExtent(line
, &lineWidth
, &lineHeight
); 
8161         switch ( horizAlign 
) 
8164                 if ( textOrientation 
== wxHORIZONTAL 
) 
8165                     x 
= rect
.x 
+ (rect
.width 
- lineWidth 
- 1); 
8167                     y 
= rect
.y 
+ lineWidth 
+ 1; 
8170             case wxALIGN_CENTRE
: 
8171                 if ( textOrientation 
== wxHORIZONTAL 
) 
8172                     x 
= rect
.x 
+ ((rect
.width 
- lineWidth
) / 2); 
8174                     y 
= rect
.y 
+ rect
.height 
- ((rect
.height 
- lineWidth
) / 2); 
8179                 if ( textOrientation 
== wxHORIZONTAL 
) 
8182                     y 
= rect
.y 
+ rect
.height 
- 1; 
8186         if ( textOrientation 
== wxHORIZONTAL 
) 
8188             dc
.DrawText( line
, x
, y 
); 
8193             dc
.DrawRotatedText( line
, x
, y
, 90.0 ); 
8199 // Split multi-line text up into an array of strings. 
8200 // Any existing contents of the string array are preserved. 
8202 // TODO: refactor wxTextFile::Read() and reuse the same code from here 
8203 void wxGrid::StringToLines( const wxString
& value
, wxArrayString
& lines 
) const 
8207     wxString eol 
= wxTextFile::GetEOL( wxTextFileType_Unix 
); 
8208     wxString tVal 
= wxTextFile::Translate( value
, wxTextFileType_Unix 
); 
8210     while ( startPos 
< (int)tVal
.length() ) 
8212         pos 
= tVal
.Mid(startPos
).Find( eol 
); 
8217         else if ( pos 
== 0 ) 
8219             lines
.Add( wxEmptyString 
); 
8223             lines
.Add( tVal
.Mid(startPos
, pos
) ); 
8226         startPos 
+= pos 
+ 1; 
8229     if ( startPos 
< (int)tVal
.length() ) 
8231         lines
.Add( tVal
.Mid( startPos 
) ); 
8235 void wxGrid::GetTextBoxSize( const wxDC
& dc
, 
8236                              const wxArrayString
& lines
, 
8237                              long *width
, long *height 
) const 
8241     wxCoord lineW 
= 0, lineH 
= 0; 
8244     for ( i 
= 0; i 
< lines
.GetCount(); i
++ ) 
8246         dc
.GetTextExtent( lines
[i
], &lineW
, &lineH 
); 
8247         w 
= wxMax( w
, lineW 
); 
8256 // ------ Batch processing. 
8258 void wxGrid::EndBatch() 
8260     if ( m_batchCount 
> 0 ) 
8263         if ( !m_batchCount 
) 
8266             m_rowLabelWin
->Refresh(); 
8267             m_colLabelWin
->Refresh(); 
8268             m_cornerLabelWin
->Refresh(); 
8269             m_gridWin
->Refresh(); 
8274 // Use this, rather than wxWindow::Refresh(), to force an immediate 
8275 // repainting of the grid. Has no effect if you are already inside a 
8276 // BeginBatch / EndBatch block. 
8278 void wxGrid::ForceRefresh() 
8284 bool wxGrid::Enable(bool enable
) 
8286     if ( !wxScrolledWindow::Enable(enable
) ) 
8289     // redraw in the new state 
8290     m_gridWin
->Refresh(); 
8296 // ------ Edit control functions 
8299 void wxGrid::EnableEditing( bool edit 
) 
8301     // TODO: improve this ? 
8303     if ( edit 
!= m_editable 
) 
8306             EnableCellEditControl(edit
); 
8311 void wxGrid::EnableCellEditControl( bool enable 
) 
8316     if ( enable 
!= m_cellEditCtrlEnabled 
) 
8320             if (SendEvent( wxEVT_GRID_EDITOR_SHOWN
) <0) 
8323             // this should be checked by the caller! 
8324             wxASSERT_MSG( CanEnableCellControl(), _T("can't enable editing for this cell!") ); 
8326             // do it before ShowCellEditControl() 
8327             m_cellEditCtrlEnabled 
= enable
; 
8329             ShowCellEditControl(); 
8333             //FIXME:add veto support 
8334             SendEvent( wxEVT_GRID_EDITOR_HIDDEN 
); 
8336             HideCellEditControl(); 
8337             SaveEditControlValue(); 
8339             // do it after HideCellEditControl() 
8340             m_cellEditCtrlEnabled 
= enable
; 
8345 bool wxGrid::IsCurrentCellReadOnly() const 
8348     wxGridCellAttr
* attr 
= ((wxGrid 
*)this)->GetCellAttr(m_currentCellCoords
); 
8349     bool readonly 
= attr
->IsReadOnly(); 
8355 bool wxGrid::CanEnableCellControl() const 
8357     return m_editable 
&& (m_currentCellCoords 
!= wxGridNoCellCoords
) && 
8358         !IsCurrentCellReadOnly(); 
8361 bool wxGrid::IsCellEditControlEnabled() const 
8363     // the cell edit control might be disable for all cells or just for the 
8364     // current one if it's read only 
8365     return m_cellEditCtrlEnabled 
? !IsCurrentCellReadOnly() : false; 
8368 bool wxGrid::IsCellEditControlShown() const 
8370     bool isShown 
= false; 
8372     if ( m_cellEditCtrlEnabled 
) 
8374         int row 
= m_currentCellCoords
.GetRow(); 
8375         int col 
= m_currentCellCoords
.GetCol(); 
8376         wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
8377         wxGridCellEditor
* editor 
= attr
->GetEditor((wxGrid
*) this, row
, col
); 
8382             if ( editor
->IsCreated() ) 
8384                 isShown 
= editor
->GetControl()->IsShown(); 
8394 void wxGrid::ShowCellEditControl() 
8396     if ( IsCellEditControlEnabled() ) 
8398         if ( !IsVisible( m_currentCellCoords
, false ) ) 
8400             m_cellEditCtrlEnabled 
= false; 
8405             wxRect rect 
= CellToRect( m_currentCellCoords 
); 
8406             int row 
= m_currentCellCoords
.GetRow(); 
8407             int col 
= m_currentCellCoords
.GetCol(); 
8409             // if this is part of a multicell, find owner (topleft) 
8410             int cell_rows
, cell_cols
; 
8411             GetCellSize( row
, col
, &cell_rows
, &cell_cols 
); 
8412             if ( cell_rows 
<= 0 || cell_cols 
<= 0 ) 
8416                 m_currentCellCoords
.SetRow( row 
); 
8417                 m_currentCellCoords
.SetCol( col 
); 
8420             // erase the highlight and the cell contents because the editor 
8421             // might not cover the entire cell 
8422             wxClientDC 
dc( m_gridWin 
); 
8424             wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
8425             dc
.SetBrush(wxBrush(attr
->GetBackgroundColour(), wxBRUSHSTYLE_SOLID
)); 
8426             dc
.SetPen(*wxTRANSPARENT_PEN
); 
8427             dc
.DrawRectangle(rect
); 
8429             // convert to scrolled coords 
8430             CalcScrolledPosition( rect
.x
, rect
.y
, &rect
.x
, &rect
.y 
); 
8436             // cell is shifted by one pixel 
8437             // However, don't allow x or y to become negative 
8438             // since the SetSize() method interprets that as 
8445             wxGridCellEditor
* editor 
= attr
->GetEditor(this, row
, col
); 
8446             if ( !editor
->IsCreated() ) 
8448                 editor
->Create(m_gridWin
, wxID_ANY
, 
8449                                new wxGridCellEditorEvtHandler(this, editor
)); 
8451                 wxGridEditorCreatedEvent 
evt(GetId(), 
8452                                              wxEVT_GRID_EDITOR_CREATED
, 
8456                                              editor
->GetControl()); 
8457                 GetEventHandler()->ProcessEvent(evt
); 
8460             // resize editor to overflow into righthand cells if allowed 
8461             int maxWidth 
= rect
.width
; 
8462             wxString value 
= GetCellValue(row
, col
); 
8463             if ( (value 
!= wxEmptyString
) && (attr
->GetOverflow()) ) 
8466                 GetTextExtent(value
, &maxWidth
, &y
, NULL
, NULL
, &attr
->GetFont()); 
8467                 if (maxWidth 
< rect
.width
) 
8468                     maxWidth 
= rect
.width
; 
8471             int client_right 
= m_gridWin
->GetClientSize().GetWidth(); 
8472             if (rect
.x 
+ maxWidth 
> client_right
) 
8473                 maxWidth 
= client_right 
- rect
.x
; 
8475             if ((maxWidth 
> rect
.width
) && (col 
< m_numCols
) && m_table
) 
8477                 GetCellSize( row
, col
, &cell_rows
, &cell_cols 
); 
8478                 // may have changed earlier 
8479                 for (int i 
= col 
+ cell_cols
; i 
< m_numCols
; i
++) 
8482                     GetCellSize( row
, i
, &c_rows
, &c_cols 
); 
8484                     // looks weird going over a multicell 
8485                     if (m_table
->IsEmptyCell( row
, i 
) && 
8486                             (rect
.width 
< maxWidth
) && (c_rows 
== 1)) 
8488                         rect
.width 
+= GetColWidth( i 
); 
8494                 if (rect
.GetRight() > client_right
) 
8495                     rect
.SetRight( client_right 
- 1 ); 
8498             editor
->SetCellAttr( attr 
); 
8499             editor
->SetSize( rect 
); 
8501                 editor
->GetControl()->Move( 
8502                     editor
->GetControl()->GetPosition().x 
+ nXMove
, 
8503                     editor
->GetControl()->GetPosition().y 
); 
8504             editor
->Show( true, attr 
); 
8506             // recalc dimensions in case we need to 
8507             // expand the scrolled window to account for editor 
8510             editor
->BeginEdit(row
, col
, this); 
8511             editor
->SetCellAttr(NULL
); 
8519 void wxGrid::HideCellEditControl() 
8521     if ( IsCellEditControlEnabled() ) 
8523         int row 
= m_currentCellCoords
.GetRow(); 
8524         int col 
= m_currentCellCoords
.GetCol(); 
8526         wxGridCellAttr 
*attr 
= GetCellAttr(row
, col
); 
8527         wxGridCellEditor 
*editor 
= attr
->GetEditor(this, row
, col
); 
8528         const bool editorHadFocus 
= editor
->GetControl()->HasFocus(); 
8529         editor
->Show( false ); 
8533         // return the focus to the grid itself if the editor had it 
8535         // note that we must not do this unconditionally to avoid stealing 
8536         // focus from the window which just received it if we are hiding the 
8537         // editor precisely because we lost focus 
8538         if ( editorHadFocus 
) 
8539             m_gridWin
->SetFocus(); 
8541         // refresh whole row to the right 
8542         wxRect 
rect( CellToRect(row
, col
) ); 
8543         CalcScrolledPosition(rect
.x
, rect
.y
, &rect
.x
, &rect
.y 
); 
8544         rect
.width 
= m_gridWin
->GetClientSize().GetWidth() - rect
.x
; 
8547         // ensure that the pixels under the focus ring get refreshed as well 
8548         rect
.Inflate(10, 10); 
8551         m_gridWin
->Refresh( false, &rect 
); 
8555 void wxGrid::SaveEditControlValue() 
8557     if ( IsCellEditControlEnabled() ) 
8559         int row 
= m_currentCellCoords
.GetRow(); 
8560         int col 
= m_currentCellCoords
.GetCol(); 
8562         wxString oldval 
= GetCellValue(row
, col
); 
8564         wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
8565         wxGridCellEditor
* editor 
= attr
->GetEditor(this, row
, col
); 
8566         bool changed 
= editor
->EndEdit(row
, col
, this); 
8573             if ( SendEvent( wxEVT_GRID_CELL_CHANGE
, 
8574                        m_currentCellCoords
.GetRow(), 
8575                        m_currentCellCoords
.GetCol() ) < 0 ) 
8577                 // Event has been vetoed, set the data back. 
8578                 SetCellValue(row
, col
, oldval
); 
8585 // ------ Grid location functions 
8586 //  Note that all of these functions work with the logical coordinates of 
8587 //  grid cells and labels so you will need to convert from device 
8588 //  coordinates for mouse events etc. 
8591 void wxGrid::XYToCell( int x
, int y
, wxGridCellCoords
& coords 
) const 
8593     int row 
= YToRow(y
); 
8594     int col 
= XToCol(x
); 
8596     if ( row 
== -1 || col 
== -1 ) 
8598         coords 
= wxGridNoCellCoords
; 
8602         coords
.Set( row
, col 
); 
8606 // Internal Helper function for computing row or column from some 
8607 // (unscrolled) coordinate value, using either 
8608 // m_defaultRowHeight/m_defaultColWidth or binary search on array 
8609 // of m_rowBottoms/m_ColRights to speed up the search! 
8611 static int CoordToRowOrCol(int coord
, int defaultDist
, int minDist
, 
8612                            const wxArrayInt
& BorderArray
, int nMax
, 
8616         return clipToMinMax 
&& (nMax 
> 0) ? 0 : -1; 
8621     size_t i_max 
= coord 
/ defaultDist
, 
8624     if (BorderArray
.IsEmpty()) 
8626         if ((int) i_max 
< nMax
) 
8628         return clipToMinMax 
? nMax 
- 1 : -1; 
8631     if ( i_max 
>= BorderArray
.GetCount()) 
8633         i_max 
= BorderArray
.GetCount() - 1; 
8637         if ( coord 
>= BorderArray
[i_max
]) 
8641                 i_max 
= coord 
/ minDist
; 
8643                 i_max 
=  BorderArray
.GetCount() - 1; 
8646         if ( i_max 
>= BorderArray
.GetCount()) 
8647             i_max 
= BorderArray
.GetCount() - 1; 
8650     if ( coord 
>= BorderArray
[i_max
]) 
8651         return clipToMinMax 
? (int)i_max 
: -1; 
8652     if ( coord 
< BorderArray
[0] ) 
8655     while ( i_max 
- i_min 
> 0 ) 
8657         wxCHECK_MSG(BorderArray
[i_min
] <= coord 
&& coord 
< BorderArray
[i_max
], 
8658                     0, _T("wxGrid: internal error in CoordToRowOrCol")); 
8659         if (coord 
>=  BorderArray
[ i_max 
- 1]) 
8663         int median 
= i_min 
+ (i_max 
- i_min 
+ 1) / 2; 
8664         if (coord 
< BorderArray
[median
]) 
8673 int wxGrid::YToRow( int y 
) const 
8675     return CoordToRowOrCol(y
, m_defaultRowHeight
, 
8676                            m_minAcceptableRowHeight
, m_rowBottoms
, m_numRows
, false); 
8679 int wxGrid::XToCol( int x
, bool clipToMinMax 
) const 
8682         return clipToMinMax 
&& (m_numCols 
> 0) ? GetColAt( 0 ) : -1; 
8684     wxASSERT_MSG(m_defaultColWidth 
> 0, wxT("Default column width can not be zero")); 
8686     int maxPos 
= x 
/ m_defaultColWidth
; 
8689     if (m_colRights
.IsEmpty()) 
8691         if(maxPos 
< m_numCols
) 
8692             return GetColAt( maxPos 
); 
8693         return clipToMinMax 
? GetColAt( m_numCols 
- 1 ) : -1; 
8696     if ( maxPos 
>= m_numCols
) 
8697         maxPos 
= m_numCols 
- 1; 
8700         if ( x 
>= m_colRights
[GetColAt( maxPos 
)]) 
8703             if (m_minAcceptableColWidth
) 
8704                 maxPos 
= x 
/ m_minAcceptableColWidth
; 
8706                 maxPos 
=  m_numCols 
- 1; 
8708         if ( maxPos 
>= m_numCols
) 
8709             maxPos 
= m_numCols 
- 1; 
8712     //X is beyond the last column 
8713     if ( x 
>= m_colRights
[GetColAt( maxPos 
)]) 
8714         return clipToMinMax 
? GetColAt( maxPos 
) : -1; 
8716     //X is before the first column 
8717     if ( x 
< m_colRights
[GetColAt( 0 )] ) 
8718         return GetColAt( 0 ); 
8720     //Perform a binary search 
8721     while ( maxPos 
- minPos 
> 0 ) 
8723         wxCHECK_MSG(m_colRights
[GetColAt( minPos 
)] <= x 
&& x 
< m_colRights
[GetColAt( maxPos 
)], 
8724                     0, _T("wxGrid: internal error in XToCol")); 
8726         if (x 
>=  m_colRights
[GetColAt( maxPos 
- 1 )]) 
8727             return GetColAt( maxPos 
); 
8730         int median 
= minPos 
+ (maxPos 
- minPos 
+ 1) / 2; 
8731         if (x 
< m_colRights
[GetColAt( median 
)]) 
8736     return GetColAt( maxPos 
); 
8739 // return the row number that that the y coord is near 
8740 //  the edge of, or -1 if not near an edge. 
8741 // coords can only possibly be near an edge if 
8742 //    (a) the row/column is large enough to still allow for an "inner" area 
8743 //        that is _not_ nead the edge (i.e., if the height/width is smaller 
8744 //        than WXGRID_LABEL_EDGE_ZONE, coords are _never_ considered to be 
8747 //    (b) resizing rows/columns (the thing for which edge detection is 
8748 //        relevant at all) is enabled. 
8750 int wxGrid::YToEdgeOfRow( int y 
) const 
8753     i 
= internalYToRow(y
); 
8755     if ( GetRowHeight(i
) > WXGRID_LABEL_EDGE_ZONE 
&& CanDragRowSize() ) 
8757         // We know that we are in row i, test whether we are 
8758         // close enough to lower or upper border, respectively. 
8759         if ( abs(GetRowBottom(i
) - y
) < WXGRID_LABEL_EDGE_ZONE 
) 
8761         else if ( i 
> 0 && y 
- GetRowTop(i
) < WXGRID_LABEL_EDGE_ZONE 
) 
8768 // return the col number that that the x coord is near the edge of, or 
8769 // -1 if not near an edge 
8770 // See comment at YToEdgeOfRow for conditions on edge detection. 
8772 int wxGrid::XToEdgeOfCol( int x 
) const 
8775     i 
= internalXToCol(x
); 
8777     if ( GetColWidth(i
) > WXGRID_LABEL_EDGE_ZONE 
&& CanDragColSize() ) 
8779         // We know that we are in column i; test whether we are 
8780         // close enough to right or left border, respectively. 
8781         if ( abs(GetColRight(i
) - x
) < WXGRID_LABEL_EDGE_ZONE 
) 
8783         else if ( i 
> 0 && x 
- GetColLeft(i
) < WXGRID_LABEL_EDGE_ZONE 
) 
8790 wxRect 
wxGrid::CellToRect( int row
, int col 
) const 
8792     wxRect 
rect( -1, -1, -1, -1 ); 
8794     if ( row 
>= 0 && row 
< m_numRows 
&& 
8795          col 
>= 0 && col 
< m_numCols 
) 
8797         int i
, cell_rows
, cell_cols
; 
8798         rect
.width 
= rect
.height 
= 0; 
8799         GetCellSize( row
, col
, &cell_rows
, &cell_cols 
); 
8800         // if negative then find multicell owner 
8805         GetCellSize( row
, col
, &cell_rows
, &cell_cols 
); 
8807         rect
.x 
= GetColLeft(col
); 
8808         rect
.y 
= GetRowTop(row
); 
8809         for (i
=col
; i 
< col 
+ cell_cols
; i
++) 
8810             rect
.width 
+= GetColWidth(i
); 
8811         for (i
=row
; i 
< row 
+ cell_rows
; i
++) 
8812             rect
.height 
+= GetRowHeight(i
); 
8815     // if grid lines are enabled, then the area of the cell is a bit smaller 
8816     if (m_gridLinesEnabled
) 
8825 bool wxGrid::IsVisible( int row
, int col
, bool wholeCellVisible 
) const 
8827     // get the cell rectangle in logical coords 
8829     wxRect 
r( CellToRect( row
, col 
) ); 
8831     // convert to device coords 
8833     int left
, top
, right
, bottom
; 
8834     CalcScrolledPosition( r
.GetLeft(), r
.GetTop(), &left
, &top 
); 
8835     CalcScrolledPosition( r
.GetRight(), r
.GetBottom(), &right
, &bottom 
); 
8837     // check against the client area of the grid window 
8839     m_gridWin
->GetClientSize( &cw
, &ch 
); 
8841     if ( wholeCellVisible 
) 
8843         // is the cell wholly visible ? 
8844         return ( left 
>= 0 && right 
<= cw 
&& 
8845                  top 
>= 0 && bottom 
<= ch 
); 
8849         // is the cell partly visible ? 
8851         return ( ((left 
>= 0 && left 
< cw
) || (right 
> 0 && right 
<= cw
)) && 
8852                  ((top 
>= 0 && top 
< ch
) || (bottom 
> 0 && bottom 
<= ch
)) ); 
8856 // make the specified cell location visible by doing a minimal amount 
8859 void wxGrid::MakeCellVisible( int row
, int col 
) 
8862     int xpos 
= -1, ypos 
= -1; 
8864     if ( row 
>= 0 && row 
< m_numRows 
&& 
8865          col 
>= 0 && col 
< m_numCols 
) 
8867         // get the cell rectangle in logical coords 
8868         wxRect 
r( CellToRect( row
, col 
) ); 
8870         // convert to device coords 
8871         int left
, top
, right
, bottom
; 
8872         CalcScrolledPosition( r
.GetLeft(), r
.GetTop(), &left
, &top 
); 
8873         CalcScrolledPosition( r
.GetRight(), r
.GetBottom(), &right
, &bottom 
); 
8876         m_gridWin
->GetClientSize( &cw
, &ch 
); 
8882         else if ( bottom 
> ch 
) 
8884             int h 
= r
.GetHeight(); 
8886             for ( i 
= row 
- 1; i 
>= 0; i
-- ) 
8888                 int rowHeight 
= GetRowHeight(i
); 
8889                 if ( h 
+ rowHeight 
> ch 
) 
8896             // we divide it later by GRID_SCROLL_LINE, make sure that we don't 
8897             // have rounding errors (this is important, because if we do, 
8898             // we might not scroll at all and some cells won't be redrawn) 
8900             // Sometimes GRID_SCROLL_LINE / 2 is not enough, 
8901             // so just add a full scroll unit... 
8902             ypos 
+= m_scrollLineY
; 
8905         // special handling for wide cells - show always left part of the cell! 
8906         // Otherwise, e.g. when stepping from row to row, it would jump between 
8907         // left and right part of the cell on every step! 
8909         if ( left 
< 0 || (right 
- left
) >= cw 
) 
8913         else if ( right 
> cw 
) 
8915             // position the view so that the cell is on the right 
8917             CalcUnscrolledPosition(0, 0, &x0
, &y0
); 
8918             xpos 
= x0 
+ (right 
- cw
); 
8920             // see comment for ypos above 
8921             xpos 
+= m_scrollLineX
; 
8924         if ( xpos 
!= -1 || ypos 
!= -1 ) 
8927                 xpos 
/= m_scrollLineX
; 
8929                 ypos 
/= m_scrollLineY
; 
8930             Scroll( xpos
, ypos 
); 
8937 // ------ Grid cursor movement functions 
8940 bool wxGrid::MoveCursorUp( bool expandSelection 
) 
8942     if ( m_currentCellCoords 
!= wxGridNoCellCoords 
&& 
8943          m_currentCellCoords
.GetRow() >= 0 ) 
8945         if ( expandSelection 
) 
8947             if ( m_selectingKeyboard 
== wxGridNoCellCoords 
) 
8948                 m_selectingKeyboard 
= m_currentCellCoords
; 
8949             if ( m_selectingKeyboard
.GetRow() > 0 ) 
8951                 m_selectingKeyboard
.SetRow( m_selectingKeyboard
.GetRow() - 1 ); 
8952                 MakeCellVisible( m_selectingKeyboard
.GetRow(), 
8953                                  m_selectingKeyboard
.GetCol() ); 
8954                 HighlightBlock( m_currentCellCoords
, m_selectingKeyboard 
); 
8957         else if ( m_currentCellCoords
.GetRow() > 0 ) 
8959             int row 
= m_currentCellCoords
.GetRow() - 1; 
8960             int col 
= m_currentCellCoords
.GetCol(); 
8962             MakeCellVisible( row
, col 
); 
8963             SetCurrentCell( row
, col 
); 
8974 bool wxGrid::MoveCursorDown( bool expandSelection 
) 
8976     if ( m_currentCellCoords 
!= wxGridNoCellCoords 
&& 
8977          m_currentCellCoords
.GetRow() < m_numRows 
) 
8979         if ( expandSelection 
) 
8981             if ( m_selectingKeyboard 
== wxGridNoCellCoords 
) 
8982                 m_selectingKeyboard 
= m_currentCellCoords
; 
8983             if ( m_selectingKeyboard
.GetRow() < m_numRows 
- 1 ) 
8985                 m_selectingKeyboard
.SetRow( m_selectingKeyboard
.GetRow() + 1 ); 
8986                 MakeCellVisible( m_selectingKeyboard
.GetRow(), 
8987                         m_selectingKeyboard
.GetCol() ); 
8988                 HighlightBlock( m_currentCellCoords
, m_selectingKeyboard 
); 
8991         else if ( m_currentCellCoords
.GetRow() < m_numRows 
- 1 ) 
8993             int row 
= m_currentCellCoords
.GetRow() + 1; 
8994             int col 
= m_currentCellCoords
.GetCol(); 
8996             MakeCellVisible( row
, col 
); 
8997             SetCurrentCell( row
, col 
); 
9008 bool wxGrid::MoveCursorLeft( bool expandSelection 
) 
9010     if ( m_currentCellCoords 
!= wxGridNoCellCoords 
&& 
9011          m_currentCellCoords
.GetCol() >= 0 ) 
9013         if ( expandSelection 
) 
9015             if ( m_selectingKeyboard 
== wxGridNoCellCoords 
) 
9016                 m_selectingKeyboard 
= m_currentCellCoords
; 
9017             if ( m_selectingKeyboard
.GetCol() > 0 ) 
9019                 m_selectingKeyboard
.SetCol( m_selectingKeyboard
.GetCol() - 1 ); 
9020                 MakeCellVisible( m_selectingKeyboard
.GetRow(), 
9021                         m_selectingKeyboard
.GetCol() ); 
9022                 HighlightBlock( m_currentCellCoords
, m_selectingKeyboard 
); 
9025         else if ( GetColPos( m_currentCellCoords
.GetCol() ) > 0 ) 
9027             int row 
= m_currentCellCoords
.GetRow(); 
9028             int col 
= GetColAt( GetColPos( m_currentCellCoords
.GetCol() ) - 1 ); 
9031             MakeCellVisible( row
, col 
); 
9032             SetCurrentCell( row
, col 
); 
9043 bool wxGrid::MoveCursorRight( bool expandSelection 
) 
9045     if ( m_currentCellCoords 
!= wxGridNoCellCoords 
&& 
9046          m_currentCellCoords
.GetCol() < m_numCols 
) 
9048         if ( expandSelection 
) 
9050             if ( m_selectingKeyboard 
== wxGridNoCellCoords 
) 
9051                 m_selectingKeyboard 
= m_currentCellCoords
; 
9052             if ( m_selectingKeyboard
.GetCol() < m_numCols 
- 1 ) 
9054                 m_selectingKeyboard
.SetCol( m_selectingKeyboard
.GetCol() + 1 ); 
9055                 MakeCellVisible( m_selectingKeyboard
.GetRow(), 
9056                         m_selectingKeyboard
.GetCol() ); 
9057                 HighlightBlock( m_currentCellCoords
, m_selectingKeyboard 
); 
9060         else if ( GetColPos( m_currentCellCoords
.GetCol() ) < m_numCols 
- 1 ) 
9062             int row 
= m_currentCellCoords
.GetRow(); 
9063             int col 
= GetColAt( GetColPos( m_currentCellCoords
.GetCol() ) + 1 ); 
9066             MakeCellVisible( row
, col 
); 
9067             SetCurrentCell( row
, col 
); 
9078 bool wxGrid::MovePageUp() 
9080     if ( m_currentCellCoords 
== wxGridNoCellCoords 
) 
9083     int row 
= m_currentCellCoords
.GetRow(); 
9087         m_gridWin
->GetClientSize( &cw
, &ch 
); 
9089         int y 
= GetRowTop(row
); 
9090         int newRow 
= internalYToRow( y 
- ch 
+ 1 ); 
9092         if ( newRow 
== row 
) 
9094             // row > 0, so newRow can never be less than 0 here. 
9098         MakeCellVisible( newRow
, m_currentCellCoords
.GetCol() ); 
9099         SetCurrentCell( newRow
, m_currentCellCoords
.GetCol() ); 
9107 bool wxGrid::MovePageDown() 
9109     if ( m_currentCellCoords 
== wxGridNoCellCoords 
) 
9112     int row 
= m_currentCellCoords
.GetRow(); 
9113     if ( (row 
+ 1) < m_numRows 
) 
9116         m_gridWin
->GetClientSize( &cw
, &ch 
); 
9118         int y 
= GetRowTop(row
); 
9119         int newRow 
= internalYToRow( y 
+ ch 
); 
9120         if ( newRow 
== row 
) 
9122             // row < m_numRows, so newRow can't overflow here. 
9126         MakeCellVisible( newRow
, m_currentCellCoords
.GetCol() ); 
9127         SetCurrentCell( newRow
, m_currentCellCoords
.GetCol() ); 
9135 bool wxGrid::MoveCursorUpBlock( bool expandSelection 
) 
9138          m_currentCellCoords 
!= wxGridNoCellCoords 
&& 
9139          m_currentCellCoords
.GetRow() > 0 ) 
9141         int row 
= m_currentCellCoords
.GetRow(); 
9142         int col 
= m_currentCellCoords
.GetCol(); 
9144         if ( m_table
->IsEmptyCell(row
, col
) ) 
9146             // starting in an empty cell: find the next block of 
9152                 if ( !(m_table
->IsEmptyCell(row
, col
)) ) 
9156         else if ( m_table
->IsEmptyCell(row 
- 1, col
) ) 
9158             // starting at the top of a block: find the next block 
9164                 if ( !(m_table
->IsEmptyCell(row
, col
)) ) 
9170             // starting within a block: find the top of the block 
9175                 if ( m_table
->IsEmptyCell(row
, col
) ) 
9183         MakeCellVisible( row
, col 
); 
9184         if ( expandSelection 
) 
9186             m_selectingKeyboard 
= wxGridCellCoords( row
, col 
); 
9187             HighlightBlock( m_currentCellCoords
, m_selectingKeyboard 
); 
9192             SetCurrentCell( row
, col 
); 
9201 bool wxGrid::MoveCursorDownBlock( bool expandSelection 
) 
9204          m_currentCellCoords 
!= wxGridNoCellCoords 
&& 
9205          m_currentCellCoords
.GetRow() < m_numRows 
- 1 ) 
9207         int row 
= m_currentCellCoords
.GetRow(); 
9208         int col 
= m_currentCellCoords
.GetCol(); 
9210         if ( m_table
->IsEmptyCell(row
, col
) ) 
9212             // starting in an empty cell: find the next block of 
9215             while ( row 
< m_numRows 
- 1 ) 
9218                 if ( !(m_table
->IsEmptyCell(row
, col
)) ) 
9222         else if ( m_table
->IsEmptyCell(row 
+ 1, col
) ) 
9224             // starting at the bottom of a block: find the next block 
9227             while ( row 
< m_numRows 
- 1 ) 
9230                 if ( !(m_table
->IsEmptyCell(row
, col
)) ) 
9236             // starting within a block: find the bottom of the block 
9238             while ( row 
< m_numRows 
- 1 ) 
9241                 if ( m_table
->IsEmptyCell(row
, col
) ) 
9249         MakeCellVisible( row
, col 
); 
9250         if ( expandSelection 
) 
9252             m_selectingKeyboard 
= wxGridCellCoords( row
, col 
); 
9253             HighlightBlock( m_currentCellCoords
, m_selectingKeyboard 
); 
9258             SetCurrentCell( row
, col 
); 
9267 bool wxGrid::MoveCursorLeftBlock( bool expandSelection 
) 
9270          m_currentCellCoords 
!= wxGridNoCellCoords 
&& 
9271          m_currentCellCoords
.GetCol() > 0 ) 
9273         int row 
= m_currentCellCoords
.GetRow(); 
9274         int col 
= m_currentCellCoords
.GetCol(); 
9276         if ( m_table
->IsEmptyCell(row
, col
) ) 
9278             // starting in an empty cell: find the next block of 
9284                 if ( !(m_table
->IsEmptyCell(row
, col
)) ) 
9288         else if ( m_table
->IsEmptyCell(row
, col 
- 1) ) 
9290             // starting at the left of a block: find the next block 
9296                 if ( !(m_table
->IsEmptyCell(row
, col
)) ) 
9302             // starting within a block: find the left of the block 
9307                 if ( m_table
->IsEmptyCell(row
, col
) ) 
9315         MakeCellVisible( row
, col 
); 
9316         if ( expandSelection 
) 
9318             m_selectingKeyboard 
= wxGridCellCoords( row
, col 
); 
9319             HighlightBlock( m_currentCellCoords
, m_selectingKeyboard 
); 
9324             SetCurrentCell( row
, col 
); 
9333 bool wxGrid::MoveCursorRightBlock( bool expandSelection 
) 
9336          m_currentCellCoords 
!= wxGridNoCellCoords 
&& 
9337          m_currentCellCoords
.GetCol() < m_numCols 
- 1 ) 
9339         int row 
= m_currentCellCoords
.GetRow(); 
9340         int col 
= m_currentCellCoords
.GetCol(); 
9342         if ( m_table
->IsEmptyCell(row
, col
) ) 
9344             // starting in an empty cell: find the next block of 
9347             while ( col 
< m_numCols 
- 1 ) 
9350                 if ( !(m_table
->IsEmptyCell(row
, col
)) ) 
9354         else if ( m_table
->IsEmptyCell(row
, col 
+ 1) ) 
9356             // starting at the right of a block: find the next block 
9359             while ( col 
< m_numCols 
- 1 ) 
9362                 if ( !(m_table
->IsEmptyCell(row
, col
)) ) 
9368             // starting within a block: find the right of the block 
9370             while ( col 
< m_numCols 
- 1 ) 
9373                 if ( m_table
->IsEmptyCell(row
, col
) ) 
9381         MakeCellVisible( row
, col 
); 
9382         if ( expandSelection 
) 
9384             m_selectingKeyboard 
= wxGridCellCoords( row
, col 
); 
9385             HighlightBlock( m_currentCellCoords
, m_selectingKeyboard 
); 
9390             SetCurrentCell( row
, col 
); 
9400 // ------ Label values and formatting 
9403 void wxGrid::GetRowLabelAlignment( int *horiz
, int *vert 
) const 
9406         *horiz 
= m_rowLabelHorizAlign
; 
9408         *vert  
= m_rowLabelVertAlign
; 
9411 void wxGrid::GetColLabelAlignment( int *horiz
, int *vert 
) const 
9414         *horiz 
= m_colLabelHorizAlign
; 
9416         *vert  
= m_colLabelVertAlign
; 
9419 int wxGrid::GetColLabelTextOrientation() const 
9421     return m_colLabelTextOrientation
; 
9424 wxString 
wxGrid::GetRowLabelValue( int row 
) const 
9428         return m_table
->GetRowLabelValue( row 
); 
9438 wxString 
wxGrid::GetColLabelValue( int col 
) const 
9442         return m_table
->GetColLabelValue( col 
); 
9452 void wxGrid::SetRowLabelSize( int width 
) 
9454     wxASSERT( width 
>= 0 || width 
== wxGRID_AUTOSIZE 
); 
9456     if ( width 
== wxGRID_AUTOSIZE 
) 
9458         width 
= CalcColOrRowLabelAreaMinSize(wxGRID_ROW
); 
9461     if ( width 
!= m_rowLabelWidth 
) 
9465             m_rowLabelWin
->Show( false ); 
9466             m_cornerLabelWin
->Show( false ); 
9468         else if ( m_rowLabelWidth 
== 0 ) 
9470             m_rowLabelWin
->Show( true ); 
9471             if ( m_colLabelHeight 
> 0 ) 
9472                 m_cornerLabelWin
->Show( true ); 
9475         m_rowLabelWidth 
= width
; 
9477         wxScrolledWindow::Refresh( true ); 
9481 void wxGrid::SetColLabelSize( int height 
) 
9483     wxASSERT( height 
>=0 || height 
== wxGRID_AUTOSIZE 
); 
9485     if ( height 
== wxGRID_AUTOSIZE 
) 
9487         height 
= CalcColOrRowLabelAreaMinSize(wxGRID_COLUMN
); 
9490     if ( height 
!= m_colLabelHeight 
) 
9494             m_colLabelWin
->Show( false ); 
9495             m_cornerLabelWin
->Show( false ); 
9497         else if ( m_colLabelHeight 
== 0 ) 
9499             m_colLabelWin
->Show( true ); 
9500             if ( m_rowLabelWidth 
> 0 ) 
9501                 m_cornerLabelWin
->Show( true ); 
9504         m_colLabelHeight 
= height
; 
9506         wxScrolledWindow::Refresh( true ); 
9510 void wxGrid::SetLabelBackgroundColour( const wxColour
& colour 
) 
9512     if ( m_labelBackgroundColour 
!= colour 
) 
9514         m_labelBackgroundColour 
= colour
; 
9515         m_rowLabelWin
->SetBackgroundColour( colour 
); 
9516         m_colLabelWin
->SetBackgroundColour( colour 
); 
9517         m_cornerLabelWin
->SetBackgroundColour( colour 
); 
9519         if ( !GetBatchCount() ) 
9521             m_rowLabelWin
->Refresh(); 
9522             m_colLabelWin
->Refresh(); 
9523             m_cornerLabelWin
->Refresh(); 
9528 void wxGrid::SetLabelTextColour( const wxColour
& colour 
) 
9530     if ( m_labelTextColour 
!= colour 
) 
9532         m_labelTextColour 
= colour
; 
9533         if ( !GetBatchCount() ) 
9535             m_rowLabelWin
->Refresh(); 
9536             m_colLabelWin
->Refresh(); 
9541 void wxGrid::SetLabelFont( const wxFont
& font 
) 
9544     if ( !GetBatchCount() ) 
9546         m_rowLabelWin
->Refresh(); 
9547         m_colLabelWin
->Refresh(); 
9551 void wxGrid::SetRowLabelAlignment( int horiz
, int vert 
) 
9553     // allow old (incorrect) defs to be used 
9556         case wxLEFT
:   horiz 
= wxALIGN_LEFT
; break; 
9557         case wxRIGHT
:  horiz 
= wxALIGN_RIGHT
; break; 
9558         case wxCENTRE
: horiz 
= wxALIGN_CENTRE
; break; 
9563         case wxTOP
:    vert 
= wxALIGN_TOP
;    break; 
9564         case wxBOTTOM
: vert 
= wxALIGN_BOTTOM
; break; 
9565         case wxCENTRE
: vert 
= wxALIGN_CENTRE
; break; 
9568     if ( horiz 
== wxALIGN_LEFT 
|| horiz 
== wxALIGN_CENTRE 
|| horiz 
== wxALIGN_RIGHT 
) 
9570         m_rowLabelHorizAlign 
= horiz
; 
9573     if ( vert 
== wxALIGN_TOP 
|| vert 
== wxALIGN_CENTRE 
|| vert 
== wxALIGN_BOTTOM 
) 
9575         m_rowLabelVertAlign 
= vert
; 
9578     if ( !GetBatchCount() ) 
9580         m_rowLabelWin
->Refresh(); 
9584 void wxGrid::SetColLabelAlignment( int horiz
, int vert 
) 
9586     // allow old (incorrect) defs to be used 
9589         case wxLEFT
:   horiz 
= wxALIGN_LEFT
; break; 
9590         case wxRIGHT
:  horiz 
= wxALIGN_RIGHT
; break; 
9591         case wxCENTRE
: horiz 
= wxALIGN_CENTRE
; break; 
9596         case wxTOP
:    vert 
= wxALIGN_TOP
;    break; 
9597         case wxBOTTOM
: vert 
= wxALIGN_BOTTOM
; break; 
9598         case wxCENTRE
: vert 
= wxALIGN_CENTRE
; break; 
9601     if ( horiz 
== wxALIGN_LEFT 
|| horiz 
== wxALIGN_CENTRE 
|| horiz 
== wxALIGN_RIGHT 
) 
9603         m_colLabelHorizAlign 
= horiz
; 
9606     if ( vert 
== wxALIGN_TOP 
|| vert 
== wxALIGN_CENTRE 
|| vert 
== wxALIGN_BOTTOM 
) 
9608         m_colLabelVertAlign 
= vert
; 
9611     if ( !GetBatchCount() ) 
9613         m_colLabelWin
->Refresh(); 
9617 // Note: under MSW, the default column label font must be changed because it 
9618 //       does not support vertical printing 
9620 // Example: wxFont font(9, wxSWISS, wxNORMAL, wxBOLD); 
9621 //                      pGrid->SetLabelFont(font); 
9622 //                      pGrid->SetColLabelTextOrientation(wxVERTICAL); 
9624 void wxGrid::SetColLabelTextOrientation( int textOrientation 
) 
9626     if ( textOrientation 
== wxHORIZONTAL 
|| textOrientation 
== wxVERTICAL 
) 
9627         m_colLabelTextOrientation 
= textOrientation
; 
9629     if ( !GetBatchCount() ) 
9630         m_colLabelWin
->Refresh(); 
9633 void wxGrid::SetRowLabelValue( int row
, const wxString
& s 
) 
9637         m_table
->SetRowLabelValue( row
, s 
); 
9638         if ( !GetBatchCount() ) 
9640             wxRect rect 
= CellToRect( row
, 0 ); 
9641             if ( rect
.height 
> 0 ) 
9643                 CalcScrolledPosition(0, rect
.y
, &rect
.x
, &rect
.y
); 
9645                 rect
.width 
= m_rowLabelWidth
; 
9646                 m_rowLabelWin
->Refresh( true, &rect 
); 
9652 void wxGrid::SetColLabelValue( int col
, const wxString
& s 
) 
9656         m_table
->SetColLabelValue( col
, s 
); 
9657         if ( !GetBatchCount() ) 
9659             wxRect rect 
= CellToRect( 0, col 
); 
9660             if ( rect
.width 
> 0 ) 
9662                 CalcScrolledPosition(rect
.x
, 0, &rect
.x
, &rect
.y
); 
9664                 rect
.height 
= m_colLabelHeight
; 
9665                 m_colLabelWin
->Refresh( true, &rect 
); 
9671 void wxGrid::SetGridLineColour( const wxColour
& colour 
) 
9673     if ( m_gridLineColour 
!= colour 
) 
9675         m_gridLineColour 
= colour
; 
9677         wxClientDC 
dc( m_gridWin 
); 
9679         DrawAllGridLines( dc
, wxRegion() ); 
9683 void wxGrid::SetCellHighlightColour( const wxColour
& colour 
) 
9685     if ( m_cellHighlightColour 
!= colour 
) 
9687         m_cellHighlightColour 
= colour
; 
9689         wxClientDC 
dc( m_gridWin 
); 
9691         wxGridCellAttr
* attr 
= GetCellAttr(m_currentCellCoords
); 
9692         DrawCellHighlight(dc
, attr
); 
9697 void wxGrid::SetCellHighlightPenWidth(int width
) 
9699     if (m_cellHighlightPenWidth 
!= width
) 
9701         m_cellHighlightPenWidth 
= width
; 
9703         // Just redrawing the cell highlight is not enough since that won't 
9704         // make any visible change if the the thickness is getting smaller. 
9705         int row 
= m_currentCellCoords
.GetRow(); 
9706         int col 
= m_currentCellCoords
.GetCol(); 
9707         if ( row 
== -1 || col 
== -1 || GetColWidth(col
) <= 0 || GetRowHeight(row
) <= 0 ) 
9710         wxRect rect 
= CellToRect(row
, col
); 
9711         m_gridWin
->Refresh(true, &rect
); 
9715 void wxGrid::SetCellHighlightROPenWidth(int width
) 
9717     if (m_cellHighlightROPenWidth 
!= width
) 
9719         m_cellHighlightROPenWidth 
= width
; 
9721         // Just redrawing the cell highlight is not enough since that won't 
9722         // make any visible change if the the thickness is getting smaller. 
9723         int row 
= m_currentCellCoords
.GetRow(); 
9724         int col 
= m_currentCellCoords
.GetCol(); 
9725         if ( row 
== -1 || col 
== -1 || 
9726                 GetColWidth(col
) <= 0 || GetRowHeight(row
) <= 0 ) 
9729         wxRect rect 
= CellToRect(row
, col
); 
9730         m_gridWin
->Refresh(true, &rect
); 
9734 void wxGrid::EnableGridLines( bool enable 
) 
9736     if ( enable 
!= m_gridLinesEnabled 
) 
9738         m_gridLinesEnabled 
= enable
; 
9740         if ( !GetBatchCount() ) 
9744                 wxClientDC 
dc( m_gridWin 
); 
9746                 DrawAllGridLines( dc
, wxRegion() ); 
9750                 m_gridWin
->Refresh(); 
9756 int wxGrid::GetDefaultRowSize() const 
9758     return m_defaultRowHeight
; 
9761 int wxGrid::GetRowSize( int row 
) const 
9763     wxCHECK_MSG( row 
>= 0 && row 
< m_numRows
, 0, _T("invalid row index") ); 
9765     return GetRowHeight(row
); 
9768 int wxGrid::GetDefaultColSize() const 
9770     return m_defaultColWidth
; 
9773 int wxGrid::GetColSize( int col 
) const 
9775     wxCHECK_MSG( col 
>= 0 && col 
< m_numCols
, 0, _T("invalid column index") ); 
9777     return GetColWidth(col
); 
9780 // ============================================================================ 
9781 // access to the grid attributes: each of them has a default value in the grid 
9782 // itself and may be overidden on a per-cell basis 
9783 // ============================================================================ 
9785 // ---------------------------------------------------------------------------- 
9786 // setting default attributes 
9787 // ---------------------------------------------------------------------------- 
9789 void wxGrid::SetDefaultCellBackgroundColour( const wxColour
& col 
) 
9791     m_defaultCellAttr
->SetBackgroundColour(col
); 
9793     m_gridWin
->SetBackgroundColour(col
); 
9797 void wxGrid::SetDefaultCellTextColour( const wxColour
& col 
) 
9799     m_defaultCellAttr
->SetTextColour(col
); 
9802 void wxGrid::SetDefaultCellAlignment( int horiz
, int vert 
) 
9804     m_defaultCellAttr
->SetAlignment(horiz
, vert
); 
9807 void wxGrid::SetDefaultCellOverflow( bool allow 
) 
9809     m_defaultCellAttr
->SetOverflow(allow
); 
9812 void wxGrid::SetDefaultCellFont( const wxFont
& font 
) 
9814     m_defaultCellAttr
->SetFont(font
); 
9817 // For editors and renderers the type registry takes precedence over the 
9818 // default attr, so we need to register the new editor/renderer for the string 
9819 // data type in order to make setting a default editor/renderer appear to 
9822 void wxGrid::SetDefaultRenderer(wxGridCellRenderer 
*renderer
) 
9824     RegisterDataType(wxGRID_VALUE_STRING
, 
9826                      GetDefaultEditorForType(wxGRID_VALUE_STRING
)); 
9829 void wxGrid::SetDefaultEditor(wxGridCellEditor 
*editor
) 
9831     RegisterDataType(wxGRID_VALUE_STRING
, 
9832                      GetDefaultRendererForType(wxGRID_VALUE_STRING
), 
9836 // ---------------------------------------------------------------------------- 
9837 // access to the default attributes 
9838 // ---------------------------------------------------------------------------- 
9840 wxColour 
wxGrid::GetDefaultCellBackgroundColour() const 
9842     return m_defaultCellAttr
->GetBackgroundColour(); 
9845 wxColour 
wxGrid::GetDefaultCellTextColour() const 
9847     return m_defaultCellAttr
->GetTextColour(); 
9850 wxFont 
wxGrid::GetDefaultCellFont() const 
9852     return m_defaultCellAttr
->GetFont(); 
9855 void wxGrid::GetDefaultCellAlignment( int *horiz
, int *vert 
) const 
9857     m_defaultCellAttr
->GetAlignment(horiz
, vert
); 
9860 bool wxGrid::GetDefaultCellOverflow() const 
9862     return m_defaultCellAttr
->GetOverflow(); 
9865 wxGridCellRenderer 
*wxGrid::GetDefaultRenderer() const 
9867     return m_defaultCellAttr
->GetRenderer(NULL
, 0, 0); 
9870 wxGridCellEditor 
*wxGrid::GetDefaultEditor() const 
9872     return m_defaultCellAttr
->GetEditor(NULL
, 0, 0); 
9875 // ---------------------------------------------------------------------------- 
9876 // access to cell attributes 
9877 // ---------------------------------------------------------------------------- 
9879 wxColour 
wxGrid::GetCellBackgroundColour(int row
, int col
) const 
9881     wxGridCellAttr 
*attr 
= GetCellAttr(row
, col
); 
9882     wxColour colour 
= attr
->GetBackgroundColour(); 
9888 wxColour 
wxGrid::GetCellTextColour( int row
, int col 
) const 
9890     wxGridCellAttr 
*attr 
= GetCellAttr(row
, col
); 
9891     wxColour colour 
= attr
->GetTextColour(); 
9897 wxFont 
wxGrid::GetCellFont( int row
, int col 
) const 
9899     wxGridCellAttr 
*attr 
= GetCellAttr(row
, col
); 
9900     wxFont font 
= attr
->GetFont(); 
9906 void wxGrid::GetCellAlignment( int row
, int col
, int *horiz
, int *vert 
) const 
9908     wxGridCellAttr 
*attr 
= GetCellAttr(row
, col
); 
9909     attr
->GetAlignment(horiz
, vert
); 
9913 bool wxGrid::GetCellOverflow( int row
, int col 
) const 
9915     wxGridCellAttr 
*attr 
= GetCellAttr(row
, col
); 
9916     bool allow 
= attr
->GetOverflow(); 
9922 void wxGrid::GetCellSize( int row
, int col
, int *num_rows
, int *num_cols 
) const 
9924     wxGridCellAttr 
*attr 
= GetCellAttr(row
, col
); 
9925     attr
->GetSize( num_rows
, num_cols 
); 
9929 wxGridCellRenderer
* wxGrid::GetCellRenderer(int row
, int col
) const 
9931     wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
9932     wxGridCellRenderer
* renderer 
= attr
->GetRenderer(this, row
, col
); 
9938 wxGridCellEditor
* wxGrid::GetCellEditor(int row
, int col
) const 
9940     wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
9941     wxGridCellEditor
* editor 
= attr
->GetEditor(this, row
, col
); 
9947 bool wxGrid::IsReadOnly(int row
, int col
) const 
9949     wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
9950     bool isReadOnly 
= attr
->IsReadOnly(); 
9956 // ---------------------------------------------------------------------------- 
9957 // attribute support: cache, automatic provider creation, ... 
9958 // ---------------------------------------------------------------------------- 
9960 bool wxGrid::CanHaveAttributes() const 
9967     return m_table
->CanHaveAttributes(); 
9970 void wxGrid::ClearAttrCache() 
9972     if ( m_attrCache
.row 
!= -1 ) 
9974         wxGridCellAttr 
*oldAttr 
= m_attrCache
.attr
; 
9975         m_attrCache
.attr 
= NULL
; 
9976         m_attrCache
.row 
= -1; 
9977         // wxSafeDecRec(...) might cause event processing that accesses 
9978         // the cached attribute, if one exists (e.g. by deleting the 
9979         // editor stored within the attribute). Therefore it is important 
9980         // to invalidate the cache  before calling wxSafeDecRef! 
9981         wxSafeDecRef(oldAttr
); 
9985 void wxGrid::CacheAttr(int row
, int col
, wxGridCellAttr 
*attr
) const 
9989         wxGrid 
*self 
= (wxGrid 
*)this;  // const_cast 
9991         self
->ClearAttrCache(); 
9992         self
->m_attrCache
.row 
= row
; 
9993         self
->m_attrCache
.col 
= col
; 
9994         self
->m_attrCache
.attr 
= attr
; 
9999 bool wxGrid::LookupAttr(int row
, int col
, wxGridCellAttr 
**attr
) const 
10001     if ( row 
== m_attrCache
.row 
&& col 
== m_attrCache
.col 
) 
10003         *attr 
= m_attrCache
.attr
; 
10004         wxSafeIncRef(m_attrCache
.attr
); 
10006 #ifdef DEBUG_ATTR_CACHE 
10007         gs_nAttrCacheHits
++; 
10014 #ifdef DEBUG_ATTR_CACHE 
10015         gs_nAttrCacheMisses
++; 
10022 wxGridCellAttr 
*wxGrid::GetCellAttr(int row
, int col
) const 
10024     wxGridCellAttr 
*attr 
= NULL
; 
10025     // Additional test to avoid looking at the cache e.g. for 
10026     // wxNoCellCoords, as this will confuse memory management. 
10029         if ( !LookupAttr(row
, col
, &attr
) ) 
10031             attr 
= m_table 
? m_table
->GetAttr(row
, col
, wxGridCellAttr::Any
) 
10032                            : (wxGridCellAttr 
*)NULL
; 
10033             CacheAttr(row
, col
, attr
); 
10039         attr
->SetDefAttr(m_defaultCellAttr
); 
10043         attr 
= m_defaultCellAttr
; 
10050 wxGridCellAttr 
*wxGrid::GetOrCreateCellAttr(int row
, int col
) const 
10052     wxGridCellAttr 
*attr 
= (wxGridCellAttr 
*)NULL
; 
10053     bool canHave 
= ((wxGrid
*)this)->CanHaveAttributes(); 
10055     wxCHECK_MSG( canHave
, attr
, _T("Cell attributes not allowed")); 
10056     wxCHECK_MSG( m_table
, attr
, _T("must have a table") ); 
10058     attr 
= m_table
->GetAttr(row
, col
, wxGridCellAttr::Cell
); 
10061         attr 
= new wxGridCellAttr(m_defaultCellAttr
); 
10063         // artificially inc the ref count to match DecRef() in caller 
10065         m_table
->SetAttr(attr
, row
, col
); 
10071 // ---------------------------------------------------------------------------- 
10072 // setting column attributes (wrappers around SetColAttr) 
10073 // ---------------------------------------------------------------------------- 
10075 void wxGrid::SetColFormatBool(int col
) 
10077     SetColFormatCustom(col
, wxGRID_VALUE_BOOL
); 
10080 void wxGrid::SetColFormatNumber(int col
) 
10082     SetColFormatCustom(col
, wxGRID_VALUE_NUMBER
); 
10085 void wxGrid::SetColFormatFloat(int col
, int width
, int precision
) 
10087     wxString typeName 
= wxGRID_VALUE_FLOAT
; 
10088     if ( (width 
!= -1) || (precision 
!= -1) ) 
10090         typeName 
<< _T(':') << width 
<< _T(',') << precision
; 
10093     SetColFormatCustom(col
, typeName
); 
10096 void wxGrid::SetColFormatCustom(int col
, const wxString
& typeName
) 
10098     wxGridCellAttr 
*attr 
= m_table
->GetAttr(-1, col
, wxGridCellAttr::Col 
); 
10100         attr 
= new wxGridCellAttr
; 
10101     wxGridCellRenderer 
*renderer 
= GetDefaultRendererForType(typeName
); 
10102     attr
->SetRenderer(renderer
); 
10103     wxGridCellEditor 
*editor 
= GetDefaultEditorForType(typeName
); 
10104     attr
->SetEditor(editor
); 
10106     SetColAttr(col
, attr
); 
10110 // ---------------------------------------------------------------------------- 
10111 // setting cell attributes: this is forwarded to the table 
10112 // ---------------------------------------------------------------------------- 
10114 void wxGrid::SetAttr(int row
, int col
, wxGridCellAttr 
*attr
) 
10116     if ( CanHaveAttributes() ) 
10118         m_table
->SetAttr(attr
, row
, col
); 
10123         wxSafeDecRef(attr
); 
10127 void wxGrid::SetRowAttr(int row
, wxGridCellAttr 
*attr
) 
10129     if ( CanHaveAttributes() ) 
10131         m_table
->SetRowAttr(attr
, row
); 
10136         wxSafeDecRef(attr
); 
10140 void wxGrid::SetColAttr(int col
, wxGridCellAttr 
*attr
) 
10142     if ( CanHaveAttributes() ) 
10144         m_table
->SetColAttr(attr
, col
); 
10149         wxSafeDecRef(attr
); 
10153 void wxGrid::SetCellBackgroundColour( int row
, int col
, const wxColour
& colour 
) 
10155     if ( CanHaveAttributes() ) 
10157         wxGridCellAttr 
*attr 
= GetOrCreateCellAttr(row
, col
); 
10158         attr
->SetBackgroundColour(colour
); 
10163 void wxGrid::SetCellTextColour( int row
, int col
, const wxColour
& colour 
) 
10165     if ( CanHaveAttributes() ) 
10167         wxGridCellAttr 
*attr 
= GetOrCreateCellAttr(row
, col
); 
10168         attr
->SetTextColour(colour
); 
10173 void wxGrid::SetCellFont( int row
, int col
, const wxFont
& font 
) 
10175     if ( CanHaveAttributes() ) 
10177         wxGridCellAttr 
*attr 
= GetOrCreateCellAttr(row
, col
); 
10178         attr
->SetFont(font
); 
10183 void wxGrid::SetCellAlignment( int row
, int col
, int horiz
, int vert 
) 
10185     if ( CanHaveAttributes() ) 
10187         wxGridCellAttr 
*attr 
= GetOrCreateCellAttr(row
, col
); 
10188         attr
->SetAlignment(horiz
, vert
); 
10193 void wxGrid::SetCellOverflow( int row
, int col
, bool allow 
) 
10195     if ( CanHaveAttributes() ) 
10197         wxGridCellAttr 
*attr 
= GetOrCreateCellAttr(row
, col
); 
10198         attr
->SetOverflow(allow
); 
10203 void wxGrid::SetCellSize( int row
, int col
, int num_rows
, int num_cols 
) 
10205     if ( CanHaveAttributes() ) 
10207         int cell_rows
, cell_cols
; 
10209         wxGridCellAttr 
*attr 
= GetOrCreateCellAttr(row
, col
); 
10210         attr
->GetSize(&cell_rows
, &cell_cols
); 
10211         attr
->SetSize(num_rows
, num_cols
); 
10214         // Cannot set the size of a cell to 0 or negative values 
10215         // While it is perfectly legal to do that, this function cannot 
10216         // handle all the possibilies, do it by hand by getting the CellAttr. 
10217         // You can only set the size of a cell to 1,1 or greater with this fn 
10218         wxASSERT_MSG( !((cell_rows 
< 1) || (cell_cols 
< 1)), 
10219                       wxT("wxGrid::SetCellSize setting cell size that is already part of another cell")); 
10220         wxASSERT_MSG( !((num_rows 
< 1) || (num_cols 
< 1)), 
10221                       wxT("wxGrid::SetCellSize setting cell size to < 1")); 
10223         // if this was already a multicell then "turn off" the other cells first 
10224         if ((cell_rows 
> 1) || (cell_cols 
> 1)) 
10227             for (j
=row
; j 
< row 
+ cell_rows
; j
++) 
10229                 for (i
=col
; i 
< col 
+ cell_cols
; i
++) 
10231                     if ((i 
!= col
) || (j 
!= row
)) 
10233                         wxGridCellAttr 
*attr_stub 
= GetOrCreateCellAttr(j
, i
); 
10234                         attr_stub
->SetSize( 1, 1 ); 
10235                         attr_stub
->DecRef(); 
10241         // mark the cells that will be covered by this cell to 
10242         // negative or zero values to point back at this cell 
10243         if (((num_rows 
> 1) || (num_cols 
> 1)) && (num_rows 
>= 1) && (num_cols 
>= 1)) 
10246             for (j
=row
; j 
< row 
+ num_rows
; j
++) 
10248                 for (i
=col
; i 
< col 
+ num_cols
; i
++) 
10250                     if ((i 
!= col
) || (j 
!= row
)) 
10252                         wxGridCellAttr 
*attr_stub 
= GetOrCreateCellAttr(j
, i
); 
10253                         attr_stub
->SetSize( row 
- j
, col 
- i 
); 
10254                         attr_stub
->DecRef(); 
10262 void wxGrid::SetCellRenderer(int row
, int col
, wxGridCellRenderer 
*renderer
) 
10264     if ( CanHaveAttributes() ) 
10266         wxGridCellAttr 
*attr 
= GetOrCreateCellAttr(row
, col
); 
10267         attr
->SetRenderer(renderer
); 
10272 void wxGrid::SetCellEditor(int row
, int col
, wxGridCellEditor
* editor
) 
10274     if ( CanHaveAttributes() ) 
10276         wxGridCellAttr 
*attr 
= GetOrCreateCellAttr(row
, col
); 
10277         attr
->SetEditor(editor
); 
10282 void wxGrid::SetReadOnly(int row
, int col
, bool isReadOnly
) 
10284     if ( CanHaveAttributes() ) 
10286         wxGridCellAttr 
*attr 
= GetOrCreateCellAttr(row
, col
); 
10287         attr
->SetReadOnly(isReadOnly
); 
10292 // ---------------------------------------------------------------------------- 
10293 // Data type registration 
10294 // ---------------------------------------------------------------------------- 
10296 void wxGrid::RegisterDataType(const wxString
& typeName
, 
10297                               wxGridCellRenderer
* renderer
, 
10298                               wxGridCellEditor
* editor
) 
10300     m_typeRegistry
->RegisterDataType(typeName
, renderer
, editor
); 
10304 wxGridCellEditor 
* wxGrid::GetDefaultEditorForCell(int row
, int col
) const 
10306     wxString typeName 
= m_table
->GetTypeName(row
, col
); 
10307     return GetDefaultEditorForType(typeName
); 
10310 wxGridCellRenderer 
* wxGrid::GetDefaultRendererForCell(int row
, int col
) const 
10312     wxString typeName 
= m_table
->GetTypeName(row
, col
); 
10313     return GetDefaultRendererForType(typeName
); 
10316 wxGridCellEditor 
* wxGrid::GetDefaultEditorForType(const wxString
& typeName
) const 
10318     int index 
= m_typeRegistry
->FindOrCloneDataType(typeName
); 
10319     if ( index 
== wxNOT_FOUND 
) 
10321         wxFAIL_MSG(wxString::Format(wxT("Unknown data type name [%s]"), typeName
.c_str())); 
10326     return m_typeRegistry
->GetEditor(index
); 
10329 wxGridCellRenderer 
* wxGrid::GetDefaultRendererForType(const wxString
& typeName
) const 
10331     int index 
= m_typeRegistry
->FindOrCloneDataType(typeName
); 
10332     if ( index 
== wxNOT_FOUND 
) 
10334         wxFAIL_MSG(wxString::Format(wxT("Unknown data type name [%s]"), typeName
.c_str())); 
10339     return m_typeRegistry
->GetRenderer(index
); 
10342 // ---------------------------------------------------------------------------- 
10344 // ---------------------------------------------------------------------------- 
10346 void wxGrid::EnableDragRowSize( bool enable 
) 
10348     m_canDragRowSize 
= enable
; 
10351 void wxGrid::EnableDragColSize( bool enable 
) 
10353     m_canDragColSize 
= enable
; 
10356 void wxGrid::EnableDragGridSize( bool enable 
) 
10358     m_canDragGridSize 
= enable
; 
10361 void wxGrid::EnableDragCell( bool enable 
) 
10363     m_canDragCell 
= enable
; 
10366 void wxGrid::SetDefaultRowSize( int height
, bool resizeExistingRows 
) 
10368     m_defaultRowHeight 
= wxMax( height
, m_minAcceptableRowHeight 
); 
10370     if ( resizeExistingRows 
) 
10372         // since we are resizing all rows to the default row size, 
10373         // we can simply clear the row heights and row bottoms 
10374         // arrays (which also allows us to take advantage of 
10375         // some speed optimisations) 
10376         m_rowHeights
.Empty(); 
10377         m_rowBottoms
.Empty(); 
10378         if ( !GetBatchCount() ) 
10383 void wxGrid::SetRowSize( int row
, int height 
) 
10385     wxCHECK_RET( row 
>= 0 && row 
< m_numRows
, _T("invalid row index") ); 
10387     // if < 0 then calculate new height from label 
10391         wxArrayString lines
; 
10392         wxClientDC 
dc(m_rowLabelWin
); 
10393         dc
.SetFont(GetLabelFont()); 
10394         StringToLines(GetRowLabelValue( row 
), lines
); 
10395         GetTextBoxSize( dc
, lines
, &w
, &h 
); 
10396         //check that it is not less than the minimal height 
10397         height 
= wxMax(h
, GetRowMinimalAcceptableHeight()); 
10400     // See comment in SetColSize 
10401     if ( height 
< GetRowMinimalAcceptableHeight()) 
10404     if ( m_rowHeights
.IsEmpty() ) 
10406         // need to really create the array 
10410     int h 
= wxMax( 0, height 
); 
10411     int diff 
= h 
- m_rowHeights
[row
]; 
10413     m_rowHeights
[row
] = h
; 
10414     for ( int i 
= row
; i 
< m_numRows
; i
++ ) 
10416         m_rowBottoms
[i
] += diff
; 
10419     if ( !GetBatchCount() ) 
10423 void wxGrid::SetDefaultColSize( int width
, bool resizeExistingCols 
) 
10425     // we dont allow zero default column width 
10426     m_defaultColWidth 
= wxMax( wxMax( width
, m_minAcceptableColWidth 
), 1 ); 
10428     if ( resizeExistingCols 
) 
10430         // since we are resizing all columns to the default column size, 
10431         // we can simply clear the col widths and col rights 
10432         // arrays (which also allows us to take advantage of 
10433         // some speed optimisations) 
10434         m_colWidths
.Empty(); 
10435         m_colRights
.Empty(); 
10436         if ( !GetBatchCount() ) 
10441 void wxGrid::SetColSize( int col
, int width 
) 
10443     wxCHECK_RET( col 
>= 0 && col 
< m_numCols
, _T("invalid column index") ); 
10445     // if < 0 then calculate new width from label 
10449         wxArrayString lines
; 
10450         wxClientDC 
dc(m_colLabelWin
); 
10451         dc
.SetFont(GetLabelFont()); 
10452         StringToLines(GetColLabelValue(col
), lines
); 
10453         if ( GetColLabelTextOrientation() == wxHORIZONTAL 
) 
10454             GetTextBoxSize( dc
, lines
, &w
, &h 
); 
10456             GetTextBoxSize( dc
, lines
, &h
, &w 
); 
10458         //check that it is not less than the minimal width 
10459         width 
= wxMax(width
, GetColMinimalAcceptableWidth()); 
10462     // should we check that it's bigger than GetColMinimalWidth(col) here? 
10464     // No, because it is reasonable to assume the library user know's 
10465     // what he is doing. However we should test against the weaker 
10466     // constraint of minimalAcceptableWidth, as this breaks rendering 
10468     // This test then fixes sf.net bug #645734 
10470     if ( width 
< GetColMinimalAcceptableWidth() ) 
10473     if ( m_colWidths
.IsEmpty() ) 
10475         // need to really create the array 
10479     int w 
= wxMax( 0, width 
); 
10480     int diff 
= w 
- m_colWidths
[col
]; 
10481     m_colWidths
[col
] = w
; 
10483     for ( int colPos 
= GetColPos(col
); colPos 
< m_numCols
; colPos
++ ) 
10485         m_colRights
[GetColAt(colPos
)] += diff
; 
10488     if ( !GetBatchCount() ) 
10492 void wxGrid::SetColMinimalWidth( int col
, int width 
) 
10494     if (width 
> GetColMinimalAcceptableWidth()) 
10496         wxLongToLongHashMap::key_type key 
= (wxLongToLongHashMap::key_type
)col
; 
10497         m_colMinWidths
[key
] = width
; 
10501 void wxGrid::SetRowMinimalHeight( int row
, int width 
) 
10503     if (width 
> GetRowMinimalAcceptableHeight()) 
10505         wxLongToLongHashMap::key_type key 
= (wxLongToLongHashMap::key_type
)row
; 
10506         m_rowMinHeights
[key
] = width
; 
10510 int wxGrid::GetColMinimalWidth(int col
) const 
10512     wxLongToLongHashMap::key_type key 
= (wxLongToLongHashMap::key_type
)col
; 
10513     wxLongToLongHashMap::const_iterator it 
= m_colMinWidths
.find(key
); 
10515     return it 
!= m_colMinWidths
.end() ? (int)it
->second 
: m_minAcceptableColWidth
; 
10518 int wxGrid::GetRowMinimalHeight(int row
) const 
10520     wxLongToLongHashMap::key_type key 
= (wxLongToLongHashMap::key_type
)row
; 
10521     wxLongToLongHashMap::const_iterator it 
= m_rowMinHeights
.find(key
); 
10523     return it 
!= m_rowMinHeights
.end() ? (int)it
->second 
: m_minAcceptableRowHeight
; 
10526 void wxGrid::SetColMinimalAcceptableWidth( int width 
) 
10528     // We do allow a width of 0 since this gives us 
10529     // an easy way to temporarily hiding columns. 
10531         m_minAcceptableColWidth 
= width
; 
10534 void wxGrid::SetRowMinimalAcceptableHeight( int height 
) 
10536     // We do allow a height of 0 since this gives us 
10537     // an easy way to temporarily hiding rows. 
10539         m_minAcceptableRowHeight 
= height
; 
10542 int  wxGrid::GetColMinimalAcceptableWidth() const 
10544     return m_minAcceptableColWidth
; 
10547 int  wxGrid::GetRowMinimalAcceptableHeight() const 
10549     return m_minAcceptableRowHeight
; 
10552 // ---------------------------------------------------------------------------- 
10554 // ---------------------------------------------------------------------------- 
10557 wxGrid::AutoSizeColOrRow(int colOrRow
, bool setAsMin
, wxGridDirection direction
) 
10559     const bool column 
= direction 
== wxGRID_COLUMN
; 
10561     wxClientDC 
dc(m_gridWin
); 
10563     // cancel editing of cell 
10564     HideCellEditControl(); 
10565     SaveEditControlValue(); 
10567     // init both of them to avoid compiler warnings, even if we only need one 
10575     wxCoord extent
, extentMax 
= 0; 
10576     int max 
= column 
? m_numRows 
: m_numCols
; 
10577     for ( int rowOrCol 
= 0; rowOrCol 
< max
; rowOrCol
++ ) 
10584         wxGridCellAttr 
*attr 
= GetCellAttr(row
, col
); 
10585         wxGridCellRenderer 
*renderer 
= attr
->GetRenderer(this, row
, col
); 
10588             wxSize size 
= renderer
->GetBestSize(*this, *attr
, dc
, row
, col
); 
10589             extent 
= column 
? size
.x 
: size
.y
; 
10590             if ( extent 
> extentMax 
) 
10591                 extentMax 
= extent
; 
10593             renderer
->DecRef(); 
10599     // now also compare with the column label extent 
10601     dc
.SetFont( GetLabelFont() ); 
10605         dc
.GetMultiLineTextExtent( GetColLabelValue(col
), &w
, &h 
); 
10606         if ( GetColLabelTextOrientation() == wxVERTICAL 
) 
10610         dc
.GetMultiLineTextExtent( GetRowLabelValue(row
), &w
, &h 
); 
10612     extent 
= column 
? w 
: h
; 
10613     if ( extent 
> extentMax 
) 
10614         extentMax 
= extent
; 
10618         // empty column - give default extent (notice that if extentMax is less 
10619         // than default extent but != 0, it's OK) 
10620         extentMax 
= column 
? m_defaultColWidth 
: m_defaultRowHeight
; 
10625             // leave some space around text 
10633         // Ensure automatic width is not less than minimal width. See the 
10634         // comment in SetColSize() for explanation of why this isn't done 
10635         // in SetColSize(). 
10637             extentMax 
= wxMax(extentMax
, GetColMinimalWidth(col
)); 
10639         SetColSize( col
, extentMax 
); 
10640         if ( !GetBatchCount() ) 
10643             m_gridWin
->GetClientSize( &cw
, &ch 
); 
10644             wxRect 
rect ( CellToRect( 0, col 
) ); 
10646             CalcScrolledPosition(rect
.x
, 0, &rect
.x
, &dummy
); 
10647             rect
.width 
= cw 
- rect
.x
; 
10648             rect
.height 
= m_colLabelHeight
; 
10649             m_colLabelWin
->Refresh( true, &rect 
); 
10654         // Ensure automatic width is not less than minimal height. See the 
10655         // comment in SetColSize() for explanation of why this isn't done 
10656         // in SetRowSize(). 
10658             extentMax 
= wxMax(extentMax
, GetRowMinimalHeight(row
)); 
10660         SetRowSize(row
, extentMax
); 
10661         if ( !GetBatchCount() ) 
10664             m_gridWin
->GetClientSize( &cw
, &ch 
); 
10665             wxRect 
rect( CellToRect( row
, 0 ) ); 
10667             CalcScrolledPosition(0, rect
.y
, &dummy
, &rect
.y
); 
10668             rect
.width 
= m_rowLabelWidth
; 
10669             rect
.height 
= ch 
- rect
.y
; 
10670             m_rowLabelWin
->Refresh( true, &rect 
); 
10677             SetColMinimalWidth(col
, extentMax
); 
10679             SetRowMinimalHeight(row
, extentMax
); 
10683 wxCoord 
wxGrid::CalcColOrRowLabelAreaMinSize(wxGridDirection direction
) 
10685     // calculate size for the rows or columns? 
10686     const bool calcRows 
= direction 
== wxGRID_ROW
; 
10688     wxClientDC 
dc(calcRows 
? GetGridRowLabelWindow() 
10689                            : GetGridColLabelWindow()); 
10690     dc
.SetFont(GetLabelFont()); 
10692     // which dimension should we take into account for calculations? 
10694     // for columns, the text can be only horizontal so it's easy but for rows 
10695     // we also have to take into account the text orientation 
10697         useWidth 
= calcRows 
|| (GetColLabelTextOrientation() == wxVERTICAL
); 
10699     wxArrayString lines
; 
10700     wxCoord extentMax 
= 0; 
10702     const int numRowsOrCols 
= calcRows 
? m_numRows 
: m_numCols
; 
10703     for ( int rowOrCol 
= 0; rowOrCol 
< numRowsOrCols
; rowOrCol
++ ) 
10707         wxString label 
= calcRows 
? GetRowLabelValue(rowOrCol
) 
10708                                   : GetColLabelValue(rowOrCol
); 
10709         StringToLines(label
, lines
); 
10712         GetTextBoxSize(dc
, lines
, &w
, &h
); 
10714         const wxCoord extent 
= useWidth 
? w 
: h
; 
10715         if ( extent 
> extentMax 
) 
10716             extentMax 
= extent
; 
10721         // empty column - give default extent (notice that if extentMax is less 
10722         // than default extent but != 0, it's OK) 
10723         extentMax 
= calcRows 
? GetDefaultRowLabelSize() 
10724                              : GetDefaultColLabelSize(); 
10727     // leave some space around text (taken from AutoSizeColOrRow) 
10736 int wxGrid::SetOrCalcColumnSizes(bool calcOnly
, bool setAsMin
) 
10738     int width 
= m_rowLabelWidth
; 
10740     wxGridUpdateLocker locker
; 
10742         locker
.Create(this); 
10744     for ( int col 
= 0; col 
< m_numCols
; col
++ ) 
10747             AutoSizeColumn(col
, setAsMin
); 
10749         width 
+= GetColWidth(col
); 
10755 int wxGrid::SetOrCalcRowSizes(bool calcOnly
, bool setAsMin
) 
10757     int height 
= m_colLabelHeight
; 
10759     wxGridUpdateLocker locker
; 
10761         locker
.Create(this); 
10763     for ( int row 
= 0; row 
< m_numRows
; row
++ ) 
10766             AutoSizeRow(row
, setAsMin
); 
10768         height 
+= GetRowHeight(row
); 
10774 void wxGrid::AutoSize() 
10776     wxGridUpdateLocker 
locker(this); 
10778     wxSize 
size(SetOrCalcColumnSizes(false) - m_rowLabelWidth 
+ m_extraWidth
, 
10779                 SetOrCalcRowSizes(false) - m_colLabelHeight 
+ m_extraHeight
); 
10781     // we know that we're not going to have scrollbars so disable them now to 
10782     // avoid trouble in SetClientSize() which can otherwise set the correct 
10783     // client size but also leave space for (not needed any more) scrollbars 
10784     SetScrollbars(0, 0, 0, 0, 0, 0, true); 
10786     // restore the scroll rate parameters overwritten by SetScrollbars() 
10787     SetScrollRate(m_scrollLineX
, m_scrollLineY
); 
10789     SetClientSize(size
.x 
+ m_rowLabelWidth
, size
.y 
+ m_colLabelHeight
); 
10792 void wxGrid::AutoSizeRowLabelSize( int row 
) 
10794     // Hide the edit control, so it 
10795     // won't interfere with drag-shrinking. 
10796     if ( IsCellEditControlShown() ) 
10798         HideCellEditControl(); 
10799         SaveEditControlValue(); 
10802     // autosize row height depending on label text 
10803     SetRowSize(row
, -1); 
10807 void wxGrid::AutoSizeColLabelSize( int col 
) 
10809     // Hide the edit control, so it 
10810     // won't interfere with drag-shrinking. 
10811     if ( IsCellEditControlShown() ) 
10813         HideCellEditControl(); 
10814         SaveEditControlValue(); 
10817     // autosize column width depending on label text 
10818     SetColSize(col
, -1); 
10822 wxSize 
wxGrid::DoGetBestSize() const 
10824     wxGrid 
*self 
= (wxGrid 
*)this;  // const_cast 
10826     // we do the same as in AutoSize() here with the exception that we don't 
10827     // change the column/row sizes, only calculate them 
10828     wxSize 
size(self
->SetOrCalcColumnSizes(true) - m_rowLabelWidth 
+ m_extraWidth
, 
10829                 self
->SetOrCalcRowSizes(true) - m_colLabelHeight 
+ m_extraHeight
); 
10831     // NOTE: This size should be cached, but first we need to add calls to 
10832     // InvalidateBestSize everywhere that could change the results of this 
10834     // CacheBestSize(size); 
10836     return wxSize(size
.x 
+ m_rowLabelWidth
, size
.y 
+ m_colLabelHeight
) 
10837             + GetWindowBorderSize(); 
10845 wxPen
& wxGrid::GetDividerPen() const 
10850 // ---------------------------------------------------------------------------- 
10851 // cell value accessor functions 
10852 // ---------------------------------------------------------------------------- 
10854 void wxGrid::SetCellValue( int row
, int col
, const wxString
& s 
) 
10858         m_table
->SetValue( row
, col
, s 
); 
10859         if ( !GetBatchCount() ) 
10862             wxRect 
rect( CellToRect( row
, col 
) ); 
10864             rect
.width 
= m_gridWin
->GetClientSize().GetWidth(); 
10865             CalcScrolledPosition(0, rect
.y
, &dummy
, &rect
.y
); 
10866             m_gridWin
->Refresh( false, &rect 
); 
10869         if ( m_currentCellCoords
.GetRow() == row 
&& 
10870              m_currentCellCoords
.GetCol() == col 
&& 
10871              IsCellEditControlShown()) 
10872              // Note: If we are using IsCellEditControlEnabled, 
10873              // this interacts badly with calling SetCellValue from 
10874              // an EVT_GRID_CELL_CHANGE handler. 
10876             HideCellEditControl(); 
10877             ShowCellEditControl(); // will reread data from table 
10882 // ---------------------------------------------------------------------------- 
10883 // block, row and column selection 
10884 // ---------------------------------------------------------------------------- 
10886 void wxGrid::SelectRow( int row
, bool addToSelected 
) 
10888     if ( IsSelection() && !addToSelected 
) 
10892         m_selection
->SelectRow( row
, false, addToSelected 
); 
10895 void wxGrid::SelectCol( int col
, bool addToSelected 
) 
10897     if ( IsSelection() && !addToSelected 
) 
10901         m_selection
->SelectCol( col
, false, addToSelected 
); 
10904 void wxGrid::SelectBlock( int topRow
, int leftCol
, int bottomRow
, int rightCol
, 
10905                           bool addToSelected 
) 
10907     if ( IsSelection() && !addToSelected 
) 
10911         m_selection
->SelectBlock( topRow
, leftCol
, bottomRow
, rightCol
, 
10912                                   false, addToSelected 
); 
10915 void wxGrid::SelectAll() 
10917     if ( m_numRows 
> 0 && m_numCols 
> 0 ) 
10920             m_selection
->SelectBlock( 0, 0, m_numRows 
- 1, m_numCols 
- 1 ); 
10924 // ---------------------------------------------------------------------------- 
10925 // cell, row and col deselection 
10926 // ---------------------------------------------------------------------------- 
10928 void wxGrid::DeselectRow( int row 
) 
10930     if ( !m_selection 
) 
10933     if ( m_selection
->GetSelectionMode() == wxGrid::wxGridSelectRows 
) 
10935         if ( m_selection
->IsInSelection(row
, 0 ) ) 
10936             m_selection
->ToggleCellSelection(row
, 0); 
10940         int nCols 
= GetNumberCols(); 
10941         for ( int i 
= 0; i 
< nCols
; i
++ ) 
10943             if ( m_selection
->IsInSelection(row
, i 
) ) 
10944                 m_selection
->ToggleCellSelection(row
, i
); 
10949 void wxGrid::DeselectCol( int col 
) 
10951     if ( !m_selection 
) 
10954     if ( m_selection
->GetSelectionMode() == wxGrid::wxGridSelectColumns 
) 
10956         if ( m_selection
->IsInSelection(0, col 
) ) 
10957             m_selection
->ToggleCellSelection(0, col
); 
10961         int nRows 
= GetNumberRows(); 
10962         for ( int i 
= 0; i 
< nRows
; i
++ ) 
10964             if ( m_selection
->IsInSelection(i
, col 
) ) 
10965                 m_selection
->ToggleCellSelection(i
, col
); 
10970 void wxGrid::DeselectCell( int row
, int col 
) 
10972     if ( m_selection 
&& m_selection
->IsInSelection(row
, col
) ) 
10973         m_selection
->ToggleCellSelection(row
, col
); 
10976 bool wxGrid::IsSelection() const 
10978     return ( m_selection 
&& (m_selection
->IsSelection() || 
10979              ( m_selectingTopLeft 
!= wxGridNoCellCoords 
&& 
10980                m_selectingBottomRight 
!= wxGridNoCellCoords
) ) ); 
10983 bool wxGrid::IsInSelection( int row
, int col 
) const 
10985     return ( m_selection 
&& (m_selection
->IsInSelection( row
, col 
) || 
10986              ( row 
>= m_selectingTopLeft
.GetRow() && 
10987                col 
>= m_selectingTopLeft
.GetCol() && 
10988                row 
<= m_selectingBottomRight
.GetRow() && 
10989                col 
<= m_selectingBottomRight
.GetCol() )) ); 
10992 wxGridCellCoordsArray 
wxGrid::GetSelectedCells() const 
10996         wxGridCellCoordsArray a
; 
11000     return m_selection
->m_cellSelection
; 
11003 wxGridCellCoordsArray 
wxGrid::GetSelectionBlockTopLeft() const 
11007         wxGridCellCoordsArray a
; 
11011     return m_selection
->m_blockSelectionTopLeft
; 
11014 wxGridCellCoordsArray 
wxGrid::GetSelectionBlockBottomRight() const 
11018         wxGridCellCoordsArray a
; 
11022     return m_selection
->m_blockSelectionBottomRight
; 
11025 wxArrayInt 
wxGrid::GetSelectedRows() const 
11033     return m_selection
->m_rowSelection
; 
11036 wxArrayInt 
wxGrid::GetSelectedCols() const 
11044     return m_selection
->m_colSelection
; 
11047 void wxGrid::ClearSelection() 
11049     wxRect r1 
= BlockToDeviceRect( m_selectingTopLeft
, m_selectingBottomRight
); 
11050     wxRect r2 
= BlockToDeviceRect( m_currentCellCoords
, m_selectingKeyboard 
); 
11051     m_selectingTopLeft 
= 
11052     m_selectingBottomRight 
= 
11053     m_selectingKeyboard 
= wxGridNoCellCoords
; 
11054     Refresh( false, &r1 
); 
11055     Refresh( false, &r2 
); 
11057         m_selection
->ClearSelection(); 
11060 // This function returns the rectangle that encloses the given block 
11061 // in device coords clipped to the client size of the grid window. 
11063 wxRect 
wxGrid::BlockToDeviceRect( const wxGridCellCoords
& topLeft
, 
11064                                   const wxGridCellCoords
& bottomRight 
) const 
11067     wxRect tempCellRect 
= CellToRect(topLeft
); 
11068     if ( tempCellRect 
!= wxGridNoCellRect 
) 
11070         resultRect 
= tempCellRect
; 
11074         resultRect 
= wxRect(0, 0, 0, 0); 
11077     tempCellRect 
= CellToRect(bottomRight
); 
11078     if ( tempCellRect 
!= wxGridNoCellRect 
) 
11080         resultRect 
+= tempCellRect
; 
11084         // If both inputs were "wxGridNoCellRect," then there's nothing to do. 
11085         return wxGridNoCellRect
; 
11088     // Ensure that left/right and top/bottom pairs are in order. 
11089     int left 
= resultRect
.GetLeft(); 
11090     int top 
= resultRect
.GetTop(); 
11091     int right 
= resultRect
.GetRight(); 
11092     int bottom 
= resultRect
.GetBottom(); 
11094     int leftCol 
= topLeft
.GetCol(); 
11095     int topRow 
= topLeft
.GetRow(); 
11096     int rightCol 
= bottomRight
.GetCol(); 
11097     int bottomRow 
= bottomRight
.GetRow(); 
11106         leftCol 
= rightCol
; 
11117         topRow 
= bottomRow
; 
11121     // The following loop is ONLY necessary to detect and handle merged cells. 
11123     m_gridWin
->GetClientSize( &cw
, &ch 
); 
11125     // Get the origin coordinates: notice that they will be negative if the 
11126     // grid is scrolled downwards/to the right. 
11127     int gridOriginX 
= 0; 
11128     int gridOriginY 
= 0; 
11129     CalcScrolledPosition(gridOriginX
, gridOriginY
, &gridOriginX
, &gridOriginY
); 
11131     int onScreenLeftmostCol 
= internalXToCol(-gridOriginX
); 
11132     int onScreenUppermostRow 
= internalYToRow(-gridOriginY
); 
11134     int onScreenRightmostCol 
= internalXToCol(-gridOriginX 
+ cw
); 
11135     int onScreenBottommostRow 
= internalYToRow(-gridOriginY 
+ ch
); 
11137     // Bound our loop so that we only examine the portion of the selected block 
11138     // that is shown on screen. Therefore, we compare the Top-Left block values 
11139     // to the Top-Left screen values, and the Bottom-Right block values to the 
11140     // Bottom-Right screen values, choosing appropriately. 
11141     const int visibleTopRow 
= wxMax(topRow
, onScreenUppermostRow
); 
11142     const int visibleBottomRow 
= wxMin(bottomRow
, onScreenBottommostRow
); 
11143     const int visibleLeftCol 
= wxMax(leftCol
, onScreenLeftmostCol
); 
11144     const int visibleRightCol 
= wxMin(rightCol
, onScreenRightmostCol
); 
11146     for ( int j 
= visibleTopRow
; j 
<= visibleBottomRow
; j
++ ) 
11148         for ( int i 
= visibleLeftCol
; i 
<= visibleRightCol
; i
++ ) 
11150             if ( (j 
== visibleTopRow
) || (j 
== visibleBottomRow
) || 
11151                     (i 
== visibleLeftCol
) || (i 
== visibleRightCol
) ) 
11153                 tempCellRect 
= CellToRect( j
, i 
); 
11155                 if (tempCellRect
.x 
< left
) 
11156                     left 
= tempCellRect
.x
; 
11157                 if (tempCellRect
.y 
< top
) 
11158                     top 
= tempCellRect
.y
; 
11159                 if (tempCellRect
.x 
+ tempCellRect
.width 
> right
) 
11160                     right 
= tempCellRect
.x 
+ tempCellRect
.width
; 
11161                 if (tempCellRect
.y 
+ tempCellRect
.height 
> bottom
) 
11162                     bottom 
= tempCellRect
.y 
+ tempCellRect
.height
; 
11166                 i 
= visibleRightCol
; // jump over inner cells. 
11171     // Convert to scrolled coords 
11172     CalcScrolledPosition( left
, top
, &left
, &top 
); 
11173     CalcScrolledPosition( right
, bottom
, &right
, &bottom 
); 
11175     if (right 
< 0 || bottom 
< 0 || left 
> cw 
|| top 
> ch
) 
11176         return wxRect(0,0,0,0); 
11178     resultRect
.SetLeft( wxMax(0, left
) ); 
11179     resultRect
.SetTop( wxMax(0, top
) ); 
11180     resultRect
.SetRight( wxMin(cw
, right
) ); 
11181     resultRect
.SetBottom( wxMin(ch
, bottom
) ); 
11186 // ---------------------------------------------------------------------------- 
11188 // ---------------------------------------------------------------------------- 
11190 #if wxUSE_DRAG_AND_DROP 
11192 // this allow setting drop target directly on wxGrid 
11193 void wxGrid::SetDropTarget(wxDropTarget 
*dropTarget
) 
11195     GetGridWindow()->SetDropTarget(dropTarget
); 
11198 #endif // wxUSE_DRAG_AND_DROP 
11200 // ---------------------------------------------------------------------------- 
11201 // grid event classes 
11202 // ---------------------------------------------------------------------------- 
11204 IMPLEMENT_DYNAMIC_CLASS( wxGridEvent
, wxNotifyEvent 
) 
11206 wxGridEvent::wxGridEvent( int id
, wxEventType type
, wxObject
* obj
, 
11207                           int row
, int col
, int x
, int y
, bool sel
, 
11208                           bool control
, bool shift
, bool alt
, bool meta 
) 
11209         : wxNotifyEvent( type
, id 
) 
11216     m_control 
= control
; 
11221     SetEventObject(obj
); 
11225 IMPLEMENT_DYNAMIC_CLASS( wxGridSizeEvent
, wxNotifyEvent 
) 
11227 wxGridSizeEvent::wxGridSizeEvent( int id
, wxEventType type
, wxObject
* obj
, 
11228                                   int rowOrCol
, int x
, int y
, 
11229                                   bool control
, bool shift
, bool alt
, bool meta 
) 
11230         : wxNotifyEvent( type
, id 
) 
11232     m_rowOrCol 
= rowOrCol
; 
11235     m_control 
= control
; 
11240     SetEventObject(obj
); 
11244 IMPLEMENT_DYNAMIC_CLASS( wxGridRangeSelectEvent
, wxNotifyEvent 
) 
11246 wxGridRangeSelectEvent::wxGridRangeSelectEvent(int id
, wxEventType type
, wxObject
* obj
, 
11247                                                const wxGridCellCoords
& topLeft
, 
11248                                                const wxGridCellCoords
& bottomRight
, 
11249                                                bool sel
, bool control
, 
11250                                                bool shift
, bool alt
, bool meta 
) 
11251         : wxNotifyEvent( type
, id 
) 
11253     m_topLeft 
= topLeft
; 
11254     m_bottomRight 
= bottomRight
; 
11256     m_control 
= control
; 
11261     SetEventObject(obj
); 
11265 IMPLEMENT_DYNAMIC_CLASS(wxGridEditorCreatedEvent
, wxCommandEvent
) 
11267 wxGridEditorCreatedEvent::wxGridEditorCreatedEvent(int id
, wxEventType type
, 
11268                                                    wxObject
* obj
, int row
, 
11269                                                    int col
, wxControl
* ctrl
) 
11270     : wxCommandEvent(type
, id
) 
11272     SetEventObject(obj
); 
11278 #endif // wxUSE_GRID