1 /////////////////////////////////////////////////////////////////////////// 
   2 // Name:        generic/grid.cpp 
   3 // Purpose:     wxGrid and related classes 
   4 // Author:      Michael Bedward (based on code by Julian Smart, Robin Dunn) 
   5 // Modified by: Robin Dunn, Vadim Zeitlin 
   8 // Copyright:   (c) Michael Bedward (mbedward@ozemail.com.au) 
   9 // Licence:     wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////////// 
  12 // ============================================================================ 
  14 // ============================================================================ 
  16 // ---------------------------------------------------------------------------- 
  18 // ---------------------------------------------------------------------------- 
  20 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) 
  21     #pragma implementation "grid.h" 
  24 // For compilers that support precompilatixon, includes "wx/wx.h". 
  25 #include "wx/wxprec.h" 
  37     #include "wx/dcclient.h" 
  38     #include "wx/settings.h" 
  40     #include "wx/textctrl.h" 
  41     #include "wx/checkbox.h" 
  42     #include "wx/combobox.h" 
  43     #include "wx/valtext.h" 
  47 #include "wx/textfile.h" 
  48 #include "wx/spinctrl.h" 
  49 #include "wx/tokenzr.h" 
  50 #include "wx/renderer.h" 
  53 #include "wx/generic/gridsel.h" 
  55 #if defined(__WXMOTIF__) 
  56     #define WXUNUSED_MOTIF(identifier)  WXUNUSED(identifier) 
  58     #define WXUNUSED_MOTIF(identifier)  identifier 
  61 #if defined(__WXGTK__) 
  62     #define WXUNUSED_GTK(identifier)    WXUNUSED(identifier) 
  64     #define WXUNUSED_GTK(identifier)    identifier 
  67 // Required for wxIs... functions 
  70 // ---------------------------------------------------------------------------- 
  72 // ---------------------------------------------------------------------------- 
  74 WX_DEFINE_ARRAY_WITH_DECL_PTR(wxGridCellAttr 
*, wxArrayAttrs
, 
  75                                  class WXDLLIMPEXP_ADV
); 
  77 struct wxGridCellWithAttr
 
  79     wxGridCellWithAttr(int row
, int col
, wxGridCellAttr 
*attr_
) 
  80         : coords(row
, col
), attr(attr_
) 
  89     wxGridCellCoords coords
; 
  93 //  DECLARE_NO_COPY_CLASS(wxGridCellWithAttr) 
  94 // without rewriting the macros, which require a public copy constructor. 
  97 WX_DECLARE_OBJARRAY_WITH_DECL(wxGridCellWithAttr
, wxGridCellWithAttrArray
, 
  98                               class WXDLLIMPEXP_ADV
); 
 100 #include "wx/arrimpl.cpp" 
 102 WX_DEFINE_OBJARRAY(wxGridCellCoordsArray
) 
 103 WX_DEFINE_OBJARRAY(wxGridCellWithAttrArray
) 
 105 // ---------------------------------------------------------------------------- 
 107 // ---------------------------------------------------------------------------- 
 109 DEFINE_EVENT_TYPE(wxEVT_GRID_CELL_LEFT_CLICK
) 
 110 DEFINE_EVENT_TYPE(wxEVT_GRID_CELL_RIGHT_CLICK
) 
 111 DEFINE_EVENT_TYPE(wxEVT_GRID_CELL_LEFT_DCLICK
) 
 112 DEFINE_EVENT_TYPE(wxEVT_GRID_CELL_RIGHT_DCLICK
) 
 113 DEFINE_EVENT_TYPE(wxEVT_GRID_CELL_BEGIN_DRAG
) 
 114 DEFINE_EVENT_TYPE(wxEVT_GRID_LABEL_LEFT_CLICK
) 
 115 DEFINE_EVENT_TYPE(wxEVT_GRID_LABEL_RIGHT_CLICK
) 
 116 DEFINE_EVENT_TYPE(wxEVT_GRID_LABEL_LEFT_DCLICK
) 
 117 DEFINE_EVENT_TYPE(wxEVT_GRID_LABEL_RIGHT_DCLICK
) 
 118 DEFINE_EVENT_TYPE(wxEVT_GRID_ROW_SIZE
) 
 119 DEFINE_EVENT_TYPE(wxEVT_GRID_COL_SIZE
) 
 120 DEFINE_EVENT_TYPE(wxEVT_GRID_RANGE_SELECT
) 
 121 DEFINE_EVENT_TYPE(wxEVT_GRID_CELL_CHANGE
) 
 122 DEFINE_EVENT_TYPE(wxEVT_GRID_SELECT_CELL
) 
 123 DEFINE_EVENT_TYPE(wxEVT_GRID_EDITOR_SHOWN
) 
 124 DEFINE_EVENT_TYPE(wxEVT_GRID_EDITOR_HIDDEN
) 
 125 DEFINE_EVENT_TYPE(wxEVT_GRID_EDITOR_CREATED
) 
 127 // ---------------------------------------------------------------------------- 
 129 // ---------------------------------------------------------------------------- 
 131 class WXDLLIMPEXP_ADV wxGridRowLabelWindow 
: public wxWindow
 
 134     wxGridRowLabelWindow() { m_owner 
= (wxGrid 
*)NULL
; } 
 135     wxGridRowLabelWindow( wxGrid 
*parent
, wxWindowID id
, 
 136                           const wxPoint 
&pos
, const wxSize 
&size 
); 
 141     void OnPaint( wxPaintEvent
& event 
); 
 142     void OnMouseEvent( wxMouseEvent
& event 
); 
 143     void OnMouseWheel( wxMouseEvent
& event 
); 
 144     void OnKeyDown( wxKeyEvent
& event 
); 
 145     void OnKeyUp( wxKeyEvent
& ); 
 146     void OnChar( wxKeyEvent
& ); 
 148     DECLARE_DYNAMIC_CLASS(wxGridRowLabelWindow
) 
 149     DECLARE_EVENT_TABLE() 
 150     DECLARE_NO_COPY_CLASS(wxGridRowLabelWindow
) 
 154 class WXDLLIMPEXP_ADV wxGridColLabelWindow 
: public wxWindow
 
 157     wxGridColLabelWindow() { m_owner 
= (wxGrid 
*)NULL
; } 
 158     wxGridColLabelWindow( wxGrid 
*parent
, wxWindowID id
, 
 159                           const wxPoint 
&pos
, const wxSize 
&size 
); 
 164     void OnPaint( wxPaintEvent 
&event 
); 
 165     void OnMouseEvent( wxMouseEvent
& event 
); 
 166     void OnMouseWheel( wxMouseEvent
& event 
); 
 167     void OnKeyDown( wxKeyEvent
& event 
); 
 168     void OnKeyUp( wxKeyEvent
& ); 
 169     void OnChar( wxKeyEvent
& ); 
 171     DECLARE_DYNAMIC_CLASS(wxGridColLabelWindow
) 
 172     DECLARE_EVENT_TABLE() 
 173     DECLARE_NO_COPY_CLASS(wxGridColLabelWindow
) 
 177 class WXDLLIMPEXP_ADV wxGridCornerLabelWindow 
: public wxWindow
 
 180     wxGridCornerLabelWindow() { m_owner 
= (wxGrid 
*)NULL
; } 
 181     wxGridCornerLabelWindow( wxGrid 
*parent
, wxWindowID id
, 
 182                              const wxPoint 
&pos
, const wxSize 
&size 
); 
 187     void OnMouseEvent( wxMouseEvent
& event 
); 
 188     void OnMouseWheel( wxMouseEvent
& event 
); 
 189     void OnKeyDown( wxKeyEvent
& event 
); 
 190     void OnKeyUp( wxKeyEvent
& ); 
 191     void OnChar( wxKeyEvent
& ); 
 192     void OnPaint( wxPaintEvent
& event 
); 
 194     DECLARE_DYNAMIC_CLASS(wxGridCornerLabelWindow
) 
 195     DECLARE_EVENT_TABLE() 
 196     DECLARE_NO_COPY_CLASS(wxGridCornerLabelWindow
) 
 199 class WXDLLIMPEXP_ADV wxGridWindow 
: public wxWindow
 
 204         m_owner 
= (wxGrid 
*)NULL
; 
 205         m_rowLabelWin 
= (wxGridRowLabelWindow 
*)NULL
; 
 206         m_colLabelWin 
= (wxGridColLabelWindow 
*)NULL
; 
 209     wxGridWindow( wxGrid 
*parent
, 
 210                   wxGridRowLabelWindow 
*rowLblWin
, 
 211                   wxGridColLabelWindow 
*colLblWin
, 
 212                   wxWindowID id
, const wxPoint 
&pos
, const wxSize 
&size 
); 
 215     void ScrollWindow( int dx
, int dy
, const wxRect 
*rect 
); 
 217     wxGrid
* GetOwner() { return m_owner
; } 
 221     wxGridRowLabelWindow     
*m_rowLabelWin
; 
 222     wxGridColLabelWindow     
*m_colLabelWin
; 
 224     void OnPaint( wxPaintEvent 
&event 
); 
 225     void OnMouseWheel( wxMouseEvent
& event 
); 
 226     void OnMouseEvent( wxMouseEvent
& event 
); 
 227     void OnKeyDown( wxKeyEvent
& ); 
 228     void OnKeyUp( wxKeyEvent
& ); 
 229     void OnChar( wxKeyEvent
& ); 
 230     void OnEraseBackground( wxEraseEvent
& ); 
 231     void OnFocus( wxFocusEvent
& ); 
 233     DECLARE_DYNAMIC_CLASS(wxGridWindow
) 
 234     DECLARE_EVENT_TABLE() 
 235     DECLARE_NO_COPY_CLASS(wxGridWindow
) 
 240 class wxGridCellEditorEvtHandler 
: public wxEvtHandler
 
 243     wxGridCellEditorEvtHandler(wxGrid
* grid
, wxGridCellEditor
* editor
) 
 249     void OnKillFocus(wxFocusEvent
& event
); 
 250     void OnKeyDown(wxKeyEvent
& event
); 
 251     void OnChar(wxKeyEvent
& event
); 
 255     wxGridCellEditor
*   m_editor
; 
 257     DECLARE_EVENT_TABLE() 
 258     DECLARE_DYNAMIC_CLASS(wxGridCellEditorEvtHandler
) 
 259     DECLARE_NO_COPY_CLASS(wxGridCellEditorEvtHandler
) 
 263 IMPLEMENT_ABSTRACT_CLASS(wxGridCellEditorEvtHandler
, wxEvtHandler
) 
 265 BEGIN_EVENT_TABLE( wxGridCellEditorEvtHandler
, wxEvtHandler 
) 
 266     EVT_KILL_FOCUS( wxGridCellEditorEvtHandler::OnKillFocus 
) 
 267     EVT_KEY_DOWN( wxGridCellEditorEvtHandler::OnKeyDown 
) 
 268     EVT_CHAR( wxGridCellEditorEvtHandler::OnChar 
) 
 273 // ---------------------------------------------------------------------------- 
 274 // the internal data representation used by wxGridCellAttrProvider 
 275 // ---------------------------------------------------------------------------- 
 277 // this class stores attributes set for cells 
 278 class WXDLLIMPEXP_ADV wxGridCellAttrData
 
 281     void SetAttr(wxGridCellAttr 
*attr
, int row
, int col
); 
 282     wxGridCellAttr 
*GetAttr(int row
, int col
) const; 
 283     void UpdateAttrRows( size_t pos
, int numRows 
); 
 284     void UpdateAttrCols( size_t pos
, int numCols 
); 
 287     // searches for the attr for given cell, returns wxNOT_FOUND if not found 
 288     int FindIndex(int row
, int col
) const; 
 290     wxGridCellWithAttrArray m_attrs
; 
 293 // this class stores attributes set for rows or columns 
 294 class WXDLLIMPEXP_ADV wxGridRowOrColAttrData
 
 297     // empty ctor to suppress warnings 
 298     wxGridRowOrColAttrData() { } 
 299     ~wxGridRowOrColAttrData(); 
 301     void SetAttr(wxGridCellAttr 
*attr
, int rowOrCol
); 
 302     wxGridCellAttr 
*GetAttr(int rowOrCol
) const; 
 303     void UpdateAttrRowsOrCols( size_t pos
, int numRowsOrCols 
); 
 306     wxArrayInt m_rowsOrCols
; 
 307     wxArrayAttrs m_attrs
; 
 310 // NB: this is just a wrapper around 3 objects: one which stores cell 
 311 //     attributes, and 2 others for row/col ones 
 312 class WXDLLIMPEXP_ADV wxGridCellAttrProviderData
 
 315     wxGridCellAttrData m_cellAttrs
; 
 316     wxGridRowOrColAttrData m_rowAttrs
, 
 321 // ---------------------------------------------------------------------------- 
 322 // data structures used for the data type registry 
 323 // ---------------------------------------------------------------------------- 
 325 struct wxGridDataTypeInfo
 
 327     wxGridDataTypeInfo(const wxString
& typeName
, 
 328                        wxGridCellRenderer
* renderer
, 
 329                        wxGridCellEditor
* editor
) 
 330         : m_typeName(typeName
), m_renderer(renderer
), m_editor(editor
) 
 333     ~wxGridDataTypeInfo() 
 335         wxSafeDecRef(m_renderer
); 
 336         wxSafeDecRef(m_editor
); 
 340     wxGridCellRenderer
* m_renderer
; 
 341     wxGridCellEditor
*   m_editor
; 
 343     DECLARE_NO_COPY_CLASS(wxGridDataTypeInfo
) 
 347 WX_DEFINE_ARRAY_WITH_DECL_PTR(wxGridDataTypeInfo
*, wxGridDataTypeInfoArray
, 
 348                                  class WXDLLIMPEXP_ADV
); 
 351 class WXDLLIMPEXP_ADV wxGridTypeRegistry
 
 354   wxGridTypeRegistry() {} 
 355     ~wxGridTypeRegistry(); 
 357     void RegisterDataType(const wxString
& typeName
, 
 358                      wxGridCellRenderer
* renderer
, 
 359                      wxGridCellEditor
* editor
); 
 361     // find one of already registered data types 
 362     int FindRegisteredDataType(const wxString
& typeName
); 
 364     // try to FindRegisteredDataType(), if this fails and typeName is one of 
 365     // standard typenames, register it and return its index 
 366     int FindDataType(const wxString
& typeName
); 
 368     // try to FindDataType(), if it fails see if it is not one of already 
 369     // registered data types with some params in which case clone the 
 370     // registered data type and set params for it 
 371     int FindOrCloneDataType(const wxString
& typeName
); 
 373     wxGridCellRenderer
* GetRenderer(int index
); 
 374     wxGridCellEditor
*   GetEditor(int index
); 
 377     wxGridDataTypeInfoArray m_typeinfo
; 
 380 // ---------------------------------------------------------------------------- 
 381 // conditional compilation 
 382 // ---------------------------------------------------------------------------- 
 384 #ifndef WXGRID_DRAW_LINES 
 385 #define WXGRID_DRAW_LINES 1 
 388 // ---------------------------------------------------------------------------- 
 390 // ---------------------------------------------------------------------------- 
 392 //#define DEBUG_ATTR_CACHE 
 393 #ifdef DEBUG_ATTR_CACHE 
 394     static size_t gs_nAttrCacheHits 
= 0; 
 395     static size_t gs_nAttrCacheMisses 
= 0; 
 396 #endif // DEBUG_ATTR_CACHE 
 398 // ---------------------------------------------------------------------------- 
 400 // ---------------------------------------------------------------------------- 
 402 wxGridCellCoords 
wxGridNoCellCoords( -1, -1 ); 
 403 wxRect           
wxGridNoCellRect( -1, -1, -1, -1 ); 
 406 // TODO: this doesn't work at all, grid cells have different sizes and approx 
 407 //       calculations don't work as because of the size mismatch scrollbars 
 408 //       sometimes fail to be shown when they should be or vice versa 
 410 //       The scroll bars may be a little flakey once in a while, but that is 
 411 //       surely much less horrible than having scroll lines of only 1!!! 
 414 //       Well, it's still seriously broken so it might be better but needs 
 417 static const size_t GRID_SCROLL_LINE_X 
= 15;  // 1; 
 418 static const size_t GRID_SCROLL_LINE_Y 
= GRID_SCROLL_LINE_X
; 
 420 // the size of hash tables used a bit everywhere (the max number of elements 
 421 // in these hash tables is the number of rows/columns) 
 422 static const int GRID_HASH_SIZE 
= 100; 
 425 // ---------------------------------------------------------------------------- 
 427 // ---------------------------------------------------------------------------- 
 429 static inline int GetScrollX(int x
) 
 431     return (x 
+ GRID_SCROLL_LINE_X 
- 1) / GRID_SCROLL_LINE_X
; 
 434 static inline int GetScrollY(int y
) 
 436     return (y 
+ GRID_SCROLL_LINE_Y 
- 1) / GRID_SCROLL_LINE_Y
; 
 440 // ============================================================================ 
 442 // ============================================================================ 
 444 // ---------------------------------------------------------------------------- 
 446 // ---------------------------------------------------------------------------- 
 448 wxGridCellEditor::wxGridCellEditor() 
 455 wxGridCellEditor::~wxGridCellEditor() 
 460 void wxGridCellEditor::Create(wxWindow
* WXUNUSED(parent
), 
 461                               wxWindowID 
WXUNUSED(id
), 
 462                               wxEvtHandler
* evtHandler
) 
 465         m_control
->PushEventHandler(evtHandler
); 
 468 void wxGridCellEditor::PaintBackground(const wxRect
& rectCell
, 
 469                                        wxGridCellAttr 
*attr
) 
 471     // erase the background because we might not fill the cell 
 472     wxClientDC 
dc(m_control
->GetParent()); 
 473     wxGridWindow
* gridWindow 
= wxDynamicCast(m_control
->GetParent(), wxGridWindow
); 
 475         gridWindow
->GetOwner()->PrepareDC(dc
); 
 477     dc
.SetPen(*wxTRANSPARENT_PEN
); 
 478     dc
.SetBrush(wxBrush(attr
->GetBackgroundColour(), wxSOLID
)); 
 479     dc
.DrawRectangle(rectCell
); 
 481     // redraw the control we just painted over 
 482     m_control
->Refresh(); 
 485 void wxGridCellEditor::Destroy() 
 489         m_control
->PopEventHandler(true /* delete it*/); 
 491         m_control
->Destroy(); 
 496 void wxGridCellEditor::Show(bool show
, wxGridCellAttr 
*attr
) 
 498     wxASSERT_MSG(m_control
, 
 499                  wxT("The wxGridCellEditor must be Created first!")); 
 500     m_control
->Show(show
); 
 504         // set the colours/fonts if we have any 
 507             m_colFgOld 
= m_control
->GetForegroundColour(); 
 508             m_control
->SetForegroundColour(attr
->GetTextColour()); 
 510             m_colBgOld 
= m_control
->GetBackgroundColour(); 
 511             m_control
->SetBackgroundColour(attr
->GetBackgroundColour()); 
 513 // Workaround for GTK+1 font setting problem on some platforms 
 514 #if !defined(__WXGTK__) || defined(__WXGTK20__) 
 515             m_fontOld 
= m_control
->GetFont(); 
 516             m_control
->SetFont(attr
->GetFont()); 
 518             // can't do anything more in the base class version, the other 
 519             // attributes may only be used by the derived classes 
 524         // restore the standard colours fonts 
 525         if ( m_colFgOld
.Ok() ) 
 527             m_control
->SetForegroundColour(m_colFgOld
); 
 528             m_colFgOld 
= wxNullColour
; 
 531         if ( m_colBgOld
.Ok() ) 
 533             m_control
->SetBackgroundColour(m_colBgOld
); 
 534             m_colBgOld 
= wxNullColour
; 
 536 // Workaround for GTK+1 font setting problem on some platforms 
 537 #if !defined(__WXGTK__) || defined(__WXGTK20__) 
 538         if ( m_fontOld
.Ok() ) 
 540             m_control
->SetFont(m_fontOld
); 
 541             m_fontOld 
= wxNullFont
; 
 547 void wxGridCellEditor::SetSize(const wxRect
& rect
) 
 549     wxASSERT_MSG(m_control
, 
 550                  wxT("The wxGridCellEditor must be Created first!")); 
 551     m_control
->SetSize(rect
, wxSIZE_ALLOW_MINUS_ONE
); 
 554 void wxGridCellEditor::HandleReturn(wxKeyEvent
& event
) 
 559 bool wxGridCellEditor::IsAcceptedKey(wxKeyEvent
& event
) 
 561     bool ctrl 
= event
.ControlDown(); 
 562     bool alt  
= event
.AltDown(); 
 564     // On the Mac the Alt key is more like shift and is used for entry of 
 565     // valid characters, so check for Ctrl and Meta instead. 
 566     alt 
= event
.MetaDown(); 
 569     // Assume it's not a valid char if ctrl or alt is down, but if both are 
 570     // down then it may be because of an AltGr key combination, so let them 
 571     // through in that case. 
 572     if ((ctrl 
|| alt
) && !(ctrl 
&& alt
)) 
 576     int key 
= event
.GetUnicodeKey(); 
 579     // if the unicode key code is not really a unicode character (it may 
 580     // be a function key or etc., the platforms appear to always give us a 
 581     // small value in this case) then fallback to the ascii key code but 
 582     // don't do anything for function keys or etc. 
 585         key 
= event
.GetKeyCode(); 
 586         keyOk 
= (key 
<= 127); 
 589 #else // !wxUSE_UNICODE 
 590     int key 
= event
.GetKeyCode(); 
 594 #endif // wxUSE_UNICODE/!wxUSE_UNICODE 
 597 void wxGridCellEditor::StartingKey(wxKeyEvent
& event
) 
 602 void wxGridCellEditor::StartingClick() 
 608 // ---------------------------------------------------------------------------- 
 609 // wxGridCellTextEditor 
 610 // ---------------------------------------------------------------------------- 
 612 wxGridCellTextEditor::wxGridCellTextEditor() 
 617 void wxGridCellTextEditor::Create(wxWindow
* parent
, 
 619                                   wxEvtHandler
* evtHandler
) 
 621     m_control 
= new wxTextCtrl(parent
, id
, wxEmptyString
, 
 622                                wxDefaultPosition
, wxDefaultSize
 
 623 #if defined(__WXMSW__) 
 624                                , wxTE_PROCESS_TAB 
| wxTE_AUTO_SCROLL
 
 628     // set max length allowed in the textctrl, if the parameter was set 
 631         ((wxTextCtrl
*)m_control
)->SetMaxLength(m_maxChars
); 
 634     wxGridCellEditor::Create(parent
, id
, evtHandler
); 
 637 void wxGridCellTextEditor::PaintBackground(const wxRect
& WXUNUSED(rectCell
), 
 638                                            wxGridCellAttr 
* WXUNUSED(attr
)) 
 640     // as we fill the entire client area, don't do anything here to minimize 
 644 void wxGridCellTextEditor::SetSize(const wxRect
& rectOrig
) 
 646     wxRect 
rect(rectOrig
); 
 648     // Make the edit control large enough to allow for internal 
 651     // TODO: remove this if the text ctrl sizing is improved esp. for 
 654 #if defined(__WXGTK__) 
 663     int extra_x 
= ( rect
.x 
> 2 )? 2 : 1; 
 665 // MB: treat MSW separately here otherwise the caret doesn't show 
 666 // when the editor is in the first row. 
 667 #if defined(__WXMSW__) 
 670     int extra_y 
= ( rect
.y 
> 2 )? 2 : 1; 
 673 #if defined(__WXMOTIF__) 
 677     rect
.SetLeft( wxMax(0, rect
.x 
- extra_x
) ); 
 678     rect
.SetTop( wxMax(0, rect
.y 
- extra_y
) ); 
 679     rect
.SetRight( rect
.GetRight() + 2*extra_x 
); 
 680     rect
.SetBottom( rect
.GetBottom() + 2*extra_y 
); 
 683     wxGridCellEditor::SetSize(rect
); 
 686 void wxGridCellTextEditor::BeginEdit(int row
, int col
, wxGrid
* grid
) 
 688     wxASSERT_MSG(m_control
, 
 689                  wxT("The wxGridCellEditor must be Created first!")); 
 691     m_startValue 
= grid
->GetTable()->GetValue(row
, col
); 
 693     DoBeginEdit(m_startValue
); 
 696 void wxGridCellTextEditor::DoBeginEdit(const wxString
& startValue
) 
 698     Text()->SetValue(startValue
); 
 699     Text()->SetInsertionPointEnd(); 
 700     Text()->SetSelection(-1,-1); 
 704 bool wxGridCellTextEditor::EndEdit(int row
, int col
, 
 707     wxASSERT_MSG(m_control
, 
 708                  wxT("The wxGridCellEditor must be Created first!")); 
 710     bool changed 
= false; 
 711     wxString value 
= Text()->GetValue(); 
 712     if (value 
!= m_startValue
) 
 716         grid
->GetTable()->SetValue(row
, col
, value
); 
 718     m_startValue 
= wxEmptyString
; 
 719     // No point in setting the text of the hidden control 
 720     //Text()->SetValue(m_startValue); 
 726 void wxGridCellTextEditor::Reset() 
 728     wxASSERT_MSG(m_control
, 
 729                  wxT("The wxGridCellEditor must be Created first!")); 
 731     DoReset(m_startValue
); 
 734 void wxGridCellTextEditor::DoReset(const wxString
& startValue
) 
 736     Text()->SetValue(startValue
); 
 737     Text()->SetInsertionPointEnd(); 
 740 bool wxGridCellTextEditor::IsAcceptedKey(wxKeyEvent
& event
) 
 742     return wxGridCellEditor::IsAcceptedKey(event
); 
 745 void wxGridCellTextEditor::StartingKey(wxKeyEvent
& event
) 
 747     // Since this is now happening in the EVT_CHAR event EmulateKeyPress is no 
 748     // longer an appropriate way to get the character into the text control. 
 749     // Do it ourselves instead.  We know that if we get this far that we have 
 750     // a valid character, so not a whole lot of testing needs to be done. 
 752     wxTextCtrl
* tc 
= Text(); 
 757     ch 
= event
.GetUnicodeKey(); 
 759         ch 
= (wxChar
)event
.GetKeyCode(); 
 761     ch 
= (wxChar
)event
.GetKeyCode(); 
 766             // delete the character at the cursor 
 767             pos 
= tc
->GetInsertionPoint(); 
 768             if (pos 
< tc
->GetLastPosition()) 
 769                 tc
->Remove(pos
, pos
+1); 
 773             // delete the character before the cursor 
 774             pos 
= tc
->GetInsertionPoint(); 
 776                 tc
->Remove(pos
-1, pos
); 
 785 void wxGridCellTextEditor::HandleReturn( wxKeyEvent
& 
 786                                          WXUNUSED_GTK(WXUNUSED_MOTIF(event
)) ) 
 788 #if defined(__WXMOTIF__) || defined(__WXGTK__) 
 789     // wxMotif needs a little extra help... 
 790     size_t pos 
= (size_t)( Text()->GetInsertionPoint() ); 
 791     wxString 
s( Text()->GetValue() ); 
 792     s 
= s
.Left(pos
) + wxT("\n") + s
.Mid(pos
); 
 794     Text()->SetInsertionPoint( pos 
); 
 796     // the other ports can handle a Return key press 
 802 void wxGridCellTextEditor::SetParameters(const wxString
& params
) 
 812         if ( !params
.ToLong(&tmp
) ) 
 814             wxLogDebug(_T("Invalid wxGridCellTextEditor parameter string '%s' ignored"), params
.c_str()); 
 818             m_maxChars 
= (size_t)tmp
; 
 823 // return the value in the text control 
 824 wxString 
wxGridCellTextEditor::GetValue() const 
 826   return Text()->GetValue(); 
 829 // ---------------------------------------------------------------------------- 
 830 // wxGridCellNumberEditor 
 831 // ---------------------------------------------------------------------------- 
 833 wxGridCellNumberEditor::wxGridCellNumberEditor(int min
, int max
) 
 839 void wxGridCellNumberEditor::Create(wxWindow
* parent
, 
 841                                     wxEvtHandler
* evtHandler
) 
 846         // create a spin ctrl 
 847         m_control 
= new wxSpinCtrl(parent
, wxID_ANY
, wxEmptyString
, 
 848                                    wxDefaultPosition
, wxDefaultSize
, 
 852         wxGridCellEditor::Create(parent
, id
, evtHandler
); 
 857         // just a text control 
 858         wxGridCellTextEditor::Create(parent
, id
, evtHandler
); 
 861         Text()->SetValidator(wxTextValidator(wxFILTER_NUMERIC
)); 
 862 #endif // wxUSE_VALIDATORS 
 866 void wxGridCellNumberEditor::BeginEdit(int row
, int col
, wxGrid
* grid
) 
 868     // first get the value 
 869     wxGridTableBase 
*table 
= grid
->GetTable(); 
 870     if ( table
->CanGetValueAs(row
, col
, wxGRID_VALUE_NUMBER
) ) 
 872         m_valueOld 
= table
->GetValueAsLong(row
, col
); 
 877         wxString sValue 
= table
->GetValue(row
, col
); 
 878         if (! sValue
.ToLong(&m_valueOld
) && ! sValue
.empty()) 
 880             wxFAIL_MSG( _T("this cell doesn't have numeric value") ); 
 888         Spin()->SetValue((int)m_valueOld
); 
 894         DoBeginEdit(GetString()); 
 898 bool wxGridCellNumberEditor::EndEdit(int row
, int col
, 
 908         value 
= Spin()->GetValue(); 
 909         changed 
= value 
!= m_valueOld
; 
 911             text 
= wxString::Format(wxT("%ld"), value
); 
 916         text 
= Text()->GetValue(); 
 917         changed 
= (text
.empty() || text
.ToLong(&value
)) && (value 
!= m_valueOld
); 
 922         if (grid
->GetTable()->CanSetValueAs(row
, col
, wxGRID_VALUE_NUMBER
)) 
 923             grid
->GetTable()->SetValueAsLong(row
, col
, value
); 
 925             grid
->GetTable()->SetValue(row
, col
, text
); 
 931 void wxGridCellNumberEditor::Reset() 
 936         Spin()->SetValue((int)m_valueOld
); 
 941         DoReset(GetString()); 
 945 bool wxGridCellNumberEditor::IsAcceptedKey(wxKeyEvent
& event
) 
 947     if ( wxGridCellEditor::IsAcceptedKey(event
) ) 
 949         int keycode 
= event
.GetKeyCode(); 
 950         if ( (keycode 
< 128) && 
 951              (wxIsdigit(keycode
) || keycode 
== '+' || keycode 
== '-')) 
 960 void wxGridCellNumberEditor::StartingKey(wxKeyEvent
& event
) 
 962     int keycode 
= event
.GetKeyCode(); 
 965         if ( wxIsdigit(keycode
) || keycode 
== '+' || keycode 
== '-') 
 967             wxGridCellTextEditor::StartingKey(event
); 
 976         if ( wxIsdigit(keycode
) ) 
 978             wxSpinCtrl
* spin 
= (wxSpinCtrl
*)m_control
; 
 979             spin
->SetValue(keycode 
- '0'); 
 980             spin
->SetSelection(1,1); 
 988 void wxGridCellNumberEditor::SetParameters(const wxString
& params
) 
 999         if ( params
.BeforeFirst(_T(',')).ToLong(&tmp
) ) 
1003             if ( params
.AfterFirst(_T(',')).ToLong(&tmp
) ) 
1007                 // skip the error message below 
1012         wxLogDebug(_T("Invalid wxGridCellNumberEditor parameter string '%s' ignored"), params
.c_str()); 
1016 // return the value in the spin control if it is there (the text control otherwise) 
1017 wxString 
wxGridCellNumberEditor::GetValue() const 
1024         long value 
= Spin()->GetValue(); 
1025         s
.Printf(wxT("%ld"), value
); 
1030         s 
= Text()->GetValue(); 
1036 // ---------------------------------------------------------------------------- 
1037 // wxGridCellFloatEditor 
1038 // ---------------------------------------------------------------------------- 
1040 wxGridCellFloatEditor::wxGridCellFloatEditor(int width
, int precision
) 
1043     m_precision 
= precision
; 
1046 void wxGridCellFloatEditor::Create(wxWindow
* parent
, 
1048                                    wxEvtHandler
* evtHandler
) 
1050     wxGridCellTextEditor::Create(parent
, id
, evtHandler
); 
1052 #if wxUSE_VALIDATORS 
1053     Text()->SetValidator(wxTextValidator(wxFILTER_NUMERIC
)); 
1054 #endif // wxUSE_VALIDATORS 
1057 void wxGridCellFloatEditor::BeginEdit(int row
, int col
, wxGrid
* grid
) 
1059     // first get the value 
1060     wxGridTableBase 
*table 
= grid
->GetTable(); 
1061     if ( table
->CanGetValueAs(row
, col
, wxGRID_VALUE_FLOAT
) ) 
1063         m_valueOld 
= table
->GetValueAsDouble(row
, col
); 
1068         wxString sValue 
= table
->GetValue(row
, col
); 
1069         if (! sValue
.ToDouble(&m_valueOld
) && ! sValue
.empty()) 
1071             wxFAIL_MSG( _T("this cell doesn't have float value") ); 
1076     DoBeginEdit(GetString()); 
1079 bool wxGridCellFloatEditor::EndEdit(int row
, int col
, 
1083     wxString 
text(Text()->GetValue()); 
1085     if ( (text
.empty() || text
.ToDouble(&value
)) && (value 
!= m_valueOld
) ) 
1087         if (grid
->GetTable()->CanSetValueAs(row
, col
, wxGRID_VALUE_FLOAT
)) 
1088             grid
->GetTable()->SetValueAsDouble(row
, col
, value
); 
1090             grid
->GetTable()->SetValue(row
, col
, text
); 
1097 void wxGridCellFloatEditor::Reset() 
1099     DoReset(GetString()); 
1102 void wxGridCellFloatEditor::StartingKey(wxKeyEvent
& event
) 
1104     int keycode 
= event
.GetKeyCode(); 
1106     tmpbuf
[0] = (char) keycode
; 
1108     wxString 
strbuf(tmpbuf
, *wxConvCurrent
); 
1110     bool is_decimal_point 
= ( strbuf 
== 
1111        wxLocale::GetInfo(wxLOCALE_DECIMAL_POINT
, wxLOCALE_CAT_NUMBER
) ); 
1113     bool is_decimal_point 
= ( strbuf 
== _T(".") ); 
1115     if ( wxIsdigit(keycode
) || keycode 
== '+' || keycode 
== '-' 
1116          || is_decimal_point 
) 
1118         wxGridCellTextEditor::StartingKey(event
); 
1120         // skip Skip() below 
1127 void wxGridCellFloatEditor::SetParameters(const wxString
& params
) 
1138         if ( params
.BeforeFirst(_T(',')).ToLong(&tmp
) ) 
1142             if ( params
.AfterFirst(_T(',')).ToLong(&tmp
) ) 
1144                 m_precision 
= (int)tmp
; 
1146                 // skip the error message below 
1151         wxLogDebug(_T("Invalid wxGridCellFloatEditor parameter string '%s' ignored"), params
.c_str()); 
1155 wxString 
wxGridCellFloatEditor::GetString() const 
1158     if ( m_width 
== -1 ) 
1160         // default width/precision 
1163     else if ( m_precision 
== -1 ) 
1165         // default precision 
1166         fmt
.Printf(_T("%%%d.f"), m_width
); 
1170         fmt
.Printf(_T("%%%d.%df"), m_width
, m_precision
); 
1173     return wxString::Format(fmt
, m_valueOld
); 
1176 bool wxGridCellFloatEditor::IsAcceptedKey(wxKeyEvent
& event
) 
1178     if ( wxGridCellEditor::IsAcceptedKey(event
) ) 
1180         int keycode 
= event
.GetKeyCode(); 
1181         printf("%d\n", keycode
); 
1182         // accept digits, 'e' as in '1e+6', also '-', '+', and '.' 
1184         tmpbuf
[0] = (char) keycode
; 
1186         wxString 
strbuf(tmpbuf
, *wxConvCurrent
); 
1188         bool is_decimal_point 
= 
1189             ( strbuf 
== wxLocale::GetInfo(wxLOCALE_DECIMAL_POINT
, 
1190                                           wxLOCALE_CAT_NUMBER
) ); 
1192         bool is_decimal_point 
= ( strbuf 
== _T(".") ); 
1194         if ( (keycode 
< 128) && 
1195              (wxIsdigit(keycode
) || tolower(keycode
) == 'e' || 
1196               is_decimal_point 
|| keycode 
== '+' || keycode 
== '-') ) 
1203 #endif // wxUSE_TEXTCTRL 
1207 // ---------------------------------------------------------------------------- 
1208 // wxGridCellBoolEditor 
1209 // ---------------------------------------------------------------------------- 
1211 void wxGridCellBoolEditor::Create(wxWindow
* parent
, 
1213                                   wxEvtHandler
* evtHandler
) 
1215     m_control 
= new wxCheckBox(parent
, id
, wxEmptyString
, 
1216                                wxDefaultPosition
, wxDefaultSize
, 
1219     wxGridCellEditor::Create(parent
, id
, evtHandler
); 
1222 void wxGridCellBoolEditor::SetSize(const wxRect
& r
) 
1224     bool resize 
= false; 
1225     wxSize size 
= m_control
->GetSize(); 
1226     wxCoord minSize 
= wxMin(r
.width
, r
.height
); 
1228     // check if the checkbox is not too big/small for this cell 
1229     wxSize sizeBest 
= m_control
->GetBestSize(); 
1230     if ( !(size 
== sizeBest
) ) 
1232         // reset to default size if it had been made smaller 
1238     if ( size
.x 
>= minSize 
|| size
.y 
>= minSize 
) 
1240         // leave 1 pixel margin 
1241         size
.x 
= size
.y 
= minSize 
- 2; 
1248         m_control
->SetSize(size
); 
1251     // position it in the centre of the rectangle (TODO: support alignment?) 
1253 #if defined(__WXGTK__) || defined (__WXMOTIF__) 
1254     // the checkbox without label still has some space to the right in wxGTK, 
1255     // so shift it to the right 
1257 #elif defined(__WXMSW__) 
1258     // here too, but in other way 
1263     int hAlign 
= wxALIGN_CENTRE
; 
1264     int vAlign 
= wxALIGN_CENTRE
; 
1266         GetCellAttr()->GetAlignment(& hAlign
, & vAlign
); 
1269     if (hAlign 
== wxALIGN_LEFT
) 
1275         y 
= r
.y 
+ r
.height
/2 - size
.y
/2; 
1277     else if (hAlign 
== wxALIGN_RIGHT
) 
1279         x 
= r
.x 
+ r
.width 
- size
.x 
- 2; 
1280         y 
= r
.y 
+ r
.height
/2 - size
.y
/2; 
1282     else if (hAlign 
== wxALIGN_CENTRE
) 
1284         x 
= r
.x 
+ r
.width
/2 - size
.x
/2; 
1285         y 
= r
.y 
+ r
.height
/2 - size
.y
/2; 
1288     m_control
->Move(x
, y
); 
1291 void wxGridCellBoolEditor::Show(bool show
, wxGridCellAttr 
*attr
) 
1293     m_control
->Show(show
); 
1297         wxColour colBg 
= attr 
? attr
->GetBackgroundColour() : *wxLIGHT_GREY
; 
1298         CBox()->SetBackgroundColour(colBg
); 
1302 void wxGridCellBoolEditor::BeginEdit(int row
, int col
, wxGrid
* grid
) 
1304     wxASSERT_MSG(m_control
, 
1305                  wxT("The wxGridCellEditor must be Created first!")); 
1307     if (grid
->GetTable()->CanGetValueAs(row
, col
, wxGRID_VALUE_BOOL
)) 
1308         m_startValue 
= grid
->GetTable()->GetValueAsBool(row
, col
); 
1311         wxString 
cellval( grid
->GetTable()->GetValue(row
, col
) ); 
1312         m_startValue 
= !( !cellval 
|| (cellval 
== wxT("0")) ); 
1314     CBox()->SetValue(m_startValue
); 
1318 bool wxGridCellBoolEditor::EndEdit(int row
, int col
, 
1321     wxASSERT_MSG(m_control
, 
1322                  wxT("The wxGridCellEditor must be Created first!")); 
1324     bool changed 
= false; 
1325     bool value 
= CBox()->GetValue(); 
1326     if ( value 
!= m_startValue 
) 
1331         if (grid
->GetTable()->CanGetValueAs(row
, col
, wxGRID_VALUE_BOOL
)) 
1332             grid
->GetTable()->SetValueAsBool(row
, col
, value
); 
1334             grid
->GetTable()->SetValue(row
, col
, value 
? _T("1") : wxEmptyString
); 
1340 void wxGridCellBoolEditor::Reset() 
1342     wxASSERT_MSG(m_control
, 
1343                  wxT("The wxGridCellEditor must be Created first!")); 
1345     CBox()->SetValue(m_startValue
); 
1348 void wxGridCellBoolEditor::StartingClick() 
1350     CBox()->SetValue(!CBox()->GetValue()); 
1353 bool wxGridCellBoolEditor::IsAcceptedKey(wxKeyEvent
& event
) 
1355     if ( wxGridCellEditor::IsAcceptedKey(event
) ) 
1357         int keycode 
= event
.GetKeyCode(); 
1370 void wxGridCellBoolEditor::StartingKey(wxKeyEvent
& event
) 
1372     int keycode 
= event
.GetKeyCode(); 
1376             CBox()->SetValue(!CBox()->GetValue()); 
1380             CBox()->SetValue(true); 
1384             CBox()->SetValue(false); 
1390 // return the value as "1" for true and the empty string for false 
1391 wxString 
wxGridCellBoolEditor::GetValue() const 
1393   bool bSet 
= CBox()->GetValue(); 
1394   return bSet 
? _T("1") : wxEmptyString
; 
1397 #endif // wxUSE_CHECKBOX 
1401 // ---------------------------------------------------------------------------- 
1402 // wxGridCellChoiceEditor 
1403 // ---------------------------------------------------------------------------- 
1405 wxGridCellChoiceEditor::wxGridCellChoiceEditor(const wxArrayString
& choices
, 
1407     : m_choices(choices
), 
1408       m_allowOthers(allowOthers
) { } 
1410 wxGridCellChoiceEditor::wxGridCellChoiceEditor(size_t count
, 
1411                                                const wxString choices
[], 
1413                       : m_allowOthers(allowOthers
) 
1417         m_choices
.Alloc(count
); 
1418         for ( size_t n 
= 0; n 
< count
; n
++ ) 
1420             m_choices
.Add(choices
[n
]); 
1425 wxGridCellEditor 
*wxGridCellChoiceEditor::Clone() const 
1427     wxGridCellChoiceEditor 
*editor 
= new wxGridCellChoiceEditor
; 
1428     editor
->m_allowOthers 
= m_allowOthers
; 
1429     editor
->m_choices 
= m_choices
; 
1434 void wxGridCellChoiceEditor::Create(wxWindow
* parent
, 
1436                                     wxEvtHandler
* evtHandler
) 
1438     m_control 
= new wxComboBox(parent
, id
, wxEmptyString
, 
1439                                wxDefaultPosition
, wxDefaultSize
, 
1441                                m_allowOthers 
? 0 : wxCB_READONLY
); 
1443     wxGridCellEditor::Create(parent
, id
, evtHandler
); 
1446 void wxGridCellChoiceEditor::PaintBackground(const wxRect
& rectCell
, 
1447                                              wxGridCellAttr 
* attr
) 
1449     // as we fill the entire client area, don't do anything here to minimize 
1452     // TODO: It doesn't actually fill the client area since the height of a 
1453     // combo always defaults to the standard...  Until someone has time to 
1454     // figure out the right rectangle to paint, just do it the normal way... 
1455     wxGridCellEditor::PaintBackground(rectCell
, attr
); 
1458 void wxGridCellChoiceEditor::BeginEdit(int row
, int col
, wxGrid
* grid
) 
1460     wxASSERT_MSG(m_control
, 
1461                  wxT("The wxGridCellEditor must be Created first!")); 
1463     m_startValue 
= grid
->GetTable()->GetValue(row
, col
); 
1466         Combo()->SetValue(m_startValue
); 
1469         // find the right position, or default to the first if not found 
1470         int pos 
= Combo()->FindString(m_startValue
); 
1471         if (pos 
== wxNOT_FOUND
) 
1473         Combo()->SetSelection(pos
); 
1475     Combo()->SetInsertionPointEnd(); 
1476     Combo()->SetFocus(); 
1479 bool wxGridCellChoiceEditor::EndEdit(int row
, int col
, 
1482     wxString value 
= Combo()->GetValue(); 
1483     if ( value 
== m_startValue 
) 
1486     grid
->GetTable()->SetValue(row
, col
, value
); 
1491 void wxGridCellChoiceEditor::Reset() 
1493     Combo()->SetValue(m_startValue
); 
1494     Combo()->SetInsertionPointEnd(); 
1497 void wxGridCellChoiceEditor::SetParameters(const wxString
& params
) 
1507     wxStringTokenizer 
tk(params
, _T(',')); 
1508     while ( tk
.HasMoreTokens() ) 
1510         m_choices
.Add(tk
.GetNextToken()); 
1514 // return the value in the text control 
1515 wxString 
wxGridCellChoiceEditor::GetValue() const 
1517   return Combo()->GetValue(); 
1520 #endif // wxUSE_COMBOBOX 
1522 // ---------------------------------------------------------------------------- 
1523 // wxGridCellEditorEvtHandler 
1524 // ---------------------------------------------------------------------------- 
1526 void wxGridCellEditorEvtHandler::OnKillFocus(wxFocusEvent
& event
) 
1529     m_grid
->DisableCellEditControl(); 
1534 void wxGridCellEditorEvtHandler::OnKeyDown(wxKeyEvent
& event
) 
1536     switch ( event
.GetKeyCode() ) 
1540             m_grid
->DisableCellEditControl(); 
1544             m_grid
->GetEventHandler()->ProcessEvent( event 
); 
1548         case WXK_NUMPAD_ENTER
: 
1549             if (!m_grid
->GetEventHandler()->ProcessEvent(event
)) 
1550                 m_editor
->HandleReturn(event
); 
1558 void wxGridCellEditorEvtHandler::OnChar(wxKeyEvent
& event
) 
1560     switch ( event
.GetKeyCode() ) 
1565         case WXK_NUMPAD_ENTER
: 
1573 // ---------------------------------------------------------------------------- 
1574 // wxGridCellWorker is an (almost) empty common base class for 
1575 // wxGridCellRenderer and wxGridCellEditor managing ref counting 
1576 // ---------------------------------------------------------------------------- 
1578 void wxGridCellWorker::SetParameters(const wxString
& WXUNUSED(params
)) 
1583 wxGridCellWorker::~wxGridCellWorker() 
1587 // ============================================================================ 
1589 // ============================================================================ 
1591 // ---------------------------------------------------------------------------- 
1592 // wxGridCellRenderer 
1593 // ---------------------------------------------------------------------------- 
1595 void wxGridCellRenderer::Draw(wxGrid
& grid
, 
1596                               wxGridCellAttr
& attr
, 
1599                               int WXUNUSED(row
), int WXUNUSED(col
), 
1602     dc
.SetBackgroundMode( wxSOLID 
); 
1604     // grey out fields if the grid is disabled 
1605     if( grid
.IsEnabled() ) 
1609             dc
.SetBrush( wxBrush(grid
.GetSelectionBackground(), wxSOLID
) ); 
1613             dc
.SetBrush( wxBrush(attr
.GetBackgroundColour(), wxSOLID
) ); 
1618         dc
.SetBrush(wxBrush(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE
), wxSOLID
)); 
1621     dc
.SetPen( *wxTRANSPARENT_PEN 
); 
1622     dc
.DrawRectangle(rect
); 
1625 // ---------------------------------------------------------------------------- 
1626 // wxGridCellStringRenderer 
1627 // ---------------------------------------------------------------------------- 
1629 void wxGridCellStringRenderer::SetTextColoursAndFont(wxGrid
& grid
, 
1630                                                      wxGridCellAttr
& attr
, 
1634     dc
.SetBackgroundMode( wxTRANSPARENT 
); 
1636     // TODO some special colours for attr.IsReadOnly() case? 
1638     // different coloured text when the grid is disabled 
1639     if( grid
.IsEnabled() ) 
1643           dc
.SetTextBackground( grid
.GetSelectionBackground() ); 
1644           dc
.SetTextForeground( grid
.GetSelectionForeground() ); 
1648           dc
.SetTextBackground( attr
.GetBackgroundColour() ); 
1649           dc
.SetTextForeground( attr
.GetTextColour() ); 
1654       dc
.SetTextBackground(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE
)); 
1655       dc
.SetTextForeground(wxSystemSettings::GetColour(wxSYS_COLOUR_GRAYTEXT
)); 
1658     dc
.SetFont( attr
.GetFont() ); 
1661 wxSize 
wxGridCellStringRenderer::DoGetBestSize(wxGridCellAttr
& attr
, 
1663                                                const wxString
& text
) 
1665     wxCoord x 
= 0, y 
= 0, max_x 
= 0; 
1666     dc
.SetFont(attr
.GetFont()); 
1667     wxStringTokenizer 
tk(text
, _T('\n')); 
1668     while ( tk
.HasMoreTokens() ) 
1670         dc
.GetTextExtent(tk
.GetNextToken(), &x
, &y
); 
1671         max_x 
= wxMax(max_x
, x
); 
1674     y 
*= 1 + text
.Freq(wxT('\n')); // multiply by the number of lines. 
1676     return wxSize(max_x
, y
); 
1679 wxSize 
wxGridCellStringRenderer::GetBestSize(wxGrid
& grid
, 
1680                                              wxGridCellAttr
& attr
, 
1684     return DoGetBestSize(attr
, dc
, grid
.GetCellValue(row
, col
)); 
1687 void wxGridCellStringRenderer::Draw(wxGrid
& grid
, 
1688                                     wxGridCellAttr
& attr
, 
1690                                     const wxRect
& rectCell
, 
1694     wxRect rect 
= rectCell
; 
1697     // erase only this cells background, overflow cells should have been erased 
1698     wxGridCellRenderer::Draw(grid
, attr
, dc
, rectCell
, row
, col
, isSelected
); 
1701     attr
.GetAlignment(&hAlign
, &vAlign
); 
1703     int overflowCols 
= 0; 
1705     if (attr
.GetOverflow()) 
1707         int cols 
= grid
.GetNumberCols(); 
1708         int best_width 
= GetBestSize(grid
,attr
,dc
,row
,col
).GetWidth(); 
1709         int cell_rows
, cell_cols
; 
1710         attr
.GetSize( &cell_rows
, &cell_cols 
); // shouldn't get here if <=0 
1711         if ((best_width 
> rectCell
.width
) && (col 
< cols
) && grid
.GetTable()) 
1713             int i
, c_cols
, c_rows
; 
1714             for (i 
= col
+cell_cols
; i 
< cols
; i
++) 
1716                 bool is_empty 
= true; 
1717                 for (int j
=row
; j
<row
+cell_rows
; j
++) 
1719                     // check w/ anchor cell for multicell block 
1720                     grid
.GetCellSize(j
, i
, &c_rows
, &c_cols
); 
1721                     if (c_rows 
> 0) c_rows 
= 0; 
1722                     if (!grid
.GetTable()->IsEmptyCell(j
+c_rows
, i
)) 
1729                     rect
.width 
+= grid
.GetColSize(i
); 
1735                 if (rect
.width 
>= best_width
) break; 
1737             overflowCols 
= i 
- col 
- cell_cols 
+ 1; 
1738             if (overflowCols 
>= cols
) overflowCols 
= cols 
- 1; 
1741         if (overflowCols 
> 0) // redraw overflow cells w/ proper hilight 
1743             hAlign 
= wxALIGN_LEFT
; // if oveflowed then it's left aligned 
1745             clip
.x 
+= rectCell
.width
; 
1746             // draw each overflow cell individually 
1747             int col_end 
= col
+cell_cols
+overflowCols
; 
1748             if (col_end 
>= grid
.GetNumberCols()) 
1749                 col_end 
= grid
.GetNumberCols() - 1; 
1750             for (int i 
= col
+cell_cols
; i 
<= col_end
; i
++) 
1752                 clip
.width 
= grid
.GetColSize(i
) - 1; 
1753                 dc
.DestroyClippingRegion(); 
1754                 dc
.SetClippingRegion(clip
); 
1756                 SetTextColoursAndFont(grid
, attr
, dc
, 
1757                         grid
.IsInSelection(row
,i
)); 
1759                 grid
.DrawTextRectangle(dc
, grid
.GetCellValue(row
, col
), 
1760                         rect
, hAlign
, vAlign
); 
1761                 clip
.x 
+= grid
.GetColSize(i
) - 1; 
1767             dc
.DestroyClippingRegion(); 
1771     // now we only have to draw the text 
1772     SetTextColoursAndFont(grid
, attr
, dc
, isSelected
); 
1774     grid
.DrawTextRectangle(dc
, grid
.GetCellValue(row
, col
), 
1775                            rect
, hAlign
, vAlign
); 
1778 // ---------------------------------------------------------------------------- 
1779 // wxGridCellNumberRenderer 
1780 // ---------------------------------------------------------------------------- 
1782 wxString 
wxGridCellNumberRenderer::GetString(wxGrid
& grid
, int row
, int col
) 
1784     wxGridTableBase 
*table 
= grid
.GetTable(); 
1786     if ( table
->CanGetValueAs(row
, col
, wxGRID_VALUE_NUMBER
) ) 
1788         text
.Printf(_T("%ld"), table
->GetValueAsLong(row
, col
)); 
1792         text 
= table
->GetValue(row
, col
); 
1798 void wxGridCellNumberRenderer::Draw(wxGrid
& grid
, 
1799                                     wxGridCellAttr
& attr
, 
1801                                     const wxRect
& rectCell
, 
1805     wxGridCellRenderer::Draw(grid
, attr
, dc
, rectCell
, row
, col
, isSelected
); 
1807     SetTextColoursAndFont(grid
, attr
, dc
, isSelected
); 
1809     // draw the text right aligned by default 
1811     attr
.GetAlignment(&hAlign
, &vAlign
); 
1812     hAlign 
= wxALIGN_RIGHT
; 
1814     wxRect rect 
= rectCell
; 
1817     grid
.DrawTextRectangle(dc
, GetString(grid
, row
, col
), rect
, hAlign
, vAlign
); 
1820 wxSize 
wxGridCellNumberRenderer::GetBestSize(wxGrid
& grid
, 
1821                                              wxGridCellAttr
& attr
, 
1825     return DoGetBestSize(attr
, dc
, GetString(grid
, row
, col
)); 
1828 // ---------------------------------------------------------------------------- 
1829 // wxGridCellFloatRenderer 
1830 // ---------------------------------------------------------------------------- 
1832 wxGridCellFloatRenderer::wxGridCellFloatRenderer(int width
, int precision
) 
1835     SetPrecision(precision
); 
1838 wxGridCellRenderer 
*wxGridCellFloatRenderer::Clone() const 
1840     wxGridCellFloatRenderer 
*renderer 
= new wxGridCellFloatRenderer
; 
1841     renderer
->m_width 
= m_width
; 
1842     renderer
->m_precision 
= m_precision
; 
1843     renderer
->m_format 
= m_format
; 
1848 wxString 
wxGridCellFloatRenderer::GetString(wxGrid
& grid
, int row
, int col
) 
1850     wxGridTableBase 
*table 
= grid
.GetTable(); 
1855     if ( table
->CanGetValueAs(row
, col
, wxGRID_VALUE_FLOAT
) ) 
1857         val 
= table
->GetValueAsDouble(row
, col
); 
1862         text 
= table
->GetValue(row
, col
); 
1863         hasDouble 
= text
.ToDouble(&val
); 
1870             if ( m_width 
== -1 ) 
1872                 if ( m_precision 
== -1 ) 
1874                     // default width/precision 
1875                     m_format 
= _T("%f"); 
1879                     m_format
.Printf(_T("%%.%df"), m_precision
); 
1882             else if ( m_precision 
== -1 ) 
1884                 // default precision 
1885                 m_format
.Printf(_T("%%%d.f"), m_width
); 
1889                 m_format
.Printf(_T("%%%d.%df"), m_width
, m_precision
); 
1893         text
.Printf(m_format
, val
); 
1896     //else: text already contains the string 
1901 void wxGridCellFloatRenderer::Draw(wxGrid
& grid
, 
1902                                    wxGridCellAttr
& attr
, 
1904                                    const wxRect
& rectCell
, 
1908     wxGridCellRenderer::Draw(grid
, attr
, dc
, rectCell
, row
, col
, isSelected
); 
1910     SetTextColoursAndFont(grid
, attr
, dc
, isSelected
); 
1912     // draw the text right aligned by default 
1914     attr
.GetAlignment(&hAlign
, &vAlign
); 
1915     hAlign 
= wxALIGN_RIGHT
; 
1917     wxRect rect 
= rectCell
; 
1920     grid
.DrawTextRectangle(dc
, GetString(grid
, row
, col
), rect
, hAlign
, vAlign
); 
1923 wxSize 
wxGridCellFloatRenderer::GetBestSize(wxGrid
& grid
, 
1924                                             wxGridCellAttr
& attr
, 
1928     return DoGetBestSize(attr
, dc
, GetString(grid
, row
, col
)); 
1931 void wxGridCellFloatRenderer::SetParameters(const wxString
& params
) 
1935         // reset to defaults 
1941         wxString tmp 
= params
.BeforeFirst(_T(',')); 
1945             if ( tmp
.ToLong(&width
) ) 
1947                 SetWidth((int)width
); 
1951                 wxLogDebug(_T("Invalid wxGridCellFloatRenderer width parameter string '%s ignored"), params
.c_str()); 
1955                 tmp 
= params
.AfterFirst(_T(',')); 
1959             if ( tmp
.ToLong(&precision
) ) 
1961                 SetPrecision((int)precision
); 
1965                 wxLogDebug(_T("Invalid wxGridCellFloatRenderer precision parameter string '%s ignored"), params
.c_str()); 
1973 // ---------------------------------------------------------------------------- 
1974 // wxGridCellBoolRenderer 
1975 // ---------------------------------------------------------------------------- 
1977 wxSize 
wxGridCellBoolRenderer::ms_sizeCheckMark
; 
1979 // FIXME these checkbox size calculations are really ugly... 
1981 // between checkmark and box 
1982 static const wxCoord wxGRID_CHECKMARK_MARGIN 
= 2; 
1984 wxSize 
wxGridCellBoolRenderer::GetBestSize(wxGrid
& grid
, 
1985                                            wxGridCellAttr
& WXUNUSED(attr
), 
1990     // compute it only once (no locks for MT safeness in GUI thread...) 
1991     if ( !ms_sizeCheckMark
.x 
) 
1993         // get checkbox size 
1994         wxCheckBox 
*checkbox 
= new wxCheckBox(&grid
, wxID_ANY
, wxEmptyString
); 
1995         wxSize size 
= checkbox
->GetBestSize(); 
1996         wxCoord checkSize 
= size
.y 
+ 2*wxGRID_CHECKMARK_MARGIN
; 
1998         // FIXME wxGTK::wxCheckBox::GetBestSize() gives "wrong" result 
1999 #if defined(__WXGTK__) || defined(__WXMOTIF__) 
2000         checkSize 
-= size
.y 
/ 2; 
2005         ms_sizeCheckMark
.x 
= ms_sizeCheckMark
.y 
= checkSize
; 
2008     return ms_sizeCheckMark
; 
2011 void wxGridCellBoolRenderer::Draw(wxGrid
& grid
, 
2012                                   wxGridCellAttr
& attr
, 
2018     wxGridCellRenderer::Draw(grid
, attr
, dc
, rect
, row
, col
, isSelected
); 
2020     // draw a check mark in the centre (ignoring alignment - TODO) 
2021     wxSize size 
= GetBestSize(grid
, attr
, dc
, row
, col
); 
2023     // don't draw outside the cell 
2024     wxCoord minSize 
= wxMin(rect
.width
, rect
.height
); 
2025     if ( size
.x 
>= minSize 
|| size
.y 
>= minSize 
) 
2027         // and even leave (at least) 1 pixel margin 
2028         size
.x 
= size
.y 
= minSize 
- 2; 
2031     // draw a border around checkmark 
2033     attr
.GetAlignment(& hAlign
, &vAlign
); 
2036     if (hAlign 
== wxALIGN_CENTRE
) 
2038         rectBorder
.x 
= rect
.x 
+ rect
.width
/2 - size
.x
/2; 
2039         rectBorder
.y 
= rect
.y 
+ rect
.height
/2 - size
.y
/2; 
2040         rectBorder
.width 
= size
.x
; 
2041         rectBorder
.height 
= size
.y
; 
2043     else if (hAlign 
== wxALIGN_LEFT
) 
2045         rectBorder
.x 
= rect
.x 
+ 2; 
2046         rectBorder
.y 
= rect
.y 
+ rect
.height
/2 - size
.y
/2; 
2047         rectBorder
.width 
= size
.x
; 
2048         rectBorder
.height 
= size
.y
; 
2050     else if (hAlign 
== wxALIGN_RIGHT
) 
2052         rectBorder
.x 
= rect
.x 
+ rect
.width 
- size
.x 
- 2; 
2053         rectBorder
.y 
= rect
.y 
+ rect
.height
/2 - size
.y
/2; 
2054         rectBorder
.width 
= size
.x
; 
2055         rectBorder
.height 
= size
.y
; 
2059     if ( grid
.GetTable()->CanGetValueAs(row
, col
, wxGRID_VALUE_BOOL
) ) 
2060         value 
= grid
.GetTable()->GetValueAsBool(row
, col
); 
2063         wxString 
cellval( grid
.GetTable()->GetValue(row
, col
) ); 
2064         value 
= !( !cellval 
|| (cellval 
== wxT("0")) ); 
2069         wxRect rectMark 
= rectBorder
; 
2071         // MSW DrawCheckMark() is weird (and should probably be changed...) 
2072         rectMark
.Inflate(-wxGRID_CHECKMARK_MARGIN
/2); 
2076         rectMark
.Inflate(-wxGRID_CHECKMARK_MARGIN
); 
2079         dc
.SetTextForeground(attr
.GetTextColour()); 
2080         dc
.DrawCheckMark(rectMark
); 
2083     dc
.SetBrush(*wxTRANSPARENT_BRUSH
); 
2084     dc
.SetPen(wxPen(attr
.GetTextColour(), 1, wxSOLID
)); 
2085     dc
.DrawRectangle(rectBorder
); 
2088 // ---------------------------------------------------------------------------- 
2090 // ---------------------------------------------------------------------------- 
2092 void wxGridCellAttr::Init(wxGridCellAttr 
*attrDefault
) 
2096     m_isReadOnly 
= Unset
; 
2101     m_attrkind 
= wxGridCellAttr::Cell
; 
2103     m_sizeRows 
= m_sizeCols 
= 1; 
2104     m_overflow 
= UnsetOverflow
; 
2106     SetDefAttr(attrDefault
); 
2109 wxGridCellAttr 
*wxGridCellAttr::Clone() const 
2111     wxGridCellAttr 
*attr 
= new wxGridCellAttr(m_defGridAttr
); 
2113     if ( HasTextColour() ) 
2114         attr
->SetTextColour(GetTextColour()); 
2115     if ( HasBackgroundColour() ) 
2116         attr
->SetBackgroundColour(GetBackgroundColour()); 
2118         attr
->SetFont(GetFont()); 
2119     if ( HasAlignment() ) 
2120         attr
->SetAlignment(m_hAlign
, m_vAlign
); 
2122     attr
->SetSize( m_sizeRows
, m_sizeCols 
); 
2126         attr
->SetRenderer(m_renderer
); 
2127         m_renderer
->IncRef(); 
2131         attr
->SetEditor(m_editor
); 
2136         attr
->SetReadOnly(); 
2138     attr
->SetKind( m_attrkind 
); 
2143 void wxGridCellAttr::MergeWith(wxGridCellAttr 
*mergefrom
) 
2145     if ( !HasTextColour() && mergefrom
->HasTextColour() ) 
2146         SetTextColour(mergefrom
->GetTextColour()); 
2147     if ( !HasBackgroundColour() && mergefrom
->HasBackgroundColour() ) 
2148         SetBackgroundColour(mergefrom
->GetBackgroundColour()); 
2149     if ( !HasFont() && mergefrom
->HasFont() ) 
2150         SetFont(mergefrom
->GetFont()); 
2151     if ( !HasAlignment() && mergefrom
->HasAlignment() ){ 
2153         mergefrom
->GetAlignment( &hAlign
, &vAlign
); 
2154         SetAlignment(hAlign
, vAlign
); 
2156     if ( !HasSize() && mergefrom
->HasSize() ) 
2157         mergefrom
->GetSize( &m_sizeRows
, &m_sizeCols 
); 
2159     // Directly access member functions as GetRender/Editor don't just return 
2160     // m_renderer/m_editor 
2162     // Maybe add support for merge of Render and Editor? 
2163     if (!HasRenderer() && mergefrom
->HasRenderer() ) 
2165         m_renderer 
= mergefrom
->m_renderer
; 
2166         m_renderer
->IncRef(); 
2168     if ( !HasEditor() && mergefrom
->HasEditor() ) 
2170         m_editor 
=  mergefrom
->m_editor
; 
2173     if ( !HasReadWriteMode()  && mergefrom
->HasReadWriteMode() ) 
2174         SetReadOnly(mergefrom
->IsReadOnly()); 
2176     if (!HasOverflowMode()  && mergefrom
->HasOverflowMode() ) 
2177         SetOverflow(mergefrom
->GetOverflow()); 
2179     SetDefAttr(mergefrom
->m_defGridAttr
); 
2182 void wxGridCellAttr::SetSize(int num_rows
, int num_cols
) 
2184     // The size of a cell is normally 1,1 
2186     // If this cell is larger (2,2) then this is the top left cell 
2187     // the other cells that will be covered (lower right cells) must be 
2188     // set to negative or zero values such that 
2189     // row + num_rows of the covered cell points to the larger cell (this cell) 
2190     // same goes for the col + num_cols. 
2192     // Size of 0,0 is NOT valid, neither is <=0 and any positive value 
2194     wxASSERT_MSG( (!((num_rows
>0)&&(num_cols
<=0)) || 
2195                   !((num_rows
<=0)&&(num_cols
>0)) || 
2196                   !((num_rows
==0)&&(num_cols
==0))), 
2197                   wxT("wxGridCellAttr::SetSize only takes two postive values or negative/zero values")); 
2199     m_sizeRows 
= num_rows
; 
2200     m_sizeCols 
= num_cols
; 
2203 const wxColour
& wxGridCellAttr::GetTextColour() const 
2205     if (HasTextColour()) 
2209     else if (m_defGridAttr 
&& m_defGridAttr 
!= this) 
2211         return m_defGridAttr
->GetTextColour(); 
2215         wxFAIL_MSG(wxT("Missing default cell attribute")); 
2216         return wxNullColour
; 
2221 const wxColour
& wxGridCellAttr::GetBackgroundColour() const 
2223     if (HasBackgroundColour()) 
2225     else if (m_defGridAttr 
&& m_defGridAttr 
!= this) 
2226         return m_defGridAttr
->GetBackgroundColour(); 
2229         wxFAIL_MSG(wxT("Missing default cell attribute")); 
2230         return wxNullColour
; 
2235 const wxFont
& wxGridCellAttr::GetFont() const 
2239     else if (m_defGridAttr 
&& m_defGridAttr 
!= this) 
2240         return m_defGridAttr
->GetFont(); 
2243         wxFAIL_MSG(wxT("Missing default cell attribute")); 
2249 void wxGridCellAttr::GetAlignment(int *hAlign
, int *vAlign
) const 
2253         if ( hAlign 
) *hAlign 
= m_hAlign
; 
2254         if ( vAlign 
) *vAlign 
= m_vAlign
; 
2256     else if (m_defGridAttr 
&& m_defGridAttr 
!= this) 
2257         m_defGridAttr
->GetAlignment(hAlign
, vAlign
); 
2260         wxFAIL_MSG(wxT("Missing default cell attribute")); 
2264 void wxGridCellAttr::GetSize( int *num_rows
, int *num_cols 
) const 
2266     if ( num_rows 
) *num_rows 
= m_sizeRows
; 
2267     if ( num_cols 
) *num_cols 
= m_sizeCols
; 
2270 // GetRenderer and GetEditor use a slightly different decision path about 
2271 // which attribute to use.  If a non-default attr object has one then it is 
2272 // used, otherwise the default editor or renderer is fetched from the grid and 
2273 // used.  It should be the default for the data type of the cell.  If it is 
2274 // NULL (because the table has a type that the grid does not have in its 
2275 // registry,) then the grid's default editor or renderer is used. 
2277 wxGridCellRenderer
* wxGridCellAttr::GetRenderer(wxGrid
* grid
, int row
, int col
) const 
2279     wxGridCellRenderer 
*renderer
; 
2281     if ( m_renderer 
&& this != m_defGridAttr 
) 
2283         // use the cells renderer if it has one 
2284         renderer 
= m_renderer
; 
2287     else // no non default cell renderer 
2289         // get default renderer for the data type 
2292             // GetDefaultRendererForCell() will do IncRef() for us 
2293             renderer 
= grid
->GetDefaultRendererForCell(row
, col
); 
2302             if (m_defGridAttr 
&&  this != m_defGridAttr 
) 
2304                 // if we still don't have one then use the grid default 
2305                 // (no need for IncRef() here neither) 
2306                 renderer 
= m_defGridAttr
->GetRenderer(NULL
, 0, 0); 
2308             else // default grid attr 
2310                 // use m_renderer which we had decided not to use initially 
2311                 renderer 
= m_renderer
; 
2318     // we're supposed to always find something 
2319     wxASSERT_MSG(renderer
, wxT("Missing default cell renderer")); 
2324 // same as above, except for s/renderer/editor/g 
2325 wxGridCellEditor
* wxGridCellAttr::GetEditor(wxGrid
* grid
, int row
, int col
) const 
2327     wxGridCellEditor 
*editor
; 
2329     if ( m_editor 
&& this != m_defGridAttr 
) 
2331         // use the cells editor if it has one 
2335     else // no non default cell editor 
2337         // get default editor for the data type 
2340             // GetDefaultEditorForCell() will do IncRef() for us 
2341             editor 
= grid
->GetDefaultEditorForCell(row
, col
); 
2350             if ( m_defGridAttr 
&& this != m_defGridAttr 
) 
2352                 // if we still don't have one then use the grid default 
2353                 // (no need for IncRef() here neither) 
2354                 editor 
= m_defGridAttr
->GetEditor(NULL
, 0, 0); 
2356             else // default grid attr 
2358                 // use m_editor which we had decided not to use initially 
2366     // we're supposed to always find something 
2367     wxASSERT_MSG(editor
, wxT("Missing default cell editor")); 
2372 // ---------------------------------------------------------------------------- 
2373 // wxGridCellAttrData 
2374 // ---------------------------------------------------------------------------- 
2376 void wxGridCellAttrData::SetAttr(wxGridCellAttr 
*attr
, int row
, int col
) 
2378     int n 
= FindIndex(row
, col
); 
2379     if ( n 
== wxNOT_FOUND 
) 
2381         // add the attribute 
2382         m_attrs
.Add(new wxGridCellWithAttr(row
, col
, attr
)); 
2386         // free the old attribute 
2387         m_attrs
[(size_t)n
].attr
->DecRef(); 
2391             // change the attribute 
2392             m_attrs
[(size_t)n
].attr 
= attr
; 
2396             // remove this attribute 
2397             m_attrs
.RemoveAt((size_t)n
); 
2402 wxGridCellAttr 
*wxGridCellAttrData::GetAttr(int row
, int col
) const 
2404     wxGridCellAttr 
*attr 
= (wxGridCellAttr 
*)NULL
; 
2406     int n 
= FindIndex(row
, col
); 
2407     if ( n 
!= wxNOT_FOUND 
) 
2409         attr 
= m_attrs
[(size_t)n
].attr
; 
2416 void wxGridCellAttrData::UpdateAttrRows( size_t pos
, int numRows 
) 
2418     size_t count 
= m_attrs
.GetCount(); 
2419     for ( size_t n 
= 0; n 
< count
; n
++ ) 
2421         wxGridCellCoords
& coords 
= m_attrs
[n
].coords
; 
2422         wxCoord row 
= coords
.GetRow(); 
2423         if ((size_t)row 
>= pos
) 
2427                 // If rows inserted, include row counter where necessary 
2428                 coords
.SetRow(row 
+ numRows
); 
2430             else if (numRows 
< 0) 
2432                 // If rows deleted ... 
2433                 if ((size_t)row 
>= pos 
- numRows
) 
2435                     // ...either decrement row counter (if row still exists)... 
2436                     coords
.SetRow(row 
+ numRows
); 
2440                     // ...or remove the attribute 
2441                     // No need to DecRef the attribute itself since this is 
2442                     // done be wxGridCellWithAttr's destructor! 
2443                     m_attrs
.RemoveAt(n
); 
2451 void wxGridCellAttrData::UpdateAttrCols( size_t pos
, int numCols 
) 
2453     size_t count 
= m_attrs
.GetCount(); 
2454     for ( size_t n 
= 0; n 
< count
; n
++ ) 
2456         wxGridCellCoords
& coords 
= m_attrs
[n
].coords
; 
2457         wxCoord col 
= coords
.GetCol(); 
2458         if ( (size_t)col 
>= pos 
) 
2462                 // If rows inserted, include row counter where necessary 
2463                 coords
.SetCol(col 
+ numCols
); 
2465             else if (numCols 
< 0) 
2467                 // If rows deleted ... 
2468                 if ((size_t)col 
>= pos 
- numCols
) 
2470                     // ...either decrement row counter (if row still exists)... 
2471                     coords
.SetCol(col 
+ numCols
); 
2475                     // ...or remove the attribute 
2476                     // No need to DecRef the attribute itself since this is 
2477                     // done be wxGridCellWithAttr's destructor! 
2478                     m_attrs
.RemoveAt(n
); 
2486 int wxGridCellAttrData::FindIndex(int row
, int col
) const 
2488     size_t count 
= m_attrs
.GetCount(); 
2489     for ( size_t n 
= 0; n 
< count
; n
++ ) 
2491         const wxGridCellCoords
& coords 
= m_attrs
[n
].coords
; 
2492         if ( (coords
.GetRow() == row
) && (coords
.GetCol() == col
) ) 
2501 // ---------------------------------------------------------------------------- 
2502 // wxGridRowOrColAttrData 
2503 // ---------------------------------------------------------------------------- 
2505 wxGridRowOrColAttrData::~wxGridRowOrColAttrData() 
2507     size_t count 
= m_attrs
.Count(); 
2508     for ( size_t n 
= 0; n 
< count
; n
++ ) 
2510         m_attrs
[n
]->DecRef(); 
2514 wxGridCellAttr 
*wxGridRowOrColAttrData::GetAttr(int rowOrCol
) const 
2516     wxGridCellAttr 
*attr 
= (wxGridCellAttr 
*)NULL
; 
2518     int n 
= m_rowsOrCols
.Index(rowOrCol
); 
2519     if ( n 
!= wxNOT_FOUND 
) 
2521         attr 
= m_attrs
[(size_t)n
]; 
2528 void wxGridRowOrColAttrData::SetAttr(wxGridCellAttr 
*attr
, int rowOrCol
) 
2530     int i 
= m_rowsOrCols
.Index(rowOrCol
); 
2531     if ( i 
== wxNOT_FOUND 
) 
2533         // add the attribute 
2534         m_rowsOrCols
.Add(rowOrCol
); 
2539         size_t n 
= (size_t)i
; 
2542             // change the attribute 
2543             m_attrs
[n
]->DecRef(); 
2548             // remove this attribute 
2549             m_attrs
[n
]->DecRef(); 
2550             m_rowsOrCols
.RemoveAt(n
); 
2551             m_attrs
.RemoveAt(n
); 
2556 void wxGridRowOrColAttrData::UpdateAttrRowsOrCols( size_t pos
, int numRowsOrCols 
) 
2558     size_t count 
= m_attrs
.GetCount(); 
2559     for ( size_t n 
= 0; n 
< count
; n
++ ) 
2561         int & rowOrCol 
= m_rowsOrCols
[n
]; 
2562         if ( (size_t)rowOrCol 
>= pos 
) 
2564             if ( numRowsOrCols 
> 0 ) 
2566                 // If rows inserted, include row counter where necessary 
2567                 rowOrCol 
+= numRowsOrCols
; 
2569             else if ( numRowsOrCols 
< 0) 
2571                 // If rows deleted, either decrement row counter (if row still exists) 
2572                 if ((size_t)rowOrCol 
>= pos 
- numRowsOrCols
) 
2573                     rowOrCol 
+= numRowsOrCols
; 
2576                     m_rowsOrCols
.RemoveAt(n
); 
2577                     m_attrs
[n
]->DecRef(); 
2578                     m_attrs
.RemoveAt(n
); 
2586 // ---------------------------------------------------------------------------- 
2587 // wxGridCellAttrProvider 
2588 // ---------------------------------------------------------------------------- 
2590 wxGridCellAttrProvider::wxGridCellAttrProvider() 
2592     m_data 
= (wxGridCellAttrProviderData 
*)NULL
; 
2595 wxGridCellAttrProvider::~wxGridCellAttrProvider() 
2600 void wxGridCellAttrProvider::InitData() 
2602     m_data 
= new wxGridCellAttrProviderData
; 
2605 wxGridCellAttr 
*wxGridCellAttrProvider::GetAttr(int row
, int col
, 
2606                                                 wxGridCellAttr::wxAttrKind  kind 
) const 
2608     wxGridCellAttr 
*attr 
= (wxGridCellAttr 
*)NULL
; 
2613             case (wxGridCellAttr::Any
): 
2614                 //Get cached merge attributes. 
2615                 // Currenlty not used as no cache implemented as not mutiable 
2616                 // attr = m_data->m_mergeAttr.GetAttr(row, col); 
2619                     //Basicaly implement old version. 
2620                     //Also check merge cache, so we don't have to re-merge every time.. 
2621                     wxGridCellAttr 
*attrcell 
= m_data
->m_cellAttrs
.GetAttr(row
, col
); 
2622                     wxGridCellAttr 
*attrrow 
= m_data
->m_rowAttrs
.GetAttr(row
); 
2623                     wxGridCellAttr 
*attrcol 
= m_data
->m_colAttrs
.GetAttr(col
); 
2625                     if((attrcell 
!= attrrow
) && (attrrow 
!= attrcol
) && (attrcell 
!= attrcol
)){ 
2626                         // Two or more are non NULL 
2627                         attr 
= new wxGridCellAttr
; 
2628                         attr
->SetKind(wxGridCellAttr::Merged
); 
2632                             attr
->MergeWith(attrcell
); 
2636                             attr
->MergeWith(attrcol
); 
2640                             attr
->MergeWith(attrrow
); 
2643                         //store merge attr if cache implemented 
2645                         //m_data->m_mergeAttr.SetAttr(attr, row, col); 
2649                         // one or none is non null return it or null. 
2650                         if(attrrow
) attr 
= attrrow
; 
2666             case (wxGridCellAttr::Cell
): 
2667                 attr 
= m_data
->m_cellAttrs
.GetAttr(row
, col
); 
2669             case (wxGridCellAttr::Col
): 
2670                 attr 
= m_data
->m_colAttrs
.GetAttr(col
); 
2672             case (wxGridCellAttr::Row
): 
2673                 attr 
= m_data
->m_rowAttrs
.GetAttr(row
); 
2677                 // (wxGridCellAttr::Default): 
2678                 // (wxGridCellAttr::Merged): 
2685 void wxGridCellAttrProvider::SetAttr(wxGridCellAttr 
*attr
, 
2691     m_data
->m_cellAttrs
.SetAttr(attr
, row
, col
); 
2694 void wxGridCellAttrProvider::SetRowAttr(wxGridCellAttr 
*attr
, int row
) 
2699     m_data
->m_rowAttrs
.SetAttr(attr
, row
); 
2702 void wxGridCellAttrProvider::SetColAttr(wxGridCellAttr 
*attr
, int col
) 
2707     m_data
->m_colAttrs
.SetAttr(attr
, col
); 
2710 void wxGridCellAttrProvider::UpdateAttrRows( size_t pos
, int numRows 
) 
2714         m_data
->m_cellAttrs
.UpdateAttrRows( pos
, numRows 
); 
2716         m_data
->m_rowAttrs
.UpdateAttrRowsOrCols( pos
, numRows 
); 
2720 void wxGridCellAttrProvider::UpdateAttrCols( size_t pos
, int numCols 
) 
2724         m_data
->m_cellAttrs
.UpdateAttrCols( pos
, numCols 
); 
2726         m_data
->m_colAttrs
.UpdateAttrRowsOrCols( pos
, numCols 
); 
2730 // ---------------------------------------------------------------------------- 
2731 // wxGridTypeRegistry 
2732 // ---------------------------------------------------------------------------- 
2734 wxGridTypeRegistry::~wxGridTypeRegistry() 
2736     size_t count 
= m_typeinfo
.Count(); 
2737     for ( size_t i 
= 0; i 
< count
; i
++ ) 
2738         delete m_typeinfo
[i
]; 
2742 void wxGridTypeRegistry::RegisterDataType(const wxString
& typeName
, 
2743                                           wxGridCellRenderer
* renderer
, 
2744                                           wxGridCellEditor
* editor
) 
2746     wxGridDataTypeInfo
* info 
= new wxGridDataTypeInfo(typeName
, renderer
, editor
); 
2748     // is it already registered? 
2749     int loc 
= FindRegisteredDataType(typeName
); 
2750     if ( loc 
!= wxNOT_FOUND 
) 
2752         delete m_typeinfo
[loc
]; 
2753         m_typeinfo
[loc
] = info
; 
2757         m_typeinfo
.Add(info
); 
2761 int wxGridTypeRegistry::FindRegisteredDataType(const wxString
& typeName
) 
2763     size_t count 
= m_typeinfo
.GetCount(); 
2764     for ( size_t i 
= 0; i 
< count
; i
++ ) 
2766         if ( typeName 
== m_typeinfo
[i
]->m_typeName 
) 
2775 int wxGridTypeRegistry::FindDataType(const wxString
& typeName
) 
2777     int index 
= FindRegisteredDataType(typeName
); 
2778     if ( index 
== wxNOT_FOUND 
) 
2780         // check whether this is one of the standard ones, in which case 
2781         // register it "on the fly" 
2783         if ( typeName 
== wxGRID_VALUE_STRING 
) 
2785             RegisterDataType(wxGRID_VALUE_STRING
, 
2786                              new wxGridCellStringRenderer
, 
2787                              new wxGridCellTextEditor
); 
2789 #endif // wxUSE_TEXTCTRL 
2791         if ( typeName 
== wxGRID_VALUE_BOOL 
) 
2793             RegisterDataType(wxGRID_VALUE_BOOL
, 
2794                              new wxGridCellBoolRenderer
, 
2795                              new wxGridCellBoolEditor
); 
2797 #endif // wxUSE_CHECKBOX 
2799         if ( typeName 
== wxGRID_VALUE_NUMBER 
) 
2801             RegisterDataType(wxGRID_VALUE_NUMBER
, 
2802                              new wxGridCellNumberRenderer
, 
2803                              new wxGridCellNumberEditor
); 
2805         else if ( typeName 
== wxGRID_VALUE_FLOAT 
) 
2807             RegisterDataType(wxGRID_VALUE_FLOAT
, 
2808                              new wxGridCellFloatRenderer
, 
2809                              new wxGridCellFloatEditor
); 
2811 #endif // wxUSE_TEXTCTRL 
2813         if ( typeName 
== wxGRID_VALUE_CHOICE 
) 
2815             RegisterDataType(wxGRID_VALUE_CHOICE
, 
2816                              new wxGridCellStringRenderer
, 
2817                              new wxGridCellChoiceEditor
); 
2819 #endif // wxUSE_COMBOBOX 
2824         // we get here only if just added the entry for this type, so return 
2826         index 
= m_typeinfo
.GetCount() - 1; 
2832 int wxGridTypeRegistry::FindOrCloneDataType(const wxString
& typeName
) 
2834     int index 
= FindDataType(typeName
); 
2835     if ( index 
== wxNOT_FOUND 
) 
2837         // the first part of the typename is the "real" type, anything after ':' 
2838         // are the parameters for the renderer 
2839         index 
= FindDataType(typeName
.BeforeFirst(_T(':'))); 
2840         if ( index 
== wxNOT_FOUND 
) 
2845         wxGridCellRenderer 
*renderer 
= GetRenderer(index
); 
2846         wxGridCellRenderer 
*rendererOld 
= renderer
; 
2847         renderer 
= renderer
->Clone(); 
2848         rendererOld
->DecRef(); 
2850         wxGridCellEditor 
*editor 
= GetEditor(index
); 
2851         wxGridCellEditor 
*editorOld 
= editor
; 
2852         editor 
= editor
->Clone(); 
2853         editorOld
->DecRef(); 
2855         // do it even if there are no parameters to reset them to defaults 
2856         wxString params 
= typeName
.AfterFirst(_T(':')); 
2857         renderer
->SetParameters(params
); 
2858         editor
->SetParameters(params
); 
2860         // register the new typename 
2861         RegisterDataType(typeName
, renderer
, editor
); 
2863         // we just registered it, it's the last one 
2864         index 
= m_typeinfo
.GetCount() - 1; 
2870 wxGridCellRenderer
* wxGridTypeRegistry::GetRenderer(int index
) 
2872     wxGridCellRenderer
* renderer 
= m_typeinfo
[index
]->m_renderer
; 
2878 wxGridCellEditor
* wxGridTypeRegistry::GetEditor(int index
) 
2880     wxGridCellEditor
* editor 
= m_typeinfo
[index
]->m_editor
; 
2886 // ---------------------------------------------------------------------------- 
2888 // ---------------------------------------------------------------------------- 
2890 IMPLEMENT_ABSTRACT_CLASS( wxGridTableBase
, wxObject 
) 
2893 wxGridTableBase::wxGridTableBase() 
2895     m_view 
= (wxGrid 
*) NULL
; 
2896     m_attrProvider 
= (wxGridCellAttrProvider 
*) NULL
; 
2899 wxGridTableBase::~wxGridTableBase() 
2901     delete m_attrProvider
; 
2904 void wxGridTableBase::SetAttrProvider(wxGridCellAttrProvider 
*attrProvider
) 
2906     delete m_attrProvider
; 
2907     m_attrProvider 
= attrProvider
; 
2910 bool wxGridTableBase::CanHaveAttributes() 
2912     if ( ! GetAttrProvider() ) 
2914         // use the default attr provider by default 
2915         SetAttrProvider(new wxGridCellAttrProvider
); 
2920 wxGridCellAttr 
*wxGridTableBase::GetAttr(int row
, int col
, wxGridCellAttr::wxAttrKind  kind
) 
2922     if ( m_attrProvider 
) 
2923         return m_attrProvider
->GetAttr(row
, col
, kind
); 
2925         return (wxGridCellAttr 
*)NULL
; 
2929 void wxGridTableBase::SetAttr(wxGridCellAttr
* attr
, int row
, int col
) 
2931     if ( m_attrProvider 
) 
2933         attr
->SetKind(wxGridCellAttr::Cell
); 
2934         m_attrProvider
->SetAttr(attr
, row
, col
); 
2938         // as we take ownership of the pointer and don't store it, we must 
2944 void wxGridTableBase::SetRowAttr(wxGridCellAttr 
*attr
, int row
) 
2946     if ( m_attrProvider 
) 
2948         attr
->SetKind(wxGridCellAttr::Row
); 
2949         m_attrProvider
->SetRowAttr(attr
, row
); 
2953         // as we take ownership of the pointer and don't store it, we must 
2959 void wxGridTableBase::SetColAttr(wxGridCellAttr 
*attr
, int col
) 
2961     if ( m_attrProvider 
) 
2963         attr
->SetKind(wxGridCellAttr::Col
); 
2964         m_attrProvider
->SetColAttr(attr
, col
); 
2968         // as we take ownership of the pointer and don't store it, we must 
2974 bool wxGridTableBase::InsertRows( size_t WXUNUSED(pos
), 
2975                                   size_t WXUNUSED(numRows
) ) 
2977     wxFAIL_MSG( wxT("Called grid table class function InsertRows\nbut your derived table class does not override this function") ); 
2982 bool wxGridTableBase::AppendRows( size_t WXUNUSED(numRows
) ) 
2984     wxFAIL_MSG( wxT("Called grid table class function AppendRows\nbut your derived table class does not override this function")); 
2989 bool wxGridTableBase::DeleteRows( size_t WXUNUSED(pos
), 
2990                                   size_t WXUNUSED(numRows
) ) 
2992     wxFAIL_MSG( wxT("Called grid table class function DeleteRows\nbut your derived table class does not override this function")); 
2997 bool wxGridTableBase::InsertCols( size_t WXUNUSED(pos
), 
2998                                   size_t WXUNUSED(numCols
) ) 
3000     wxFAIL_MSG( wxT("Called grid table class function InsertCols\nbut your derived table class does not override this function")); 
3005 bool wxGridTableBase::AppendCols( size_t WXUNUSED(numCols
) ) 
3007     wxFAIL_MSG(wxT("Called grid table class function AppendCols\nbut your derived table class does not override this function")); 
3012 bool wxGridTableBase::DeleteCols( size_t WXUNUSED(pos
), 
3013                                   size_t WXUNUSED(numCols
) ) 
3015     wxFAIL_MSG( wxT("Called grid table class function DeleteCols\nbut your derived table class does not override this function")); 
3021 wxString 
wxGridTableBase::GetRowLabelValue( int row 
) 
3024     s 
<< row 
+ 1; // RD: Starting the rows at zero confuses users, no matter 
3025                   //     how much it makes sense to us geeks. 
3029 wxString 
wxGridTableBase::GetColLabelValue( int col 
) 
3031     // default col labels are: 
3032     //   cols 0 to 25   : A-Z 
3033     //   cols 26 to 675 : AA-ZZ 
3038     for ( n 
= 1; ; n
++ ) 
3040         s 
+= (wxChar
) (_T('A') + (wxChar
)( col%26 
)); 
3042         if ( col 
< 0 ) break; 
3045     // reverse the string... 
3047     for ( i 
= 0;  i 
< n
;  i
++ ) 
3056 wxString 
wxGridTableBase::GetTypeName( int WXUNUSED(row
), int WXUNUSED(col
) ) 
3058     return wxGRID_VALUE_STRING
; 
3061 bool wxGridTableBase::CanGetValueAs( int WXUNUSED(row
), int WXUNUSED(col
), 
3062                                      const wxString
& typeName 
) 
3064     return typeName 
== wxGRID_VALUE_STRING
; 
3067 bool wxGridTableBase::CanSetValueAs( int row
, int col
, const wxString
& typeName 
) 
3069     return CanGetValueAs(row
, col
, typeName
); 
3072 long wxGridTableBase::GetValueAsLong( int WXUNUSED(row
), int WXUNUSED(col
) ) 
3077 double wxGridTableBase::GetValueAsDouble( int WXUNUSED(row
), int WXUNUSED(col
) ) 
3082 bool wxGridTableBase::GetValueAsBool( int WXUNUSED(row
), int WXUNUSED(col
) ) 
3087 void wxGridTableBase::SetValueAsLong( int WXUNUSED(row
), int WXUNUSED(col
), 
3088                                       long WXUNUSED(value
) ) 
3092 void wxGridTableBase::SetValueAsDouble( int WXUNUSED(row
), int WXUNUSED(col
), 
3093                                         double WXUNUSED(value
) ) 
3097 void wxGridTableBase::SetValueAsBool( int WXUNUSED(row
), int WXUNUSED(col
), 
3098                                       bool WXUNUSED(value
) ) 
3103 void* wxGridTableBase::GetValueAsCustom( int WXUNUSED(row
), int WXUNUSED(col
), 
3104                                          const wxString
& WXUNUSED(typeName
) ) 
3109 void  wxGridTableBase::SetValueAsCustom( int WXUNUSED(row
), int WXUNUSED(col
), 
3110                                          const wxString
& WXUNUSED(typeName
), 
3111                                          void* WXUNUSED(value
) ) 
3115 ////////////////////////////////////////////////////////////////////// 
3117 // Message class for the grid table to send requests and notifications 
3121 wxGridTableMessage::wxGridTableMessage() 
3123     m_table 
= (wxGridTableBase 
*) NULL
; 
3129 wxGridTableMessage::wxGridTableMessage( wxGridTableBase 
*table
, int id
, 
3130                                         int commandInt1
, int commandInt2 
) 
3134     m_comInt1 
= commandInt1
; 
3135     m_comInt2 
= commandInt2
; 
3140 ////////////////////////////////////////////////////////////////////// 
3142 // A basic grid table for string data. An object of this class will 
3143 // created by wxGrid if you don't specify an alternative table class. 
3146 WX_DEFINE_OBJARRAY(wxGridStringArray
) 
3148 IMPLEMENT_DYNAMIC_CLASS( wxGridStringTable
, wxGridTableBase 
) 
3150 wxGridStringTable::wxGridStringTable() 
3155 wxGridStringTable::wxGridStringTable( int numRows
, int numCols 
) 
3158     m_data
.Alloc( numRows 
); 
3161     sa
.Alloc( numCols 
); 
3162     sa
.Add( wxEmptyString
, numCols 
); 
3164     m_data
.Add( sa
, numRows 
); 
3167 wxGridStringTable::~wxGridStringTable() 
3171 int wxGridStringTable::GetNumberRows() 
3173     return m_data
.GetCount(); 
3176 int wxGridStringTable::GetNumberCols() 
3178     if ( m_data
.GetCount() > 0 ) 
3179         return m_data
[0].GetCount(); 
3184 wxString 
wxGridStringTable::GetValue( int row
, int col 
) 
3186     wxCHECK_MSG( (row 
< GetNumberRows()) && (col 
< GetNumberCols()), 
3188                  _T("invalid row or column index in wxGridStringTable") ); 
3190     return m_data
[row
][col
]; 
3193 void wxGridStringTable::SetValue( int row
, int col
, const wxString
& value 
) 
3195     wxCHECK_RET( (row 
< GetNumberRows()) && (col 
< GetNumberCols()), 
3196                  _T("invalid row or column index in wxGridStringTable") ); 
3198     m_data
[row
][col
] = value
; 
3201 bool wxGridStringTable::IsEmptyCell( int row
, int col 
) 
3203     wxCHECK_MSG( (row 
< GetNumberRows()) && (col 
< GetNumberCols()), 
3205                   _T("invalid row or column index in wxGridStringTable") ); 
3207     return (m_data
[row
][col
] == wxEmptyString
); 
3210 void wxGridStringTable::Clear() 
3213     int numRows
, numCols
; 
3215     numRows 
= m_data
.GetCount(); 
3218         numCols 
= m_data
[0].GetCount(); 
3220         for ( row 
= 0;  row 
< numRows
;  row
++ ) 
3222             for ( col 
= 0;  col 
< numCols
;  col
++ ) 
3224                 m_data
[row
][col
] = wxEmptyString
; 
3231 bool wxGridStringTable::InsertRows( size_t pos
, size_t numRows 
) 
3233     size_t curNumRows 
= m_data
.GetCount(); 
3234     size_t curNumCols 
= ( curNumRows 
> 0 ? m_data
[0].GetCount() : 
3235                           ( GetView() ? GetView()->GetNumberCols() : 0 ) ); 
3237     if ( pos 
>= curNumRows 
) 
3239         return AppendRows( numRows 
); 
3243     sa
.Alloc( curNumCols 
); 
3244     sa
.Add( wxEmptyString
, curNumCols 
); 
3245     m_data
.Insert( sa
, pos
, numRows 
); 
3248         wxGridTableMessage 
msg( this, 
3249                                 wxGRIDTABLE_NOTIFY_ROWS_INSERTED
, 
3253         GetView()->ProcessTableMessage( msg 
); 
3259 bool wxGridStringTable::AppendRows( size_t numRows 
) 
3261     size_t curNumRows 
= m_data
.GetCount(); 
3262     size_t curNumCols 
= ( curNumRows 
> 0 ? m_data
[0].GetCount() : 
3263                           ( GetView() ? GetView()->GetNumberCols() : 0 ) ); 
3266     if ( curNumCols 
> 0 ) 
3268         sa
.Alloc( curNumCols 
); 
3269         sa
.Add( wxEmptyString
, curNumCols 
); 
3272     m_data
.Add( sa
, numRows 
); 
3276         wxGridTableMessage 
msg( this, 
3277                                 wxGRIDTABLE_NOTIFY_ROWS_APPENDED
, 
3280         GetView()->ProcessTableMessage( msg 
); 
3286 bool wxGridStringTable::DeleteRows( size_t pos
, size_t numRows 
) 
3288     size_t curNumRows 
= m_data
.GetCount(); 
3290     if ( pos 
>= curNumRows 
) 
3292         wxFAIL_MSG( wxString::Format
 
3294                         wxT("Called wxGridStringTable::DeleteRows(pos=%lu, N=%lu)\nPos value is invalid for present table with %lu rows"), 
3296                         (unsigned long)numRows
, 
3297                         (unsigned long)curNumRows
 
3303     if ( numRows 
> curNumRows 
- pos 
) 
3305         numRows 
= curNumRows 
- pos
; 
3308     if ( numRows 
>= curNumRows 
) 
3314         m_data
.RemoveAt( pos
, numRows 
); 
3318         wxGridTableMessage 
msg( this, 
3319                                 wxGRIDTABLE_NOTIFY_ROWS_DELETED
, 
3323         GetView()->ProcessTableMessage( msg 
); 
3329 bool wxGridStringTable::InsertCols( size_t pos
, size_t numCols 
) 
3333     size_t curNumRows 
= m_data
.GetCount(); 
3334     size_t curNumCols 
= ( curNumRows 
> 0 ? m_data
[0].GetCount() : 
3335                           ( GetView() ? GetView()->GetNumberCols() : 0 ) ); 
3337     if ( pos 
>= curNumCols 
) 
3339         return AppendCols( numCols 
); 
3342     for ( row 
= 0;  row 
< curNumRows
;  row
++ ) 
3344         for ( col 
= pos
;  col 
< pos 
+ numCols
;  col
++ ) 
3346             m_data
[row
].Insert( wxEmptyString
, col 
); 
3351         wxGridTableMessage 
msg( this, 
3352                                 wxGRIDTABLE_NOTIFY_COLS_INSERTED
, 
3356         GetView()->ProcessTableMessage( msg 
); 
3362 bool wxGridStringTable::AppendCols( size_t numCols 
) 
3366     size_t curNumRows 
= m_data
.GetCount(); 
3370         // TODO: something better than this ? 
3372         wxFAIL_MSG( wxT("Unable to append cols to a grid table with no rows.\nCall AppendRows() first") ); 
3377     for ( row 
= 0;  row 
< curNumRows
;  row
++ ) 
3379         m_data
[row
].Add( wxEmptyString
, numCols 
); 
3384         wxGridTableMessage 
msg( this, 
3385                                 wxGRIDTABLE_NOTIFY_COLS_APPENDED
, 
3388         GetView()->ProcessTableMessage( msg 
); 
3394 bool wxGridStringTable::DeleteCols( size_t pos
, size_t numCols 
) 
3398     size_t curNumRows 
= m_data
.GetCount(); 
3399     size_t curNumCols 
= ( curNumRows 
> 0 ? m_data
[0].GetCount() : 
3400                           ( GetView() ? GetView()->GetNumberCols() : 0 ) ); 
3402     if ( pos 
>= curNumCols 
) 
3404         wxFAIL_MSG( wxString::Format
 
3406                         wxT("Called wxGridStringTable::DeleteCols(pos=%lu, N=%lu)\nPos value is invalid for present table with %lu cols"), 
3408                         (unsigned long)numCols
, 
3409                         (unsigned long)curNumCols
 
3414     if ( numCols 
> curNumCols 
- pos 
) 
3416         numCols 
= curNumCols 
- pos
; 
3419     for ( row 
= 0;  row 
< curNumRows
;  row
++ ) 
3421         if ( numCols 
>= curNumCols 
) 
3423             m_data
[row
].Clear(); 
3427             m_data
[row
].RemoveAt( pos
, numCols 
); 
3432         wxGridTableMessage 
msg( this, 
3433                                 wxGRIDTABLE_NOTIFY_COLS_DELETED
, 
3437         GetView()->ProcessTableMessage( msg 
); 
3443 wxString 
wxGridStringTable::GetRowLabelValue( int row 
) 
3445     if ( row 
> (int)(m_rowLabels
.GetCount()) - 1 ) 
3447         // using default label 
3449         return wxGridTableBase::GetRowLabelValue( row 
); 
3453         return m_rowLabels
[ row 
]; 
3457 wxString 
wxGridStringTable::GetColLabelValue( int col 
) 
3459     if ( col 
> (int)(m_colLabels
.GetCount()) - 1 ) 
3461         // using default label 
3463         return wxGridTableBase::GetColLabelValue( col 
); 
3467         return m_colLabels
[ col 
]; 
3471 void wxGridStringTable::SetRowLabelValue( int row
, const wxString
& value 
) 
3473     if ( row 
> (int)(m_rowLabels
.GetCount()) - 1 ) 
3475         int n 
= m_rowLabels
.GetCount(); 
3477         for ( i 
= n
;  i 
<= row
;  i
++ ) 
3479             m_rowLabels
.Add( wxGridTableBase::GetRowLabelValue(i
) ); 
3483     m_rowLabels
[row
] = value
; 
3486 void wxGridStringTable::SetColLabelValue( int col
, const wxString
& value 
) 
3488     if ( col 
> (int)(m_colLabels
.GetCount()) - 1 ) 
3490         int n 
= m_colLabels
.GetCount(); 
3492         for ( i 
= n
;  i 
<= col
;  i
++ ) 
3494             m_colLabels
.Add( wxGridTableBase::GetColLabelValue(i
) ); 
3498     m_colLabels
[col
] = value
; 
3503 ////////////////////////////////////////////////////////////////////// 
3504 ////////////////////////////////////////////////////////////////////// 
3506 IMPLEMENT_DYNAMIC_CLASS( wxGridRowLabelWindow
, wxWindow 
) 
3508 BEGIN_EVENT_TABLE( wxGridRowLabelWindow
, wxWindow 
) 
3509     EVT_PAINT( wxGridRowLabelWindow::OnPaint 
) 
3510     EVT_MOUSEWHEEL( wxGridRowLabelWindow::OnMouseWheel
) 
3511     EVT_MOUSE_EVENTS( wxGridRowLabelWindow::OnMouseEvent 
) 
3512     EVT_KEY_DOWN( wxGridRowLabelWindow::OnKeyDown 
) 
3513     EVT_KEY_UP( wxGridRowLabelWindow::OnKeyUp 
) 
3514     EVT_CHAR ( wxGridRowLabelWindow::OnChar 
) 
3517 wxGridRowLabelWindow::wxGridRowLabelWindow( wxGrid 
*parent
, 
3519                                             const wxPoint 
&pos
, const wxSize 
&size 
) 
3520   : wxWindow( parent
, id
, pos
, size
, wxWANTS_CHARS
|wxBORDER_NONE
|wxFULL_REPAINT_ON_RESIZE 
) 
3525 void wxGridRowLabelWindow::OnPaint( wxPaintEvent
& WXUNUSED(event
) ) 
3529     // NO - don't do this because it will set both the x and y origin 
3530     // coords to match the parent scrolled window and we just want to 
3531     // set the y coord  - MB 
3533     // m_owner->PrepareDC( dc ); 
3536     m_owner
->CalcUnscrolledPosition( 0, 0, &x
, &y 
); 
3537     dc
.SetDeviceOrigin( 0, -y 
); 
3539     wxArrayInt rows 
= m_owner
->CalcRowLabelsExposed( GetUpdateRegion() ); 
3540     m_owner
->DrawRowLabels( dc 
, rows 
); 
3544 void wxGridRowLabelWindow::OnMouseEvent( wxMouseEvent
& event 
) 
3546     m_owner
->ProcessRowLabelMouseEvent( event 
); 
3550 void wxGridRowLabelWindow::OnMouseWheel( wxMouseEvent
& event 
) 
3552     m_owner
->GetEventHandler()->ProcessEvent(event
); 
3556 // This seems to be required for wxMotif otherwise the mouse 
3557 // cursor must be in the cell edit control to get key events 
3559 void wxGridRowLabelWindow::OnKeyDown( wxKeyEvent
& event 
) 
3561     if ( !m_owner
->GetEventHandler()->ProcessEvent( event 
) ) event
.Skip(); 
3564 void wxGridRowLabelWindow::OnKeyUp( wxKeyEvent
& event 
) 
3566     if ( !m_owner
->GetEventHandler()->ProcessEvent( event 
) ) event
.Skip(); 
3569 void wxGridRowLabelWindow::OnChar( wxKeyEvent
& event 
) 
3571     if ( !m_owner
->GetEventHandler()->ProcessEvent( event 
) ) event
.Skip(); 
3576 ////////////////////////////////////////////////////////////////////// 
3578 IMPLEMENT_DYNAMIC_CLASS( wxGridColLabelWindow
, wxWindow 
) 
3580 BEGIN_EVENT_TABLE( wxGridColLabelWindow
, wxWindow 
) 
3581     EVT_PAINT( wxGridColLabelWindow::OnPaint 
) 
3582     EVT_MOUSEWHEEL( wxGridColLabelWindow::OnMouseWheel
) 
3583     EVT_MOUSE_EVENTS( wxGridColLabelWindow::OnMouseEvent 
) 
3584     EVT_KEY_DOWN( wxGridColLabelWindow::OnKeyDown 
) 
3585     EVT_KEY_UP( wxGridColLabelWindow::OnKeyUp 
) 
3586     EVT_CHAR ( wxGridColLabelWindow::OnChar 
) 
3589 wxGridColLabelWindow::wxGridColLabelWindow( wxGrid 
*parent
, 
3591                                             const wxPoint 
&pos
, const wxSize 
&size 
) 
3592   : wxWindow( parent
, id
, pos
, size
, wxWANTS_CHARS
|wxBORDER_NONE
|wxFULL_REPAINT_ON_RESIZE 
) 
3597 void wxGridColLabelWindow::OnPaint( wxPaintEvent
& WXUNUSED(event
) ) 
3601     // NO - don't do this because it will set both the x and y origin 
3602     // coords to match the parent scrolled window and we just want to 
3603     // set the x coord  - MB 
3605     // m_owner->PrepareDC( dc ); 
3608     m_owner
->CalcUnscrolledPosition( 0, 0, &x
, &y 
); 
3609     dc
.SetDeviceOrigin( -x
, 0 ); 
3611     wxArrayInt cols 
= m_owner
->CalcColLabelsExposed( GetUpdateRegion() ); 
3612     m_owner
->DrawColLabels( dc 
, cols 
); 
3616 void wxGridColLabelWindow::OnMouseEvent( wxMouseEvent
& event 
) 
3618     m_owner
->ProcessColLabelMouseEvent( event 
); 
3621 void wxGridColLabelWindow::OnMouseWheel( wxMouseEvent
& event 
) 
3623     m_owner
->GetEventHandler()->ProcessEvent(event
); 
3627 // This seems to be required for wxMotif otherwise the mouse 
3628 // cursor must be in the cell edit control to get key events 
3630 void wxGridColLabelWindow::OnKeyDown( wxKeyEvent
& event 
) 
3632     if ( !m_owner
->GetEventHandler()->ProcessEvent( event 
) ) event
.Skip(); 
3635 void wxGridColLabelWindow::OnKeyUp( wxKeyEvent
& event 
) 
3637     if ( !m_owner
->GetEventHandler()->ProcessEvent( event 
) ) event
.Skip(); 
3640 void wxGridColLabelWindow::OnChar( wxKeyEvent
& event 
) 
3642     if ( !m_owner
->GetEventHandler()->ProcessEvent( event 
) ) event
.Skip(); 
3646 ////////////////////////////////////////////////////////////////////// 
3648 IMPLEMENT_DYNAMIC_CLASS( wxGridCornerLabelWindow
, wxWindow 
) 
3650 BEGIN_EVENT_TABLE( wxGridCornerLabelWindow
, wxWindow 
) 
3651     EVT_MOUSEWHEEL( wxGridCornerLabelWindow::OnMouseWheel
) 
3652     EVT_MOUSE_EVENTS( wxGridCornerLabelWindow::OnMouseEvent 
) 
3653     EVT_PAINT( wxGridCornerLabelWindow::OnPaint
) 
3654     EVT_KEY_DOWN( wxGridCornerLabelWindow::OnKeyDown 
) 
3655     EVT_KEY_UP( wxGridCornerLabelWindow::OnKeyUp 
) 
3656     EVT_CHAR ( wxGridCornerLabelWindow::OnChar 
) 
3659 wxGridCornerLabelWindow::wxGridCornerLabelWindow( wxGrid 
*parent
, 
3661                                                   const wxPoint 
&pos
, const wxSize 
&size 
) 
3662   : wxWindow( parent
, id
, pos
, size
, wxWANTS_CHARS
|wxBORDER_NONE
|wxFULL_REPAINT_ON_RESIZE 
) 
3667 void wxGridCornerLabelWindow::OnPaint( wxPaintEvent
& WXUNUSED(event
) ) 
3671     int client_height 
= 0; 
3672     int client_width 
= 0; 
3673     GetClientSize( &client_width
, &client_height 
); 
3679     rect
.SetWidth( client_width 
- 2 ); 
3680     rect
.SetHeight( client_height 
- 2 ); 
3682     wxRendererNative::Get().DrawHeaderButton( this, dc
, rect
, 0 ); 
3684     dc
.SetPen( wxPen(wxSystemSettings::GetColour(wxSYS_COLOUR_3DDKSHADOW
),1, wxSOLID
) ); 
3685     dc
.DrawLine( client_width
-1, client_height
-1, client_width
-1, 0 ); 
3686     dc
.DrawLine( client_width
-1, client_height
-1, 0, client_height
-1 ); 
3687     dc
.DrawLine( 0, 0, client_width
, 0 ); 
3688     dc
.DrawLine( 0, 0, 0, client_height 
); 
3690     dc
.SetPen( *wxWHITE_PEN 
); 
3691     dc
.DrawLine( 1, 1, client_width
-1, 1 ); 
3692     dc
.DrawLine( 1, 1, 1, client_height
-1 ); 
3697 void wxGridCornerLabelWindow::OnMouseEvent( wxMouseEvent
& event 
) 
3699     m_owner
->ProcessCornerLabelMouseEvent( event 
); 
3703 void wxGridCornerLabelWindow::OnMouseWheel( wxMouseEvent
& event 
) 
3705     m_owner
->GetEventHandler()->ProcessEvent(event
); 
3708 // This seems to be required for wxMotif otherwise the mouse 
3709 // cursor must be in the cell edit control to get key events 
3711 void wxGridCornerLabelWindow::OnKeyDown( wxKeyEvent
& event 
) 
3713     if ( !m_owner
->GetEventHandler()->ProcessEvent( event 
) ) event
.Skip(); 
3716 void wxGridCornerLabelWindow::OnKeyUp( wxKeyEvent
& event 
) 
3718     if ( !m_owner
->GetEventHandler()->ProcessEvent( event 
) ) event
.Skip(); 
3721 void wxGridCornerLabelWindow::OnChar( wxKeyEvent
& event 
) 
3723     if ( !m_owner
->GetEventHandler()->ProcessEvent( event 
) ) event
.Skip(); 
3727 ////////////////////////////////////////////////////////////////////// 
3729 IMPLEMENT_DYNAMIC_CLASS( wxGridWindow
, wxWindow 
) 
3731 BEGIN_EVENT_TABLE( wxGridWindow
, wxWindow 
) 
3732     EVT_PAINT( wxGridWindow::OnPaint 
) 
3733     EVT_MOUSEWHEEL( wxGridWindow::OnMouseWheel
) 
3734     EVT_MOUSE_EVENTS( wxGridWindow::OnMouseEvent 
) 
3735     EVT_KEY_DOWN( wxGridWindow::OnKeyDown 
) 
3736     EVT_KEY_UP( wxGridWindow::OnKeyUp 
) 
3737     EVT_CHAR ( wxGridWindow::OnChar 
) 
3738     EVT_SET_FOCUS( wxGridWindow::OnFocus 
) 
3739     EVT_KILL_FOCUS( wxGridWindow::OnFocus 
) 
3740     EVT_ERASE_BACKGROUND( wxGridWindow::OnEraseBackground 
) 
3743 wxGridWindow::wxGridWindow( wxGrid 
*parent
, 
3744                             wxGridRowLabelWindow 
*rowLblWin
, 
3745                             wxGridColLabelWindow 
*colLblWin
, 
3748                             const wxSize 
&size 
) 
3749             : wxWindow( parent
, id
, pos
, size
, wxWANTS_CHARS 
| wxBORDER_NONE 
| wxCLIP_CHILDREN
|wxFULL_REPAINT_ON_RESIZE
, 
3750                         wxT("grid window") ) 
3754     m_rowLabelWin 
= rowLblWin
; 
3755     m_colLabelWin 
= colLblWin
; 
3759 void wxGridWindow::OnPaint( wxPaintEvent 
&WXUNUSED(event
) ) 
3761     wxPaintDC 
dc( this ); 
3762     m_owner
->PrepareDC( dc 
); 
3763     wxRegion reg 
= GetUpdateRegion(); 
3764     wxGridCellCoordsArray DirtyCells 
= m_owner
->CalcCellsExposed( reg 
); 
3765     m_owner
->DrawGridCellArea( dc 
, DirtyCells
); 
3766 #if WXGRID_DRAW_LINES 
3767     m_owner
->DrawAllGridLines( dc
, reg 
); 
3769     m_owner
->DrawGridSpace( dc 
); 
3770     m_owner
->DrawHighlight( dc 
, DirtyCells 
); 
3774 void wxGridWindow::ScrollWindow( int dx
, int dy
, const wxRect 
*rect 
) 
3776     wxWindow::ScrollWindow( dx
, dy
, rect 
); 
3777     m_rowLabelWin
->ScrollWindow( 0, dy
, rect 
); 
3778     m_colLabelWin
->ScrollWindow( dx
, 0, rect 
); 
3782 void wxGridWindow::OnMouseEvent( wxMouseEvent
& event 
) 
3784     if (event
.ButtonDown(wxMOUSE_BTN_LEFT
) && FindFocus() != this) 
3787     m_owner
->ProcessGridCellMouseEvent( event 
); 
3790 void wxGridWindow::OnMouseWheel( wxMouseEvent
& event 
) 
3792     m_owner
->GetEventHandler()->ProcessEvent(event
); 
3795 // This seems to be required for wxMotif/wxGTK otherwise the mouse 
3796 // cursor must be in the cell edit control to get key events 
3798 void wxGridWindow::OnKeyDown( wxKeyEvent
& event 
) 
3800     if ( !m_owner
->GetEventHandler()->ProcessEvent( event 
) ) event
.Skip(); 
3803 void wxGridWindow::OnKeyUp( wxKeyEvent
& event 
) 
3805     if ( !m_owner
->GetEventHandler()->ProcessEvent( event 
) ) event
.Skip(); 
3808 void wxGridWindow::OnChar( wxKeyEvent
& event 
) 
3810     if ( !m_owner
->GetEventHandler()->ProcessEvent( event 
) ) event
.Skip(); 
3813 void wxGridWindow::OnEraseBackground( wxEraseEvent
& WXUNUSED(event
) ) 
3817 void wxGridWindow::OnFocus(wxFocusEvent
& event
) 
3819     if ( !m_owner
->GetEventHandler()->ProcessEvent( event 
) ) 
3823 ////////////////////////////////////////////////////////////////////// 
3825 // Internal Helper function for computing row or column from some 
3826 // (unscrolled) coordinate value, using either 
3827 // m_defaultRowHeight/m_defaultColWidth or binary search on array 
3828 // of m_rowBottoms/m_ColRights to speed up the search! 
3830 // Internal helper macros for simpler use of that function 
3832 static int CoordToRowOrCol(int coord
, int defaultDist
, int minDist
, 
3833                            const wxArrayInt
& BorderArray
, int nMax
, 
3836 #define internalXToCol(x) CoordToRowOrCol(x, m_defaultColWidth, \ 
3837                                           m_minAcceptableColWidth, \ 
3838                                           m_colRights, m_numCols, true) 
3839 #define internalYToRow(y) CoordToRowOrCol(y, m_defaultRowHeight, \ 
3840                                           m_minAcceptableRowHeight, \ 
3841                                           m_rowBottoms, m_numRows, true) 
3842 ///////////////////////////////////////////////////////////////////// 
3844 #if wxUSE_EXTENDED_RTTI 
3845 WX_DEFINE_FLAGS( wxGridStyle 
) 
3847 wxBEGIN_FLAGS( wxGridStyle 
) 
3848     // new style border flags, we put them first to 
3849     // use them for streaming out 
3850     wxFLAGS_MEMBER(wxBORDER_SIMPLE
) 
3851     wxFLAGS_MEMBER(wxBORDER_SUNKEN
) 
3852     wxFLAGS_MEMBER(wxBORDER_DOUBLE
) 
3853     wxFLAGS_MEMBER(wxBORDER_RAISED
) 
3854     wxFLAGS_MEMBER(wxBORDER_STATIC
) 
3855     wxFLAGS_MEMBER(wxBORDER_NONE
) 
3857     // old style border flags 
3858     wxFLAGS_MEMBER(wxSIMPLE_BORDER
) 
3859     wxFLAGS_MEMBER(wxSUNKEN_BORDER
) 
3860     wxFLAGS_MEMBER(wxDOUBLE_BORDER
) 
3861     wxFLAGS_MEMBER(wxRAISED_BORDER
) 
3862     wxFLAGS_MEMBER(wxSTATIC_BORDER
) 
3863     wxFLAGS_MEMBER(wxBORDER
) 
3865     // standard window styles 
3866     wxFLAGS_MEMBER(wxTAB_TRAVERSAL
) 
3867     wxFLAGS_MEMBER(wxCLIP_CHILDREN
) 
3868     wxFLAGS_MEMBER(wxTRANSPARENT_WINDOW
) 
3869     wxFLAGS_MEMBER(wxWANTS_CHARS
) 
3870     wxFLAGS_MEMBER(wxFULL_REPAINT_ON_RESIZE
) 
3871     wxFLAGS_MEMBER(wxALWAYS_SHOW_SB 
) 
3872     wxFLAGS_MEMBER(wxVSCROLL
) 
3873     wxFLAGS_MEMBER(wxHSCROLL
) 
3875 wxEND_FLAGS( wxGridStyle 
) 
3877 IMPLEMENT_DYNAMIC_CLASS_XTI(wxGrid
, wxScrolledWindow
,"wx/grid.h") 
3879 wxBEGIN_PROPERTIES_TABLE(wxGrid
) 
3880     wxHIDE_PROPERTY( Children 
) 
3881     wxPROPERTY_FLAGS( WindowStyle 
, wxGridStyle 
, long , SetWindowStyleFlag 
, GetWindowStyleFlag 
, EMPTY_MACROVALUE
, 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // style 
3882 wxEND_PROPERTIES_TABLE() 
3884 wxBEGIN_HANDLERS_TABLE(wxGrid
) 
3885 wxEND_HANDLERS_TABLE() 
3887 wxCONSTRUCTOR_5( wxGrid 
, wxWindow
* , Parent 
, wxWindowID 
, Id 
, wxPoint 
, Position 
, wxSize 
, Size 
, long , WindowStyle 
) 
3890  TODO : Expose more information of a list's layout etc. via appropriate objects (\81à la NotebookPageInfo) 
3893 IMPLEMENT_DYNAMIC_CLASS( wxGrid
, wxScrolledWindow 
) 
3896 BEGIN_EVENT_TABLE( wxGrid
, wxScrolledWindow 
) 
3897     EVT_PAINT( wxGrid::OnPaint 
) 
3898     EVT_SIZE( wxGrid::OnSize 
) 
3899     EVT_KEY_DOWN( wxGrid::OnKeyDown 
) 
3900     EVT_KEY_UP( wxGrid::OnKeyUp 
) 
3901     EVT_CHAR ( wxGrid::OnChar 
) 
3902     EVT_ERASE_BACKGROUND( wxGrid::OnEraseBackground 
) 
3907     // in order to make sure that a size event is not 
3908     // trigerred in a unfinished state 
3909     m_cornerLabelWin 
= NULL 
; 
3910     m_rowLabelWin 
= NULL 
; 
3911     m_colLabelWin 
= NULL 
; 
3915 wxGrid::wxGrid( wxWindow 
*parent
, 
3920                  const wxString
& name 
) 
3921   : wxScrolledWindow( parent
, id
, pos
, size
, (style 
| wxWANTS_CHARS
), name 
), 
3922     m_colMinWidths(GRID_HASH_SIZE
), 
3923     m_rowMinHeights(GRID_HASH_SIZE
) 
3926     SetBestFittingSize(size
); 
3929 bool wxGrid::Create(wxWindow 
*parent
, wxWindowID id
, 
3930                           const wxPoint
& pos
, const wxSize
& size
, 
3931                           long style
, const wxString
& name
) 
3933     if (!wxScrolledWindow::Create(parent
, id
, pos
, size
, 
3934                                   style 
| wxWANTS_CHARS 
, name
)) 
3937     m_colMinWidths 
= wxLongToLongHashMap(GRID_HASH_SIZE
) ; 
3938     m_rowMinHeights 
= wxLongToLongHashMap(GRID_HASH_SIZE
) ; 
3941     SetBestFittingSize(size
); 
3949     // Must do this or ~wxScrollHelper will pop the wrong event handler 
3950     SetTargetWindow(this); 
3952     wxSafeDecRef(m_defaultCellAttr
); 
3954 #ifdef DEBUG_ATTR_CACHE 
3955     size_t total 
= gs_nAttrCacheHits 
+ gs_nAttrCacheMisses
; 
3956     wxPrintf(_T("wxGrid attribute cache statistics: " 
3957                 "total: %u, hits: %u (%u%%)\n"), 
3958              total
, gs_nAttrCacheHits
, 
3959              total 
? (gs_nAttrCacheHits
*100) / total 
: 0); 
3965     delete m_typeRegistry
; 
3971 // ----- internal init and update functions 
3974 // NOTE: If using the default visual attributes works everywhere then this can 
3975 // be removed as well as the #else cases below. 
3976 #define _USE_VISATTR 0 
3979 #include "wx/listbox.h" 
3982 void wxGrid::Create() 
3984     m_created 
= false;    // set to true by CreateGrid 
3986     m_table        
= (wxGridTableBase 
*) NULL
; 
3989     m_cellEditCtrlEnabled 
= false; 
3991     m_defaultCellAttr 
= new wxGridCellAttr(); 
3993     // Set default cell attributes 
3994     m_defaultCellAttr
->SetDefAttr(m_defaultCellAttr
); 
3995     m_defaultCellAttr
->SetKind(wxGridCellAttr::Default
); 
3996     m_defaultCellAttr
->SetFont(GetFont()); 
3997     m_defaultCellAttr
->SetAlignment(wxALIGN_LEFT
, wxALIGN_TOP
); 
3998     m_defaultCellAttr
->SetRenderer(new wxGridCellStringRenderer
); 
3999     m_defaultCellAttr
->SetEditor(new wxGridCellTextEditor
); 
4002     wxVisualAttributes gva 
= wxListBox::GetClassDefaultAttributes(); 
4003     wxVisualAttributes lva 
= wxPanel::GetClassDefaultAttributes(); 
4005     m_defaultCellAttr
->SetTextColour(gva
.colFg
); 
4006     m_defaultCellAttr
->SetBackgroundColour(gva
.colBg
); 
4009     m_defaultCellAttr
->SetTextColour( 
4010         wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT
)); 
4011     m_defaultCellAttr
->SetBackgroundColour( 
4012         wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW
)); 
4017     m_currentCellCoords 
= wxGridNoCellCoords
; 
4019     m_rowLabelWidth 
= WXGRID_DEFAULT_ROW_LABEL_WIDTH
; 
4020     m_colLabelHeight 
= WXGRID_DEFAULT_COL_LABEL_HEIGHT
; 
4022     // create the type registry 
4023     m_typeRegistry 
= new wxGridTypeRegistry
; 
4026     // subwindow components that make up the wxGrid 
4027     m_cornerLabelWin 
= new wxGridCornerLabelWindow( this, 
4032     m_rowLabelWin 
= new wxGridRowLabelWindow( this, 
4037     m_colLabelWin 
= new wxGridColLabelWindow( this, 
4042     m_gridWin 
= new wxGridWindow( this, 
4049     SetTargetWindow( m_gridWin 
); 
4052     wxColour gfg 
= gva
.colFg
; 
4053     wxColour gbg 
= gva
.colBg
; 
4054     wxColour lfg 
= lva
.colFg
; 
4055     wxColour lbg 
= lva
.colBg
; 
4057     wxColour gfg 
= wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOWTEXT 
); 
4058     wxColour gbg 
= wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW 
); 
4059     wxColour lfg 
= wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOWTEXT 
); 
4060     wxColour lbg 
= wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE 
); 
4062     m_cornerLabelWin
->SetOwnForegroundColour(lfg
); 
4063     m_cornerLabelWin
->SetOwnBackgroundColour(lbg
); 
4064     m_rowLabelWin
->SetOwnForegroundColour(lfg
); 
4065     m_rowLabelWin
->SetOwnBackgroundColour(lbg
); 
4066     m_colLabelWin
->SetOwnForegroundColour(lfg
); 
4067     m_colLabelWin
->SetOwnBackgroundColour(lbg
); 
4069     m_gridWin
->SetOwnForegroundColour(gfg
); 
4070     m_gridWin
->SetOwnBackgroundColour(gbg
); 
4076 bool wxGrid::CreateGrid( int numRows
, int numCols
, 
4077                          wxGrid::wxGridSelectionModes selmode 
) 
4079     wxCHECK_MSG( !m_created
, 
4081                  wxT("wxGrid::CreateGrid or wxGrid::SetTable called more than once") ); 
4083     m_numRows 
= numRows
; 
4084     m_numCols 
= numCols
; 
4086     m_table 
= new wxGridStringTable( m_numRows
, m_numCols 
); 
4087     m_table
->SetView( this ); 
4089     m_selection 
= new wxGridSelection( this, selmode 
); 
4098 void wxGrid::SetSelectionMode(wxGrid::wxGridSelectionModes selmode
) 
4100     wxCHECK_RET( m_created
, 
4101                  wxT("Called wxGrid::SetSelectionMode() before calling CreateGrid()") ); 
4103     m_selection
->SetSelectionMode( selmode 
); 
4106 wxGrid::wxGridSelectionModes 
wxGrid::GetSelectionMode() const 
4108     wxCHECK_MSG( m_created
, wxGrid::wxGridSelectCells
, 
4109                  wxT("Called wxGrid::GetSelectionMode() before calling CreateGrid()") ); 
4111     return m_selection
->GetSelectionMode(); 
4114 bool wxGrid::SetTable( wxGridTableBase 
*table
, bool takeOwnership
, 
4115                        wxGrid::wxGridSelectionModes selmode 
) 
4119         // stop all processing 
4124             wxGridTableBase 
*t
=m_table
; 
4137         m_numRows 
= table
->GetNumberRows(); 
4138         m_numCols 
= table
->GetNumberCols(); 
4141         m_table
->SetView( this ); 
4144         m_selection 
= new wxGridSelection( this, selmode 
); 
4157     m_rowLabelWidth  
= WXGRID_DEFAULT_ROW_LABEL_WIDTH
; 
4158     m_colLabelHeight 
= WXGRID_DEFAULT_COL_LABEL_HEIGHT
; 
4160     if ( m_rowLabelWin 
) 
4162         m_labelBackgroundColour 
= m_rowLabelWin
->GetBackgroundColour(); 
4166         m_labelBackgroundColour 
= wxColour( _T("WHITE") ); 
4169     m_labelTextColour 
= wxColour( _T("BLACK") ); 
4172     m_attrCache
.row 
= -1; 
4173     m_attrCache
.col 
= -1; 
4174     m_attrCache
.attr 
= NULL
; 
4176     // TODO: something better than this ? 
4178     m_labelFont 
= this->GetFont(); 
4179     m_labelFont
.SetWeight( wxBOLD 
); 
4181     m_rowLabelHorizAlign 
= wxALIGN_CENTRE
; 
4182     m_rowLabelVertAlign  
= wxALIGN_CENTRE
; 
4184     m_colLabelHorizAlign 
= wxALIGN_CENTRE
; 
4185     m_colLabelVertAlign  
= wxALIGN_CENTRE
; 
4186     m_colLabelTextOrientation 
= wxHORIZONTAL
; 
4188     m_defaultColWidth  
= WXGRID_DEFAULT_COL_WIDTH
; 
4189     m_defaultRowHeight 
= m_gridWin
->GetCharHeight(); 
4191     m_minAcceptableColWidth  
= WXGRID_MIN_COL_WIDTH
; 
4192     m_minAcceptableRowHeight 
= WXGRID_MIN_ROW_HEIGHT
; 
4194 #if defined(__WXMOTIF__) || defined(__WXGTK__)  // see also text ctrl sizing in ShowCellEditControl() 
4195     m_defaultRowHeight 
+= 8; 
4197     m_defaultRowHeight 
+= 4; 
4200     m_gridLineColour 
= wxColour( 192,192,192 ); 
4201     m_gridLinesEnabled 
= true; 
4202     m_cellHighlightColour 
= *wxBLACK
; 
4203     m_cellHighlightPenWidth 
= 2; 
4204     m_cellHighlightROPenWidth 
= 1; 
4206     m_cursorMode  
= WXGRID_CURSOR_SELECT_CELL
; 
4207     m_winCapture 
= (wxWindow 
*)NULL
; 
4208     m_canDragRowSize 
= true; 
4209     m_canDragColSize 
= true; 
4210     m_canDragGridSize 
= true; 
4211     m_canDragCell 
= false; 
4213     m_dragRowOrCol 
= -1; 
4214     m_isDragging 
= false; 
4215     m_startDragPos 
= wxDefaultPosition
; 
4217     m_waitForSlowClick 
= false; 
4219     m_rowResizeCursor 
= wxCursor( wxCURSOR_SIZENS 
); 
4220     m_colResizeCursor 
= wxCursor( wxCURSOR_SIZEWE 
); 
4222     m_currentCellCoords 
= wxGridNoCellCoords
; 
4224     m_selectingTopLeft 
= wxGridNoCellCoords
; 
4225     m_selectingBottomRight 
= wxGridNoCellCoords
; 
4226     m_selectionBackground 
= wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT
); 
4227     m_selectionForeground 
= wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHTTEXT
); 
4229     m_editable 
= true;  // default for whole grid 
4231     m_inOnKeyDown 
= false; 
4237     m_scrollLineX 
= GRID_SCROLL_LINE_X
; 
4238     m_scrollLineY 
= GRID_SCROLL_LINE_Y
; 
4241 // ---------------------------------------------------------------------------- 
4242 // the idea is to call these functions only when necessary because they create 
4243 // quite big arrays which eat memory mostly unnecessary - in particular, if 
4244 // default widths/heights are used for all rows/columns, we may not use these 
4247 // with some extra code, it should be possible to only store the 
4248 // widths/heights different from default ones but this will be done later... 
4249 // ---------------------------------------------------------------------------- 
4251 void wxGrid::InitRowHeights() 
4253     m_rowHeights
.Empty(); 
4254     m_rowBottoms
.Empty(); 
4256     m_rowHeights
.Alloc( m_numRows 
); 
4257     m_rowBottoms
.Alloc( m_numRows 
); 
4261     m_rowHeights
.Add( m_defaultRowHeight
, m_numRows 
); 
4263     for ( int i 
= 0;  i 
< m_numRows
;  i
++ ) 
4265         rowBottom 
+= m_defaultRowHeight
; 
4266         m_rowBottoms
.Add( rowBottom 
); 
4270 void wxGrid::InitColWidths() 
4272     m_colWidths
.Empty(); 
4273     m_colRights
.Empty(); 
4275     m_colWidths
.Alloc( m_numCols 
); 
4276     m_colRights
.Alloc( m_numCols 
); 
4279     m_colWidths
.Add( m_defaultColWidth
, m_numCols 
); 
4281     for ( int i 
= 0;  i 
< m_numCols
;  i
++ ) 
4283         colRight 
+= m_defaultColWidth
; 
4284         m_colRights
.Add( colRight 
); 
4288 int wxGrid::GetColWidth(int col
) const 
4290     return m_colWidths
.IsEmpty() ? m_defaultColWidth 
: m_colWidths
[col
]; 
4293 int wxGrid::GetColLeft(int col
) const 
4295     return m_colRights
.IsEmpty() ? col 
* m_defaultColWidth
 
4296                                  : m_colRights
[col
] - m_colWidths
[col
]; 
4299 int wxGrid::GetColRight(int col
) const 
4301     return m_colRights
.IsEmpty() ? (col 
+ 1) * m_defaultColWidth
 
4305 int wxGrid::GetRowHeight(int row
) const 
4307     return m_rowHeights
.IsEmpty() ? m_defaultRowHeight 
: m_rowHeights
[row
]; 
4310 int wxGrid::GetRowTop(int row
) const 
4312     return m_rowBottoms
.IsEmpty() ? row 
* m_defaultRowHeight
 
4313                                   : m_rowBottoms
[row
] - m_rowHeights
[row
]; 
4316 int wxGrid::GetRowBottom(int row
) const 
4318     return m_rowBottoms
.IsEmpty() ? (row 
+ 1) * m_defaultRowHeight
 
4319                                   : m_rowBottoms
[row
]; 
4322 void wxGrid::CalcDimensions() 
4325     GetClientSize( &cw
, &ch 
); 
4327     if ( m_rowLabelWin
->IsShown() ) 
4328         cw 
-= m_rowLabelWidth
; 
4329     if ( m_colLabelWin
->IsShown() ) 
4330         ch 
-= m_colLabelHeight
; 
4333     int w 
= m_numCols 
> 0 ? GetColRight(m_numCols 
- 1) + m_extraWidth 
+ 1 : 0; 
4334     int h 
= m_numRows 
> 0 ? GetRowBottom(m_numRows 
- 1) + m_extraHeight 
+ 1 : 0; 
4336     // take into account editor if shown 
4337     if( IsCellEditControlShown() ) 
4340       int r 
= m_currentCellCoords
.GetRow(); 
4341       int c 
= m_currentCellCoords
.GetCol(); 
4342       int x 
= GetColLeft(c
); 
4343       int y 
= GetRowTop(r
); 
4345       // how big is the editor 
4346       wxGridCellAttr
* attr 
= GetCellAttr(r
, c
); 
4347       wxGridCellEditor
* editor 
= attr
->GetEditor(this, r
, c
); 
4348       editor
->GetControl()->GetSize(&w2
, &h2
); 
4351       if( w2 
> w 
) w 
= w2
; 
4352       if( h2 
> h 
) h 
= h2
; 
4357     // preserve (more or less) the previous position 
4359     GetViewStart( &x
, &y 
); 
4361     // ensure the position is valid for the new scroll ranges 
4363         x 
= wxMax( w 
- 1, 0 ); 
4365         y 
= wxMax( h 
- 1, 0 ); 
4367     // do set scrollbar parameters 
4368     SetScrollbars( m_scrollLineX
, m_scrollLineY
, 
4369                    GetScrollX(w
), GetScrollY(h
), x
, y
, 
4370                    GetBatchCount() != 0); 
4372     // if our OnSize() hadn't been called (it would if we have scrollbars), we 
4373     // still must reposition the children 
4378 void wxGrid::CalcWindowSizes() 
4380     // escape if the window is has not been fully created yet 
4382     if ( m_cornerLabelWin 
== NULL 
) 
4386     GetClientSize( &cw
, &ch 
); 
4388     if ( m_cornerLabelWin 
&& m_cornerLabelWin
->IsShown() ) 
4389         m_cornerLabelWin
->SetSize( 0, 0, m_rowLabelWidth
, m_colLabelHeight 
); 
4391     if (  m_colLabelWin 
&& m_colLabelWin
->IsShown() ) 
4392         m_colLabelWin
->SetSize( m_rowLabelWidth
, 0, cw
-m_rowLabelWidth
, m_colLabelHeight
); 
4394     if ( m_rowLabelWin 
&& m_rowLabelWin
->IsShown() ) 
4395         m_rowLabelWin
->SetSize( 0, m_colLabelHeight
, m_rowLabelWidth
, ch
-m_colLabelHeight
); 
4397     if ( m_gridWin 
&& m_gridWin
->IsShown() ) 
4398         m_gridWin
->SetSize( m_rowLabelWidth
, m_colLabelHeight
, cw
-m_rowLabelWidth
, ch
-m_colLabelHeight
); 
4402 // this is called when the grid table sends a message to say that it 
4403 // has been redimensioned 
4405 bool wxGrid::Redimension( wxGridTableMessage
& msg 
) 
4408     bool result 
= false; 
4410     // Clear the attribute cache as the attribute might refer to a different 
4411     // cell than stored in the cache after adding/removing rows/columns. 
4413     // By the same reasoning, the editor should be dismissed if columns are 
4414     // added or removed. And for consistency, it should IMHO always be 
4415     // removed, not only if the cell "underneath" it actually changes. 
4416     // For now, I intentionally do not save the editor's content as the 
4417     // cell it might want to save that stuff to might no longer exist. 
4418     HideCellEditControl(); 
4420     // if we were using the default widths/heights so far, we must change them 
4422     if ( m_colWidths
.IsEmpty() ) 
4427     if ( m_rowHeights
.IsEmpty() ) 
4433     switch ( msg
.GetId() ) 
4435         case wxGRIDTABLE_NOTIFY_ROWS_INSERTED
: 
4437             size_t pos 
= msg
.GetCommandInt(); 
4438             int numRows 
= msg
.GetCommandInt2(); 
4440             m_numRows 
+= numRows
; 
4442             if ( !m_rowHeights
.IsEmpty() ) 
4444                 m_rowHeights
.Insert( m_defaultRowHeight
, pos
, numRows 
); 
4445                 m_rowBottoms
.Insert( 0, pos
, numRows 
); 
4448                 if ( pos 
> 0 ) bottom 
= m_rowBottoms
[pos
-1]; 
4450                 for ( i 
= pos
;  i 
< m_numRows
;  i
++ ) 
4452                     bottom 
+= m_rowHeights
[i
]; 
4453                     m_rowBottoms
[i
] = bottom
; 
4456             if ( m_currentCellCoords 
== wxGridNoCellCoords 
) 
4458                 // if we have just inserted cols into an empty grid the current 
4459                 // cell will be undefined... 
4461                 SetCurrentCell( 0, 0 ); 
4465                 m_selection
->UpdateRows( pos
, numRows 
); 
4466             wxGridCellAttrProvider 
* attrProvider 
= m_table
->GetAttrProvider(); 
4468                 attrProvider
->UpdateAttrRows( pos
, numRows 
); 
4470             if ( !GetBatchCount() ) 
4473                 m_rowLabelWin
->Refresh(); 
4479         case wxGRIDTABLE_NOTIFY_ROWS_APPENDED
: 
4481             int numRows 
= msg
.GetCommandInt(); 
4482             int oldNumRows 
= m_numRows
; 
4483             m_numRows 
+= numRows
; 
4485             if ( !m_rowHeights
.IsEmpty() ) 
4487                 m_rowHeights
.Add( m_defaultRowHeight
, numRows 
); 
4488                 m_rowBottoms
.Add( 0, numRows 
); 
4491                 if ( oldNumRows 
> 0 ) bottom 
= m_rowBottoms
[oldNumRows
-1]; 
4493                 for ( i 
= oldNumRows
;  i 
< m_numRows
;  i
++ ) 
4495                     bottom 
+= m_rowHeights
[i
]; 
4496                     m_rowBottoms
[i
] = bottom
; 
4499             if ( m_currentCellCoords 
== wxGridNoCellCoords 
) 
4501                 // if we have just inserted cols into an empty grid the current 
4502                 // cell will be undefined... 
4504                 SetCurrentCell( 0, 0 ); 
4506             if ( !GetBatchCount() ) 
4509                 m_rowLabelWin
->Refresh(); 
4515         case wxGRIDTABLE_NOTIFY_ROWS_DELETED
: 
4517             size_t pos 
= msg
.GetCommandInt(); 
4518             int numRows 
= msg
.GetCommandInt2(); 
4519             m_numRows 
-= numRows
; 
4521             if ( !m_rowHeights
.IsEmpty() ) 
4523                 m_rowHeights
.RemoveAt( pos
, numRows 
); 
4524                 m_rowBottoms
.RemoveAt( pos
, numRows 
); 
4527                 for ( i 
= 0;  i 
< m_numRows
;  i
++ ) 
4529                     h 
+= m_rowHeights
[i
]; 
4530                     m_rowBottoms
[i
] = h
; 
4535                 m_currentCellCoords 
= wxGridNoCellCoords
; 
4539                 if ( m_currentCellCoords
.GetRow() >= m_numRows 
) 
4540                     m_currentCellCoords
.Set( 0, 0 ); 
4544                 m_selection
->UpdateRows( pos
, -((int)numRows
) ); 
4545             wxGridCellAttrProvider 
* attrProvider 
= m_table
->GetAttrProvider(); 
4547                 attrProvider
->UpdateAttrRows( pos
, -((int)numRows
) ); 
4548 // ifdef'd out following patch from Paul Gammans 
4550                 // No need to touch column attributes, unless we 
4551                 // removed _all_ rows, in this case, we remove 
4552                 // all column attributes. 
4553                 // I hate to do this here, but the 
4554                 // needed data is not available inside UpdateAttrRows. 
4555                 if ( !GetNumberRows() ) 
4556                     attrProvider
->UpdateAttrCols( 0, -GetNumberCols() ); 
4559             if ( !GetBatchCount() ) 
4562                 m_rowLabelWin
->Refresh(); 
4568         case wxGRIDTABLE_NOTIFY_COLS_INSERTED
: 
4570             size_t pos 
= msg
.GetCommandInt(); 
4571             int numCols 
= msg
.GetCommandInt2(); 
4572             m_numCols 
+= numCols
; 
4574             if ( !m_colWidths
.IsEmpty() ) 
4576                 m_colWidths
.Insert( m_defaultColWidth
, pos
, numCols 
); 
4577                 m_colRights
.Insert( 0, pos
, numCols 
); 
4580                 if ( pos 
> 0 ) right 
= m_colRights
[pos
-1]; 
4582                 for ( i 
= pos
;  i 
< m_numCols
;  i
++ ) 
4584                     right 
+= m_colWidths
[i
]; 
4585                     m_colRights
[i
] = right
; 
4588             if ( m_currentCellCoords 
== wxGridNoCellCoords 
) 
4590                 // if we have just inserted cols into an empty grid the current 
4591                 // cell will be undefined... 
4593                 SetCurrentCell( 0, 0 ); 
4597                 m_selection
->UpdateCols( pos
, numCols 
); 
4598             wxGridCellAttrProvider 
* attrProvider 
= m_table
->GetAttrProvider(); 
4600                 attrProvider
->UpdateAttrCols( pos
, numCols 
); 
4601             if ( !GetBatchCount() ) 
4604                 m_colLabelWin
->Refresh(); 
4611         case wxGRIDTABLE_NOTIFY_COLS_APPENDED
: 
4613             int numCols 
= msg
.GetCommandInt(); 
4614             int oldNumCols 
= m_numCols
; 
4615             m_numCols 
+= numCols
; 
4616             if ( !m_colWidths
.IsEmpty() ) 
4618                 m_colWidths
.Add( m_defaultColWidth
, numCols 
); 
4619                 m_colRights
.Add( 0, numCols 
); 
4622                 if ( oldNumCols 
> 0 ) right 
= m_colRights
[oldNumCols
-1]; 
4624                 for ( i 
= oldNumCols
;  i 
< m_numCols
;  i
++ ) 
4626                     right 
+= m_colWidths
[i
]; 
4627                     m_colRights
[i
] = right
; 
4630             if ( m_currentCellCoords 
== wxGridNoCellCoords 
) 
4632                 // if we have just inserted cols into an empty grid the current 
4633                 // cell will be undefined... 
4635                 SetCurrentCell( 0, 0 ); 
4637             if ( !GetBatchCount() ) 
4640                 m_colLabelWin
->Refresh(); 
4646         case wxGRIDTABLE_NOTIFY_COLS_DELETED
: 
4648             size_t pos 
= msg
.GetCommandInt(); 
4649             int numCols 
= msg
.GetCommandInt2(); 
4650             m_numCols 
-= numCols
; 
4652             if ( !m_colWidths
.IsEmpty() ) 
4654                 m_colWidths
.RemoveAt( pos
, numCols 
); 
4655                 m_colRights
.RemoveAt( pos
, numCols 
); 
4658                 for ( i 
= 0;  i 
< m_numCols
;  i
++ ) 
4660                     w 
+= m_colWidths
[i
]; 
4666                 m_currentCellCoords 
= wxGridNoCellCoords
; 
4670                 if ( m_currentCellCoords
.GetCol() >= m_numCols 
) 
4671                   m_currentCellCoords
.Set( 0, 0 ); 
4675                 m_selection
->UpdateCols( pos
, -((int)numCols
) ); 
4676             wxGridCellAttrProvider 
* attrProvider 
= m_table
->GetAttrProvider(); 
4678                 attrProvider
->UpdateAttrCols( pos
, -((int)numCols
) ); 
4679 // ifdef'd out following patch from Paul Gammans 
4681                 // No need to touch row attributes, unless we 
4682                 // removed _all_ columns, in this case, we remove 
4683                 // all row attributes. 
4684                 // I hate to do this here, but the 
4685                 // needed data is not available inside UpdateAttrCols. 
4686                 if ( !GetNumberCols() ) 
4687                     attrProvider
->UpdateAttrRows( 0, -GetNumberRows() ); 
4690             if ( !GetBatchCount() ) 
4693                 m_colLabelWin
->Refresh(); 
4700     if (result 
&& !GetBatchCount() ) 
4701         m_gridWin
->Refresh(); 
4706 wxArrayInt 
wxGrid::CalcRowLabelsExposed( const wxRegion
& reg 
) 
4708     wxRegionIterator 
iter( reg 
); 
4711     wxArrayInt  rowlabels
; 
4718         // TODO: remove this when we can... 
4719         // There is a bug in wxMotif that gives garbage update 
4720         // rectangles if you jump-scroll a long way by clicking the 
4721         // scrollbar with middle button.  This is a work-around 
4723 #if defined(__WXMOTIF__) 
4725         m_gridWin
->GetClientSize( &cw
, &ch 
); 
4726         if ( r
.GetTop() > ch 
) r
.SetTop( 0 ); 
4727         r
.SetBottom( wxMin( r
.GetBottom(), ch 
) ); 
4730         // logical bounds of update region 
4733         CalcUnscrolledPosition( 0, r
.GetTop(), &dummy
, &top 
); 
4734         CalcUnscrolledPosition( 0, r
.GetBottom(), &dummy
, &bottom 
); 
4736         // find the row labels within these bounds 
4739         for ( row 
= internalYToRow(top
);  row 
< m_numRows
;  row
++ ) 
4741             if ( GetRowBottom(row
) < top 
) 
4744             if ( GetRowTop(row
) > bottom 
) 
4747             rowlabels
.Add( row 
); 
4757 wxArrayInt 
wxGrid::CalcColLabelsExposed( const wxRegion
& reg 
) 
4759     wxRegionIterator 
iter( reg 
); 
4762     wxArrayInt colLabels
; 
4769         // TODO: remove this when we can... 
4770         // There is a bug in wxMotif that gives garbage update 
4771         // rectangles if you jump-scroll a long way by clicking the 
4772         // scrollbar with middle button.  This is a work-around 
4774 #if defined(__WXMOTIF__) 
4776         m_gridWin
->GetClientSize( &cw
, &ch 
); 
4777         if ( r
.GetLeft() > cw 
) r
.SetLeft( 0 ); 
4778         r
.SetRight( wxMin( r
.GetRight(), cw 
) ); 
4781         // logical bounds of update region 
4784         CalcUnscrolledPosition( r
.GetLeft(), 0, &left
, &dummy 
); 
4785         CalcUnscrolledPosition( r
.GetRight(), 0, &right
, &dummy 
); 
4787         // find the cells within these bounds 
4790         for ( col 
= internalXToCol(left
);  col 
< m_numCols
;  col
++ ) 
4792             if ( GetColRight(col
) < left 
) 
4795             if ( GetColLeft(col
) > right 
) 
4798             colLabels
.Add( col 
); 
4807 wxGridCellCoordsArray 
wxGrid::CalcCellsExposed( const wxRegion
& reg 
) 
4809     wxRegionIterator 
iter( reg 
); 
4812     wxGridCellCoordsArray  cellsExposed
; 
4814     int left
, top
, right
, bottom
; 
4819         // TODO: remove this when we can... 
4820         // There is a bug in wxMotif that gives garbage update 
4821         // rectangles if you jump-scroll a long way by clicking the 
4822         // scrollbar with middle button.  This is a work-around 
4824 #if defined(__WXMOTIF__) 
4826         m_gridWin
->GetClientSize( &cw
, &ch 
); 
4827         if ( r
.GetTop() > ch 
) r
.SetTop( 0 ); 
4828         if ( r
.GetLeft() > cw 
) r
.SetLeft( 0 ); 
4829         r
.SetRight( wxMin( r
.GetRight(), cw 
) ); 
4830         r
.SetBottom( wxMin( r
.GetBottom(), ch 
) ); 
4833         // logical bounds of update region 
4835         CalcUnscrolledPosition( r
.GetLeft(), r
.GetTop(), &left
, &top 
); 
4836         CalcUnscrolledPosition( r
.GetRight(), r
.GetBottom(), &right
, &bottom 
); 
4838         // find the cells within these bounds 
4841         for ( row 
= internalYToRow(top
);  row 
< m_numRows
;  row
++ ) 
4843             if ( GetRowBottom(row
) <= top 
) 
4846             if ( GetRowTop(row
) > bottom 
) 
4849             for ( col 
= internalXToCol(left
);  col 
< m_numCols
;  col
++ ) 
4851                 if ( GetColRight(col
) <= left 
) 
4854                 if ( GetColLeft(col
) > right 
) 
4857                 cellsExposed
.Add( wxGridCellCoords( row
, col 
) ); 
4864     return cellsExposed
; 
4868 void wxGrid::ProcessRowLabelMouseEvent( wxMouseEvent
& event 
) 
4871     wxPoint 
pos( event
.GetPosition() ); 
4872     CalcUnscrolledPosition( pos
.x
, pos
.y
, &x
, &y 
); 
4874     if ( event
.Dragging() ) 
4878             m_isDragging 
= true; 
4879             m_rowLabelWin
->CaptureMouse(); 
4882         if ( event
.LeftIsDown() ) 
4884             switch( m_cursorMode 
) 
4886                 case WXGRID_CURSOR_RESIZE_ROW
: 
4888                     int cw
, ch
, left
, dummy
; 
4889                     m_gridWin
->GetClientSize( &cw
, &ch 
); 
4890                     CalcUnscrolledPosition( 0, 0, &left
, &dummy 
); 
4892                     wxClientDC 
dc( m_gridWin 
); 
4895                                GetRowTop(m_dragRowOrCol
) + 
4896                                GetRowMinimalHeight(m_dragRowOrCol
) ); 
4897                     dc
.SetLogicalFunction(wxINVERT
); 
4898                     if ( m_dragLastPos 
>= 0 ) 
4900                         dc
.DrawLine( left
, m_dragLastPos
, left
+cw
, m_dragLastPos 
); 
4902                     dc
.DrawLine( left
, y
, left
+cw
, y 
); 
4907                 case WXGRID_CURSOR_SELECT_ROW
: 
4909                     if ( (row 
= YToRow( y 
)) >= 0 ) 
4913                             m_selection
->SelectRow( row
, 
4914                                                     event
.ControlDown(), 
4923                 // default label to suppress warnings about "enumeration value 
4924                 // 'xxx' not handled in switch 
4932     if ( m_isDragging 
&& (event
.Entering() || event
.Leaving()) ) 
4937         if (m_rowLabelWin
->HasCapture()) m_rowLabelWin
->ReleaseMouse(); 
4938         m_isDragging 
= false; 
4941     // ------------ Entering or leaving the window 
4943     if ( event
.Entering() || event
.Leaving() ) 
4945         ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
, m_rowLabelWin
); 
4949     // ------------ Left button pressed 
4951     else if ( event
.LeftDown() ) 
4953         // don't send a label click event for a hit on the 
4954         // edge of the row label - this is probably the user 
4955         // wanting to resize the row 
4957         if ( YToEdgeOfRow(y
) < 0 ) 
4961                  !SendEvent( wxEVT_GRID_LABEL_LEFT_CLICK
, row
, -1, event 
) ) 
4963                 if ( !event
.ShiftDown() && !event
.ControlDown() ) 
4967                     if ( event
.ShiftDown() ) 
4969                         m_selection
->SelectBlock( m_currentCellCoords
.GetRow(), 
4972                                                   GetNumberCols() - 1, 
4973                                                   event
.ControlDown(), 
4980                         m_selection
->SelectRow( row
, 
4981                                                 event
.ControlDown(), 
4988                 ChangeCursorMode(WXGRID_CURSOR_SELECT_ROW
, m_rowLabelWin
); 
4993             // starting to drag-resize a row 
4995             if ( CanDragRowSize() ) 
4996                 ChangeCursorMode(WXGRID_CURSOR_RESIZE_ROW
, m_rowLabelWin
); 
5001     // ------------ Left double click 
5003     else if (event
.LeftDClick() ) 
5005         int row 
= YToEdgeOfRow(y
); 
5010                  !SendEvent( wxEVT_GRID_LABEL_LEFT_DCLICK
, row
, -1, event 
) ) 
5012                 // no default action at the moment 
5017             // adjust row height depending on label text 
5018             AutoSizeRowLabelSize( row 
); 
5020             ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
, m_colLabelWin
); 
5026     // ------------ Left button released 
5028     else if ( event
.LeftUp() ) 
5030         if ( m_cursorMode 
== WXGRID_CURSOR_RESIZE_ROW 
) 
5032             DoEndDragResizeRow(); 
5034             // Note: we are ending the event *after* doing 
5035             // default processing in this case 
5037             SendEvent( wxEVT_GRID_ROW_SIZE
, m_dragRowOrCol
, -1, event 
); 
5040         ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
, m_rowLabelWin
); 
5045     // ------------ Right button down 
5047     else if ( event
.RightDown() ) 
5051              !SendEvent( wxEVT_GRID_LABEL_RIGHT_CLICK
, row
, -1, event 
) ) 
5053             // no default action at the moment 
5058     // ------------ Right double click 
5060     else if ( event
.RightDClick() ) 
5064              !SendEvent( wxEVT_GRID_LABEL_RIGHT_DCLICK
, row
, -1, event 
) ) 
5066             // no default action at the moment 
5071     // ------------ No buttons down and mouse moving 
5073     else if ( event
.Moving() ) 
5075         m_dragRowOrCol 
= YToEdgeOfRow( y 
); 
5076         if ( m_dragRowOrCol 
>= 0 ) 
5078             if ( m_cursorMode 
== WXGRID_CURSOR_SELECT_CELL 
) 
5080                 // don't capture the mouse yet 
5081                 if ( CanDragRowSize() ) 
5082                     ChangeCursorMode(WXGRID_CURSOR_RESIZE_ROW
, m_rowLabelWin
, false); 
5085         else if ( m_cursorMode 
!= WXGRID_CURSOR_SELECT_CELL 
) 
5087             ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
, m_rowLabelWin
, false); 
5093 void wxGrid::ProcessColLabelMouseEvent( wxMouseEvent
& event 
) 
5096     wxPoint 
pos( event
.GetPosition() ); 
5097     CalcUnscrolledPosition( pos
.x
, pos
.y
, &x
, &y 
); 
5099     if ( event
.Dragging() ) 
5103             m_isDragging 
= true; 
5104             m_colLabelWin
->CaptureMouse(); 
5107         if ( event
.LeftIsDown() ) 
5109             switch( m_cursorMode 
) 
5111                 case WXGRID_CURSOR_RESIZE_COL
: 
5113                     int cw
, ch
, dummy
, top
; 
5114                     m_gridWin
->GetClientSize( &cw
, &ch 
); 
5115                     CalcUnscrolledPosition( 0, 0, &dummy
, &top 
); 
5117                     wxClientDC 
dc( m_gridWin 
); 
5120                     x 
= wxMax( x
, GetColLeft(m_dragRowOrCol
) + 
5121                                   GetColMinimalWidth(m_dragRowOrCol
)); 
5122                     dc
.SetLogicalFunction(wxINVERT
); 
5123                     if ( m_dragLastPos 
>= 0 ) 
5125                         dc
.DrawLine( m_dragLastPos
, top
, m_dragLastPos
, top
+ch 
); 
5127                     dc
.DrawLine( x
, top
, x
, top
+ch 
); 
5132                 case WXGRID_CURSOR_SELECT_COL
: 
5134                     if ( (col 
= XToCol( x 
)) >= 0 ) 
5138                             m_selection
->SelectCol( col
, 
5139                                                     event
.ControlDown(), 
5148                 // default label to suppress warnings about "enumeration value 
5149                 // 'xxx' not handled in switch 
5157     if ( m_isDragging 
&& (event
.Entering() || event
.Leaving()) ) 
5162         if (m_colLabelWin
->HasCapture()) m_colLabelWin
->ReleaseMouse(); 
5163         m_isDragging 
= false; 
5166     // ------------ Entering or leaving the window 
5168     if ( event
.Entering() || event
.Leaving() ) 
5170         ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
, m_colLabelWin
); 
5174     // ------------ Left button pressed 
5176     else if ( event
.LeftDown() ) 
5178         // don't send a label click event for a hit on the 
5179         // edge of the col label - this is probably the user 
5180         // wanting to resize the col 
5182         if ( XToEdgeOfCol(x
) < 0 ) 
5186                  !SendEvent( wxEVT_GRID_LABEL_LEFT_CLICK
, -1, col
, event 
) ) 
5188                 if ( !event
.ShiftDown() && !event
.ControlDown() ) 
5192                     if ( event
.ShiftDown() ) 
5194                         m_selection
->SelectBlock( 0, 
5195                                                   m_currentCellCoords
.GetCol(), 
5196                                                   GetNumberRows() - 1, col
, 
5197                                                   event
.ControlDown(), 
5204                         m_selection
->SelectCol( col
, 
5205                                                 event
.ControlDown(), 
5212                 ChangeCursorMode(WXGRID_CURSOR_SELECT_COL
, m_colLabelWin
); 
5217             // starting to drag-resize a col 
5219             if ( CanDragColSize() ) 
5220                 ChangeCursorMode(WXGRID_CURSOR_RESIZE_COL
, m_colLabelWin
); 
5225     // ------------ Left double click 
5227     if ( event
.LeftDClick() ) 
5229         int col 
= XToEdgeOfCol(x
); 
5234                  ! SendEvent( wxEVT_GRID_LABEL_LEFT_DCLICK
, -1, col
, event 
) ) 
5236                 // no default action at the moment 
5241             // adjust column width depending on label text 
5242             AutoSizeColLabelSize( col 
); 
5244             ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
, m_colLabelWin
); 
5250     // ------------ Left button released 
5252     else if ( event
.LeftUp() ) 
5254         if ( m_cursorMode 
== WXGRID_CURSOR_RESIZE_COL 
) 
5256             DoEndDragResizeCol(); 
5258             // Note: we are ending the event *after* doing 
5259             // default processing in this case 
5261             SendEvent( wxEVT_GRID_COL_SIZE
, -1, m_dragRowOrCol
, event 
); 
5264         ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
, m_colLabelWin
); 
5269     // ------------ Right button down 
5271     else if ( event
.RightDown() ) 
5275              !SendEvent( wxEVT_GRID_LABEL_RIGHT_CLICK
, -1, col
, event 
) ) 
5277             // no default action at the moment 
5282     // ------------ Right double click 
5284     else if ( event
.RightDClick() ) 
5288              !SendEvent( wxEVT_GRID_LABEL_RIGHT_DCLICK
, -1, col
, event 
) ) 
5290             // no default action at the moment 
5295     // ------------ No buttons down and mouse moving 
5297     else if ( event
.Moving() ) 
5299         m_dragRowOrCol 
= XToEdgeOfCol( x 
); 
5300         if ( m_dragRowOrCol 
>= 0 ) 
5302             if ( m_cursorMode 
== WXGRID_CURSOR_SELECT_CELL 
) 
5304                 // don't capture the cursor yet 
5305                 if ( CanDragColSize() ) 
5306                     ChangeCursorMode(WXGRID_CURSOR_RESIZE_COL
, m_colLabelWin
, false); 
5309         else if ( m_cursorMode 
!= WXGRID_CURSOR_SELECT_CELL 
) 
5311             ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
, m_colLabelWin
, false); 
5317 void wxGrid::ProcessCornerLabelMouseEvent( wxMouseEvent
& event 
) 
5319     if ( event
.LeftDown() ) 
5321         // indicate corner label by having both row and 
5324         if ( !SendEvent( wxEVT_GRID_LABEL_LEFT_CLICK
, -1, -1, event 
) ) 
5330     else if ( event
.LeftDClick() ) 
5332         SendEvent( wxEVT_GRID_LABEL_LEFT_DCLICK
, -1, -1, event 
); 
5335     else if ( event
.RightDown() ) 
5337         if ( !SendEvent( wxEVT_GRID_LABEL_RIGHT_CLICK
, -1, -1, event 
) ) 
5339             // no default action at the moment 
5343     else if ( event
.RightDClick() ) 
5345         if ( !SendEvent( wxEVT_GRID_LABEL_RIGHT_DCLICK
, -1, -1, event 
) ) 
5347             // no default action at the moment 
5352 void wxGrid::ChangeCursorMode(CursorMode mode
, 
5357     static const wxChar 
*cursorModes
[] = 
5366     wxLogTrace(_T("grid"), 
5367                _T("wxGrid cursor mode (mouse capture for %s): %s -> %s"), 
5368                win 
== m_colLabelWin 
? _T("colLabelWin") 
5369                                     : win 
? _T("rowLabelWin") 
5371                cursorModes
[m_cursorMode
], cursorModes
[mode
]); 
5372 #endif // __WXDEBUG__ 
5374     if ( mode 
== m_cursorMode 
&& 
5375          win 
== m_winCapture 
&& 
5376          captureMouse 
== (m_winCapture 
!= NULL
)) 
5381         // by default use the grid itself 
5387         if (m_winCapture
->HasCapture()) m_winCapture
->ReleaseMouse(); 
5388         m_winCapture 
= (wxWindow 
*)NULL
; 
5391     m_cursorMode 
= mode
; 
5393     switch ( m_cursorMode 
) 
5395         case WXGRID_CURSOR_RESIZE_ROW
: 
5396             win
->SetCursor( m_rowResizeCursor 
); 
5399         case WXGRID_CURSOR_RESIZE_COL
: 
5400             win
->SetCursor( m_colResizeCursor 
); 
5404             win
->SetCursor( *wxSTANDARD_CURSOR 
); 
5407     // we need to capture mouse when resizing 
5408     bool resize 
= m_cursorMode 
== WXGRID_CURSOR_RESIZE_ROW 
|| 
5409                   m_cursorMode 
== WXGRID_CURSOR_RESIZE_COL
; 
5411     if ( captureMouse 
&& resize 
) 
5413         win
->CaptureMouse(); 
5418 void wxGrid::ProcessGridCellMouseEvent( wxMouseEvent
& event 
) 
5421     wxPoint 
pos( event
.GetPosition() ); 
5422     CalcUnscrolledPosition( pos
.x
, pos
.y
, &x
, &y 
); 
5424     wxGridCellCoords coords
; 
5425     XYToCell( x
, y
, coords 
); 
5427     int cell_rows
, cell_cols
; 
5428     bool isFirstDrag 
= !m_isDragging
; 
5429     GetCellSize( coords
.GetRow(), coords
.GetCol(), &cell_rows
, &cell_cols 
); 
5430     if ((cell_rows 
< 0) || (cell_cols 
< 0)) 
5432         coords
.SetRow(coords
.GetRow() + cell_rows
); 
5433         coords
.SetCol(coords
.GetCol() + cell_cols
); 
5436     if ( event
.Dragging() ) 
5438         //wxLogDebug("pos(%d, %d) coords(%d, %d)", pos.x, pos.y, coords.GetRow(), coords.GetCol()); 
5440         // Don't start doing anything until the mouse has been drug at 
5441         // least 3 pixels in any direction... 
5444             if (m_startDragPos 
== wxDefaultPosition
) 
5446                 m_startDragPos 
= pos
; 
5449             if (abs(m_startDragPos
.x 
- pos
.x
) < 4 && abs(m_startDragPos
.y 
- pos
.y
) < 4) 
5453         m_isDragging 
= true; 
5454         if ( m_cursorMode 
== WXGRID_CURSOR_SELECT_CELL 
) 
5456             // Hide the edit control, so it 
5457             // won't interfer with drag-shrinking. 
5458             if ( IsCellEditControlShown() ) 
5460                 HideCellEditControl(); 
5461                 SaveEditControlValue(); 
5464             // Have we captured the mouse yet? 
5467                 m_winCapture 
= m_gridWin
; 
5468                 m_winCapture
->CaptureMouse(); 
5471             if ( coords 
!= wxGridNoCellCoords 
) 
5473                 if ( event
.ControlDown() ) 
5475                     if ( m_selectingKeyboard 
== wxGridNoCellCoords
) 
5476                         m_selectingKeyboard 
= coords
; 
5477                     HighlightBlock ( m_selectingKeyboard
, coords 
); 
5479                 else if ( CanDragCell() ) 
5483                         if ( m_selectingKeyboard 
== wxGridNoCellCoords
) 
5484                             m_selectingKeyboard 
= coords
; 
5486                         SendEvent( wxEVT_GRID_CELL_BEGIN_DRAG
, 
5494                     if ( !IsSelection() ) 
5496                         HighlightBlock( coords
, coords 
); 
5500                         HighlightBlock( m_currentCellCoords
, coords 
); 
5504                 if (! IsVisible(coords
)) 
5506                     MakeCellVisible(coords
); 
5507                     // TODO: need to introduce a delay or something here.  The 
5508                     // scrolling is way to fast, at least on MSW - also on GTK. 
5512         else if ( m_cursorMode 
== WXGRID_CURSOR_RESIZE_ROW 
) 
5514             int cw
, ch
, left
, dummy
; 
5515             m_gridWin
->GetClientSize( &cw
, &ch 
); 
5516             CalcUnscrolledPosition( 0, 0, &left
, &dummy 
); 
5518             wxClientDC 
dc( m_gridWin 
); 
5520             y 
= wxMax( y
, GetRowTop(m_dragRowOrCol
) + 
5521                           GetRowMinimalHeight(m_dragRowOrCol
) ); 
5522             dc
.SetLogicalFunction(wxINVERT
); 
5523             if ( m_dragLastPos 
>= 0 ) 
5525                 dc
.DrawLine( left
, m_dragLastPos
, left
+cw
, m_dragLastPos 
); 
5527             dc
.DrawLine( left
, y
, left
+cw
, y 
); 
5530         else if ( m_cursorMode 
== WXGRID_CURSOR_RESIZE_COL 
) 
5532             int cw
, ch
, dummy
, top
; 
5533             m_gridWin
->GetClientSize( &cw
, &ch 
); 
5534             CalcUnscrolledPosition( 0, 0, &dummy
, &top 
); 
5536             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 
); 
5552     m_isDragging 
= false; 
5553     m_startDragPos 
= wxDefaultPosition
; 
5555     // VZ: if we do this, the mode is reset to WXGRID_CURSOR_SELECT_CELL 
5556     //     immediately after it becomes WXGRID_CURSOR_RESIZE_ROW/COL under 
5559     if ( event
.Entering() || event
.Leaving() ) 
5561         ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
); 
5562         m_gridWin
->SetCursor( *wxSTANDARD_CURSOR 
); 
5567     // ------------ Left button pressed 
5569     if ( event
.LeftDown() && coords 
!= wxGridNoCellCoords 
) 
5571         if ( !SendEvent( wxEVT_GRID_CELL_LEFT_CLICK
, 
5576             if ( !event
.ControlDown() ) 
5578             if ( event
.ShiftDown() ) 
5582                     m_selection
->SelectBlock( m_currentCellCoords
.GetRow(), 
5583                                               m_currentCellCoords
.GetCol(), 
5586                                               event
.ControlDown(), 
5592             else if ( XToEdgeOfCol(x
) < 0  && 
5593                       YToEdgeOfRow(y
) < 0 ) 
5595                 DisableCellEditControl(); 
5596                 MakeCellVisible( coords 
); 
5598                 if ( event
.ControlDown() ) 
5602                         m_selection
->ToggleCellSelection( coords
.GetRow(), 
5604                                                           event
.ControlDown(), 
5609                     m_selectingTopLeft 
= wxGridNoCellCoords
; 
5610                     m_selectingBottomRight 
= wxGridNoCellCoords
; 
5611                     m_selectingKeyboard 
= coords
; 
5615                     m_waitForSlowClick 
= m_currentCellCoords 
== coords 
&& coords 
!= wxGridNoCellCoords
; 
5616                     SetCurrentCell( coords 
); 
5619                         if ( m_selection
->GetSelectionMode() != 
5620                                 wxGrid::wxGridSelectCells 
) 
5622                             HighlightBlock( coords
, coords 
); 
5631     // ------------ Left double click 
5633     else if ( event
.LeftDClick() && coords 
!= wxGridNoCellCoords 
) 
5635         DisableCellEditControl(); 
5637         if ( XToEdgeOfCol(x
) < 0  &&  YToEdgeOfRow(y
) < 0 ) 
5639             if ( !SendEvent( wxEVT_GRID_CELL_LEFT_DCLICK
, 
5644                 // we want double click to select a cell and start editing 
5645                 // (i.e. to behave in same way as sequence of two slow clicks): 
5646                 m_waitForSlowClick 
= true; 
5653     // ------------ Left button released 
5655     else if ( event
.LeftUp() ) 
5657         if ( m_cursorMode 
== WXGRID_CURSOR_SELECT_CELL 
) 
5661                 if (m_winCapture
->HasCapture()) m_winCapture
->ReleaseMouse(); 
5662                 m_winCapture 
= NULL
; 
5665             if ( coords 
== m_currentCellCoords 
&& m_waitForSlowClick 
&& CanEnableCellControl()) 
5668                 EnableCellEditControl(); 
5670                 wxGridCellAttr
* attr 
= GetCellAttr(coords
); 
5671                 wxGridCellEditor 
*editor 
= attr
->GetEditor(this, coords
.GetRow(), coords
.GetCol()); 
5672                 editor
->StartingClick(); 
5676                 m_waitForSlowClick 
= false; 
5678             else if ( m_selectingTopLeft 
!= wxGridNoCellCoords 
&& 
5679                  m_selectingBottomRight 
!= wxGridNoCellCoords 
) 
5683                     m_selection
->SelectBlock( m_selectingTopLeft
.GetRow(), 
5684                                               m_selectingTopLeft
.GetCol(), 
5685                                               m_selectingBottomRight
.GetRow(), 
5686                                               m_selectingBottomRight
.GetCol(), 
5687                                               event
.ControlDown(), 
5693                 m_selectingTopLeft 
= wxGridNoCellCoords
; 
5694                 m_selectingBottomRight 
= wxGridNoCellCoords
; 
5696                 // Show the edit control, if it has been hidden for 
5698                 ShowCellEditControl(); 
5701         else if ( m_cursorMode 
== WXGRID_CURSOR_RESIZE_ROW 
) 
5703             ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
); 
5704             DoEndDragResizeRow(); 
5706             // Note: we are ending the event *after* doing 
5707             // default processing in this case 
5709             SendEvent( wxEVT_GRID_ROW_SIZE
, m_dragRowOrCol
, -1, event 
); 
5711         else if ( m_cursorMode 
== WXGRID_CURSOR_RESIZE_COL 
) 
5713             ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
); 
5714             DoEndDragResizeCol(); 
5716             // Note: we are ending the event *after* doing 
5717             // default processing in this case 
5719             SendEvent( wxEVT_GRID_COL_SIZE
, -1, m_dragRowOrCol
, event 
); 
5726     // ------------ Right button down 
5728     else if ( event
.RightDown() && coords 
!= wxGridNoCellCoords 
) 
5730         DisableCellEditControl(); 
5731         if ( !SendEvent( wxEVT_GRID_CELL_RIGHT_CLICK
, 
5736             // no default action at the moment 
5741     // ------------ Right double click 
5743     else if ( event
.RightDClick() && coords 
!= wxGridNoCellCoords 
) 
5745         DisableCellEditControl(); 
5746         if ( !SendEvent( wxEVT_GRID_CELL_RIGHT_DCLICK
, 
5751             // no default action at the moment 
5755     // ------------ Moving and no button action 
5757     else if ( event
.Moving() && !event
.IsButton() ) 
5759         if( coords
.GetRow() < 0 || coords
.GetCol() < 0 ) 
5761             // out of grid cell area 
5762             ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
); 
5766         int dragRow 
= YToEdgeOfRow( y 
); 
5767         int dragCol 
= XToEdgeOfCol( x 
); 
5769         // Dragging on the corner of a cell to resize in both 
5770         // directions is not implemented yet... 
5772         if ( dragRow 
>= 0  &&  dragCol 
>= 0 ) 
5774             ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
); 
5780             m_dragRowOrCol 
= dragRow
; 
5782             if ( m_cursorMode 
== WXGRID_CURSOR_SELECT_CELL 
) 
5784                 if ( CanDragRowSize() && CanDragGridSize() ) 
5785                     ChangeCursorMode(WXGRID_CURSOR_RESIZE_ROW
); 
5790                 m_dragRowOrCol 
= dragCol
; 
5798             m_dragRowOrCol 
= dragCol
; 
5800             if ( m_cursorMode 
== WXGRID_CURSOR_SELECT_CELL 
) 
5802                 if ( CanDragColSize() && CanDragGridSize() ) 
5803                     ChangeCursorMode(WXGRID_CURSOR_RESIZE_COL
); 
5809         // Neither on a row or col edge 
5811         if ( m_cursorMode 
!= WXGRID_CURSOR_SELECT_CELL 
) 
5813             ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
); 
5819 void wxGrid::DoEndDragResizeRow() 
5821     if ( m_dragLastPos 
>= 0 ) 
5823         // erase the last line and resize the row 
5825         int cw
, ch
, left
, dummy
; 
5826         m_gridWin
->GetClientSize( &cw
, &ch 
); 
5827         CalcUnscrolledPosition( 0, 0, &left
, &dummy 
); 
5829         wxClientDC 
dc( m_gridWin 
); 
5831         dc
.SetLogicalFunction( wxINVERT 
); 
5832         dc
.DrawLine( left
, m_dragLastPos
, left
+cw
, m_dragLastPos 
); 
5833         HideCellEditControl(); 
5834         SaveEditControlValue(); 
5836         int rowTop 
= GetRowTop(m_dragRowOrCol
); 
5837         SetRowSize( m_dragRowOrCol
, 
5838                     wxMax( m_dragLastPos 
- rowTop
, m_minAcceptableRowHeight 
) ); 
5840         if ( !GetBatchCount() ) 
5842             // Only needed to get the correct rect.y: 
5843             wxRect 
rect ( CellToRect( m_dragRowOrCol
, 0 ) ); 
5845             CalcScrolledPosition(0, rect
.y
, &dummy
, &rect
.y
); 
5846             rect
.width 
= m_rowLabelWidth
; 
5847             rect
.height 
= ch 
- rect
.y
; 
5848             m_rowLabelWin
->Refresh( true, &rect 
); 
5850             // if there is a multicell block, paint all of it 
5853                 int i
, cell_rows
, cell_cols
, subtract_rows 
= 0; 
5854                 int leftCol 
= XToCol(left
); 
5855                 int rightCol 
= internalXToCol(left
+cw
); 
5858                     for (i
=leftCol
; i
<rightCol
; i
++) 
5860                         GetCellSize(m_dragRowOrCol
, i
, &cell_rows
, &cell_cols
); 
5861                         if (cell_rows 
< subtract_rows
) 
5862                             subtract_rows 
= cell_rows
; 
5864                     rect
.y 
= GetRowTop(m_dragRowOrCol 
+ subtract_rows
); 
5865                     CalcScrolledPosition(0, rect
.y
, &dummy
, &rect
.y
); 
5866                     rect
.height 
= ch 
- rect
.y
; 
5869             m_gridWin
->Refresh( false, &rect 
); 
5872         ShowCellEditControl(); 
5877 void wxGrid::DoEndDragResizeCol() 
5879     if ( m_dragLastPos 
>= 0 ) 
5881         // erase the last line and resize the col 
5883         int cw
, ch
, dummy
, top
; 
5884         m_gridWin
->GetClientSize( &cw
, &ch 
); 
5885         CalcUnscrolledPosition( 0, 0, &dummy
, &top 
); 
5887         wxClientDC 
dc( m_gridWin 
); 
5889         dc
.SetLogicalFunction( wxINVERT 
); 
5890         dc
.DrawLine( m_dragLastPos
, top
, m_dragLastPos
, top
+ch 
); 
5891         HideCellEditControl(); 
5892         SaveEditControlValue(); 
5894         int colLeft 
= GetColLeft(m_dragRowOrCol
); 
5895         SetColSize( m_dragRowOrCol
, 
5896                     wxMax( m_dragLastPos 
- colLeft
, 
5897                            GetColMinimalWidth(m_dragRowOrCol
) ) ); 
5899         if ( !GetBatchCount() ) 
5901             // Only needed to get the correct rect.x: 
5902             wxRect 
rect ( CellToRect( 0, m_dragRowOrCol 
) ); 
5904             CalcScrolledPosition(rect
.x
, 0, &rect
.x
, &dummy
); 
5905             rect
.width 
= cw 
- rect
.x
; 
5906             rect
.height 
= m_colLabelHeight
; 
5907             m_colLabelWin
->Refresh( true, &rect 
); 
5909             // if there is a multicell block, paint all of it 
5912                 int i
, cell_rows
, cell_cols
, subtract_cols 
= 0; 
5913                 int topRow 
= YToRow(top
); 
5914                 int bottomRow 
= internalYToRow(top
+cw
); 
5917                     for (i
=topRow
; i
<bottomRow
; i
++) 
5919                         GetCellSize(i
, m_dragRowOrCol
, &cell_rows
, &cell_cols
); 
5920                         if (cell_cols 
< subtract_cols
) 
5921                             subtract_cols 
= cell_cols
; 
5923                     rect
.x 
= GetColLeft(m_dragRowOrCol 
+ subtract_cols
); 
5924                     CalcScrolledPosition(rect
.x
, 0, &rect
.x
, &dummy
); 
5925                     rect
.width 
= cw 
- rect
.x
; 
5928             m_gridWin
->Refresh( false, &rect 
); 
5931         ShowCellEditControl(); 
5938 // ------ interaction with data model 
5940 bool wxGrid::ProcessTableMessage( wxGridTableMessage
& msg 
) 
5942     switch ( msg
.GetId() ) 
5944         case wxGRIDTABLE_REQUEST_VIEW_GET_VALUES
: 
5945             return GetModelValues(); 
5947         case wxGRIDTABLE_REQUEST_VIEW_SEND_VALUES
: 
5948             return SetModelValues(); 
5950         case wxGRIDTABLE_NOTIFY_ROWS_INSERTED
: 
5951         case wxGRIDTABLE_NOTIFY_ROWS_APPENDED
: 
5952         case wxGRIDTABLE_NOTIFY_ROWS_DELETED
: 
5953         case wxGRIDTABLE_NOTIFY_COLS_INSERTED
: 
5954         case wxGRIDTABLE_NOTIFY_COLS_APPENDED
: 
5955         case wxGRIDTABLE_NOTIFY_COLS_DELETED
: 
5956             return Redimension( msg 
); 
5965 // The behaviour of this function depends on the grid table class 
5966 // Clear() function.  For the default wxGridStringTable class the 
5967 // behavious is to replace all cell contents with wxEmptyString but 
5968 // not to change the number of rows or cols. 
5970 void wxGrid::ClearGrid() 
5974         if (IsCellEditControlEnabled()) 
5975             DisableCellEditControl(); 
5978         if ( !GetBatchCount() ) m_gridWin
->Refresh(); 
5983 bool wxGrid::InsertRows( int pos
, int numRows
, bool WXUNUSED(updateLabels
) ) 
5985     // TODO: something with updateLabels flag 
5989         wxFAIL_MSG( wxT("Called wxGrid::InsertRows() before calling CreateGrid()") ); 
5995         if (IsCellEditControlEnabled()) 
5996             DisableCellEditControl(); 
5998         bool done 
= m_table
->InsertRows( pos
, numRows 
); 
6001         // the table will have sent the results of the insert row 
6002         // operation to this view object as a grid table message 
6008 bool wxGrid::AppendRows( int numRows
, bool WXUNUSED(updateLabels
) ) 
6010     // TODO: something with updateLabels flag 
6014         wxFAIL_MSG( wxT("Called wxGrid::AppendRows() before calling CreateGrid()") ); 
6020         bool done 
= m_table 
&& m_table
->AppendRows( numRows 
); 
6022         // the table will have sent the results of the append row 
6023         // operation to this view object as a grid table message 
6029 bool wxGrid::DeleteRows( int pos
, int numRows
, bool WXUNUSED(updateLabels
) ) 
6031     // TODO: something with updateLabels flag 
6035         wxFAIL_MSG( wxT("Called wxGrid::DeleteRows() before calling CreateGrid()") ); 
6041         if (IsCellEditControlEnabled()) 
6042             DisableCellEditControl(); 
6044         bool done 
= m_table
->DeleteRows( pos
, numRows 
); 
6046         // the table will have sent the results of the delete row 
6047         // operation to this view object as a grid table message 
6053 bool wxGrid::InsertCols( int pos
, int numCols
, bool WXUNUSED(updateLabels
) ) 
6055     // TODO: something with updateLabels flag 
6059         wxFAIL_MSG( wxT("Called wxGrid::InsertCols() before calling CreateGrid()") ); 
6065         if (IsCellEditControlEnabled()) 
6066             DisableCellEditControl(); 
6068         bool done 
= m_table
->InsertCols( pos
, numCols 
); 
6070         // the table will have sent the results of the insert col 
6071         // operation to this view object as a grid table message 
6077 bool wxGrid::AppendCols( int numCols
, bool WXUNUSED(updateLabels
) ) 
6079     // TODO: something with updateLabels flag 
6083         wxFAIL_MSG( wxT("Called wxGrid::AppendCols() before calling CreateGrid()") ); 
6089         bool done 
= m_table
->AppendCols( numCols 
); 
6091         // the table will have sent the results of the append col 
6092         // operation to this view object as a grid table message 
6098 bool wxGrid::DeleteCols( int pos
, int numCols
, bool WXUNUSED(updateLabels
) ) 
6100     // TODO: something with updateLabels flag 
6104         wxFAIL_MSG( wxT("Called wxGrid::DeleteCols() before calling CreateGrid()") ); 
6110         if (IsCellEditControlEnabled()) 
6111             DisableCellEditControl(); 
6113         bool done 
= m_table
->DeleteCols( pos
, numCols 
); 
6115         // the table will have sent the results of the delete col 
6116         // operation to this view object as a grid table message 
6124 // ----- event handlers 
6127 // Generate a grid event based on a mouse event and 
6128 // return the result of ProcessEvent() 
6130 int wxGrid::SendEvent( const wxEventType type
, 
6132                         wxMouseEvent
& mouseEv 
) 
6137    if ( type 
== wxEVT_GRID_ROW_SIZE 
|| type 
== wxEVT_GRID_COL_SIZE 
) 
6139        int rowOrCol 
= (row 
== -1 ? col 
: row
); 
6141        wxGridSizeEvent 
gridEvt( GetId(), 
6145                mouseEv
.GetX() + GetRowLabelSize(), 
6146                mouseEv
.GetY() + GetColLabelSize(), 
6147                mouseEv
.ControlDown(), 
6148                mouseEv
.ShiftDown(), 
6150                mouseEv
.MetaDown() ); 
6152        claimed 
= GetEventHandler()->ProcessEvent(gridEvt
); 
6153        vetoed 
= !gridEvt
.IsAllowed(); 
6155    else if ( type 
== wxEVT_GRID_RANGE_SELECT 
) 
6157        // Right now, it should _never_ end up here! 
6158        wxGridRangeSelectEvent 
gridEvt( GetId(), 
6162                m_selectingBottomRight
, 
6164                mouseEv
.ControlDown(), 
6165                mouseEv
.ShiftDown(), 
6167                mouseEv
.MetaDown() ); 
6169        claimed 
= GetEventHandler()->ProcessEvent(gridEvt
); 
6170        vetoed 
= !gridEvt
.IsAllowed(); 
6174        wxGridEvent 
gridEvt( GetId(), 
6178                mouseEv
.GetX() + GetRowLabelSize(), 
6179                mouseEv
.GetY() + GetColLabelSize(), 
6181                mouseEv
.ControlDown(), 
6182                mouseEv
.ShiftDown(), 
6184                mouseEv
.MetaDown() ); 
6185        claimed 
= GetEventHandler()->ProcessEvent(gridEvt
); 
6186        vetoed 
= !gridEvt
.IsAllowed(); 
6189    // A Veto'd event may not be `claimed' so test this first 
6190    if (vetoed
) return -1; 
6191    return claimed 
? 1 : 0; 
6195 // Generate a grid event of specified type and return the result 
6196 // of ProcessEvent(). 
6198 int wxGrid::SendEvent( const wxEventType type
, 
6204     if ( type 
== wxEVT_GRID_ROW_SIZE 
|| type 
== wxEVT_GRID_COL_SIZE 
) 
6206         int rowOrCol 
= (row 
== -1 ? col 
: row
); 
6208         wxGridSizeEvent 
gridEvt( GetId(), 
6213         claimed 
= GetEventHandler()->ProcessEvent(gridEvt
); 
6214         vetoed  
= !gridEvt
.IsAllowed(); 
6218         wxGridEvent 
gridEvt( GetId(), 
6223         claimed 
= GetEventHandler()->ProcessEvent(gridEvt
); 
6224         vetoed  
= !gridEvt
.IsAllowed(); 
6227     // A Veto'd event may not be `claimed' so test this first 
6228     if (vetoed
) return -1; 
6229     return claimed 
? 1 : 0; 
6233 void wxGrid::OnPaint( wxPaintEvent
& WXUNUSED(event
) ) 
6235     wxPaintDC 
dc(this);  // needed to prevent zillions of paint events on MSW 
6238 void wxGrid::Refresh(bool eraseb
, const wxRect
* rect
) 
6240     // Don't do anything if between Begin/EndBatch... 
6241     // EndBatch() will do all this on the last nested one anyway. 
6242     if (! GetBatchCount()) 
6244         // Refresh to get correct scrolled position: 
6245         wxScrolledWindow::Refresh(eraseb
,rect
); 
6249             int rect_x
, rect_y
, rectWidth
, rectHeight
; 
6250             int width_label
, width_cell
, height_label
, height_cell
; 
6253             //Copy rectangle can get scroll offsets.. 
6254             rect_x 
= rect
->GetX(); 
6255             rect_y 
= rect
->GetY(); 
6256             rectWidth 
= rect
->GetWidth(); 
6257             rectHeight 
= rect
->GetHeight(); 
6259             width_label 
= m_rowLabelWidth 
- rect_x
; 
6260             if (width_label 
> rectWidth
) width_label 
= rectWidth
; 
6262             height_label 
= m_colLabelHeight 
- rect_y
; 
6263             if (height_label 
> rectHeight
) height_label 
= rectHeight
; 
6265             if (rect_x 
> m_rowLabelWidth
) 
6267                 x 
= rect_x 
- m_rowLabelWidth
; 
6268                 width_cell 
= rectWidth
; 
6273                 width_cell 
= rectWidth 
- (m_rowLabelWidth 
- rect_x
); 
6276             if (rect_y 
> m_colLabelHeight
) 
6278                 y 
= rect_y 
- m_colLabelHeight
; 
6279                 height_cell 
= rectHeight
; 
6284                 height_cell 
= rectHeight 
- (m_colLabelHeight 
- rect_y
); 
6287             // Paint corner label part intersecting rect. 
6288             if ( width_label 
> 0 && height_label 
> 0 ) 
6290                 wxRect 
anotherrect(rect_x
, rect_y
, width_label
, height_label
); 
6291                 m_cornerLabelWin
->Refresh(eraseb
, &anotherrect
); 
6294             // Paint col labels part intersecting rect. 
6295             if ( width_cell 
> 0 && height_label 
> 0 ) 
6297                 wxRect 
anotherrect(x
, rect_y
, width_cell
, height_label
); 
6298                 m_colLabelWin
->Refresh(eraseb
, &anotherrect
); 
6301             // Paint row labels part intersecting rect. 
6302             if ( width_label 
> 0 && height_cell 
> 0 ) 
6304                 wxRect 
anotherrect(rect_x
, y
, width_label
, height_cell
); 
6305                 m_rowLabelWin
->Refresh(eraseb
, &anotherrect
); 
6308             // Paint cell area part intersecting rect. 
6309             if ( width_cell 
> 0 && height_cell 
> 0 ) 
6311                 wxRect 
anotherrect(x
, y
, width_cell
, height_cell
); 
6312                 m_gridWin
->Refresh(eraseb
, &anotherrect
); 
6317             m_cornerLabelWin
->Refresh(eraseb
, NULL
); 
6318             m_colLabelWin
->Refresh(eraseb
, NULL
); 
6319             m_rowLabelWin
->Refresh(eraseb
, NULL
); 
6320             m_gridWin
->Refresh(eraseb
, NULL
); 
6325 void wxGrid::OnSize( wxSizeEvent
& event 
) 
6327     // position the child windows 
6330     // don't call CalcDimensions() from here, the base class handles the size 
6336 void wxGrid::OnKeyDown( wxKeyEvent
& event 
) 
6338     if ( m_inOnKeyDown 
) 
6340         // shouldn't be here - we are going round in circles... 
6342         wxFAIL_MSG( wxT("wxGrid::OnKeyDown called while already active") ); 
6345     m_inOnKeyDown 
= true; 
6347     // propagate the event up and see if it gets processed 
6349     wxWindow 
*parent 
= GetParent(); 
6350     wxKeyEvent 
keyEvt( event 
); 
6351     keyEvt
.SetEventObject( parent 
); 
6353     if ( !parent
->GetEventHandler()->ProcessEvent( keyEvt 
) ) 
6356         // try local handlers 
6358         switch ( event
.GetKeyCode() ) 
6361                 if ( event
.ControlDown() ) 
6363                     MoveCursorUpBlock( event
.ShiftDown() ); 
6367                     MoveCursorUp( event
.ShiftDown() ); 
6372                 if ( event
.ControlDown() ) 
6374                     MoveCursorDownBlock( event
.ShiftDown() ); 
6378                     MoveCursorDown( event
.ShiftDown() ); 
6383                 if ( event
.ControlDown() ) 
6385                     MoveCursorLeftBlock( event
.ShiftDown() ); 
6389                     MoveCursorLeft( event
.ShiftDown() ); 
6394                 if ( event
.ControlDown() ) 
6396                     MoveCursorRightBlock( event
.ShiftDown() ); 
6400                     MoveCursorRight( event
.ShiftDown() ); 
6405             case WXK_NUMPAD_ENTER
: 
6406                 if ( event
.ControlDown() ) 
6408                     event
.Skip();  // to let the edit control have the return 
6412                     if ( GetGridCursorRow() < GetNumberRows()-1 ) 
6414                         MoveCursorDown( event
.ShiftDown() ); 
6418                         // at the bottom of a column 
6419                         DisableCellEditControl(); 
6429                 if (event
.ShiftDown()) 
6431                     if ( GetGridCursorCol() > 0 ) 
6433                         MoveCursorLeft( false ); 
6438                         DisableCellEditControl(); 
6443                     if ( GetGridCursorCol() < GetNumberCols()-1 ) 
6445                         MoveCursorRight( false ); 
6450                         DisableCellEditControl(); 
6456                 if ( event
.ControlDown() ) 
6458                     MakeCellVisible( 0, 0 ); 
6459                     SetCurrentCell( 0, 0 ); 
6468                 if ( event
.ControlDown() ) 
6470                     MakeCellVisible( m_numRows
-1, m_numCols
-1 ); 
6471                     SetCurrentCell( m_numRows
-1, m_numCols
-1 ); 
6488                 if ( event
.ControlDown() ) 
6492                         m_selection
->ToggleCellSelection( m_currentCellCoords
.GetRow(), 
6493                                                           m_currentCellCoords
.GetCol(), 
6494                                                           event
.ControlDown(), 
6501                 if ( !IsEditable() ) 
6503                     MoveCursorRight( false ); 
6506                 // Otherwise fall through to default 
6514     m_inOnKeyDown 
= false; 
6517 void wxGrid::OnKeyUp( wxKeyEvent
& event 
) 
6519     // try local handlers 
6521     if ( event
.GetKeyCode() == WXK_SHIFT 
) 
6523         if ( m_selectingTopLeft 
!= wxGridNoCellCoords 
&& 
6524              m_selectingBottomRight 
!= wxGridNoCellCoords 
) 
6528                 m_selection
->SelectBlock( m_selectingTopLeft
.GetRow(), 
6529                                           m_selectingTopLeft
.GetCol(), 
6530                                           m_selectingBottomRight
.GetRow(), 
6531                                           m_selectingBottomRight
.GetCol(), 
6532                                           event
.ControlDown(), 
6539         m_selectingTopLeft 
= wxGridNoCellCoords
; 
6540         m_selectingBottomRight 
= wxGridNoCellCoords
; 
6541         m_selectingKeyboard 
= wxGridNoCellCoords
; 
6545 void wxGrid::OnChar( wxKeyEvent
& event 
) 
6547     // is it possible to edit the current cell at all? 
6548     if ( !IsCellEditControlEnabled() && CanEnableCellControl() ) 
6550         // yes, now check whether the cells editor accepts the key 
6551         int row 
= m_currentCellCoords
.GetRow(); 
6552         int col 
= m_currentCellCoords
.GetCol(); 
6553         wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
6554         wxGridCellEditor 
*editor 
= attr
->GetEditor(this, row
, col
); 
6556         // <F2> is special and will always start editing, for 
6557         // other keys - ask the editor itself 
6558         if ( (event
.GetKeyCode() == WXK_F2 
&& !event
.HasModifiers()) 
6559              || editor
->IsAcceptedKey(event
) ) 
6561             // ensure cell is visble 
6562             MakeCellVisible(row
, col
); 
6563             EnableCellEditControl(); 
6565             // a problem can arise if the cell is not completely 
6566             // visible (even after calling MakeCellVisible the 
6567             // control is not created and calling StartingKey will 
6569             if ( event
.GetKeyCode() != WXK_F2 
&& editor
->IsCreated() && m_cellEditCtrlEnabled 
) 
6570                 editor
->StartingKey(event
); 
6587 void wxGrid::OnEraseBackground(wxEraseEvent
&) 
6591 void wxGrid::SetCurrentCell( const wxGridCellCoords
& coords 
) 
6593     if ( SendEvent( wxEVT_GRID_SELECT_CELL
, coords
.GetRow(), coords
.GetCol() ) ) 
6595         // the event has been intercepted - do nothing 
6599     wxClientDC 
dc(m_gridWin
); 
6602     if ( m_currentCellCoords 
!= wxGridNoCellCoords 
) 
6604         DisableCellEditControl(); 
6606         if ( IsVisible( m_currentCellCoords
, false ) ) 
6609             r 
= BlockToDeviceRect(m_currentCellCoords
, m_currentCellCoords
); 
6610             if ( !m_gridLinesEnabled 
) 
6618             wxGridCellCoordsArray cells 
= CalcCellsExposed( r 
); 
6620             // Otherwise refresh redraws the highlight! 
6621             m_currentCellCoords 
= coords
; 
6623             DrawGridCellArea(dc
,cells
); 
6624             DrawAllGridLines( dc
, r 
); 
6628     m_currentCellCoords 
= coords
; 
6630     wxGridCellAttr
* attr 
= GetCellAttr(coords
); 
6631     DrawCellHighlight(dc
, attr
); 
6636 void wxGrid::HighlightBlock( int topRow
, int leftCol
, int bottomRow
, int rightCol 
) 
6639     wxGridCellCoords updateTopLeft
, updateBottomRight
; 
6643         if ( m_selection
->GetSelectionMode() == wxGrid::wxGridSelectRows 
) 
6646             rightCol 
= GetNumberCols() - 1; 
6648         else if ( m_selection
->GetSelectionMode() == wxGrid::wxGridSelectColumns 
) 
6651             bottomRow 
= GetNumberRows() - 1; 
6655     if ( topRow 
> bottomRow 
) 
6662     if ( leftCol 
> rightCol 
) 
6669     updateTopLeft 
= wxGridCellCoords( topRow
, leftCol 
); 
6670     updateBottomRight 
= wxGridCellCoords( bottomRow
, rightCol 
); 
6672     // First the case that we selected a completely new area 
6673     if ( m_selectingTopLeft 
== wxGridNoCellCoords 
|| 
6674          m_selectingBottomRight 
== wxGridNoCellCoords 
) 
6677         rect 
= BlockToDeviceRect( wxGridCellCoords ( topRow
, leftCol 
), 
6678                                   wxGridCellCoords ( bottomRow
, rightCol 
) ); 
6679         m_gridWin
->Refresh( false, &rect 
); 
6681     // Now handle changing an existing selection area. 
6682     else if ( m_selectingTopLeft 
!= updateTopLeft 
|| 
6683               m_selectingBottomRight 
!= updateBottomRight 
) 
6685         // Compute two optimal update rectangles: 
6686         // Either one rectangle is a real subset of the 
6687         // other, or they are (almost) disjoint! 
6689         bool    need_refresh
[4]; 
6693         need_refresh
[3] = false; 
6696         // Store intermediate values 
6697         wxCoord oldLeft   
= m_selectingTopLeft
.GetCol(); 
6698         wxCoord oldTop    
= m_selectingTopLeft
.GetRow(); 
6699         wxCoord oldRight  
= m_selectingBottomRight
.GetCol(); 
6700         wxCoord oldBottom 
= m_selectingBottomRight
.GetRow(); 
6702         // Determine the outer/inner coordinates. 
6703         if (oldLeft 
> leftCol
) 
6709         if (oldTop 
> topRow 
) 
6715         if (oldRight 
< rightCol 
) 
6718             oldRight 
= rightCol
; 
6721         if (oldBottom 
< bottomRow
) 
6724             oldBottom 
= bottomRow
; 
6728         // Now, either the stuff marked old is the outer 
6729         // rectangle or we don't have a situation where one 
6730         // is contained in the other. 
6732         if ( oldLeft 
< leftCol 
) 
6734             // Refresh the newly selected or deselected 
6735             // area to the left of the old or new selection. 
6736             need_refresh
[0] = true; 
6737             rect
[0] = BlockToDeviceRect( wxGridCellCoords ( oldTop
, 
6739                                          wxGridCellCoords ( oldBottom
, 
6743         if ( oldTop  
< topRow 
) 
6745             // Refresh the newly selected or deselected 
6746             // area above the old or new selection. 
6747             need_refresh
[1] = true; 
6748             rect
[1] = BlockToDeviceRect( wxGridCellCoords ( oldTop
, 
6750                                          wxGridCellCoords ( topRow 
- 1, 
6754         if ( oldRight 
> rightCol 
) 
6756             // Refresh the newly selected or deselected 
6757             // area to the right of the old or new selection. 
6758             need_refresh
[2] = true; 
6759             rect
[2] = BlockToDeviceRect( wxGridCellCoords ( oldTop
, 
6761                                          wxGridCellCoords ( oldBottom
, 
6765         if ( oldBottom 
> bottomRow 
) 
6767             // Refresh the newly selected or deselected 
6768             // area below the old or new selection. 
6769             need_refresh
[3] = true; 
6770             rect
[3] = BlockToDeviceRect( wxGridCellCoords ( bottomRow 
+ 1, 
6772                                          wxGridCellCoords ( oldBottom
, 
6776         // various Refresh() calls 
6777         for (i 
= 0; i 
< 4; i
++ ) 
6778             if ( need_refresh
[i
] && rect
[i
] != wxGridNoCellRect 
) 
6779                 m_gridWin
->Refresh( false, &(rect
[i
]) ); 
6782     m_selectingTopLeft 
= updateTopLeft
; 
6783     m_selectingBottomRight 
= updateBottomRight
; 
6787 // ------ functions to get/send data (see also public functions) 
6790 bool wxGrid::GetModelValues() 
6792     // Hide the editor, so it won't hide a changed value. 
6793     HideCellEditControl(); 
6797         // all we need to do is repaint the grid 
6799         m_gridWin
->Refresh(); 
6807 bool wxGrid::SetModelValues() 
6811     // Disable the editor, so it won't hide a changed value. 
6812     // Do we also want to save the current value of the editor first? 
6814     DisableCellEditControl(); 
6818         for ( row 
= 0;  row 
< m_numRows
;  row
++ ) 
6820             for ( col 
= 0;  col 
< m_numCols
;  col
++ ) 
6822                 m_table
->SetValue( row
, col
, GetCellValue(row
, col
) ); 
6834 // Note - this function only draws cells that are in the list of 
6835 // exposed cells (usually set from the update region by 
6836 // CalcExposedCells) 
6838 void wxGrid::DrawGridCellArea( wxDC
& dc
, const wxGridCellCoordsArray
& cells 
) 
6840     if ( !m_numRows 
|| !m_numCols 
) return; 
6842     int i
, numCells 
= cells
.GetCount(); 
6843     int row
, col
, cell_rows
, cell_cols
; 
6844     wxGridCellCoordsArray redrawCells
; 
6846     for ( i 
= numCells
-1; i 
>= 0;  i
-- ) 
6848         row 
= cells
[i
].GetRow(); 
6849         col 
= cells
[i
].GetCol(); 
6850         GetCellSize( row
, col
, &cell_rows
, &cell_cols 
); 
6852         // If this cell is part of a multicell block, find owner for repaint 
6853         if ( cell_rows 
<= 0 || cell_cols 
<= 0 ) 
6855             wxGridCellCoords 
cell(row
+cell_rows
, col
+cell_cols
); 
6856             bool marked 
= false; 
6857             for ( int j 
= 0;  j 
< numCells
;  j
++ ) 
6859                 if ( cell 
== cells
[j
] ) 
6867                 int count 
= redrawCells
.GetCount(); 
6868                 for (int j 
= 0; j 
< count
; j
++) 
6870                     if ( cell 
== redrawCells
[j
] ) 
6876                 if (!marked
) redrawCells
.Add( cell 
); 
6878             continue; // don't bother drawing this cell 
6881         // If this cell is empty, find cell to left that might want to overflow 
6882         if (m_table 
&& m_table
->IsEmptyCell(row
, col
)) 
6884             for ( int l 
= 0; l 
< cell_rows
; l
++ ) 
6886                 // find a cell in this row to left alreay marked for repaint 
6888                 for (int k 
= 0; k 
< int(redrawCells
.GetCount()); k
++) 
6889                     if ((redrawCells
[k
].GetCol() < left
) && 
6890                         (redrawCells
[k
].GetRow() == row
)) 
6891                         left
=redrawCells
[k
].GetCol(); 
6893                 if (left 
== col
) left 
= 0; // oh well 
6895                 for (int j 
= col
-1; j 
>= left
; j
--) 
6897                     if (!m_table
->IsEmptyCell(row
+l
, j
)) 
6899                         if (GetCellOverflow(row
+l
, j
)) 
6901                             wxGridCellCoords 
cell(row
+l
, j
); 
6902                             bool marked 
= false; 
6904                             for (int k 
= 0; k 
< numCells
; k
++) 
6906                                 if ( cell 
== cells
[k
] ) 
6914                                 int count 
= redrawCells
.GetCount(); 
6915                                 for (int k 
= 0; k 
< count
; k
++) 
6917                                     if ( cell 
== redrawCells
[k
] ) 
6923                                 if (!marked
) redrawCells
.Add( cell 
); 
6931         DrawCell( dc
, cells
[i
] ); 
6934     numCells 
= redrawCells
.GetCount(); 
6936     for ( i 
= numCells 
- 1; i 
>= 0;  i
-- ) 
6938         DrawCell( dc
, redrawCells
[i
] ); 
6943 void wxGrid::DrawGridSpace( wxDC
& dc 
) 
6946   m_gridWin
->GetClientSize( &cw
, &ch 
); 
6949   CalcUnscrolledPosition( cw
, ch
, &right
, &bottom 
); 
6951   int rightCol 
= m_numCols 
> 0 ? GetColRight(m_numCols 
- 1) : 0; 
6952   int bottomRow 
= m_numRows 
> 0 ? GetRowBottom(m_numRows 
- 1) : 0 ; 
6954   if ( right 
> rightCol 
|| bottom 
> bottomRow 
) 
6957       CalcUnscrolledPosition( 0, 0, &left
, &top 
); 
6959       dc
.SetBrush( wxBrush(GetDefaultCellBackgroundColour(), wxSOLID
) ); 
6960       dc
.SetPen( *wxTRANSPARENT_PEN 
); 
6962       if ( right 
> rightCol 
) 
6964           dc
.DrawRectangle( rightCol
, top
, right 
- rightCol
, ch
); 
6967       if ( bottom 
> bottomRow 
) 
6969           dc
.DrawRectangle( left
, bottomRow
, cw
, bottom 
- bottomRow
); 
6975 void wxGrid::DrawCell( wxDC
& dc
, const wxGridCellCoords
& coords 
) 
6977     int row 
= coords
.GetRow(); 
6978     int col 
= coords
.GetCol(); 
6980     if ( GetColWidth(col
) <= 0 || GetRowHeight(row
) <= 0 ) 
6983     // we draw the cell border ourselves 
6984 #if !WXGRID_DRAW_LINES 
6985     if ( m_gridLinesEnabled 
) 
6986         DrawCellBorder( dc
, coords 
); 
6989     wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
6991     bool isCurrent 
= coords 
== m_currentCellCoords
; 
6993     wxRect rect 
= CellToRect( row
, col 
); 
6995     // if the editor is shown, we should use it and not the renderer 
6996     // Note: However, only if it is really _shown_, i.e. not hidden! 
6997     if ( isCurrent 
&& IsCellEditControlShown() ) 
6999         wxGridCellEditor 
*editor 
= attr
->GetEditor(this, row
, col
); 
7000         editor
->PaintBackground(rect
, attr
); 
7005         // but all the rest is drawn by the cell renderer and hence may be 
7007         wxGridCellRenderer 
*renderer 
= attr
->GetRenderer(this, row
, col
); 
7008         renderer
->Draw(*this, *attr
, dc
, rect
, row
, col
, IsInSelection(coords
)); 
7015 void wxGrid::DrawCellHighlight( wxDC
& dc
, const wxGridCellAttr 
*attr 
) 
7017     int row 
= m_currentCellCoords
.GetRow(); 
7018     int col 
= m_currentCellCoords
.GetCol(); 
7020     if ( GetColWidth(col
) <= 0 || GetRowHeight(row
) <= 0 ) 
7023     wxRect rect 
= CellToRect(row
, col
); 
7025     // hmmm... what could we do here to show that the cell is disabled? 
7026     // for now, I just draw a thinner border than for the other ones, but 
7027     // it doesn't look really good 
7029     int penWidth 
= attr
->IsReadOnly() ? m_cellHighlightROPenWidth 
: m_cellHighlightPenWidth
; 
7033         // The center of th drawn line is where the position/width/height of 
7034         // the rectangle is actually at, (on wxMSW atr least,) so we will 
7035         // reduce the size of the rectangle to compensate for the thickness of 
7036         // the line.  If this is too strange on non wxMSW platforms then 
7037         // please #ifdef this appropriately. 
7038         rect
.x 
+= penWidth
/2; 
7039         rect
.y 
+= penWidth
/2; 
7040         rect
.width 
-= penWidth
-1; 
7041         rect
.height 
-= penWidth
-1; 
7044         // Now draw the rectangle 
7045         // use the cellHighlightColour if the cell is inside a selection, this 
7046         // will ensure the cell is always visible. 
7047         dc
.SetPen(wxPen(IsInSelection(row
,col
)?m_selectionForeground
:m_cellHighlightColour
, penWidth
, wxSOLID
)); 
7048         dc
.SetBrush(*wxTRANSPARENT_BRUSH
); 
7049         dc
.DrawRectangle(rect
); 
7053         // VZ: my experiments with 3d borders... 
7055         // how to properly set colours for arbitrary bg? 
7056         wxCoord x1 
= rect
.x
, 
7058                 x2 
= rect
.x 
+ rect
.width 
-1, 
7059                 y2 
= rect
.y 
+ rect
.height 
-1; 
7061         dc
.SetPen(*wxWHITE_PEN
); 
7062         dc
.DrawLine(x1
, y1
, x2
, y1
); 
7063         dc
.DrawLine(x1
, y1
, x1
, y2
); 
7065         dc
.DrawLine(x1 
+ 1, y2 
- 1, x2 
- 1, y2 
- 1); 
7066         dc
.DrawLine(x2 
- 1, y1 
+ 1, x2 
- 1, y2 
); 
7068         dc
.SetPen(*wxBLACK_PEN
); 
7069         dc
.DrawLine(x1
, y2
, x2
, y2
); 
7070         dc
.DrawLine(x2
, y1
, x2
, y2
+1); 
7075 void wxGrid::DrawCellBorder( wxDC
& dc
, const wxGridCellCoords
& coords 
) 
7077     int row 
= coords
.GetRow(); 
7078     int col 
= coords
.GetCol(); 
7079     if ( GetColWidth(col
) <= 0 || GetRowHeight(row
) <= 0 ) 
7082     dc
.SetPen( wxPen(GetGridLineColour(), 1, wxSOLID
) ); 
7084     wxRect rect 
= CellToRect( row
, col 
); 
7086     // right hand border 
7088     dc
.DrawLine( rect
.x 
+ rect
.width
, rect
.y
, 
7089                  rect
.x 
+ rect
.width
, rect
.y 
+ rect
.height 
+ 1 ); 
7093     dc
.DrawLine( rect
.x
,              rect
.y 
+ rect
.height
, 
7094                  rect
.x 
+ rect
.width
, rect
.y 
+ rect
.height
); 
7097 void wxGrid::DrawHighlight(wxDC
& dc
,const  wxGridCellCoordsArray
& cells
) 
7099     // This if block was previously in wxGrid::OnPaint but that doesn't 
7100     // seem to get called under wxGTK - MB 
7102     if ( m_currentCellCoords 
== wxGridNoCellCoords  
&& 
7103          m_numRows 
&& m_numCols 
) 
7105         m_currentCellCoords
.Set(0, 0); 
7108     if ( IsCellEditControlShown() ) 
7110         // don't show highlight when the edit control is shown 
7114     // if the active cell was repainted, repaint its highlight too because it 
7115     // might have been damaged by the grid lines 
7116     size_t count 
= cells
.GetCount(); 
7117     for ( size_t n 
= 0; n 
< count
; n
++ ) 
7119         if ( cells
[n
] == m_currentCellCoords 
) 
7121             wxGridCellAttr
* attr 
= GetCellAttr(m_currentCellCoords
); 
7122             DrawCellHighlight(dc
, attr
); 
7130 // TODO: remove this ??? 
7131 // This is used to redraw all grid lines e.g. when the grid line colour 
7134 void wxGrid::DrawAllGridLines( wxDC
& dc
, const wxRegion 
& WXUNUSED(reg
) ) 
7136 #if !WXGRID_DRAW_LINES 
7140     if ( !m_gridLinesEnabled 
|| 
7142          !m_numCols 
) return; 
7144     int top
, bottom
, left
, right
; 
7146 #if 0  //#ifndef __WXGTK__ 
7150       m_gridWin
->GetClientSize(&cw
, &ch
); 
7152       // virtual coords of visible area 
7154       CalcUnscrolledPosition( 0, 0, &left
, &top 
); 
7155       CalcUnscrolledPosition( cw
, ch
, &right
, &bottom 
); 
7160       reg
.GetBox(x
, y
, w
, h
); 
7161       CalcUnscrolledPosition( x
, y
, &left
, &top 
); 
7162       CalcUnscrolledPosition( x 
+ w
, y 
+ h
, &right
, &bottom 
); 
7166       m_gridWin
->GetClientSize(&cw
, &ch
); 
7167       CalcUnscrolledPosition( 0, 0, &left
, &top 
); 
7168       CalcUnscrolledPosition( cw
, ch
, &right
, &bottom 
); 
7171     // avoid drawing grid lines past the last row and col 
7173     right 
= wxMin( right
, GetColRight(m_numCols 
- 1) ); 
7174     bottom 
= wxMin( bottom
, GetRowBottom(m_numRows 
- 1) ); 
7176     // no gridlines inside multicells, clip them out 
7177     int leftCol   
= internalXToCol(left
); 
7178     int topRow    
= internalYToRow(top
); 
7179     int rightCol  
= internalXToCol(right
); 
7180     int bottomRow 
= internalYToRow(bottom
); 
7183     // CS: I don't know why suddenly unscrolled coordinates are used for clipping 
7184     wxRegion 
clippedcells(0, 0, cw
, ch
); 
7186     int i
, j
, cell_rows
, cell_cols
; 
7189     for (j
=topRow
; j
<bottomRow
; j
++) 
7191         for (i
=leftCol
; i
<rightCol
; i
++) 
7193             GetCellSize( j
, i
, &cell_rows
, &cell_cols 
); 
7194             if ((cell_rows 
> 1) || (cell_cols 
> 1)) 
7196                 rect 
= CellToRect(j
,i
); 
7197                 CalcScrolledPosition( rect
.x
, rect
.y
, &rect
.x
, &rect
.y 
); 
7198                 clippedcells
.Subtract(rect
); 
7200             else if ((cell_rows 
< 0) || (cell_cols 
< 0)) 
7202                 rect 
= CellToRect(j
+cell_rows
, i
+cell_cols
); 
7203                 CalcScrolledPosition( rect
.x
, rect
.y
, &rect
.x
, &rect
.y 
); 
7204                 clippedcells
.Subtract(rect
); 
7209     wxRegion 
clippedcells( left 
, top
, right 
- left
, bottom 
- top
); 
7211     int i
, j
, cell_rows
, cell_cols
; 
7214     for (j
=topRow
; j
<bottomRow
; j
++) 
7216         for (i
=leftCol
; i
<rightCol
; i
++) 
7218             GetCellSize( j
, i
, &cell_rows
, &cell_cols 
); 
7219             if ((cell_rows 
> 1) || (cell_cols 
> 1)) 
7221                 rect 
= CellToRect(j
,i
); 
7222                 clippedcells
.Subtract(rect
); 
7224             else if ((cell_rows 
< 0) || (cell_cols 
< 0)) 
7226                 rect 
= CellToRect(j
+cell_rows
, i
+cell_cols
); 
7227                 clippedcells
.Subtract(rect
); 
7232     dc
.SetClippingRegion( clippedcells 
); 
7234     dc
.SetPen( wxPen(GetGridLineColour(), 1, wxSOLID
) ); 
7236     // horizontal grid lines 
7238     // already declared above - int i; 
7239     for ( i 
= internalYToRow(top
); i 
< m_numRows
; i
++ ) 
7241         int bot 
= GetRowBottom(i
) - 1; 
7250             dc
.DrawLine( left
, bot
, right
, bot 
); 
7255     // vertical grid lines 
7257     for ( i 
= internalXToCol(left
); i 
< m_numCols
; i
++ ) 
7259         int colRight 
= GetColRight(i
) - 1; 
7260         if ( colRight 
> right 
) 
7265         if ( colRight 
>= left 
) 
7267             dc
.DrawLine( colRight
, top
, colRight
, bottom 
); 
7270     dc
.DestroyClippingRegion(); 
7274 void wxGrid::DrawRowLabels( wxDC
& dc 
,const wxArrayInt
& rows
) 
7276     if ( !m_numRows 
) return; 
7279     size_t numLabels 
= rows
.GetCount(); 
7281     for ( i 
= 0;  i 
< numLabels
;  i
++ ) 
7283         DrawRowLabel( dc
, rows
[i
] ); 
7288 void wxGrid::DrawRowLabel( wxDC
& dc
, int row 
) 
7290     if ( GetRowHeight(row
) <= 0 || m_rowLabelWidth 
<= 0 ) 
7296     rect
.SetY( GetRowTop(row
) + 1 ); 
7297     rect
.SetWidth( m_rowLabelWidth 
- 2 ); 
7298     rect
.SetHeight( GetRowHeight(row
) - 2 ); 
7300     CalcScrolledPosition( 0, rect
.y
, NULL
, &rect
.y 
); 
7302     wxWindowDC 
*win_dc 
= (wxWindowDC
*) &dc
; 
7304     wxRendererNative::Get().DrawHeaderButton( win_dc
->m_owner
, dc
, rect
, 0 ); 
7306     int rowTop 
= GetRowTop(row
), 
7307         rowBottom 
= GetRowBottom(row
) - 1; 
7309     dc
.SetPen( wxPen(wxSystemSettings::GetColour(wxSYS_COLOUR_3DDKSHADOW
),1, wxSOLID
) ); 
7310     dc
.DrawLine( m_rowLabelWidth
-1, rowTop
, 
7311                  m_rowLabelWidth
-1, rowBottom 
); 
7313     dc
.DrawLine( 0, rowTop
, 0, rowBottom 
); 
7315     dc
.DrawLine( 0, rowBottom
, m_rowLabelWidth
, rowBottom 
); 
7317     dc
.SetPen( *wxWHITE_PEN 
); 
7318     dc
.DrawLine( 1, rowTop
, 1, rowBottom 
); 
7319     dc
.DrawLine( 1, rowTop
, m_rowLabelWidth
-1, rowTop 
); 
7321     dc
.SetBackgroundMode( wxTRANSPARENT 
); 
7322     dc
.SetTextForeground( GetLabelTextColour() ); 
7323     dc
.SetFont( GetLabelFont() ); 
7326     GetRowLabelAlignment( &hAlign
, &vAlign 
); 
7329     rect
.SetY( GetRowTop(row
) + 2 ); 
7330     rect
.SetWidth( m_rowLabelWidth 
- 4 ); 
7331     rect
.SetHeight( GetRowHeight(row
) - 4 ); 
7332     DrawTextRectangle( dc
, GetRowLabelValue( row 
), rect
, hAlign
, vAlign 
); 
7336 void wxGrid::DrawColLabels( wxDC
& dc
,const wxArrayInt
& cols 
) 
7338     if ( !m_numCols 
) return; 
7341     size_t numLabels 
= cols
.GetCount(); 
7343     for ( i 
= 0;  i 
< numLabels
;  i
++ ) 
7345         DrawColLabel( dc
, cols
[i
] ); 
7350 void wxGrid::DrawColLabel( wxDC
& dc
, int col 
) 
7352     if ( GetColWidth(col
) <= 0 || m_colLabelHeight 
<= 0 ) 
7355     int colLeft 
= GetColLeft(col
); 
7359     rect
.SetX( colLeft 
+ 1 ); 
7361     rect
.SetWidth( GetColWidth(col
) - 2 ); 
7362     rect
.SetHeight( m_colLabelHeight 
- 2 ); 
7364     wxWindowDC 
*win_dc 
= (wxWindowDC
*) &dc
; 
7366     wxRendererNative::Get().DrawHeaderButton( win_dc
->m_owner
, dc
, rect
, 0 ); 
7368     int colRight 
= GetColRight(col
) - 1; 
7370     dc
.SetPen( wxPen(wxSystemSettings::GetColour(wxSYS_COLOUR_3DDKSHADOW
),1, wxSOLID
) ); 
7371     dc
.DrawLine( colRight
, 0, 
7372                  colRight
, m_colLabelHeight
-1 ); 
7374     dc
.DrawLine( colLeft
, 0, colRight
, 0 ); 
7376     dc
.DrawLine( colLeft
, m_colLabelHeight
-1, 
7377                  colRight
+1, m_colLabelHeight
-1 ); 
7379     dc
.SetPen( *wxWHITE_PEN 
); 
7380     dc
.DrawLine( colLeft
, 1, colLeft
, m_colLabelHeight
-1 ); 
7381     dc
.DrawLine( colLeft
, 1, colRight
, 1 ); 
7383     dc
.SetBackgroundMode( wxTRANSPARENT 
); 
7384     dc
.SetTextForeground( GetLabelTextColour() ); 
7385     dc
.SetFont( GetLabelFont() ); 
7387     int hAlign
, vAlign
, orient
; 
7388     GetColLabelAlignment( &hAlign
, &vAlign 
); 
7389     orient 
= GetColLabelTextOrientation(); 
7391     rect
.SetX( colLeft 
+ 2 ); 
7393     rect
.SetWidth( GetColWidth(col
) - 4 ); 
7394     rect
.SetHeight( m_colLabelHeight 
- 4 ); 
7395     DrawTextRectangle( dc
, GetColLabelValue( col 
), rect
, hAlign
, vAlign
, orient 
); 
7398 void wxGrid::DrawTextRectangle( wxDC
& dc
, 
7399                                 const wxString
& value
, 
7403                                 int textOrientation 
) 
7405     wxArrayString lines
; 
7407     StringToLines( value
, lines 
); 
7410     //Forward to new API. 
7411     DrawTextRectangle(  dc
, 
7420 void wxGrid::DrawTextRectangle( wxDC
& dc
, 
7421                                const wxArrayString
& lines
, 
7425                                int textOrientation 
) 
7427     long textWidth
, textHeight
; 
7428     long lineWidth
, lineHeight
; 
7431     dc
.SetClippingRegion( rect 
); 
7433     nLines 
= lines
.GetCount(); 
7437         float x 
= 0.0, y 
= 0.0; 
7439         if( textOrientation 
== wxHORIZONTAL 
) 
7440             GetTextBoxSize(dc
, lines
, &textWidth
, &textHeight
); 
7442             GetTextBoxSize( dc
, lines
, &textHeight
, &textWidth 
); 
7446         case wxALIGN_BOTTOM
: 
7447             if( textOrientation 
== wxHORIZONTAL 
) 
7448                 y 
= rect
.y 
+ (rect
.height 
- textHeight 
- 1); 
7450                 x 
= rect
.x 
+ rect
.width 
- textWidth
; 
7453         case wxALIGN_CENTRE
: 
7454             if( textOrientation 
== wxHORIZONTAL 
) 
7455                 y 
= rect
.y 
+ ((rect
.height 
- textHeight
)/2); 
7457                 x 
= rect
.x 
+ ((rect
.width 
- textWidth
)/2); 
7462             if( textOrientation 
== wxHORIZONTAL 
) 
7469         // Align each line of a multi-line label 
7470         for( l 
= 0; l 
< nLines
; l
++ ) 
7472             dc
.GetTextExtent(lines
[l
], &lineWidth
, &lineHeight
); 
7474             switch( horizAlign 
) 
7477                 if( textOrientation 
== wxHORIZONTAL 
) 
7478                     x 
= rect
.x 
+ (rect
.width 
- lineWidth 
- 1); 
7480                     y 
= rect
.y 
+ lineWidth 
+ 1; 
7483             case wxALIGN_CENTRE
: 
7484                 if( textOrientation 
== wxHORIZONTAL 
) 
7485                     x 
= rect
.x 
+ ((rect
.width 
- lineWidth
)/2); 
7487                     y 
= rect
.y 
+ rect
.height 
- ((rect
.height 
- lineWidth
)/2); 
7492                 if( textOrientation 
== wxHORIZONTAL 
) 
7495                     y 
= rect
.y 
+ rect
.height 
- 1; 
7499             if( textOrientation 
== wxHORIZONTAL 
) 
7501                 dc
.DrawText( lines
[l
], (int)x
, (int)y 
); 
7506                 dc
.DrawRotatedText( lines
[l
], (int)x
, (int)y
, 90.0 ); 
7511     dc
.DestroyClippingRegion(); 
7515 // Split multi line text up into an array of strings.  Any existing 
7516 // contents of the string array are preserved. 
7518 void wxGrid::StringToLines( const wxString
& value
, wxArrayString
& lines 
) 
7522     wxString eol 
= wxTextFile::GetEOL( wxTextFileType_Unix 
); 
7523     wxString tVal 
= wxTextFile::Translate( value
, wxTextFileType_Unix 
); 
7525     while ( startPos 
< (int)tVal
.Length() ) 
7527         pos 
= tVal
.Mid(startPos
).Find( eol 
); 
7532         else if ( pos 
== 0 ) 
7534             lines
.Add( wxEmptyString 
); 
7538             lines
.Add( value
.Mid(startPos
, pos
) ); 
7542     if ( startPos 
< (int)value
.Length() ) 
7544         lines
.Add( value
.Mid( startPos 
) ); 
7549 void wxGrid::GetTextBoxSize( wxDC
& dc
, 
7550                              const wxArrayString
& lines
, 
7551                              long *width
, long *height 
) 
7558     for ( i 
= 0;  i 
< lines
.GetCount();  i
++ ) 
7560         dc
.GetTextExtent( lines
[i
], &lineW
, &lineH 
); 
7561         w 
= wxMax( w
, lineW 
); 
7570 // ------ Batch processing. 
7572 void wxGrid::EndBatch() 
7574     if ( m_batchCount 
> 0 ) 
7577         if ( !m_batchCount 
) 
7580             m_rowLabelWin
->Refresh(); 
7581             m_colLabelWin
->Refresh(); 
7582             m_cornerLabelWin
->Refresh(); 
7583             m_gridWin
->Refresh(); 
7588 // Use this, rather than wxWindow::Refresh(), to force an immediate 
7589 // repainting of the grid. Has no effect if you are already inside a 
7590 // BeginBatch / EndBatch block. 
7592 void wxGrid::ForceRefresh() 
7598 bool wxGrid::Enable(bool enable
) 
7600     if ( !wxScrolledWindow::Enable(enable
) ) 
7603     // redraw in the new state 
7604     m_gridWin
->Refresh(); 
7610 // ------ Edit control functions 
7614 void wxGrid::EnableEditing( bool edit 
) 
7616     // TODO: improve this ? 
7618     if ( edit 
!= m_editable 
) 
7620         if(!edit
) EnableCellEditControl(edit
); 
7626 void wxGrid::EnableCellEditControl( bool enable 
) 
7631     if ( m_currentCellCoords 
== wxGridNoCellCoords 
) 
7632         SetCurrentCell( 0, 0 ); 
7634     if ( enable 
!= m_cellEditCtrlEnabled 
) 
7638             if (SendEvent( wxEVT_GRID_EDITOR_SHOWN
) <0) 
7641             // this should be checked by the caller! 
7642             wxASSERT_MSG( CanEnableCellControl(), 
7643                           _T("can't enable editing for this cell!") ); 
7645             // do it before ShowCellEditControl() 
7646             m_cellEditCtrlEnabled 
= enable
; 
7648             ShowCellEditControl(); 
7652             //FIXME:add veto support 
7653             SendEvent( wxEVT_GRID_EDITOR_HIDDEN
); 
7655             HideCellEditControl(); 
7656             SaveEditControlValue(); 
7658             // do it after HideCellEditControl() 
7659             m_cellEditCtrlEnabled 
= enable
; 
7664 bool wxGrid::IsCurrentCellReadOnly() const 
7667     wxGridCellAttr
* attr 
= ((wxGrid 
*)this)->GetCellAttr(m_currentCellCoords
); 
7668     bool readonly 
= attr
->IsReadOnly(); 
7674 bool wxGrid::CanEnableCellControl() const 
7676     return m_editable 
&& (m_currentCellCoords 
!= wxGridNoCellCoords
) && 
7677         !IsCurrentCellReadOnly(); 
7681 bool wxGrid::IsCellEditControlEnabled() const 
7683     // the cell edit control might be disable for all cells or just for the 
7684     // current one if it's read only 
7685     return m_cellEditCtrlEnabled 
? !IsCurrentCellReadOnly() : false; 
7688 bool wxGrid::IsCellEditControlShown() const 
7690     bool isShown 
= false; 
7692     if ( m_cellEditCtrlEnabled 
) 
7694         int row 
= m_currentCellCoords
.GetRow(); 
7695         int col 
= m_currentCellCoords
.GetCol(); 
7696         wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
7697         wxGridCellEditor
* editor 
= attr
->GetEditor((wxGrid
*) this, row
, col
); 
7702             if ( editor
->IsCreated() ) 
7704                 isShown 
= editor
->GetControl()->IsShown(); 
7714 void wxGrid::ShowCellEditControl() 
7716     if ( IsCellEditControlEnabled() ) 
7718         if ( !IsVisible( m_currentCellCoords 
) ) 
7720             m_cellEditCtrlEnabled 
= false; 
7725             wxRect rect 
= CellToRect( m_currentCellCoords 
); 
7726             int row 
= m_currentCellCoords
.GetRow(); 
7727             int col 
= m_currentCellCoords
.GetCol(); 
7729             // if this is part of a multicell, find owner (topleft) 
7730             int cell_rows
, cell_cols
; 
7731             GetCellSize( row
, col
, &cell_rows
, &cell_cols 
); 
7732             if ( cell_rows 
<= 0 || cell_cols 
<= 0 ) 
7736                 m_currentCellCoords
.SetRow( row 
); 
7737                 m_currentCellCoords
.SetCol( col 
); 
7740             // convert to scrolled coords 
7742             CalcScrolledPosition( rect
.x
, rect
.y
, &rect
.x
, &rect
.y 
); 
7744             // done in PaintBackground() 
7746             // erase the highlight and the cell contents because the editor 
7747             // might not cover the entire cell 
7748             wxClientDC 
dc( m_gridWin 
); 
7750             dc
.SetBrush(*wxLIGHT_GREY_BRUSH
); //wxBrush(attr->GetBackgroundColour(), wxSOLID)); 
7751             dc
.SetPen(*wxTRANSPARENT_PEN
); 
7752             dc
.DrawRectangle(rect
); 
7755             // cell is shifted by one pixel 
7756             // However, don't allow x or y to become negative 
7757             // since the SetSize() method interprets that as 
7764             wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
7765             wxGridCellEditor
* editor 
= attr
->GetEditor(this, row
, col
); 
7766             if ( !editor
->IsCreated() ) 
7768                 editor
->Create(m_gridWin
, wxID_ANY
, 
7769                                new wxGridCellEditorEvtHandler(this, editor
)); 
7771                 wxGridEditorCreatedEvent 
evt(GetId(), 
7772                                              wxEVT_GRID_EDITOR_CREATED
, 
7776                                              editor
->GetControl()); 
7777                 GetEventHandler()->ProcessEvent(evt
); 
7781             // resize editor to overflow into righthand cells if allowed 
7782             int maxWidth 
= rect
.width
; 
7783             wxString value 
= GetCellValue(row
, col
); 
7784             if ( (value 
!= wxEmptyString
) && (attr
->GetOverflow()) ) 
7787                 GetTextExtent(value
, &maxWidth
, &y
, 
7788                         NULL
, NULL
, &attr
->GetFont()); 
7789                 if (maxWidth 
< rect
.width
) maxWidth 
= rect
.width
; 
7791             int client_right 
= m_gridWin
->GetClientSize().GetWidth(); 
7792             if (rect
.x
+maxWidth 
> client_right
) 
7793                 maxWidth 
= client_right 
- rect
.x
; 
7795             if ((maxWidth 
> rect
.width
) && (col 
< m_numCols
) && m_table
) 
7797                 GetCellSize( row
, col
, &cell_rows
, &cell_cols 
); 
7798                 // may have changed earlier 
7799                 for (int i 
= col
+cell_cols
; i 
< m_numCols
; i
++) 
7802                     GetCellSize( row
, i
, &c_rows
, &c_cols 
); 
7803                     // looks weird going over a multicell 
7804                     if (m_table
->IsEmptyCell(row
,i
) && 
7805                             (rect
.width 
< maxWidth
) && (c_rows 
== 1)) 
7806                         rect
.width 
+= GetColWidth(i
); 
7810                 if (rect
.GetRight() > client_right
) 
7811                     rect
.SetRight(client_right
-1); 
7814             editor
->SetCellAttr(attr
); 
7815             editor
->SetSize( rect 
); 
7816             editor
->Show( true, attr 
); 
7818             // recalc dimensions in case we need to 
7819             // expand the scrolled window to account for editor 
7822             editor
->BeginEdit(row
, col
, this); 
7823             editor
->SetCellAttr(NULL
); 
7832 void wxGrid::HideCellEditControl() 
7834     if ( IsCellEditControlEnabled() ) 
7836         int row 
= m_currentCellCoords
.GetRow(); 
7837         int col 
= m_currentCellCoords
.GetCol(); 
7839         wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
7840         wxGridCellEditor 
*editor 
= attr
->GetEditor(this, row
, col
); 
7841         editor
->Show( false ); 
7844         m_gridWin
->SetFocus(); 
7845         // refresh whole row to the right 
7846         wxRect 
rect( CellToRect(row
, col
) ); 
7847         CalcScrolledPosition(rect
.x
, rect
.y
, &rect
.x
, &rect
.y 
); 
7848         rect
.width 
= m_gridWin
->GetClientSize().GetWidth() - rect
.x
; 
7850         // ensure that the pixels under the focus ring get refreshed as well 
7851         rect
.Inflate(10,10); 
7853         m_gridWin
->Refresh( false, &rect 
); 
7858 void wxGrid::SaveEditControlValue() 
7860     if ( IsCellEditControlEnabled() ) 
7862         int row 
= m_currentCellCoords
.GetRow(); 
7863         int col 
= m_currentCellCoords
.GetCol(); 
7865         wxString oldval 
= GetCellValue(row
,col
); 
7867         wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
7868         wxGridCellEditor
* editor 
= attr
->GetEditor(this, row
, col
); 
7869         bool changed 
= editor
->EndEdit(row
, col
, this); 
7876             if ( SendEvent( wxEVT_GRID_CELL_CHANGE
, 
7877                        m_currentCellCoords
.GetRow(), 
7878                        m_currentCellCoords
.GetCol() ) < 0 ) { 
7880                 // Event has been vetoed, set the data back. 
7881                 SetCellValue(row
,col
,oldval
); 
7889 // ------ Grid location functions 
7890 //  Note that all of these functions work with the logical coordinates of 
7891 //  grid cells and labels so you will need to convert from device 
7892 //  coordinates for mouse events etc. 
7895 void wxGrid::XYToCell( int x
, int y
, wxGridCellCoords
& coords 
) 
7897     int row 
= YToRow(y
); 
7898     int col 
= XToCol(x
); 
7900     if ( row 
== -1  ||  col 
== -1 ) 
7902         coords 
= wxGridNoCellCoords
; 
7906         coords
.Set( row
, col 
); 
7911 // Internal Helper function for computing row or column from some 
7912 // (unscrolled) coordinate value, using either 
7913 // m_defaultRowHeight/m_defaultColWidth or binary search on array 
7914 // of m_rowBottoms/m_ColRights to speed up the search! 
7916 static int CoordToRowOrCol(int coord
, int defaultDist
, int minDist
, 
7917                            const wxArrayInt
& BorderArray
, int nMax
, 
7922         return clipToMinMax 
&& (nMax 
> 0) ? 0 : -1; 
7928     size_t i_max 
= coord 
/ defaultDist
, 
7931     if (BorderArray
.IsEmpty()) 
7933         if((int) i_max 
< nMax
) 
7935         return clipToMinMax 
? nMax 
- 1 : -1; 
7938     if ( i_max 
>= BorderArray
.GetCount()) 
7939         i_max 
= BorderArray
.GetCount() - 1; 
7942         if ( coord 
>= BorderArray
[i_max
]) 
7946                 i_max 
= coord 
/ minDist
; 
7948                 i_max 
=  BorderArray
.GetCount() - 1; 
7950         if ( i_max 
>= BorderArray
.GetCount()) 
7951             i_max 
= BorderArray
.GetCount() - 1; 
7953     if ( coord 
>= BorderArray
[i_max
]) 
7954         return clipToMinMax 
? (int)i_max 
: -1; 
7955     if ( coord 
< BorderArray
[0] ) 
7958     while ( i_max 
- i_min 
> 0 ) 
7960         wxCHECK_MSG(BorderArray
[i_min
] <= coord 
&& coord 
< BorderArray
[i_max
], 
7961                     0, _T("wxGrid: internal error in CoordToRowOrCol")); 
7962         if (coord 
>=  BorderArray
[ i_max 
- 1]) 
7966         int median 
= i_min 
+ (i_max 
- i_min 
+ 1) / 2; 
7967         if (coord 
< BorderArray
[median
]) 
7975 int wxGrid::YToRow( int y 
) 
7977     return CoordToRowOrCol(y
, m_defaultRowHeight
, 
7978                            m_minAcceptableRowHeight
, m_rowBottoms
, m_numRows
, false); 
7982 int wxGrid::XToCol( int x 
) 
7984     return CoordToRowOrCol(x
, m_defaultColWidth
, 
7985                            m_minAcceptableColWidth
, m_colRights
, m_numCols
, false); 
7989 // return the row number that that the y coord is near the edge of, or 
7990 // -1 if not near an edge 
7992 int wxGrid::YToEdgeOfRow( int y 
) 
7995     i 
= internalYToRow(y
); 
7997     if ( GetRowHeight(i
) > WXGRID_LABEL_EDGE_ZONE 
) 
7999         // We know that we are in row i, test whether we are 
8000         // close enough to lower or upper border, respectively. 
8001         if ( abs(GetRowBottom(i
) - y
) < WXGRID_LABEL_EDGE_ZONE 
) 
8003         else if( i 
> 0 && y 
- GetRowTop(i
) < WXGRID_LABEL_EDGE_ZONE 
) 
8011 // return the col number that that the x coord is near the edge of, or 
8012 // -1 if not near an edge 
8014 int wxGrid::XToEdgeOfCol( int x 
) 
8017     i 
= internalXToCol(x
); 
8019     if ( GetColWidth(i
) > WXGRID_LABEL_EDGE_ZONE 
) 
8021         // We know that we are in column i,  test whether we are 
8022         // close enough to right or left border, respectively. 
8023         if ( abs(GetColRight(i
) - x
) < WXGRID_LABEL_EDGE_ZONE 
) 
8025         else if( i 
> 0 && x 
- GetColLeft(i
) < WXGRID_LABEL_EDGE_ZONE 
) 
8033 wxRect 
wxGrid::CellToRect( int row
, int col 
) 
8035     wxRect 
rect( -1, -1, -1, -1 ); 
8037     if ( row 
>= 0  &&  row 
< m_numRows  
&& 
8038          col 
>= 0  &&  col 
< m_numCols 
) 
8040         int i
, cell_rows
, cell_cols
; 
8041         rect
.width 
= rect
.height 
= 0; 
8042         GetCellSize( row
, col
, &cell_rows
, &cell_cols 
); 
8043         // if negative then find multicell owner 
8044         if (cell_rows 
< 0) row 
+= cell_rows
; 
8045         if (cell_cols 
< 0) col 
+= cell_cols
; 
8046         GetCellSize( row
, col
, &cell_rows
, &cell_cols 
); 
8048         rect
.x 
= GetColLeft(col
); 
8049         rect
.y 
= GetRowTop(row
); 
8050         for (i
=col
; i
<col
+cell_cols
; i
++) 
8051             rect
.width  
+= GetColWidth(i
); 
8052         for (i
=row
; i
<row
+cell_rows
; i
++) 
8053             rect
.height 
+= GetRowHeight(i
); 
8056     // if grid lines are enabled, then the area of the cell is a bit smaller 
8057     if (m_gridLinesEnabled
) { 
8065 bool wxGrid::IsVisible( int row
, int col
, bool wholeCellVisible 
) 
8067     // get the cell rectangle in logical coords 
8069     wxRect 
r( CellToRect( row
, col 
) ); 
8071     // convert to device coords 
8073     int left
, top
, right
, bottom
; 
8074     CalcScrolledPosition( r
.GetLeft(), r
.GetTop(), &left
, &top 
); 
8075     CalcScrolledPosition( r
.GetRight(), r
.GetBottom(), &right
, &bottom 
); 
8077     // check against the client area of the grid window 
8080     m_gridWin
->GetClientSize( &cw
, &ch 
); 
8082     if ( wholeCellVisible 
) 
8084         // is the cell wholly visible ? 
8086         return ( left 
>= 0  &&  right 
<= cw  
&& 
8087                  top 
>= 0  &&  bottom 
<= ch 
); 
8091         // is the cell partly visible ? 
8093         return ( ((left 
>=0 && left 
< cw
) || (right 
> 0 && right 
<= cw
))  && 
8094                  ((top 
>=0 && top 
< ch
) || (bottom 
> 0 && bottom 
<= ch
)) ); 
8099 // make the specified cell location visible by doing a minimal amount 
8102 void wxGrid::MakeCellVisible( int row
, int col 
) 
8106     int xpos 
= -1, ypos 
= -1; 
8108     if ( row 
>= 0  &&  row 
< m_numRows  
&& 
8109          col 
>= 0  &&  col 
< m_numCols 
) 
8111         // get the cell rectangle in logical coords 
8113         wxRect 
r( CellToRect( row
, col 
) ); 
8115         // convert to device coords 
8117         int left
, top
, right
, bottom
; 
8118         CalcScrolledPosition( r
.GetLeft(), r
.GetTop(), &left
, &top 
); 
8119         CalcScrolledPosition( r
.GetRight(), r
.GetBottom(), &right
, &bottom 
); 
8122         m_gridWin
->GetClientSize( &cw
, &ch 
); 
8128         else if ( bottom 
> ch 
) 
8130             int h 
= r
.GetHeight(); 
8132             for ( i 
= row
-1;  i 
>= 0;  i
-- ) 
8134                 int rowHeight 
= GetRowHeight(i
); 
8135                 if ( h 
+ rowHeight 
> ch 
) 
8142             // we divide it later by GRID_SCROLL_LINE, make sure that we don't 
8143             // have rounding errors (this is important, because if we do, we 
8144             // might not scroll at all and some cells won't be redrawn) 
8146             // Sometimes GRID_SCROLL_LINE/2 is not enough, so just add a full 
8148             ypos 
+= m_scrollLineY
; 
8155         else if ( right 
> cw 
) 
8157             // position the view so that the cell is on the right 
8159             CalcUnscrolledPosition(0, 0, &x0
, &y0
); 
8160             xpos 
= x0 
+ (right 
- cw
); 
8162             // see comment for ypos above 
8163             xpos 
+= m_scrollLineX
; 
8166         if ( xpos 
!= -1  ||  ypos 
!= -1 ) 
8169                 xpos 
/= m_scrollLineX
; 
8171                 ypos 
/= m_scrollLineY
; 
8172             Scroll( xpos
, ypos 
); 
8180 // ------ Grid cursor movement functions 
8183 bool wxGrid::MoveCursorUp( bool expandSelection 
) 
8185     if ( m_currentCellCoords 
!= wxGridNoCellCoords  
&& 
8186          m_currentCellCoords
.GetRow() >= 0 ) 
8188         if ( expandSelection
) 
8190             if ( m_selectingKeyboard 
== wxGridNoCellCoords 
) 
8191                 m_selectingKeyboard 
= m_currentCellCoords
; 
8192             if ( m_selectingKeyboard
.GetRow() > 0 ) 
8194                 m_selectingKeyboard
.SetRow( m_selectingKeyboard
.GetRow() - 1 ); 
8195                 MakeCellVisible( m_selectingKeyboard
.GetRow(), 
8196                                  m_selectingKeyboard
.GetCol() ); 
8197                 HighlightBlock( m_currentCellCoords
, m_selectingKeyboard 
); 
8200         else if ( m_currentCellCoords
.GetRow() > 0 ) 
8203             MakeCellVisible( m_currentCellCoords
.GetRow() - 1, 
8204                              m_currentCellCoords
.GetCol() ); 
8205             SetCurrentCell( m_currentCellCoords
.GetRow() - 1, 
8206                             m_currentCellCoords
.GetCol() ); 
8217 bool wxGrid::MoveCursorDown( bool expandSelection 
) 
8219     if ( m_currentCellCoords 
!= wxGridNoCellCoords  
&& 
8220          m_currentCellCoords
.GetRow() < m_numRows 
) 
8222         if ( expandSelection 
) 
8224             if ( m_selectingKeyboard 
== wxGridNoCellCoords 
) 
8225                 m_selectingKeyboard 
= m_currentCellCoords
; 
8226             if ( m_selectingKeyboard
.GetRow() < m_numRows
-1 ) 
8228                 m_selectingKeyboard
.SetRow( m_selectingKeyboard
.GetRow() + 1 ); 
8229                 MakeCellVisible( m_selectingKeyboard
.GetRow(), 
8230                         m_selectingKeyboard
.GetCol() ); 
8231                 HighlightBlock( m_currentCellCoords
, m_selectingKeyboard 
); 
8234         else if ( m_currentCellCoords
.GetRow() < m_numRows 
- 1 ) 
8237             MakeCellVisible( m_currentCellCoords
.GetRow() + 1, 
8238                              m_currentCellCoords
.GetCol() ); 
8239             SetCurrentCell( m_currentCellCoords
.GetRow() + 1, 
8240                             m_currentCellCoords
.GetCol() ); 
8251 bool wxGrid::MoveCursorLeft( bool expandSelection 
) 
8253     if ( m_currentCellCoords 
!= wxGridNoCellCoords  
&& 
8254          m_currentCellCoords
.GetCol() >= 0 ) 
8256         if ( expandSelection 
) 
8258             if ( m_selectingKeyboard 
== wxGridNoCellCoords 
) 
8259                 m_selectingKeyboard 
= m_currentCellCoords
; 
8260             if ( m_selectingKeyboard
.GetCol() > 0 ) 
8262                 m_selectingKeyboard
.SetCol( m_selectingKeyboard
.GetCol() - 1 ); 
8263                 MakeCellVisible( m_selectingKeyboard
.GetRow(), 
8264                         m_selectingKeyboard
.GetCol() ); 
8265                 HighlightBlock( m_currentCellCoords
, m_selectingKeyboard 
); 
8268         else if ( m_currentCellCoords
.GetCol() > 0 ) 
8271             MakeCellVisible( m_currentCellCoords
.GetRow(), 
8272                              m_currentCellCoords
.GetCol() - 1 ); 
8273             SetCurrentCell( m_currentCellCoords
.GetRow(), 
8274                             m_currentCellCoords
.GetCol() - 1 ); 
8285 bool wxGrid::MoveCursorRight( bool expandSelection 
) 
8287     if ( m_currentCellCoords 
!= wxGridNoCellCoords  
&& 
8288          m_currentCellCoords
.GetCol() < m_numCols 
) 
8290         if ( expandSelection 
) 
8292             if ( m_selectingKeyboard 
== wxGridNoCellCoords 
) 
8293                 m_selectingKeyboard 
= m_currentCellCoords
; 
8294             if ( m_selectingKeyboard
.GetCol() < m_numCols 
- 1 ) 
8296                 m_selectingKeyboard
.SetCol( m_selectingKeyboard
.GetCol() + 1 ); 
8297                 MakeCellVisible( m_selectingKeyboard
.GetRow(), 
8298                         m_selectingKeyboard
.GetCol() ); 
8299                 HighlightBlock( m_currentCellCoords
, m_selectingKeyboard 
); 
8302         else if ( m_currentCellCoords
.GetCol() < m_numCols 
- 1 ) 
8305             MakeCellVisible( m_currentCellCoords
.GetRow(), 
8306                              m_currentCellCoords
.GetCol() + 1 ); 
8307             SetCurrentCell( m_currentCellCoords
.GetRow(), 
8308                             m_currentCellCoords
.GetCol() + 1 ); 
8319 bool wxGrid::MovePageUp() 
8321     if ( m_currentCellCoords 
== wxGridNoCellCoords 
) return false; 
8323     int row 
= m_currentCellCoords
.GetRow(); 
8327         m_gridWin
->GetClientSize( &cw
, &ch 
); 
8329         int y 
= GetRowTop(row
); 
8330         int newRow 
= internalYToRow( y 
- ch 
+ 1 ); 
8332         if ( newRow 
== row 
) 
8334             //row > 0 , so newrow can never be less than 0 here. 
8338         MakeCellVisible( newRow
, m_currentCellCoords
.GetCol() ); 
8339         SetCurrentCell( newRow
, m_currentCellCoords
.GetCol() ); 
8347 bool wxGrid::MovePageDown() 
8349     if ( m_currentCellCoords 
== wxGridNoCellCoords 
) return false; 
8351     int row 
= m_currentCellCoords
.GetRow(); 
8352     if ( (row
+1) < m_numRows 
) 
8355         m_gridWin
->GetClientSize( &cw
, &ch 
); 
8357         int y 
= GetRowTop(row
); 
8358         int newRow 
= internalYToRow( y 
+ ch 
); 
8359         if ( newRow 
== row 
) 
8361             // row < m_numRows , so newrow can't overflow here. 
8365         MakeCellVisible( newRow
, m_currentCellCoords
.GetCol() ); 
8366         SetCurrentCell( newRow
, m_currentCellCoords
.GetCol() ); 
8374 bool wxGrid::MoveCursorUpBlock( bool expandSelection 
) 
8377          m_currentCellCoords 
!= wxGridNoCellCoords  
&& 
8378          m_currentCellCoords
.GetRow() > 0 ) 
8380         int row 
= m_currentCellCoords
.GetRow(); 
8381         int col 
= m_currentCellCoords
.GetCol(); 
8383         if ( m_table
->IsEmptyCell(row
, col
) ) 
8385             // starting in an empty cell: find the next block of 
8391                 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break; 
8394         else if ( m_table
->IsEmptyCell(row
-1, col
) ) 
8396             // starting at the top of a block: find the next block 
8402                 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break; 
8407             // starting within a block: find the top of the block 
8412                 if ( m_table
->IsEmptyCell(row
, col
) ) 
8420         MakeCellVisible( row
, col 
); 
8421         if ( expandSelection 
) 
8423             m_selectingKeyboard 
= wxGridCellCoords( row
, col 
); 
8424             HighlightBlock( m_currentCellCoords
, m_selectingKeyboard 
); 
8429             SetCurrentCell( row
, col 
); 
8437 bool wxGrid::MoveCursorDownBlock( bool expandSelection 
) 
8440          m_currentCellCoords 
!= wxGridNoCellCoords  
&& 
8441          m_currentCellCoords
.GetRow() < m_numRows
-1 ) 
8443         int row 
= m_currentCellCoords
.GetRow(); 
8444         int col 
= m_currentCellCoords
.GetCol(); 
8446         if ( m_table
->IsEmptyCell(row
, col
) ) 
8448             // starting in an empty cell: find the next block of 
8451             while ( row 
< m_numRows
-1 ) 
8454                 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break; 
8457         else if ( m_table
->IsEmptyCell(row
+1, col
) ) 
8459             // starting at the bottom of a block: find the next block 
8462             while ( row 
< m_numRows
-1 ) 
8465                 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break; 
8470             // starting within a block: find the bottom of the block 
8472             while ( row 
< m_numRows
-1 ) 
8475                 if ( m_table
->IsEmptyCell(row
, col
) ) 
8483         MakeCellVisible( row
, col 
); 
8484         if ( expandSelection 
) 
8486             m_selectingKeyboard 
= wxGridCellCoords( row
, col 
); 
8487             HighlightBlock( m_currentCellCoords
, m_selectingKeyboard 
); 
8492             SetCurrentCell( row
, col 
); 
8501 bool wxGrid::MoveCursorLeftBlock( bool expandSelection 
) 
8504          m_currentCellCoords 
!= wxGridNoCellCoords  
&& 
8505          m_currentCellCoords
.GetCol() > 0 ) 
8507         int row 
= m_currentCellCoords
.GetRow(); 
8508         int col 
= m_currentCellCoords
.GetCol(); 
8510         if ( m_table
->IsEmptyCell(row
, col
) ) 
8512             // starting in an empty cell: find the next block of 
8518                 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break; 
8521         else if ( m_table
->IsEmptyCell(row
, col
-1) ) 
8523             // starting at the left of a block: find the next block 
8529                 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break; 
8534             // starting within a block: find the left of the block 
8539                 if ( m_table
->IsEmptyCell(row
, col
) ) 
8547         MakeCellVisible( row
, col 
); 
8548         if ( expandSelection 
) 
8550             m_selectingKeyboard 
= wxGridCellCoords( row
, col 
); 
8551             HighlightBlock( m_currentCellCoords
, m_selectingKeyboard 
); 
8556             SetCurrentCell( row
, col 
); 
8565 bool wxGrid::MoveCursorRightBlock( bool expandSelection 
) 
8568          m_currentCellCoords 
!= wxGridNoCellCoords  
&& 
8569          m_currentCellCoords
.GetCol() < m_numCols
-1 ) 
8571         int row 
= m_currentCellCoords
.GetRow(); 
8572         int col 
= m_currentCellCoords
.GetCol(); 
8574         if ( m_table
->IsEmptyCell(row
, col
) ) 
8576             // starting in an empty cell: find the next block of 
8579             while ( col 
< m_numCols
-1 ) 
8582                 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break; 
8585         else if ( m_table
->IsEmptyCell(row
, col
+1) ) 
8587             // starting at the right of a block: find the next block 
8590             while ( col 
< m_numCols
-1 ) 
8593                 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break; 
8598             // starting within a block: find the right of the block 
8600             while ( col 
< m_numCols
-1 ) 
8603                 if ( m_table
->IsEmptyCell(row
, col
) ) 
8611         MakeCellVisible( row
, col 
); 
8612         if ( expandSelection 
) 
8614             m_selectingKeyboard 
= wxGridCellCoords( row
, col 
); 
8615             HighlightBlock( m_currentCellCoords
, m_selectingKeyboard 
); 
8620             SetCurrentCell( row
, col 
); 
8632 // ------ Label values and formatting 
8635 void wxGrid::GetRowLabelAlignment( int *horiz
, int *vert 
) 
8637     *horiz 
= m_rowLabelHorizAlign
; 
8638     *vert  
= m_rowLabelVertAlign
; 
8641 void wxGrid::GetColLabelAlignment( int *horiz
, int *vert 
) 
8643     *horiz 
= m_colLabelHorizAlign
; 
8644     *vert  
= m_colLabelVertAlign
; 
8647 int wxGrid::GetColLabelTextOrientation() 
8649     return m_colLabelTextOrientation
; 
8652 wxString 
wxGrid::GetRowLabelValue( int row 
) 
8656         return m_table
->GetRowLabelValue( row 
); 
8666 wxString 
wxGrid::GetColLabelValue( int col 
) 
8670         return m_table
->GetColLabelValue( col 
); 
8681 void wxGrid::SetRowLabelSize( int width 
) 
8683     width 
= wxMax( width
, 0 ); 
8684     if ( width 
!= m_rowLabelWidth 
) 
8688             m_rowLabelWin
->Show( false ); 
8689             m_cornerLabelWin
->Show( false ); 
8691         else if ( m_rowLabelWidth 
== 0 ) 
8693             m_rowLabelWin
->Show( true ); 
8694             if ( m_colLabelHeight 
> 0 ) m_cornerLabelWin
->Show( true ); 
8697         m_rowLabelWidth 
= width
; 
8699         wxScrolledWindow::Refresh( true ); 
8704 void wxGrid::SetColLabelSize( int height 
) 
8706     height 
= wxMax( height
, 0 ); 
8707     if ( height 
!= m_colLabelHeight 
) 
8711             m_colLabelWin
->Show( false ); 
8712             m_cornerLabelWin
->Show( false ); 
8714         else if ( m_colLabelHeight 
== 0 ) 
8716             m_colLabelWin
->Show( true ); 
8717             if ( m_rowLabelWidth 
> 0 ) m_cornerLabelWin
->Show( true ); 
8720         m_colLabelHeight 
= height
; 
8722         wxScrolledWindow::Refresh( true ); 
8727 void wxGrid::SetLabelBackgroundColour( const wxColour
& colour 
) 
8729     if ( m_labelBackgroundColour 
!= colour 
) 
8731         m_labelBackgroundColour 
= colour
; 
8732         m_rowLabelWin
->SetBackgroundColour( colour 
); 
8733         m_colLabelWin
->SetBackgroundColour( colour 
); 
8734         m_cornerLabelWin
->SetBackgroundColour( colour 
); 
8736         if ( !GetBatchCount() ) 
8738             m_rowLabelWin
->Refresh(); 
8739             m_colLabelWin
->Refresh(); 
8740             m_cornerLabelWin
->Refresh(); 
8745 void wxGrid::SetLabelTextColour( const wxColour
& colour 
) 
8747     if ( m_labelTextColour 
!= colour 
) 
8749         m_labelTextColour 
= colour
; 
8750         if ( !GetBatchCount() ) 
8752             m_rowLabelWin
->Refresh(); 
8753             m_colLabelWin
->Refresh(); 
8758 void wxGrid::SetLabelFont( const wxFont
& font 
) 
8761     if ( !GetBatchCount() ) 
8763         m_rowLabelWin
->Refresh(); 
8764         m_colLabelWin
->Refresh(); 
8768 void wxGrid::SetRowLabelAlignment( int horiz
, int vert 
) 
8770     // allow old (incorrect) defs to be used 
8773         case wxLEFT
:   horiz 
= wxALIGN_LEFT
; break; 
8774         case wxRIGHT
:  horiz 
= wxALIGN_RIGHT
; break; 
8775         case wxCENTRE
: horiz 
= wxALIGN_CENTRE
; break; 
8780         case wxTOP
:    vert 
= wxALIGN_TOP
;    break; 
8781         case wxBOTTOM
: vert 
= wxALIGN_BOTTOM
; break; 
8782         case wxCENTRE
: vert 
= wxALIGN_CENTRE
; break; 
8785     if ( horiz 
== wxALIGN_LEFT 
|| horiz 
== wxALIGN_CENTRE 
|| horiz 
== wxALIGN_RIGHT 
) 
8787         m_rowLabelHorizAlign 
= horiz
; 
8790     if ( vert 
== wxALIGN_TOP 
|| vert 
== wxALIGN_CENTRE 
|| vert 
== wxALIGN_BOTTOM 
) 
8792         m_rowLabelVertAlign 
= vert
; 
8795     if ( !GetBatchCount() ) 
8797         m_rowLabelWin
->Refresh(); 
8801 void wxGrid::SetColLabelAlignment( int horiz
, int vert 
) 
8803     // allow old (incorrect) defs to be used 
8806         case wxLEFT
:   horiz 
= wxALIGN_LEFT
; break; 
8807         case wxRIGHT
:  horiz 
= wxALIGN_RIGHT
; break; 
8808         case wxCENTRE
: horiz 
= wxALIGN_CENTRE
; break; 
8813         case wxTOP
:    vert 
= wxALIGN_TOP
;    break; 
8814         case wxBOTTOM
: vert 
= wxALIGN_BOTTOM
; break; 
8815         case wxCENTRE
: vert 
= wxALIGN_CENTRE
; break; 
8818     if ( horiz 
== wxALIGN_LEFT 
|| horiz 
== wxALIGN_CENTRE 
|| horiz 
== wxALIGN_RIGHT 
) 
8820         m_colLabelHorizAlign 
= horiz
; 
8823     if ( vert 
== wxALIGN_TOP 
|| vert 
== wxALIGN_CENTRE 
|| vert 
== wxALIGN_BOTTOM 
) 
8825         m_colLabelVertAlign 
= vert
; 
8828     if ( !GetBatchCount() ) 
8830         m_colLabelWin
->Refresh(); 
8834 // Note: under MSW, the default column label font must be changed because it 
8835 //       does not support vertical printing 
8837 // Example: wxFont font(9, wxSWISS, wxNORMAL, wxBOLD); 
8838 //                      pGrid->SetLabelFont(font); 
8839 //                      pGrid->SetColLabelTextOrientation(wxVERTICAL); 
8841 void wxGrid::SetColLabelTextOrientation( int textOrientation 
) 
8843     if( textOrientation 
== wxHORIZONTAL 
|| textOrientation 
== wxVERTICAL 
) 
8845         m_colLabelTextOrientation 
= textOrientation
; 
8848     if ( !GetBatchCount() ) 
8850         m_colLabelWin
->Refresh(); 
8854 void wxGrid::SetRowLabelValue( int row
, const wxString
& s 
) 
8858         m_table
->SetRowLabelValue( row
, s 
); 
8859         if ( !GetBatchCount() ) 
8861             wxRect rect 
= CellToRect( row
, 0); 
8862             if ( rect
.height 
> 0 ) 
8864                 CalcScrolledPosition(0, rect
.y
, &rect
.x
, &rect
.y
); 
8866                 rect
.width 
= m_rowLabelWidth
; 
8867                 m_rowLabelWin
->Refresh( true, &rect 
); 
8873 void wxGrid::SetColLabelValue( int col
, const wxString
& s 
) 
8877         m_table
->SetColLabelValue( col
, s 
); 
8878         if ( !GetBatchCount() ) 
8880             wxRect rect 
= CellToRect( 0, col 
); 
8881             if ( rect
.width 
> 0 ) 
8883                 CalcScrolledPosition(rect
.x
, 0, &rect
.x
, &rect
.y
); 
8885                 rect
.height 
= m_colLabelHeight
; 
8886                 m_colLabelWin
->Refresh( true, &rect 
); 
8892 void wxGrid::SetGridLineColour( const wxColour
& colour 
) 
8894     if ( m_gridLineColour 
!= colour 
) 
8896         m_gridLineColour 
= colour
; 
8898         wxClientDC 
dc( m_gridWin 
); 
8900         DrawAllGridLines( dc
, wxRegion() ); 
8905 void wxGrid::SetCellHighlightColour( const wxColour
& colour 
) 
8907     if ( m_cellHighlightColour 
!= colour 
) 
8909         m_cellHighlightColour 
= colour
; 
8911         wxClientDC 
dc( m_gridWin 
); 
8913         wxGridCellAttr
* attr 
= GetCellAttr(m_currentCellCoords
); 
8914         DrawCellHighlight(dc
, attr
); 
8919 void wxGrid::SetCellHighlightPenWidth(int width
) 
8921     if (m_cellHighlightPenWidth 
!= width
) { 
8922         m_cellHighlightPenWidth 
= width
; 
8924         // Just redrawing the cell highlight is not enough since that won't 
8925         // make any visible change if the the thickness is getting smaller. 
8926         int row 
= m_currentCellCoords
.GetRow(); 
8927         int col 
= m_currentCellCoords
.GetCol(); 
8928         if ( GetColWidth(col
) <= 0 || GetRowHeight(row
) <= 0 ) 
8930         wxRect rect 
= CellToRect(row
, col
); 
8931         m_gridWin
->Refresh(true, &rect
); 
8935 void wxGrid::SetCellHighlightROPenWidth(int width
) 
8937     if (m_cellHighlightROPenWidth 
!= width
) { 
8938         m_cellHighlightROPenWidth 
= width
; 
8940         // Just redrawing the cell highlight is not enough since that won't 
8941         // make any visible change if the the thickness is getting smaller. 
8942         int row 
= m_currentCellCoords
.GetRow(); 
8943         int col 
= m_currentCellCoords
.GetCol(); 
8944         if ( GetColWidth(col
) <= 0 || GetRowHeight(row
) <= 0 ) 
8946         wxRect rect 
= CellToRect(row
, col
); 
8947         m_gridWin
->Refresh(true, &rect
); 
8951 void wxGrid::EnableGridLines( bool enable 
) 
8953     if ( enable 
!= m_gridLinesEnabled 
) 
8955         m_gridLinesEnabled 
= enable
; 
8957         if ( !GetBatchCount() ) 
8961                 wxClientDC 
dc( m_gridWin 
); 
8963                 DrawAllGridLines( dc
, wxRegion() ); 
8967                 m_gridWin
->Refresh(); 
8974 int wxGrid::GetDefaultRowSize() 
8976     return m_defaultRowHeight
; 
8979 int wxGrid::GetRowSize( int row 
) 
8981     wxCHECK_MSG( row 
>= 0 && row 
< m_numRows
, 0, _T("invalid row index") ); 
8983     return GetRowHeight(row
); 
8986 int wxGrid::GetDefaultColSize() 
8988     return m_defaultColWidth
; 
8991 int wxGrid::GetColSize( int col 
) 
8993     wxCHECK_MSG( col 
>= 0 && col 
< m_numCols
, 0, _T("invalid column index") ); 
8995     return GetColWidth(col
); 
8998 // ============================================================================ 
8999 // access to the grid attributes: each of them has a default value in the grid 
9000 // itself and may be overidden on a per-cell basis 
9001 // ============================================================================ 
9003 // ---------------------------------------------------------------------------- 
9004 // setting default attributes 
9005 // ---------------------------------------------------------------------------- 
9007 void wxGrid::SetDefaultCellBackgroundColour( const wxColour
& col 
) 
9009     m_defaultCellAttr
->SetBackgroundColour(col
); 
9011     m_gridWin
->SetBackgroundColour(col
); 
9015 void wxGrid::SetDefaultCellTextColour( const wxColour
& col 
) 
9017     m_defaultCellAttr
->SetTextColour(col
); 
9020 void wxGrid::SetDefaultCellAlignment( int horiz
, int vert 
) 
9022     m_defaultCellAttr
->SetAlignment(horiz
, vert
); 
9025 void wxGrid::SetDefaultCellOverflow( bool allow 
) 
9027     m_defaultCellAttr
->SetOverflow(allow
); 
9030 void wxGrid::SetDefaultCellFont( const wxFont
& font 
) 
9032     m_defaultCellAttr
->SetFont(font
); 
9036 // For editors and renderers the type registry takes precedence over the 
9037 // default attr, so we need to register the new editor/renderer for the string 
9038 // data type in order to make setting a default editor/renderer appear to 
9041 void wxGrid::SetDefaultRenderer(wxGridCellRenderer 
*renderer
) 
9043     RegisterDataType(wxGRID_VALUE_STRING
, 
9045                      GetDefaultEditorForType(wxGRID_VALUE_STRING
)); 
9048 void wxGrid::SetDefaultEditor(wxGridCellEditor 
*editor
) 
9050     RegisterDataType(wxGRID_VALUE_STRING
, 
9051                      GetDefaultRendererForType(wxGRID_VALUE_STRING
), 
9055 // ---------------------------------------------------------------------------- 
9056 // access to the default attrbiutes 
9057 // ---------------------------------------------------------------------------- 
9059 wxColour 
wxGrid::GetDefaultCellBackgroundColour() 
9061     return m_defaultCellAttr
->GetBackgroundColour(); 
9064 wxColour 
wxGrid::GetDefaultCellTextColour() 
9066     return m_defaultCellAttr
->GetTextColour(); 
9069 wxFont 
wxGrid::GetDefaultCellFont() 
9071     return m_defaultCellAttr
->GetFont(); 
9074 void wxGrid::GetDefaultCellAlignment( int *horiz
, int *vert 
) 
9076     m_defaultCellAttr
->GetAlignment(horiz
, vert
); 
9079 bool wxGrid::GetDefaultCellOverflow() 
9081     return m_defaultCellAttr
->GetOverflow(); 
9084 wxGridCellRenderer 
*wxGrid::GetDefaultRenderer() const 
9086     return m_defaultCellAttr
->GetRenderer(NULL
, 0, 0); 
9089 wxGridCellEditor 
*wxGrid::GetDefaultEditor() const 
9091     return m_defaultCellAttr
->GetEditor(NULL
,0,0); 
9094 // ---------------------------------------------------------------------------- 
9095 // access to cell attributes 
9096 // ---------------------------------------------------------------------------- 
9098 wxColour 
wxGrid::GetCellBackgroundColour(int row
, int col
) 
9100     wxGridCellAttr 
*attr 
= GetCellAttr(row
, col
); 
9101     wxColour colour 
= attr
->GetBackgroundColour(); 
9106 wxColour 
wxGrid::GetCellTextColour( int row
, int col 
) 
9108     wxGridCellAttr 
*attr 
= GetCellAttr(row
, col
); 
9109     wxColour colour 
= attr
->GetTextColour(); 
9114 wxFont 
wxGrid::GetCellFont( int row
, int col 
) 
9116     wxGridCellAttr 
*attr 
= GetCellAttr(row
, col
); 
9117     wxFont font 
= attr
->GetFont(); 
9122 void wxGrid::GetCellAlignment( int row
, int col
, int *horiz
, int *vert 
) 
9124     wxGridCellAttr 
*attr 
= GetCellAttr(row
, col
); 
9125     attr
->GetAlignment(horiz
, vert
); 
9129 bool wxGrid::GetCellOverflow( int row
, int col 
) 
9131     wxGridCellAttr 
*attr 
= GetCellAttr(row
, col
); 
9132     bool allow 
= attr
->GetOverflow(); 
9137 void wxGrid::GetCellSize( int row
, int col
, int *num_rows
, int *num_cols 
) 
9139     wxGridCellAttr 
*attr 
= GetCellAttr(row
, col
); 
9140     attr
->GetSize( num_rows
, num_cols 
); 
9144 wxGridCellRenderer
* wxGrid::GetCellRenderer(int row
, int col
) 
9146     wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
9147     wxGridCellRenderer
* renderer 
= attr
->GetRenderer(this, row
, col
); 
9153 wxGridCellEditor
* wxGrid::GetCellEditor(int row
, int col
) 
9155     wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
9156     wxGridCellEditor
* editor 
= attr
->GetEditor(this, row
, col
); 
9162 bool wxGrid::IsReadOnly(int row
, int col
) const 
9164     wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
9165     bool isReadOnly 
= attr
->IsReadOnly(); 
9170 // ---------------------------------------------------------------------------- 
9171 // attribute support: cache, automatic provider creation, ... 
9172 // ---------------------------------------------------------------------------- 
9174 bool wxGrid::CanHaveAttributes() 
9181     return m_table
->CanHaveAttributes(); 
9184 void wxGrid::ClearAttrCache() 
9186     if ( m_attrCache
.row 
!= -1 ) 
9188         wxSafeDecRef(m_attrCache
.attr
); 
9189         m_attrCache
.attr 
= NULL
; 
9190         m_attrCache
.row 
= -1; 
9194 void wxGrid::CacheAttr(int row
, int col
, wxGridCellAttr 
*attr
) const 
9198         wxGrid 
*self 
= (wxGrid 
*)this;  // const_cast 
9200         self
->ClearAttrCache(); 
9201         self
->m_attrCache
.row 
= row
; 
9202         self
->m_attrCache
.col 
= col
; 
9203         self
->m_attrCache
.attr 
= attr
; 
9208 bool wxGrid::LookupAttr(int row
, int col
, wxGridCellAttr 
**attr
) const 
9210     if ( row 
== m_attrCache
.row 
&& col 
== m_attrCache
.col 
) 
9212         *attr 
= m_attrCache
.attr
; 
9213         wxSafeIncRef(m_attrCache
.attr
); 
9215 #ifdef DEBUG_ATTR_CACHE 
9216         gs_nAttrCacheHits
++; 
9223 #ifdef DEBUG_ATTR_CACHE 
9224         gs_nAttrCacheMisses
++; 
9230 wxGridCellAttr 
*wxGrid::GetCellAttr(int row
, int col
) const 
9232     wxGridCellAttr 
*attr 
= NULL
; 
9233     // Additional test to avoid looking at the cache e.g. for 
9234     // wxNoCellCoords, as this will confuse memory management. 
9237         if ( !LookupAttr(row
, col
, &attr
) ) 
9239             attr 
= m_table 
? m_table
->GetAttr(row
, col 
, wxGridCellAttr::Any
) 
9240                            : (wxGridCellAttr 
*)NULL
; 
9241             CacheAttr(row
, col
, attr
); 
9246         attr
->SetDefAttr(m_defaultCellAttr
); 
9250         attr 
= m_defaultCellAttr
; 
9257 wxGridCellAttr 
*wxGrid::GetOrCreateCellAttr(int row
, int col
) const 
9259     wxGridCellAttr 
*attr 
= (wxGridCellAttr 
*)NULL
; 
9260     bool canHave 
= ((wxGrid
*)this)->CanHaveAttributes(); 
9262     wxCHECK_MSG( canHave
, attr
, _T("Cell attributes not allowed")); 
9263     wxCHECK_MSG( m_table
, attr
, _T("must have a table") ); 
9265     attr 
= m_table
->GetAttr(row
, col
, wxGridCellAttr::Cell
); 
9268         attr 
= new wxGridCellAttr(m_defaultCellAttr
); 
9270         // artificially inc the ref count to match DecRef() in caller 
9272         m_table
->SetAttr(attr
, row
, col
); 
9278 // ---------------------------------------------------------------------------- 
9279 // setting column attributes (wrappers around SetColAttr) 
9280 // ---------------------------------------------------------------------------- 
9282 void wxGrid::SetColFormatBool(int col
) 
9284     SetColFormatCustom(col
, wxGRID_VALUE_BOOL
); 
9287 void wxGrid::SetColFormatNumber(int col
) 
9289     SetColFormatCustom(col
, wxGRID_VALUE_NUMBER
); 
9292 void wxGrid::SetColFormatFloat(int col
, int width
, int precision
) 
9294     wxString typeName 
= wxGRID_VALUE_FLOAT
; 
9295     if ( (width 
!= -1) || (precision 
!= -1) ) 
9297         typeName 
<< _T(':') << width 
<< _T(',') << precision
; 
9300     SetColFormatCustom(col
, typeName
); 
9303 void wxGrid::SetColFormatCustom(int col
, const wxString
& typeName
) 
9305     wxGridCellAttr 
*attr 
= m_table
->GetAttr(-1, col
, wxGridCellAttr::Col 
); 
9307         attr 
= new wxGridCellAttr
; 
9308     wxGridCellRenderer 
*renderer 
= GetDefaultRendererForType(typeName
); 
9309     attr
->SetRenderer(renderer
); 
9311     SetColAttr(col
, attr
); 
9315 // ---------------------------------------------------------------------------- 
9316 // setting cell attributes: this is forwarded to the table 
9317 // ---------------------------------------------------------------------------- 
9319 void wxGrid::SetAttr(int row
, int col
, wxGridCellAttr 
*attr
) 
9321     if ( CanHaveAttributes() ) 
9323         m_table
->SetAttr(attr
, row
, col
); 
9332 void wxGrid::SetRowAttr(int row
, wxGridCellAttr 
*attr
) 
9334     if ( CanHaveAttributes() ) 
9336         m_table
->SetRowAttr(attr
, row
); 
9345 void wxGrid::SetColAttr(int col
, wxGridCellAttr 
*attr
) 
9347     if ( CanHaveAttributes() ) 
9349         m_table
->SetColAttr(attr
, col
); 
9358 void wxGrid::SetCellBackgroundColour( int row
, int col
, const wxColour
& colour 
) 
9360     if ( CanHaveAttributes() ) 
9362         wxGridCellAttr 
*attr 
= GetOrCreateCellAttr(row
, col
); 
9363         attr
->SetBackgroundColour(colour
); 
9368 void wxGrid::SetCellTextColour( int row
, int col
, const wxColour
& colour 
) 
9370     if ( CanHaveAttributes() ) 
9372         wxGridCellAttr 
*attr 
= GetOrCreateCellAttr(row
, col
); 
9373         attr
->SetTextColour(colour
); 
9378 void wxGrid::SetCellFont( int row
, int col
, const wxFont
& font 
) 
9380     if ( CanHaveAttributes() ) 
9382         wxGridCellAttr 
*attr 
= GetOrCreateCellAttr(row
, col
); 
9383         attr
->SetFont(font
); 
9388 void wxGrid::SetCellAlignment( int row
, int col
, int horiz
, int vert 
) 
9390     if ( CanHaveAttributes() ) 
9392         wxGridCellAttr 
*attr 
= GetOrCreateCellAttr(row
, col
); 
9393         attr
->SetAlignment(horiz
, vert
); 
9398 void wxGrid::SetCellOverflow( int row
, int col
, bool allow 
) 
9400     if ( CanHaveAttributes() ) 
9402         wxGridCellAttr 
*attr 
= GetOrCreateCellAttr(row
, col
); 
9403         attr
->SetOverflow(allow
); 
9408 void wxGrid::SetCellSize( int row
, int col
, int num_rows
, int num_cols 
) 
9410     if ( CanHaveAttributes() ) 
9412         int cell_rows
, cell_cols
; 
9414         wxGridCellAttr 
*attr 
= GetOrCreateCellAttr(row
, col
); 
9415         attr
->GetSize(&cell_rows
, &cell_cols
); 
9416         attr
->SetSize(num_rows
, num_cols
); 
9419         // Cannot set the size of a cell to 0 or negative values 
9420         // While it is perfectly legal to do that, this function cannot 
9421         // handle all the possibilies, do it by hand by getting the CellAttr. 
9422         // You can only set the size of a cell to 1,1 or greater with this fn 
9423         wxASSERT_MSG( !((cell_rows 
< 1) || (cell_cols 
< 1)), 
9424                       wxT("wxGrid::SetCellSize setting cell size that is already part of another cell")); 
9425         wxASSERT_MSG( !((num_rows 
< 1) || (num_cols 
< 1)), 
9426                       wxT("wxGrid::SetCellSize setting cell size to < 1")); 
9428         // if this was already a multicell then "turn off" the other cells first 
9429         if ((cell_rows 
> 1) || (cell_rows 
> 1)) 
9432             for (j
=row
; j
<row
+cell_rows
; j
++) 
9434                 for (i
=col
; i
<col
+cell_cols
; i
++) 
9436                     if ((i 
!= col
) || (j 
!= row
)) 
9438                         wxGridCellAttr 
*attr_stub 
= GetOrCreateCellAttr(j
, i
); 
9439                         attr_stub
->SetSize( 1, 1 ); 
9440                         attr_stub
->DecRef(); 
9446         // mark the cells that will be covered by this cell to 
9447         // negative or zero values to point back at this cell 
9448         if (((num_rows 
> 1) || (num_cols 
> 1)) && (num_rows 
>= 1) && (num_cols 
>= 1)) 
9451             for (j
=row
; j
<row
+num_rows
; j
++) 
9453                 for (i
=col
; i
<col
+num_cols
; i
++) 
9455                     if ((i 
!= col
) || (j 
!= row
)) 
9457                         wxGridCellAttr 
*attr_stub 
= GetOrCreateCellAttr(j
, i
); 
9458                         attr_stub
->SetSize( row
-j
, col
-i 
); 
9459                         attr_stub
->DecRef(); 
9467 void wxGrid::SetCellRenderer(int row
, int col
, wxGridCellRenderer 
*renderer
) 
9469     if ( CanHaveAttributes() ) 
9471         wxGridCellAttr 
*attr 
= GetOrCreateCellAttr(row
, col
); 
9472         attr
->SetRenderer(renderer
); 
9477 void wxGrid::SetCellEditor(int row
, int col
, wxGridCellEditor
* editor
) 
9479     if ( CanHaveAttributes() ) 
9481         wxGridCellAttr 
*attr 
= GetOrCreateCellAttr(row
, col
); 
9482         attr
->SetEditor(editor
); 
9487 void wxGrid::SetReadOnly(int row
, int col
, bool isReadOnly
) 
9489     if ( CanHaveAttributes() ) 
9491         wxGridCellAttr 
*attr 
= GetOrCreateCellAttr(row
, col
); 
9492         attr
->SetReadOnly(isReadOnly
); 
9497 // ---------------------------------------------------------------------------- 
9498 // Data type registration 
9499 // ---------------------------------------------------------------------------- 
9501 void wxGrid::RegisterDataType(const wxString
& typeName
, 
9502                               wxGridCellRenderer
* renderer
, 
9503                               wxGridCellEditor
* editor
) 
9505     m_typeRegistry
->RegisterDataType(typeName
, renderer
, editor
); 
9509 wxGridCellEditor
* wxGrid::GetDefaultEditorForCell(int row
, int col
) const 
9511     wxString typeName 
= m_table
->GetTypeName(row
, col
); 
9512     return GetDefaultEditorForType(typeName
); 
9515 wxGridCellRenderer
* wxGrid::GetDefaultRendererForCell(int row
, int col
) const 
9517     wxString typeName 
= m_table
->GetTypeName(row
, col
); 
9518     return GetDefaultRendererForType(typeName
); 
9522 wxGrid::GetDefaultEditorForType(const wxString
& typeName
) const 
9524     int index 
= m_typeRegistry
->FindOrCloneDataType(typeName
); 
9525     if ( index 
== wxNOT_FOUND 
) 
9527         wxFAIL_MSG(wxT("Unknown data type name")); 
9532     return m_typeRegistry
->GetEditor(index
); 
9536 wxGrid::GetDefaultRendererForType(const wxString
& typeName
) const 
9538     int index 
= m_typeRegistry
->FindOrCloneDataType(typeName
); 
9539     if ( index 
== wxNOT_FOUND 
) 
9541         wxFAIL_MSG(wxT("Unknown data type name")); 
9546     return m_typeRegistry
->GetRenderer(index
); 
9550 // ---------------------------------------------------------------------------- 
9552 // ---------------------------------------------------------------------------- 
9554 void wxGrid::EnableDragRowSize( bool enable 
) 
9556     m_canDragRowSize 
= enable
; 
9560 void wxGrid::EnableDragColSize( bool enable 
) 
9562     m_canDragColSize 
= enable
; 
9565 void wxGrid::EnableDragGridSize( bool enable 
) 
9567     m_canDragGridSize 
= enable
; 
9570 void wxGrid::EnableDragCell( bool enable 
) 
9572     m_canDragCell 
= enable
; 
9575 void wxGrid::SetDefaultRowSize( int height
, bool resizeExistingRows 
) 
9577     m_defaultRowHeight 
= wxMax( height
, m_minAcceptableRowHeight 
); 
9579     if ( resizeExistingRows 
) 
9581         // since we are resizing all rows to the default row size, 
9582         // we can simply clear the row heights and row bottoms 
9583         // arrays (which also allows us to take advantage of 
9584         // some speed optimisations) 
9585         m_rowHeights
.Empty(); 
9586         m_rowBottoms
.Empty(); 
9587         if ( !GetBatchCount() ) 
9592 void wxGrid::SetRowSize( int row
, int height 
) 
9594     wxCHECK_RET( row 
>= 0 && row 
< m_numRows
, _T("invalid row index") ); 
9596     // See comment in SetColSize 
9597     if ( height 
< GetRowMinimalAcceptableHeight()) { return; } 
9599     if ( m_rowHeights
.IsEmpty() ) 
9601         // need to really create the array 
9605     int h 
= wxMax( 0, height 
); 
9606     int diff 
= h 
- m_rowHeights
[row
]; 
9608     m_rowHeights
[row
] = h
; 
9610     for ( i 
= row
;  i 
< m_numRows
;  i
++ ) 
9612         m_rowBottoms
[i
] += diff
; 
9614     if ( !GetBatchCount() ) 
9618 void wxGrid::SetDefaultColSize( int width
, bool resizeExistingCols 
) 
9620     m_defaultColWidth 
= wxMax( width
, m_minAcceptableColWidth 
); 
9622     if ( resizeExistingCols 
) 
9624         // since we are resizing all columns to the default column size, 
9625         // we can simply clear the col widths and col rights 
9626         // arrays (which also allows us to take advantage of 
9627         // some speed optimisations) 
9628         m_colWidths
.Empty(); 
9629         m_colRights
.Empty(); 
9630         if ( !GetBatchCount() ) 
9635 void wxGrid::SetColSize( int col
, int width 
) 
9637     wxCHECK_RET( col 
>= 0 && col 
< m_numCols
, _T("invalid column index") ); 
9639     // should we check that it's bigger than GetColMinimalWidth(col) here? 
9641     // No, because it is reasonable to assume the library user know's 
9642     // what he is doing. However whe should test against the weaker 
9643     // constariant of minimalAcceptableWidth, as this breaks rendering 
9645     // This test then fixes sf.net bug #645734 
9647     if ( width 
< GetColMinimalAcceptableWidth()) { return; } 
9649     if ( m_colWidths
.IsEmpty() ) 
9651         // need to really create the array 
9655     // if < 0 calc new width from label 
9659       wxArrayString lines
; 
9660       wxClientDC 
dc(m_colLabelWin
); 
9661       dc
.SetFont(GetLabelFont()); 
9662       StringToLines(GetColLabelValue(col
), lines
); 
9663       GetTextBoxSize(dc
, lines
, &w
, &h
); 
9666     int w 
= wxMax( 0, width 
); 
9667     int diff 
= w 
- m_colWidths
[col
]; 
9668     m_colWidths
[col
] = w
; 
9671     for ( i 
= col
;  i 
< m_numCols
;  i
++ ) 
9673         m_colRights
[i
] += diff
; 
9675     if ( !GetBatchCount() ) 
9680 void wxGrid::SetColMinimalWidth( int col
, int width 
) 
9682     if (width 
> GetColMinimalAcceptableWidth()) { 
9683         wxLongToLongHashMap::key_type key 
= (wxLongToLongHashMap::key_type
)col
; 
9684         m_colMinWidths
[key
] = width
; 
9688 void wxGrid::SetRowMinimalHeight( int row
, int width 
) 
9690     if (width 
> GetRowMinimalAcceptableHeight()) { 
9691         wxLongToLongHashMap::key_type key 
= (wxLongToLongHashMap::key_type
)row
; 
9692         m_rowMinHeights
[key
] = width
; 
9696 int wxGrid::GetColMinimalWidth(int col
) const 
9698     wxLongToLongHashMap::key_type key 
= (wxLongToLongHashMap::key_type
)col
; 
9699     wxLongToLongHashMap::const_iterator it 
= m_colMinWidths
.find(key
); 
9700     return it 
!= m_colMinWidths
.end() ? (int)it
->second 
: m_minAcceptableColWidth
; 
9703 int wxGrid::GetRowMinimalHeight(int row
) const 
9705     wxLongToLongHashMap::key_type key 
= (wxLongToLongHashMap::key_type
)row
; 
9706     wxLongToLongHashMap::const_iterator it 
= m_rowMinHeights
.find(key
); 
9707     return it 
!= m_rowMinHeights
.end() ? (int)it
->second 
: m_minAcceptableRowHeight
; 
9710 void wxGrid::SetColMinimalAcceptableWidth( int width 
) 
9712     // We do allow a width of 0 since this gives us 
9713     // an easy way to temporarily hidding columns. 
9716     m_minAcceptableColWidth 
= width
; 
9719 void wxGrid::SetRowMinimalAcceptableHeight( int height 
) 
9721     // We do allow a height of 0 since this gives us 
9722     // an easy way to temporarily hidding rows. 
9725     m_minAcceptableRowHeight 
= height
; 
9728 int  wxGrid::GetColMinimalAcceptableWidth() const 
9730     return m_minAcceptableColWidth
; 
9733 int  wxGrid::GetRowMinimalAcceptableHeight() const 
9735     return m_minAcceptableRowHeight
; 
9738 // ---------------------------------------------------------------------------- 
9740 // ---------------------------------------------------------------------------- 
9742 void wxGrid::AutoSizeColOrRow( int colOrRow
, bool setAsMin
, bool column 
) 
9744     wxClientDC 
dc(m_gridWin
); 
9746     //Cancel editting of cell 
9747     HideCellEditControl(); 
9748     SaveEditControlValue(); 
9750     // init both of them to avoid compiler warnings, even if weo nly need one 
9758     wxCoord extent
, extentMax 
= 0; 
9759     int max 
= column 
? m_numRows 
: m_numCols
; 
9760     for ( int rowOrCol 
= 0; rowOrCol 
< max
; rowOrCol
++ ) 
9767         wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
9768         wxGridCellRenderer
* renderer 
= attr
->GetRenderer(this, row
, col
); 
9771             wxSize size 
= renderer
->GetBestSize(*this, *attr
, dc
, row
, col
); 
9772             extent 
= column 
? size
.x 
: size
.y
; 
9773             if ( extent 
> extentMax 
) 
9784     // now also compare with the column label extent 
9786     dc
.SetFont( GetLabelFont() ); 
9790         dc
.GetTextExtent( GetColLabelValue(col
), &w
, &h 
); 
9791         if( GetColLabelTextOrientation() == wxVERTICAL 
) 
9795         dc
.GetTextExtent( GetRowLabelValue(row
), &w
, &h 
); 
9797     extent 
= column 
? w 
: h
; 
9798     if ( extent 
> extentMax 
) 
9805         // empty column - give default extent (notice that if extentMax is less 
9806         // than default extent but != 0, it's ok) 
9807         extentMax 
= column 
? m_defaultColWidth 
: m_defaultRowHeight
; 
9813             // leave some space around text 
9824         SetColSize(col
, extentMax
); 
9825         if ( !GetBatchCount() ) 
9828             m_gridWin
->GetClientSize( &cw
, &ch 
); 
9829             wxRect 
rect ( CellToRect( 0, col 
) ); 
9831             CalcScrolledPosition(rect
.x
, 0, &rect
.x
, &dummy
); 
9832             rect
.width 
= cw 
- rect
.x
; 
9833             rect
.height 
= m_colLabelHeight
; 
9834             m_colLabelWin
->Refresh( true, &rect 
); 
9839         SetRowSize(row
, extentMax
); 
9840         if ( !GetBatchCount() ) 
9843             m_gridWin
->GetClientSize( &cw
, &ch 
); 
9844             wxRect 
rect ( CellToRect( row
, 0 ) ); 
9846             CalcScrolledPosition(0, rect
.y
, &dummy
, &rect
.y
); 
9847             rect
.width 
= m_rowLabelWidth
; 
9848             rect
.height 
= ch 
- rect
.y
; 
9849             m_rowLabelWin
->Refresh( true, &rect 
); 
9855             SetColMinimalWidth(col
, extentMax
); 
9857             SetRowMinimalHeight(row
, extentMax
); 
9861 int wxGrid::SetOrCalcColumnSizes(bool calcOnly
, bool setAsMin
) 
9863     int width 
= m_rowLabelWidth
; 
9868     for ( int col 
= 0; col 
< m_numCols
; col
++ ) 
9872             AutoSizeColumn(col
, setAsMin
); 
9875         width 
+= GetColWidth(col
); 
9884 int wxGrid::SetOrCalcRowSizes(bool calcOnly
, bool setAsMin
) 
9886     int height 
= m_colLabelHeight
; 
9891     for ( int row 
= 0; row 
< m_numRows
; row
++ ) 
9895             AutoSizeRow(row
, setAsMin
); 
9898         height 
+= GetRowHeight(row
); 
9907 void wxGrid::AutoSize() 
9911     wxSize 
size(SetOrCalcColumnSizes(false), SetOrCalcRowSizes(false)); 
9913     // round up the size to a multiple of scroll step - this ensures that we 
9914     // won't get the scrollbars if we're sized exactly to this width 
9915     // CalcDimension adds m_extraWidth + 1 etc. to calculate the necessary 
9917     wxSize 
sizeFit(GetScrollX(size
.x 
+ m_extraWidth 
+ 1) * m_scrollLineX
, 
9918                    GetScrollY(size
.y 
+ m_extraHeight 
+ 1) * m_scrollLineY
); 
9920     // distribute the extra space between the columns/rows to avoid having 
9921     // extra white space 
9923     // Remove the extra m_extraWidth + 1 added above 
9924     wxCoord diff 
= sizeFit
.x 
- size
.x 
+ (m_extraWidth 
+ 1); 
9925     if ( diff 
&& m_numCols 
) 
9927         // try to resize the columns uniformly 
9928         wxCoord diffPerCol 
= diff 
/ m_numCols
; 
9931             for ( int col 
= 0; col 
< m_numCols
; col
++ ) 
9933                 SetColSize(col
, GetColWidth(col
) + diffPerCol
); 
9937         // add remaining amount to the last columns 
9938         diff 
-= diffPerCol 
* m_numCols
; 
9941             for ( int col 
= m_numCols 
- 1; col 
>= m_numCols 
- diff
; col
-- ) 
9943                 SetColSize(col
, GetColWidth(col
) + 1); 
9949     diff 
= sizeFit
.y 
- size
.y 
- (m_extraHeight 
+ 1); 
9950     if ( diff 
&& m_numRows 
) 
9952         // try to resize the columns uniformly 
9953         wxCoord diffPerRow 
= diff 
/ m_numRows
; 
9956             for ( int row 
= 0; row 
< m_numRows
; row
++ ) 
9958                 SetRowSize(row
, GetRowHeight(row
) + diffPerRow
); 
9962         // add remaining amount to the last rows 
9963         diff 
-= diffPerRow 
* m_numRows
; 
9966             for ( int row 
= m_numRows 
- 1; row 
>= m_numRows 
- diff
; row
-- ) 
9968                 SetRowSize(row
, GetRowHeight(row
) + 1); 
9975     SetClientSize(sizeFit
); 
9978 void wxGrid::AutoSizeRowLabelSize( int row 
) 
9980     wxArrayString lines
; 
9983     // Hide the edit control, so it 
9984     // won't interfer with drag-shrinking. 
9985     if( IsCellEditControlShown() ) 
9987         HideCellEditControl(); 
9988         SaveEditControlValue(); 
9991     // autosize row height depending on label text 
9992     StringToLines( GetRowLabelValue( row 
), lines 
); 
9993     wxClientDC 
dc( m_rowLabelWin 
); 
9994     GetTextBoxSize( dc
, lines
, &w
, &h
); 
9995     if( h 
< m_defaultRowHeight 
) 
9996         h 
= m_defaultRowHeight
; 
10001 void wxGrid::AutoSizeColLabelSize( int col 
) 
10003     wxArrayString lines
; 
10006     // Hide the edit control, so it 
10007     // won't interfer with drag-shrinking. 
10008     if( IsCellEditControlShown() ) 
10010         HideCellEditControl(); 
10011         SaveEditControlValue(); 
10014     // autosize column width depending on label text 
10015     StringToLines( GetColLabelValue( col 
), lines 
); 
10016     wxClientDC 
dc( m_colLabelWin 
); 
10017     if( GetColLabelTextOrientation() == wxHORIZONTAL 
) 
10018         GetTextBoxSize( dc
, lines
, &w
, &h
); 
10020         GetTextBoxSize( dc
, lines
, &h
, &w
); 
10021     if( w 
< m_defaultColWidth 
) 
10022         w 
= m_defaultColWidth
; 
10023     SetColSize(col
, w
); 
10027 wxSize 
wxGrid::DoGetBestSize() const 
10029     // don't set sizes, only calculate them 
10030     wxGrid 
*self 
= (wxGrid 
*)this;  // const_cast 
10033     width 
= self
->SetOrCalcColumnSizes(true); 
10034     height 
= self
->SetOrCalcRowSizes(true); 
10036     if (!width
) width
=100; 
10037     if (!height
) height
=80; 
10039     // Round up to a multiple the scroll rate NOTE: this still doesn't get rid 
10040     // of the scrollbars, is there any magic incantaion for that? 
10042     GetScrollPixelsPerUnit(&xpu
, &ypu
); 
10044         width  
+= 1 + xpu 
- (width  
% xpu
); 
10046         height 
+= 1 + ypu 
- (height 
% ypu
); 
10048     // limit to 1/4 of the screen size 
10049     int maxwidth
, maxheight
; 
10050     wxDisplaySize( & maxwidth
, & maxheight 
); 
10053     if ( width 
> maxwidth 
) width 
= maxwidth
; 
10054     if ( height 
> maxheight 
) height 
= maxheight
; 
10057     wxSize 
best(width
, height
); 
10058     // NOTE: This size should be cached, but first we need to add calls to 
10059     // InvalidateBestSize everywhere that could change the results of this 
10061     // CacheBestSize(size); 
10071 wxPen
& wxGrid::GetDividerPen() const 
10076 // ---------------------------------------------------------------------------- 
10077 // cell value accessor functions 
10078 // ---------------------------------------------------------------------------- 
10080 void wxGrid::SetCellValue( int row
, int col
, const wxString
& s 
) 
10084         m_table
->SetValue( row
, col
, s 
); 
10085         if ( !GetBatchCount() ) 
10088             wxRect 
rect( CellToRect( row
, col 
) ); 
10090             rect
.width 
= m_gridWin
->GetClientSize().GetWidth(); 
10091             CalcScrolledPosition(0, rect
.y
, &dummy
, &rect
.y
); 
10092             m_gridWin
->Refresh( false, &rect 
); 
10095         if ( m_currentCellCoords
.GetRow() == row 
&& 
10096              m_currentCellCoords
.GetCol() == col 
&& 
10097              IsCellEditControlShown()) 
10098              // Note: If we are using IsCellEditControlEnabled, 
10099              // this interacts badly with calling SetCellValue from 
10100              // an EVT_GRID_CELL_CHANGE handler. 
10102             HideCellEditControl(); 
10103             ShowCellEditControl(); // will reread data from table 
10110 // ------ Block, row and col selection 
10113 void wxGrid::SelectRow( int row
, bool addToSelected 
) 
10115     if ( IsSelection() && !addToSelected 
) 
10119         m_selection
->SelectRow( row
, false, addToSelected 
); 
10123 void wxGrid::SelectCol( int col
, bool addToSelected 
) 
10125     if ( IsSelection() && !addToSelected 
) 
10129         m_selection
->SelectCol( col
, false, addToSelected 
); 
10133 void wxGrid::SelectBlock( int topRow
, int leftCol
, int bottomRow
, int rightCol
, 
10134                           bool addToSelected 
) 
10136     if ( IsSelection() && !addToSelected 
) 
10140         m_selection
->SelectBlock( topRow
, leftCol
, bottomRow
, rightCol
, 
10141                                   false, addToSelected 
); 
10145 void wxGrid::SelectAll() 
10147     if ( m_numRows 
> 0 && m_numCols 
> 0 ) 
10150             m_selection
->SelectBlock( 0, 0, m_numRows
-1, m_numCols
-1 ); 
10155 // ------ Cell, row and col deselection 
10158 void wxGrid::DeselectRow( int row 
) 
10160     if ( !m_selection 
) 
10163     if ( m_selection
->GetSelectionMode() == wxGrid::wxGridSelectRows 
) 
10165         if ( m_selection
->IsInSelection(row
, 0 ) ) 
10166             m_selection
->ToggleCellSelection( row
, 0); 
10170         int nCols 
= GetNumberCols(); 
10171         for ( int i 
= 0; i 
< nCols 
; i
++ ) 
10173             if ( m_selection
->IsInSelection(row
, i 
) ) 
10174                 m_selection
->ToggleCellSelection( row
, i
); 
10179 void wxGrid::DeselectCol( int col 
) 
10181     if ( !m_selection 
) 
10184     if ( m_selection
->GetSelectionMode() == wxGrid::wxGridSelectColumns 
) 
10186         if ( m_selection
->IsInSelection(0, col 
) ) 
10187             m_selection
->ToggleCellSelection( 0, col
); 
10191         int nRows 
= GetNumberRows(); 
10192         for ( int i 
= 0; i 
< nRows 
; i
++ ) 
10194             if ( m_selection
->IsInSelection(i
, col 
) ) 
10195                 m_selection
->ToggleCellSelection(i
, col
); 
10200 void wxGrid::DeselectCell( int row
, int col 
) 
10202     if ( m_selection 
&& m_selection
->IsInSelection(row
, col
) ) 
10203         m_selection
->ToggleCellSelection(row
, col
); 
10206 bool wxGrid::IsSelection() 
10208     return ( m_selection 
&& (m_selection
->IsSelection() || 
10209              ( m_selectingTopLeft 
!= wxGridNoCellCoords 
&& 
10210                m_selectingBottomRight 
!= wxGridNoCellCoords
) ) ); 
10213 bool wxGrid::IsInSelection( int row
, int col 
) const 
10215     return ( m_selection 
&& (m_selection
->IsInSelection( row
, col 
) || 
10216              ( row 
>= m_selectingTopLeft
.GetRow() && 
10217                col 
>= m_selectingTopLeft
.GetCol() && 
10218                row 
<= m_selectingBottomRight
.GetRow() && 
10219                col 
<= m_selectingBottomRight
.GetCol() )) ); 
10222 wxGridCellCoordsArray 
wxGrid::GetSelectedCells() const 
10224     if (!m_selection
) { wxGridCellCoordsArray a
; return a
; } 
10225     return m_selection
->m_cellSelection
; 
10227 wxGridCellCoordsArray 
wxGrid::GetSelectionBlockTopLeft() const 
10229     if (!m_selection
) { wxGridCellCoordsArray a
; return a
; } 
10230     return m_selection
->m_blockSelectionTopLeft
; 
10232 wxGridCellCoordsArray 
wxGrid::GetSelectionBlockBottomRight() const 
10234     if (!m_selection
) { wxGridCellCoordsArray a
; return a
; } 
10235     return m_selection
->m_blockSelectionBottomRight
; 
10237 wxArrayInt 
wxGrid::GetSelectedRows() const 
10239     if (!m_selection
) { wxArrayInt a
; return a
; } 
10240     return m_selection
->m_rowSelection
; 
10242 wxArrayInt 
wxGrid::GetSelectedCols() const 
10244     if (!m_selection
) { wxArrayInt a
; return a
; } 
10245     return m_selection
->m_colSelection
; 
10249 void wxGrid::ClearSelection() 
10251     m_selectingTopLeft 
= wxGridNoCellCoords
; 
10252     m_selectingBottomRight 
= wxGridNoCellCoords
; 
10254         m_selection
->ClearSelection(); 
10258 // This function returns the rectangle that encloses the given block 
10259 // in device coords clipped to the client size of the grid window. 
10261 wxRect 
wxGrid::BlockToDeviceRect( const wxGridCellCoords 
&topLeft
, 
10262                                   const wxGridCellCoords 
&bottomRight 
) 
10264     wxRect 
rect( wxGridNoCellRect 
); 
10267     cellRect 
= CellToRect( topLeft 
); 
10268     if ( cellRect 
!= wxGridNoCellRect 
) 
10274         rect 
= wxRect(0,0,0,0); 
10277     cellRect 
= CellToRect( bottomRight 
); 
10278     if ( cellRect 
!= wxGridNoCellRect 
) 
10284         return wxGridNoCellRect
; 
10288     int left 
= rect
.GetLeft(); 
10289     int top 
= rect
.GetTop(); 
10290     int right 
= rect
.GetRight(); 
10291     int bottom 
= rect
.GetBottom(); 
10293     int leftCol 
= topLeft
.GetCol(); 
10294     int topRow 
= topLeft
.GetRow(); 
10295     int rightCol 
= bottomRight
.GetCol(); 
10296     int bottomRow 
= bottomRight
.GetRow(); 
10314         topRow 
= bottomRow
; 
10319     for ( j 
= topRow
; j 
<= bottomRow
; j
++ ) 
10321         for ( i 
= leftCol
; i 
<= rightCol
; i
++ ) 
10323             if ((j
==topRow
) || (j
==bottomRow
) || (i
==leftCol
) || (i
==rightCol
)) 
10325                 cellRect 
= CellToRect( j
, i 
); 
10327                 if (cellRect
.x 
< left
) 
10329                 if (cellRect
.y 
< top
) 
10331                 if (cellRect
.x 
+ cellRect
.width 
> right
) 
10332                     right 
= cellRect
.x 
+ cellRect
.width
; 
10333                 if (cellRect
.y 
+ cellRect
.height 
> bottom
) 
10334                     bottom 
= cellRect
.y 
+ cellRect
.height
; 
10336             else i 
= rightCol
; // jump over inner cells. 
10340     // convert to scrolled coords 
10342     CalcScrolledPosition( left
, top
, &left
, &top 
); 
10343     CalcScrolledPosition( right
, bottom
, &right
, &bottom 
); 
10346     m_gridWin
->GetClientSize( &cw
, &ch 
); 
10348     if (right 
< 0 || bottom 
< 0 || left 
> cw 
|| top 
> ch
) 
10349         return wxRect(0,0,0,0); 
10351     rect
.SetLeft( wxMax(0, left
) ); 
10352     rect
.SetTop( wxMax(0, top
) ); 
10353     rect
.SetRight( wxMin(cw
, right
) ); 
10354     rect
.SetBottom( wxMin(ch
, bottom
) ); 
10360 // ------ Grid event classes 
10363 IMPLEMENT_DYNAMIC_CLASS( wxGridEvent
, wxNotifyEvent 
) 
10365 wxGridEvent::wxGridEvent( int id
, wxEventType type
, wxObject
* obj
, 
10366                           int row
, int col
, int x
, int y
, bool sel
, 
10367                           bool control
, bool shift
, bool alt
, bool meta 
) 
10368         : wxNotifyEvent( type
, id 
) 
10375     m_control 
= control
; 
10380     SetEventObject(obj
); 
10384 IMPLEMENT_DYNAMIC_CLASS( wxGridSizeEvent
, wxNotifyEvent 
) 
10386 wxGridSizeEvent::wxGridSizeEvent( int id
, wxEventType type
, wxObject
* obj
, 
10387                                   int rowOrCol
, int x
, int y
, 
10388                                   bool control
, bool shift
, bool alt
, bool meta 
) 
10389         : wxNotifyEvent( type
, id 
) 
10391     m_rowOrCol 
= rowOrCol
; 
10394     m_control 
= control
; 
10399     SetEventObject(obj
); 
10403 IMPLEMENT_DYNAMIC_CLASS( wxGridRangeSelectEvent
, wxNotifyEvent 
) 
10405 wxGridRangeSelectEvent::wxGridRangeSelectEvent(int id
, wxEventType type
, wxObject
* obj
, 
10406                                                const wxGridCellCoords
& topLeft
, 
10407                                                const wxGridCellCoords
& bottomRight
, 
10408                                                bool sel
, bool control
, 
10409                                                bool shift
, bool alt
, bool meta 
) 
10410         : wxNotifyEvent( type
, id 
) 
10412     m_topLeft     
= topLeft
; 
10413     m_bottomRight 
= bottomRight
; 
10415     m_control     
= control
; 
10420     SetEventObject(obj
); 
10424 IMPLEMENT_DYNAMIC_CLASS(wxGridEditorCreatedEvent
, wxCommandEvent
) 
10426 wxGridEditorCreatedEvent::wxGridEditorCreatedEvent(int id
, wxEventType type
, 
10427                                                    wxObject
* obj
, int row
, 
10428                                                    int col
, wxControl
* ctrl
) 
10429     : wxCommandEvent(type
, id
) 
10431     SetEventObject(obj
); 
10437 #endif // wxUSE_GRID