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" 
  46 #include "wx/textfile.h" 
  47 #include "wx/spinctrl.h" 
  48 #include "wx/tokenzr.h" 
  51 #include "wx/generic/gridsel.h" 
  53 #if defined(__WXMOTIF__) 
  54     #define WXUNUSED_MOTIF(identifier)  WXUNUSED(identifier) 
  56     #define WXUNUSED_MOTIF(identifier)  identifier 
  59 #if defined(__WXGTK__) 
  60     #define WXUNUSED_GTK(identifier)    WXUNUSED(identifier) 
  62     #define WXUNUSED_GTK(identifier)    identifier 
  65 // Required for wxIs... functions 
  68 // ---------------------------------------------------------------------------- 
  70 // ---------------------------------------------------------------------------- 
  72 WX_DEFINE_ARRAY_WITH_DECL_NO_PTR(wxGridCellAttr 
*, wxArrayAttrs
, 
  73                                  class WXDLLIMPEXP_ADV
); 
  75 struct wxGridCellWithAttr
 
  77     wxGridCellWithAttr(int row
, int col
, wxGridCellAttr 
*attr_
) 
  78         : coords(row
, col
), attr(attr_
) 
  87     wxGridCellCoords coords
; 
  91 //  DECLARE_NO_COPY_CLASS(wxGridCellWithAttr) 
  92 // without rewriting the macros, which require a public copy constructor. 
  95 WX_DECLARE_OBJARRAY_WITH_DECL(wxGridCellWithAttr
, wxGridCellWithAttrArray
, 
  96                               class WXDLLIMPEXP_ADV
); 
  98 #include "wx/arrimpl.cpp" 
 100 WX_DEFINE_OBJARRAY(wxGridCellCoordsArray
) 
 101 WX_DEFINE_OBJARRAY(wxGridCellWithAttrArray
) 
 103 // ---------------------------------------------------------------------------- 
 105 // ---------------------------------------------------------------------------- 
 107 DEFINE_EVENT_TYPE(wxEVT_GRID_CELL_LEFT_CLICK
) 
 108 DEFINE_EVENT_TYPE(wxEVT_GRID_CELL_RIGHT_CLICK
) 
 109 DEFINE_EVENT_TYPE(wxEVT_GRID_CELL_LEFT_DCLICK
) 
 110 DEFINE_EVENT_TYPE(wxEVT_GRID_CELL_RIGHT_DCLICK
) 
 111 DEFINE_EVENT_TYPE(wxEVT_GRID_LABEL_LEFT_CLICK
) 
 112 DEFINE_EVENT_TYPE(wxEVT_GRID_LABEL_RIGHT_CLICK
) 
 113 DEFINE_EVENT_TYPE(wxEVT_GRID_LABEL_LEFT_DCLICK
) 
 114 DEFINE_EVENT_TYPE(wxEVT_GRID_LABEL_RIGHT_DCLICK
) 
 115 DEFINE_EVENT_TYPE(wxEVT_GRID_ROW_SIZE
) 
 116 DEFINE_EVENT_TYPE(wxEVT_GRID_COL_SIZE
) 
 117 DEFINE_EVENT_TYPE(wxEVT_GRID_RANGE_SELECT
) 
 118 DEFINE_EVENT_TYPE(wxEVT_GRID_CELL_CHANGE
) 
 119 DEFINE_EVENT_TYPE(wxEVT_GRID_SELECT_CELL
) 
 120 DEFINE_EVENT_TYPE(wxEVT_GRID_EDITOR_SHOWN
) 
 121 DEFINE_EVENT_TYPE(wxEVT_GRID_EDITOR_HIDDEN
) 
 122 DEFINE_EVENT_TYPE(wxEVT_GRID_EDITOR_CREATED
) 
 124 // ---------------------------------------------------------------------------- 
 126 // ---------------------------------------------------------------------------- 
 128 class WXDLLIMPEXP_ADV wxGridRowLabelWindow 
: public wxWindow
 
 131     wxGridRowLabelWindow() { m_owner 
= (wxGrid 
*)NULL
; } 
 132     wxGridRowLabelWindow( wxGrid 
*parent
, wxWindowID id
, 
 133                           const wxPoint 
&pos
, const wxSize 
&size 
); 
 138     void OnPaint( wxPaintEvent
& event 
); 
 139     void OnMouseEvent( wxMouseEvent
& event 
); 
 140     void OnMouseWheel( wxMouseEvent
& event 
); 
 141     void OnKeyDown( wxKeyEvent
& event 
); 
 142     void OnKeyUp( wxKeyEvent
& ); 
 144     DECLARE_DYNAMIC_CLASS(wxGridRowLabelWindow
) 
 145     DECLARE_EVENT_TABLE() 
 146     DECLARE_NO_COPY_CLASS(wxGridRowLabelWindow
) 
 150 class WXDLLIMPEXP_ADV wxGridColLabelWindow 
: public wxWindow
 
 153     wxGridColLabelWindow() { m_owner 
= (wxGrid 
*)NULL
; } 
 154     wxGridColLabelWindow( wxGrid 
*parent
, wxWindowID id
, 
 155                           const wxPoint 
&pos
, const wxSize 
&size 
); 
 160     void OnPaint( wxPaintEvent 
&event 
); 
 161     void OnMouseEvent( wxMouseEvent
& event 
); 
 162     void OnMouseWheel( wxMouseEvent
& event 
); 
 163     void OnKeyDown( wxKeyEvent
& event 
); 
 164     void OnKeyUp( wxKeyEvent
& ); 
 166     DECLARE_DYNAMIC_CLASS(wxGridColLabelWindow
) 
 167     DECLARE_EVENT_TABLE() 
 168     DECLARE_NO_COPY_CLASS(wxGridColLabelWindow
) 
 172 class WXDLLIMPEXP_ADV wxGridCornerLabelWindow 
: public wxWindow
 
 175     wxGridCornerLabelWindow() { m_owner 
= (wxGrid 
*)NULL
; } 
 176     wxGridCornerLabelWindow( wxGrid 
*parent
, wxWindowID id
, 
 177                              const wxPoint 
&pos
, const wxSize 
&size 
); 
 182     void OnMouseEvent( wxMouseEvent
& event 
); 
 183     void OnMouseWheel( wxMouseEvent
& event 
); 
 184     void OnKeyDown( wxKeyEvent
& event 
); 
 185     void OnKeyUp( wxKeyEvent
& ); 
 186     void OnPaint( wxPaintEvent
& event 
); 
 188     DECLARE_DYNAMIC_CLASS(wxGridCornerLabelWindow
) 
 189     DECLARE_EVENT_TABLE() 
 190     DECLARE_NO_COPY_CLASS(wxGridCornerLabelWindow
) 
 193 class WXDLLIMPEXP_ADV wxGridWindow 
: public wxWindow
 
 198         m_owner 
= (wxGrid 
*)NULL
; 
 199         m_rowLabelWin 
= (wxGridRowLabelWindow 
*)NULL
; 
 200         m_colLabelWin 
= (wxGridColLabelWindow 
*)NULL
; 
 203     wxGridWindow( wxGrid 
*parent
, 
 204                   wxGridRowLabelWindow 
*rowLblWin
, 
 205                   wxGridColLabelWindow 
*colLblWin
, 
 206                   wxWindowID id
, const wxPoint 
&pos
, const wxSize 
&size 
); 
 209     void ScrollWindow( int dx
, int dy
, const wxRect 
*rect 
); 
 211     wxGrid
* GetOwner() { return m_owner
; } 
 215     wxGridRowLabelWindow     
*m_rowLabelWin
; 
 216     wxGridColLabelWindow     
*m_colLabelWin
; 
 218     void OnPaint( wxPaintEvent 
&event 
); 
 219     void OnMouseWheel( wxMouseEvent
& event 
); 
 220     void OnMouseEvent( wxMouseEvent
& event 
); 
 221     void OnKeyDown( wxKeyEvent
& ); 
 222     void OnKeyUp( wxKeyEvent
& ); 
 223     void OnEraseBackground( wxEraseEvent
& ); 
 226     DECLARE_DYNAMIC_CLASS(wxGridWindow
) 
 227     DECLARE_EVENT_TABLE() 
 228     DECLARE_NO_COPY_CLASS(wxGridWindow
) 
 233 class wxGridCellEditorEvtHandler 
: public wxEvtHandler
 
 236     wxGridCellEditorEvtHandler() 
 237         : m_grid(0), m_editor(0) 
 239     wxGridCellEditorEvtHandler(wxGrid
* grid
, wxGridCellEditor
* editor
) 
 240         : m_grid(grid
), m_editor(editor
) 
 243     void OnKeyDown(wxKeyEvent
& event
); 
 244     void OnChar(wxKeyEvent
& event
); 
 248     wxGridCellEditor
*   m_editor
; 
 249     DECLARE_DYNAMIC_CLASS(wxGridCellEditorEvtHandler
) 
 250     DECLARE_EVENT_TABLE() 
 251     DECLARE_NO_COPY_CLASS(wxGridCellEditorEvtHandler
) 
 255 IMPLEMENT_DYNAMIC_CLASS( wxGridCellEditorEvtHandler
, wxEvtHandler 
) 
 256 BEGIN_EVENT_TABLE( wxGridCellEditorEvtHandler
, wxEvtHandler 
) 
 257     EVT_KEY_DOWN( wxGridCellEditorEvtHandler::OnKeyDown 
) 
 258     EVT_CHAR( wxGridCellEditorEvtHandler::OnChar 
) 
 263 // ---------------------------------------------------------------------------- 
 264 // the internal data representation used by wxGridCellAttrProvider 
 265 // ---------------------------------------------------------------------------- 
 267 // this class stores attributes set for cells 
 268 class WXDLLIMPEXP_ADV wxGridCellAttrData
 
 271     void SetAttr(wxGridCellAttr 
*attr
, int row
, int col
); 
 272     wxGridCellAttr 
*GetAttr(int row
, int col
) const; 
 273     void UpdateAttrRows( size_t pos
, int numRows 
); 
 274     void UpdateAttrCols( size_t pos
, int numCols 
); 
 277     // searches for the attr for given cell, returns wxNOT_FOUND if not found 
 278     int FindIndex(int row
, int col
) const; 
 280     wxGridCellWithAttrArray m_attrs
; 
 283 // this class stores attributes set for rows or columns 
 284 class WXDLLIMPEXP_ADV wxGridRowOrColAttrData
 
 287     // empty ctor to suppress warnings 
 288     wxGridRowOrColAttrData() { } 
 289     ~wxGridRowOrColAttrData(); 
 291     void SetAttr(wxGridCellAttr 
*attr
, int rowOrCol
); 
 292     wxGridCellAttr 
*GetAttr(int rowOrCol
) const; 
 293     void UpdateAttrRowsOrCols( size_t pos
, int numRowsOrCols 
); 
 296     wxArrayInt m_rowsOrCols
; 
 297     wxArrayAttrs m_attrs
; 
 300 // NB: this is just a wrapper around 3 objects: one which stores cell 
 301 //     attributes, and 2 others for row/col ones 
 302 class WXDLLIMPEXP_ADV wxGridCellAttrProviderData
 
 305     wxGridCellAttrData m_cellAttrs
; 
 306     wxGridRowOrColAttrData m_rowAttrs
, 
 311 // ---------------------------------------------------------------------------- 
 312 // data structures used for the data type registry 
 313 // ---------------------------------------------------------------------------- 
 315 struct wxGridDataTypeInfo
 
 317     wxGridDataTypeInfo(const wxString
& typeName
, 
 318                        wxGridCellRenderer
* renderer
, 
 319                        wxGridCellEditor
* editor
) 
 320         : m_typeName(typeName
), m_renderer(renderer
), m_editor(editor
) 
 323     ~wxGridDataTypeInfo() 
 325         wxSafeDecRef(m_renderer
); 
 326         wxSafeDecRef(m_editor
); 
 330     wxGridCellRenderer
* m_renderer
; 
 331     wxGridCellEditor
*   m_editor
; 
 333     DECLARE_NO_COPY_CLASS(wxGridDataTypeInfo
) 
 337 WX_DEFINE_ARRAY_WITH_DECL_NO_PTR(wxGridDataTypeInfo
*, wxGridDataTypeInfoArray
, 
 338                                  class WXDLLIMPEXP_ADV
); 
 341 class WXDLLIMPEXP_ADV wxGridTypeRegistry
 
 344   wxGridTypeRegistry() {} 
 345     ~wxGridTypeRegistry(); 
 347     void RegisterDataType(const wxString
& typeName
, 
 348                      wxGridCellRenderer
* renderer
, 
 349                      wxGridCellEditor
* editor
); 
 351     // find one of already registered data types 
 352     int FindRegisteredDataType(const wxString
& typeName
); 
 354     // try to FindRegisteredDataType(), if this fails and typeName is one of 
 355     // standard typenames, register it and return its index 
 356     int FindDataType(const wxString
& typeName
); 
 358     // try to FindDataType(), if it fails see if it is not one of already 
 359     // registered data types with some params in which case clone the 
 360     // registered data type and set params for it 
 361     int FindOrCloneDataType(const wxString
& typeName
); 
 363     wxGridCellRenderer
* GetRenderer(int index
); 
 364     wxGridCellEditor
*   GetEditor(int index
); 
 367     wxGridDataTypeInfoArray m_typeinfo
; 
 370 // ---------------------------------------------------------------------------- 
 371 // conditional compilation 
 372 // ---------------------------------------------------------------------------- 
 374 #ifndef WXGRID_DRAW_LINES 
 375 #define WXGRID_DRAW_LINES 1 
 378 // ---------------------------------------------------------------------------- 
 380 // ---------------------------------------------------------------------------- 
 382 //#define DEBUG_ATTR_CACHE 
 383 #ifdef DEBUG_ATTR_CACHE 
 384     static size_t gs_nAttrCacheHits 
= 0; 
 385     static size_t gs_nAttrCacheMisses 
= 0; 
 386 #endif // DEBUG_ATTR_CACHE 
 388 // ---------------------------------------------------------------------------- 
 390 // ---------------------------------------------------------------------------- 
 392 wxGridCellCoords 
wxGridNoCellCoords( -1, -1 ); 
 393 wxRect           
wxGridNoCellRect( -1, -1, -1, -1 ); 
 396 // TODO: this doesn't work at all, grid cells have different sizes and approx 
 397 //       calculations don't work as because of the size mismatch scrollbars 
 398 //       sometimes fail to be shown when they should be or vice versa 
 400 //       The scroll bars may be a little flakey once in a while, but that is 
 401 //       surely much less horrible than having scroll lines of only 1!!! 
 404 //       Well, it's still seriously broken so it might be better but needs 
 407 static const size_t GRID_SCROLL_LINE_X 
= 15;  // 1; 
 408 static const size_t GRID_SCROLL_LINE_Y 
= GRID_SCROLL_LINE_X
; 
 410 // the size of hash tables used a bit everywhere (the max number of elements 
 411 // in these hash tables is the number of rows/columns) 
 412 static const int GRID_HASH_SIZE 
= 100; 
 414 // ---------------------------------------------------------------------------- 
 416 // ---------------------------------------------------------------------------- 
 418 static inline int GetScrollX(int x
) 
 420     return (x 
+ GRID_SCROLL_LINE_X 
- 1) / GRID_SCROLL_LINE_X
; 
 423 static inline int GetScrollY(int y
) 
 425     return (y 
+ GRID_SCROLL_LINE_Y 
- 1) / GRID_SCROLL_LINE_Y
; 
 428 // ============================================================================ 
 430 // ============================================================================ 
 432 // ---------------------------------------------------------------------------- 
 434 // ---------------------------------------------------------------------------- 
 436 wxGridCellEditor::wxGridCellEditor() 
 443 wxGridCellEditor::~wxGridCellEditor() 
 448 void wxGridCellEditor::Create(wxWindow
* WXUNUSED(parent
), 
 449                               wxWindowID 
WXUNUSED(id
), 
 450                               wxEvtHandler
* evtHandler
) 
 453         m_control
->PushEventHandler(evtHandler
); 
 456 void wxGridCellEditor::PaintBackground(const wxRect
& rectCell
, 
 457                                        wxGridCellAttr 
*attr
) 
 459     // erase the background because we might not fill the cell 
 460     wxClientDC 
dc(m_control
->GetParent()); 
 461     wxGridWindow
* gridWindow 
= wxDynamicCast(m_control
->GetParent(), wxGridWindow
); 
 463         gridWindow
->GetOwner()->PrepareDC(dc
); 
 465     dc
.SetPen(*wxTRANSPARENT_PEN
); 
 466     dc
.SetBrush(wxBrush(attr
->GetBackgroundColour(), wxSOLID
)); 
 467     dc
.DrawRectangle(rectCell
); 
 469     // redraw the control we just painted over 
 470     m_control
->Refresh(); 
 473 void wxGridCellEditor::Destroy() 
 477         m_control
->PopEventHandler(TRUE 
/* delete it*/); 
 479         m_control
->Destroy(); 
 484 void wxGridCellEditor::Show(bool show
, wxGridCellAttr 
*attr
) 
 486     wxASSERT_MSG(m_control
, 
 487                  wxT("The wxGridCellEditor must be Created first!")); 
 488     m_control
->Show(show
); 
 492         // set the colours/fonts if we have any 
 495             m_colFgOld 
= m_control
->GetForegroundColour(); 
 496             m_control
->SetForegroundColour(attr
->GetTextColour()); 
 498             m_colBgOld 
= m_control
->GetBackgroundColour(); 
 499             m_control
->SetBackgroundColour(attr
->GetBackgroundColour()); 
 501             m_fontOld 
= m_control
->GetFont(); 
 502             m_control
->SetFont(attr
->GetFont()); 
 504             // can't do anything more in the base class version, the other 
 505             // attributes may only be used by the derived classes 
 510         // restore the standard colours fonts 
 511         if ( m_colFgOld
.Ok() ) 
 513             m_control
->SetForegroundColour(m_colFgOld
); 
 514             m_colFgOld 
= wxNullColour
; 
 517         if ( m_colBgOld
.Ok() ) 
 519             m_control
->SetBackgroundColour(m_colBgOld
); 
 520             m_colBgOld 
= wxNullColour
; 
 523         if ( m_fontOld
.Ok() ) 
 525             m_control
->SetFont(m_fontOld
); 
 526             m_fontOld 
= wxNullFont
; 
 531 void wxGridCellEditor::SetSize(const wxRect
& rect
) 
 533     wxASSERT_MSG(m_control
, 
 534                  wxT("The wxGridCellEditor must be Created first!")); 
 535     m_control
->SetSize(rect
, wxSIZE_ALLOW_MINUS_ONE
); 
 538 void wxGridCellEditor::HandleReturn(wxKeyEvent
& event
) 
 543 bool wxGridCellEditor::IsAcceptedKey(wxKeyEvent
& event
) 
 545     // accept the simple key presses, not anything with Ctrl/Alt/Meta 
 546     return !(event
.ControlDown() || event
.AltDown()); 
 549 void wxGridCellEditor::StartingKey(wxKeyEvent
& event
) 
 554 void wxGridCellEditor::StartingClick() 
 560 // ---------------------------------------------------------------------------- 
 561 // wxGridCellTextEditor 
 562 // ---------------------------------------------------------------------------- 
 564 wxGridCellTextEditor::wxGridCellTextEditor() 
 569 void wxGridCellTextEditor::Create(wxWindow
* parent
, 
 571                                   wxEvtHandler
* evtHandler
) 
 573     m_control 
= new wxTextCtrl(parent
, id
, wxEmptyString
, 
 574                                wxDefaultPosition
, wxDefaultSize
 
 575 #if defined(__WXMSW__) 
 576                                , wxTE_PROCESS_TAB 
| wxTE_MULTILINE 
| 
 577                                  wxTE_NO_VSCROLL 
| wxTE_AUTO_SCROLL
 
 581     // set max length allowed in the textctrl, if the parameter was set 
 584         ((wxTextCtrl
*)m_control
)->SetMaxLength(m_maxChars
); 
 587     wxGridCellEditor::Create(parent
, id
, evtHandler
); 
 590 void wxGridCellTextEditor::PaintBackground(const wxRect
& WXUNUSED(rectCell
), 
 591                                            wxGridCellAttr 
* WXUNUSED(attr
)) 
 593     // as we fill the entire client area, don't do anything here to minimize 
 597 void wxGridCellTextEditor::SetSize(const wxRect
& rectOrig
) 
 599     wxRect 
rect(rectOrig
); 
 601     // Make the edit control large enough to allow for internal 
 604     // TODO: remove this if the text ctrl sizing is improved esp. for 
 607 #if defined(__WXGTK__) 
 616     int extra_x 
= ( rect
.x 
> 2 )? 2 : 1; 
 618 // MB: treat MSW separately here otherwise the caret doesn't show 
 619 // when the editor is in the first row. 
 620 #if defined(__WXMSW__) 
 623     int extra_y 
= ( rect
.y 
> 2 )? 2 : 1; 
 626 #if defined(__WXMOTIF__) 
 630     rect
.SetLeft( wxMax(0, rect
.x 
- extra_x
) ); 
 631     rect
.SetTop( wxMax(0, rect
.y 
- extra_y
) ); 
 632     rect
.SetRight( rect
.GetRight() + 2*extra_x 
); 
 633     rect
.SetBottom( rect
.GetBottom() + 2*extra_y 
); 
 636     wxGridCellEditor::SetSize(rect
); 
 639 void wxGridCellTextEditor::BeginEdit(int row
, int col
, wxGrid
* grid
) 
 641     wxASSERT_MSG(m_control
, 
 642                  wxT("The wxGridCellEditor must be Created first!")); 
 644     m_startValue 
= grid
->GetTable()->GetValue(row
, col
); 
 646     DoBeginEdit(m_startValue
); 
 649 void wxGridCellTextEditor::DoBeginEdit(const wxString
& startValue
) 
 651     Text()->SetValue(startValue
); 
 652     Text()->SetInsertionPointEnd(); 
 653     Text()->SetSelection(-1,-1); 
 657 bool wxGridCellTextEditor::EndEdit(int row
, int col
, 
 660     wxASSERT_MSG(m_control
, 
 661                  wxT("The wxGridCellEditor must be Created first!")); 
 663     bool changed 
= FALSE
; 
 664     wxString value 
= Text()->GetValue(); 
 665     if (value 
!= m_startValue
) 
 669         grid
->GetTable()->SetValue(row
, col
, value
); 
 671     m_startValue 
= wxEmptyString
; 
 672     Text()->SetValue(m_startValue
); 
 678 void wxGridCellTextEditor::Reset() 
 680     wxASSERT_MSG(m_control
, 
 681                  wxT("The wxGridCellEditor must be Created first!")); 
 683     DoReset(m_startValue
); 
 686 void wxGridCellTextEditor::DoReset(const wxString
& startValue
) 
 688     Text()->SetValue(startValue
); 
 689     Text()->SetInsertionPointEnd(); 
 692 bool wxGridCellTextEditor::IsAcceptedKey(wxKeyEvent
& event
) 
 694     if ( wxGridCellEditor::IsAcceptedKey(event
) ) 
 696         int keycode 
= event
.GetKeyCode(); 
 710             case WXK_NUMPAD_MULTIPLY
: 
 714             case WXK_NUMPAD_SUBTRACT
: 
 716             case WXK_NUMPAD_DECIMAL
: 
 718             case WXK_NUMPAD_DIVIDE
: 
 722                 // accept 8 bit chars too if isprint() agrees 
 723                 if ( (keycode 
< 255) && (wxIsprint(keycode
)) ) 
 731 void wxGridCellTextEditor::StartingKey(wxKeyEvent
& event
) 
 733     if ( !Text()->EmulateKeyPress(event
) ) 
 739 void wxGridCellTextEditor::HandleReturn( wxKeyEvent
& 
 740                                          WXUNUSED_GTK(WXUNUSED_MOTIF(event
)) ) 
 742 #if defined(__WXMOTIF__) || defined(__WXGTK__) 
 743     // wxMotif needs a little extra help... 
 744     size_t pos 
= (size_t)( Text()->GetInsertionPoint() ); 
 745     wxString 
s( Text()->GetValue() ); 
 746     s 
= s
.Left(pos
) + wxT("\n") + s
.Mid(pos
); 
 748     Text()->SetInsertionPoint( pos 
); 
 750     // the other ports can handle a Return key press 
 756 void wxGridCellTextEditor::SetParameters(const wxString
& params
) 
 766         if ( !params
.ToLong(&tmp
) ) 
 768             wxLogDebug(_T("Invalid wxGridCellTextEditor parameter string '%s' ignored"), params
.c_str()); 
 772             m_maxChars 
= (size_t)tmp
; 
 777 // return the value in the text control 
 778 wxString 
wxGridCellTextEditor::GetValue() const 
 780   return Text()->GetValue(); 
 783 // ---------------------------------------------------------------------------- 
 784 // wxGridCellNumberEditor 
 785 // ---------------------------------------------------------------------------- 
 787 wxGridCellNumberEditor::wxGridCellNumberEditor(int min
, int max
) 
 793 void wxGridCellNumberEditor::Create(wxWindow
* parent
, 
 795                                     wxEvtHandler
* evtHandler
) 
 799         // create a spin ctrl 
 800         m_control 
= new wxSpinCtrl(parent
, -1, wxEmptyString
, 
 801                                    wxDefaultPosition
, wxDefaultSize
, 
 805         wxGridCellEditor::Create(parent
, id
, evtHandler
); 
 809         // just a text control 
 810         wxGridCellTextEditor::Create(parent
, id
, evtHandler
); 
 813         Text()->SetValidator(wxTextValidator(wxFILTER_NUMERIC
)); 
 814 #endif // wxUSE_VALIDATORS 
 818 void wxGridCellNumberEditor::BeginEdit(int row
, int col
, wxGrid
* grid
) 
 820     // first get the value 
 821     wxGridTableBase 
*table 
= grid
->GetTable(); 
 822     if ( table
->CanGetValueAs(row
, col
, wxGRID_VALUE_NUMBER
) ) 
 824         m_valueOld 
= table
->GetValueAsLong(row
, col
); 
 829         wxString sValue 
= table
->GetValue(row
, col
); 
 830         if (! sValue
.ToLong(&m_valueOld
) && ! sValue
.IsEmpty()) 
 832             wxFAIL_MSG( _T("this cell doesn't have numeric value") ); 
 839         Spin()->SetValue((int)m_valueOld
); 
 844         DoBeginEdit(GetString()); 
 848 bool wxGridCellNumberEditor::EndEdit(int row
, int col
, 
 857         value 
= Spin()->GetValue(); 
 858         changed 
= value 
!= m_valueOld
; 
 860             text 
= wxString::Format(wxT("%ld"), value
); 
 864         text 
= Text()->GetValue(); 
 865         changed 
= (text
.IsEmpty() || text
.ToLong(&value
)) && (value 
!= m_valueOld
); 
 870         if (grid
->GetTable()->CanSetValueAs(row
, col
, wxGRID_VALUE_NUMBER
)) 
 871             grid
->GetTable()->SetValueAsLong(row
, col
, value
); 
 873             grid
->GetTable()->SetValue(row
, col
, text
); 
 879 void wxGridCellNumberEditor::Reset() 
 883         Spin()->SetValue((int)m_valueOld
); 
 887         DoReset(GetString()); 
 891 bool wxGridCellNumberEditor::IsAcceptedKey(wxKeyEvent
& event
) 
 893     if ( wxGridCellEditor::IsAcceptedKey(event
) ) 
 895         int keycode 
= event
.GetKeyCode(); 
 911             case WXK_NUMPAD_SUBTRACT
: 
 917                 if ( (keycode 
< 128) && wxIsdigit(keycode
) ) 
 925 void wxGridCellNumberEditor::StartingKey(wxKeyEvent
& event
) 
 929         int keycode 
= event
.GetKeyCode(); 
 930         if ( wxIsdigit(keycode
) || keycode 
== '+' || keycode 
== '-' 
 931             || keycode 
==  WXK_NUMPAD0
 
 932             || keycode 
==  WXK_NUMPAD1
 
 933             || keycode 
==  WXK_NUMPAD2
 
 934             || keycode 
==  WXK_NUMPAD3
 
 935             || keycode 
==  WXK_NUMPAD4
 
 936             || keycode 
==  WXK_NUMPAD5
 
 937             || keycode 
==  WXK_NUMPAD6
 
 938             || keycode 
==  WXK_NUMPAD7
 
 939             || keycode 
==  WXK_NUMPAD8
 
 940             || keycode 
==  WXK_NUMPAD9
 
 941             || keycode 
==  WXK_ADD
 
 942             || keycode 
==  WXK_NUMPAD_ADD
 
 943             || keycode 
==  WXK_SUBTRACT
 
 944             || keycode 
==  WXK_NUMPAD_SUBTRACT
) 
 946             wxGridCellTextEditor::StartingKey(event
); 
 956 void wxGridCellNumberEditor::SetParameters(const wxString
& params
) 
 967         if ( params
.BeforeFirst(_T(',')).ToLong(&tmp
) ) 
 971             if ( params
.AfterFirst(_T(',')).ToLong(&tmp
) ) 
 975                 // skip the error message below 
 980         wxLogDebug(_T("Invalid wxGridCellNumberEditor parameter string '%s' ignored"), params
.c_str()); 
 984 // return the value in the spin control if it is there (the text control otherwise) 
 985 wxString 
wxGridCellNumberEditor::GetValue() const 
 991     long value 
= Spin()->GetValue(); 
 992     s
.Printf(wxT("%ld"), value
); 
 996     s 
= Text()->GetValue(); 
1001 // ---------------------------------------------------------------------------- 
1002 // wxGridCellFloatEditor 
1003 // ---------------------------------------------------------------------------- 
1005 wxGridCellFloatEditor::wxGridCellFloatEditor(int width
, int precision
) 
1008     m_precision 
= precision
; 
1011 void wxGridCellFloatEditor::Create(wxWindow
* parent
, 
1013                                    wxEvtHandler
* evtHandler
) 
1015     wxGridCellTextEditor::Create(parent
, id
, evtHandler
); 
1017 #if wxUSE_VALIDATORS 
1018     Text()->SetValidator(wxTextValidator(wxFILTER_NUMERIC
)); 
1019 #endif // wxUSE_VALIDATORS 
1022 void wxGridCellFloatEditor::BeginEdit(int row
, int col
, wxGrid
* grid
) 
1024     // first get the value 
1025     wxGridTableBase 
*table 
= grid
->GetTable(); 
1026     if ( table
->CanGetValueAs(row
, col
, wxGRID_VALUE_FLOAT
) ) 
1028         m_valueOld 
= table
->GetValueAsDouble(row
, col
); 
1033         wxString sValue 
= table
->GetValue(row
, col
); 
1034         if (! sValue
.ToDouble(&m_valueOld
) && ! sValue
.IsEmpty()) 
1036             wxFAIL_MSG( _T("this cell doesn't have float value") ); 
1041     DoBeginEdit(GetString()); 
1044 bool wxGridCellFloatEditor::EndEdit(int row
, int col
, 
1048     wxString 
text(Text()->GetValue()); 
1050     if ( (text
.IsEmpty() || text
.ToDouble(&value
)) && (value 
!= m_valueOld
) ) 
1052         if (grid
->GetTable()->CanSetValueAs(row
, col
, wxGRID_VALUE_FLOAT
)) 
1053             grid
->GetTable()->SetValueAsDouble(row
, col
, value
); 
1055             grid
->GetTable()->SetValue(row
, col
, text
); 
1062 void wxGridCellFloatEditor::Reset() 
1064     DoReset(GetString()); 
1067 void wxGridCellFloatEditor::StartingKey(wxKeyEvent
& event
) 
1069     int keycode 
= event
.GetKeyCode(); 
1070         if ( wxIsdigit(keycode
) || keycode 
== '+' || keycode 
== '-' || keycode 
== '.' 
1071             || keycode 
==  WXK_NUMPAD0
 
1072             || keycode 
==  WXK_NUMPAD1
 
1073             || keycode 
==  WXK_NUMPAD2
 
1074             || keycode 
==  WXK_NUMPAD3
 
1075             || keycode 
==  WXK_NUMPAD4
 
1076             || keycode 
==  WXK_NUMPAD5
 
1077             || keycode 
==  WXK_NUMPAD6
 
1078             || keycode 
==  WXK_NUMPAD7
 
1079             || keycode 
==  WXK_NUMPAD8
 
1080             || keycode 
==  WXK_NUMPAD9
 
1081             || keycode 
==  WXK_ADD
 
1082             || keycode 
==  WXK_NUMPAD_ADD
 
1083             || keycode 
==  WXK_SUBTRACT
 
1084             || keycode 
==  WXK_NUMPAD_SUBTRACT
) 
1086         wxGridCellTextEditor::StartingKey(event
); 
1088         // skip Skip() below 
1095 void wxGridCellFloatEditor::SetParameters(const wxString
& params
) 
1106         if ( params
.BeforeFirst(_T(',')).ToLong(&tmp
) ) 
1110             if ( params
.AfterFirst(_T(',')).ToLong(&tmp
) ) 
1112                 m_precision 
= (int)tmp
; 
1114                 // skip the error message below 
1119         wxLogDebug(_T("Invalid wxGridCellFloatEditor parameter string '%s' ignored"), params
.c_str()); 
1123 wxString 
wxGridCellFloatEditor::GetString() const 
1126     if ( m_width 
== -1 ) 
1128         // default width/precision 
1131     else if ( m_precision 
== -1 ) 
1133         // default precision 
1134         fmt
.Printf(_T("%%%d.f"), m_width
); 
1138         fmt
.Printf(_T("%%%d.%df"), m_width
, m_precision
); 
1141     return wxString::Format(fmt
, m_valueOld
); 
1144 bool wxGridCellFloatEditor::IsAcceptedKey(wxKeyEvent
& event
) 
1146     if ( wxGridCellEditor::IsAcceptedKey(event
) ) 
1148         int keycode 
= event
.GetKeyCode(); 
1162             case WXK_NUMPAD_ADD
: 
1164             case WXK_NUMPAD_SUBTRACT
: 
1166             case WXK_NUMPAD_DECIMAL
: 
1170                 // additionally accept 'e' as in '1e+6' 
1171                 if ( (keycode 
< 128) && 
1172                      (wxIsdigit(keycode
) || tolower(keycode
) == 'e') ) 
1180 #endif // wxUSE_TEXTCTRL 
1184 // ---------------------------------------------------------------------------- 
1185 // wxGridCellBoolEditor 
1186 // ---------------------------------------------------------------------------- 
1188 void wxGridCellBoolEditor::Create(wxWindow
* parent
, 
1190                                   wxEvtHandler
* evtHandler
) 
1192     m_control 
= new wxCheckBox(parent
, id
, wxEmptyString
, 
1193                                wxDefaultPosition
, wxDefaultSize
, 
1196     wxGridCellEditor::Create(parent
, id
, evtHandler
); 
1199 void wxGridCellBoolEditor::SetSize(const wxRect
& r
) 
1201     bool resize 
= FALSE
; 
1202     wxSize size 
= m_control
->GetSize(); 
1203     wxCoord minSize 
= wxMin(r
.width
, r
.height
); 
1205     // check if the checkbox is not too big/small for this cell 
1206     wxSize sizeBest 
= m_control
->GetBestSize(); 
1207     if ( !(size 
== sizeBest
) ) 
1209         // reset to default size if it had been made smaller 
1215     if ( size
.x 
>= minSize 
|| size
.y 
>= minSize 
) 
1217         // leave 1 pixel margin 
1218         size
.x 
= size
.y 
= minSize 
- 2; 
1225         m_control
->SetSize(size
); 
1228     // position it in the centre of the rectangle (TODO: support alignment?) 
1230 #if defined(__WXGTK__) || defined (__WXMOTIF__) 
1231     // the checkbox without label still has some space to the right in wxGTK, 
1232     // so shift it to the right 
1234 #elif defined(__WXMSW__) 
1235     // here too, but in other way 
1240     int hAlign 
= wxALIGN_CENTRE
; 
1241     int vAlign 
= wxALIGN_CENTRE
; 
1243         GetCellAttr()->GetAlignment(& hAlign
, & vAlign
); 
1246     if (hAlign 
== wxALIGN_LEFT
) 
1252         y 
= r
.y 
+ r
.height
/2 - size
.y
/2; 
1254     else if (hAlign 
== wxALIGN_RIGHT
) 
1256         x 
= r
.x 
+ r
.width 
- size
.x 
- 2; 
1257         y 
= r
.y 
+ r
.height
/2 - size
.y
/2; 
1259     else if (hAlign 
== wxALIGN_CENTRE
) 
1261         x 
= r
.x 
+ r
.width
/2 - size
.x
/2; 
1262         y 
= r
.y 
+ r
.height
/2 - size
.y
/2; 
1265     m_control
->Move(x
, y
); 
1268 void wxGridCellBoolEditor::Show(bool show
, wxGridCellAttr 
*attr
) 
1270     m_control
->Show(show
); 
1274         wxColour colBg 
= attr 
? attr
->GetBackgroundColour() : *wxLIGHT_GREY
; 
1275         CBox()->SetBackgroundColour(colBg
); 
1279 void wxGridCellBoolEditor::BeginEdit(int row
, int col
, wxGrid
* grid
) 
1281     wxASSERT_MSG(m_control
, 
1282                  wxT("The wxGridCellEditor must be Created first!")); 
1284     if (grid
->GetTable()->CanGetValueAs(row
, col
, wxGRID_VALUE_BOOL
)) 
1285         m_startValue 
= grid
->GetTable()->GetValueAsBool(row
, col
); 
1288         wxString 
cellval( grid
->GetTable()->GetValue(row
, col
) ); 
1289         m_startValue 
= !( !cellval 
|| (cellval 
== wxT("0")) ); 
1291     CBox()->SetValue(m_startValue
); 
1295 bool wxGridCellBoolEditor::EndEdit(int row
, int col
, 
1298     wxASSERT_MSG(m_control
, 
1299                  wxT("The wxGridCellEditor must be Created first!")); 
1301     bool changed 
= FALSE
; 
1302     bool value 
= CBox()->GetValue(); 
1303     if ( value 
!= m_startValue 
) 
1308         if (grid
->GetTable()->CanGetValueAs(row
, col
, wxGRID_VALUE_BOOL
)) 
1309             grid
->GetTable()->SetValueAsBool(row
, col
, value
); 
1311             grid
->GetTable()->SetValue(row
, col
, value 
? _T("1") : wxEmptyString
); 
1317 void wxGridCellBoolEditor::Reset() 
1319     wxASSERT_MSG(m_control
, 
1320                  wxT("The wxGridCellEditor must be Created first!")); 
1322     CBox()->SetValue(m_startValue
); 
1325 void wxGridCellBoolEditor::StartingClick() 
1327     CBox()->SetValue(!CBox()->GetValue()); 
1330 bool wxGridCellBoolEditor::IsAcceptedKey(wxKeyEvent
& event
) 
1332     if ( wxGridCellEditor::IsAcceptedKey(event
) ) 
1334         int keycode 
= event
.GetKeyCode(); 
1338             case WXK_NUMPAD_MULTIPLY
: 
1340             case WXK_NUMPAD_ADD
: 
1342             case WXK_NUMPAD_SUBTRACT
: 
1353 // return the value as "1" for true and the empty string for false 
1354 wxString 
wxGridCellBoolEditor::GetValue() const 
1356   bool bSet 
= CBox()->GetValue(); 
1357   return bSet 
? _T("1") : wxEmptyString
; 
1360 #endif // wxUSE_CHECKBOX 
1364 // ---------------------------------------------------------------------------- 
1365 // wxGridCellChoiceEditor 
1366 // ---------------------------------------------------------------------------- 
1368 wxGridCellChoiceEditor::wxGridCellChoiceEditor(size_t count
, 
1369                                                const wxString choices
[], 
1371                       : m_allowOthers(allowOthers
) 
1375         m_choices
.Alloc(count
); 
1376         for ( size_t n 
= 0; n 
< count
; n
++ ) 
1378             m_choices
.Add(choices
[n
]); 
1383 wxGridCellEditor 
*wxGridCellChoiceEditor::Clone() const 
1385     wxGridCellChoiceEditor 
*editor 
= new wxGridCellChoiceEditor
; 
1386     editor
->m_allowOthers 
= m_allowOthers
; 
1387     editor
->m_choices 
= m_choices
; 
1392 void wxGridCellChoiceEditor::Create(wxWindow
* parent
, 
1394                                     wxEvtHandler
* evtHandler
) 
1396     size_t count 
= m_choices
.GetCount(); 
1397     wxString 
*choices 
= new wxString
[count
]; 
1398     for ( size_t n 
= 0; n 
< count
; n
++ ) 
1400         choices
[n
] = m_choices
[n
]; 
1403     m_control 
= new wxComboBox(parent
, id
, wxEmptyString
, 
1404                                wxDefaultPosition
, wxDefaultSize
, 
1406                                m_allowOthers 
? 0 : wxCB_READONLY
); 
1410     wxGridCellEditor::Create(parent
, id
, evtHandler
); 
1413 void wxGridCellChoiceEditor::PaintBackground(const wxRect
& rectCell
, 
1414                                              wxGridCellAttr 
* attr
) 
1416     // as we fill the entire client area, don't do anything here to minimize 
1419     // TODO: It doesn't actually fill the client area since the height of a 
1420     // combo always defaults to the standard...  Until someone has time to 
1421     // figure out the right rectangle to paint, just do it the normal way... 
1422     wxGridCellEditor::PaintBackground(rectCell
, attr
); 
1425 void wxGridCellChoiceEditor::BeginEdit(int row
, int col
, wxGrid
* grid
) 
1427     wxASSERT_MSG(m_control
, 
1428                  wxT("The wxGridCellEditor must be Created first!")); 
1430     m_startValue 
= grid
->GetTable()->GetValue(row
, col
); 
1433         Combo()->SetValue(m_startValue
); 
1436         // find the right position, or default to the first if not found 
1437         int pos 
= Combo()->FindString(m_startValue
); 
1440         Combo()->SetSelection(pos
); 
1442     Combo()->SetInsertionPointEnd(); 
1443     Combo()->SetFocus(); 
1446 bool wxGridCellChoiceEditor::EndEdit(int row
, int col
, 
1449     wxString value 
= Combo()->GetValue(); 
1450     bool changed 
= value 
!= m_startValue
; 
1453         grid
->GetTable()->SetValue(row
, col
, value
); 
1455     m_startValue 
= wxEmptyString
; 
1457         Combo()->SetValue(m_startValue
); 
1459         Combo()->SetSelection(0); 
1464 void wxGridCellChoiceEditor::Reset() 
1466     Combo()->SetValue(m_startValue
); 
1467     Combo()->SetInsertionPointEnd(); 
1470 void wxGridCellChoiceEditor::SetParameters(const wxString
& params
) 
1480     wxStringTokenizer 
tk(params
, _T(',')); 
1481     while ( tk
.HasMoreTokens() ) 
1483         m_choices
.Add(tk
.GetNextToken()); 
1487 // return the value in the text control 
1488 wxString 
wxGridCellChoiceEditor::GetValue() const 
1490   return Combo()->GetValue(); 
1493 #endif // wxUSE_COMBOBOX 
1495 // ---------------------------------------------------------------------------- 
1496 // wxGridCellEditorEvtHandler 
1497 // ---------------------------------------------------------------------------- 
1499 void wxGridCellEditorEvtHandler::OnKeyDown(wxKeyEvent
& event
) 
1501     switch ( event
.GetKeyCode() ) 
1505             m_grid
->DisableCellEditControl(); 
1509             m_grid
->GetEventHandler()->ProcessEvent( event 
); 
1513         case WXK_NUMPAD_ENTER
: 
1514             if (!m_grid
->GetEventHandler()->ProcessEvent(event
)) 
1515                 m_editor
->HandleReturn(event
); 
1524 void wxGridCellEditorEvtHandler::OnChar(wxKeyEvent
& event
) 
1526     switch ( event
.GetKeyCode() ) 
1531         case WXK_NUMPAD_ENTER
: 
1539 // ---------------------------------------------------------------------------- 
1540 // wxGridCellWorker is an (almost) empty common base class for 
1541 // wxGridCellRenderer and wxGridCellEditor managing ref counting 
1542 // ---------------------------------------------------------------------------- 
1544 void wxGridCellWorker::SetParameters(const wxString
& WXUNUSED(params
)) 
1549 wxGridCellWorker::~wxGridCellWorker() 
1553 // ============================================================================ 
1555 // ============================================================================ 
1557 // ---------------------------------------------------------------------------- 
1558 // wxGridCellRenderer 
1559 // ---------------------------------------------------------------------------- 
1561 void wxGridCellRenderer::Draw(wxGrid
& grid
, 
1562                               wxGridCellAttr
& attr
, 
1565                               int WXUNUSED(row
), int WXUNUSED(col
), 
1568     dc
.SetBackgroundMode( wxSOLID 
); 
1570     // grey out fields if the grid is disabled 
1571     if( grid
.IsEnabled() ) 
1575           dc
.SetBrush( wxBrush(grid
.GetSelectionBackground(), wxSOLID
) ); 
1579           dc
.SetBrush( wxBrush(attr
.GetBackgroundColour(), wxSOLID
) ); 
1584       dc
.SetBrush(wxBrush(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE
), wxSOLID
)); 
1587     dc
.SetPen( *wxTRANSPARENT_PEN 
); 
1588     dc
.DrawRectangle(rect
); 
1591 // ---------------------------------------------------------------------------- 
1592 // wxGridCellStringRenderer 
1593 // ---------------------------------------------------------------------------- 
1595 void wxGridCellStringRenderer::SetTextColoursAndFont(wxGrid
& grid
, 
1596                                                      wxGridCellAttr
& attr
, 
1600     dc
.SetBackgroundMode( wxTRANSPARENT 
); 
1602     // TODO some special colours for attr.IsReadOnly() case? 
1604     // different coloured text when the grid is disabled 
1605     if( grid
.IsEnabled() ) 
1609           dc
.SetTextBackground( grid
.GetSelectionBackground() ); 
1610           dc
.SetTextForeground( grid
.GetSelectionForeground() ); 
1614           dc
.SetTextBackground( attr
.GetBackgroundColour() ); 
1615           dc
.SetTextForeground( attr
.GetTextColour() ); 
1620       dc
.SetTextBackground(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE
)); 
1621       dc
.SetTextForeground(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_GRAYTEXT
)); 
1624     dc
.SetFont( attr
.GetFont() ); 
1627 wxSize 
wxGridCellStringRenderer::DoGetBestSize(wxGridCellAttr
& attr
, 
1629                                                const wxString
& text
) 
1631     wxCoord x 
= 0, y 
= 0, max_x 
= 0; 
1632     dc
.SetFont(attr
.GetFont()); 
1633     wxStringTokenizer 
tk(text
, _T('\n')); 
1634     while ( tk
.HasMoreTokens() ) 
1636         dc
.GetTextExtent(tk
.GetNextToken(), &x
, &y
); 
1637         max_x 
= wxMax(max_x
, x
); 
1640     y 
*= 1 + text
.Freq(wxT('\n')); // multiply by the number of lines. 
1642     return wxSize(max_x
, y
); 
1645 wxSize 
wxGridCellStringRenderer::GetBestSize(wxGrid
& grid
, 
1646                                              wxGridCellAttr
& attr
, 
1650     return DoGetBestSize(attr
, dc
, grid
.GetCellValue(row
, col
)); 
1653 void wxGridCellStringRenderer::Draw(wxGrid
& grid
, 
1654                                     wxGridCellAttr
& attr
, 
1656                                     const wxRect
& rectCell
, 
1660     wxRect rect 
= rectCell
; 
1663     // erase only this cells background, overflow cells should have been erased 
1664     wxGridCellRenderer::Draw(grid
, attr
, dc
, rectCell
, row
, col
, isSelected
); 
1667     attr
.GetAlignment(&hAlign
, &vAlign
); 
1669     int overflowCols 
= 0; 
1671     if (attr
.GetOverflow()) 
1673         int cols 
= grid
.GetNumberCols(); 
1674         int best_width 
= GetBestSize(grid
,attr
,dc
,row
,col
).GetWidth(); 
1675         int cell_rows
, cell_cols
; 
1676         attr
.GetSize( &cell_rows
, &cell_cols 
); // shouldn't get here if <=0 
1677         if ((best_width 
> rectCell
.width
) && (col 
< cols
) && grid
.GetTable()) 
1679             int i
, c_cols
, c_rows
; 
1680             for (i 
= col
+cell_cols
; i 
< cols
; i
++) 
1682                 bool is_empty 
= TRUE
; 
1683                 for (int j
=row
; j
<row
+cell_rows
; j
++) 
1685                     // check w/ anchor cell for multicell block 
1686                     grid
.GetCellSize(j
, i
, &c_rows
, &c_cols
); 
1687                     if (c_rows 
> 0) c_rows 
= 0; 
1688                     if (!grid
.GetTable()->IsEmptyCell(j
+c_rows
, i
)) 
1695                     rect
.width 
+= grid
.GetColSize(i
); 
1701                 if (rect
.width 
>= best_width
) break; 
1703             overflowCols 
= i 
- col 
- cell_cols 
+ 1; 
1704             if (overflowCols 
>= cols
) overflowCols 
= cols 
- 1; 
1707         if (overflowCols 
> 0) // redraw overflow cells w/ proper hilight 
1709             hAlign 
= wxALIGN_LEFT
; // if oveflowed then it's left aligned 
1711             clip
.x 
+= rectCell
.width
; 
1712             // draw each overflow cell individually 
1713             int col_end 
= col
+cell_cols
+overflowCols
; 
1714             if (col_end 
>= grid
.GetNumberCols()) 
1715                 col_end 
= grid
.GetNumberCols() - 1; 
1716             for (int i 
= col
+cell_cols
; i 
<= col_end
; i
++) 
1718                 clip
.width 
= grid
.GetColSize(i
) - 1; 
1719                 dc
.DestroyClippingRegion(); 
1720                 dc
.SetClippingRegion(clip
); 
1722                 SetTextColoursAndFont(grid
, attr
, dc
, 
1723                         grid
.IsInSelection(row
,i
)); 
1725                 grid
.DrawTextRectangle(dc
, grid
.GetCellValue(row
, col
), 
1726                         rect
, hAlign
, vAlign
); 
1727                 clip
.x 
+= grid
.GetColSize(i
) - 1; 
1733             dc
.DestroyClippingRegion(); 
1737     // now we only have to draw the text 
1738     SetTextColoursAndFont(grid
, attr
, dc
, isSelected
); 
1740     grid
.DrawTextRectangle(dc
, grid
.GetCellValue(row
, col
), 
1741                            rect
, hAlign
, vAlign
); 
1744 // ---------------------------------------------------------------------------- 
1745 // wxGridCellNumberRenderer 
1746 // ---------------------------------------------------------------------------- 
1748 wxString 
wxGridCellNumberRenderer::GetString(wxGrid
& grid
, int row
, int col
) 
1750     wxGridTableBase 
*table 
= grid
.GetTable(); 
1752     if ( table
->CanGetValueAs(row
, col
, wxGRID_VALUE_NUMBER
) ) 
1754         text
.Printf(_T("%ld"), table
->GetValueAsLong(row
, col
)); 
1758         text 
= table
->GetValue(row
, col
); 
1764 void wxGridCellNumberRenderer::Draw(wxGrid
& grid
, 
1765                                     wxGridCellAttr
& attr
, 
1767                                     const wxRect
& rectCell
, 
1771     wxGridCellRenderer::Draw(grid
, attr
, dc
, rectCell
, row
, col
, isSelected
); 
1773     SetTextColoursAndFont(grid
, attr
, dc
, isSelected
); 
1775     // draw the text right aligned by default 
1777     attr
.GetAlignment(&hAlign
, &vAlign
); 
1778     hAlign 
= wxALIGN_RIGHT
; 
1780     wxRect rect 
= rectCell
; 
1783     grid
.DrawTextRectangle(dc
, GetString(grid
, row
, col
), rect
, hAlign
, vAlign
); 
1786 wxSize 
wxGridCellNumberRenderer::GetBestSize(wxGrid
& grid
, 
1787                                              wxGridCellAttr
& attr
, 
1791     return DoGetBestSize(attr
, dc
, GetString(grid
, row
, col
)); 
1794 // ---------------------------------------------------------------------------- 
1795 // wxGridCellFloatRenderer 
1796 // ---------------------------------------------------------------------------- 
1798 wxGridCellFloatRenderer::wxGridCellFloatRenderer(int width
, int precision
) 
1801     SetPrecision(precision
); 
1804 wxGridCellRenderer 
*wxGridCellFloatRenderer::Clone() const 
1806     wxGridCellFloatRenderer 
*renderer 
= new wxGridCellFloatRenderer
; 
1807     renderer
->m_width 
= m_width
; 
1808     renderer
->m_precision 
= m_precision
; 
1809     renderer
->m_format 
= m_format
; 
1814 wxString 
wxGridCellFloatRenderer::GetString(wxGrid
& grid
, int row
, int col
) 
1816     wxGridTableBase 
*table 
= grid
.GetTable(); 
1821     if ( table
->CanGetValueAs(row
, col
, wxGRID_VALUE_FLOAT
) ) 
1823         val 
= table
->GetValueAsDouble(row
, col
); 
1828         text 
= table
->GetValue(row
, col
); 
1829         hasDouble 
= text
.ToDouble(&val
); 
1836             if ( m_width 
== -1 ) 
1838                 if ( m_precision 
== -1 ) 
1840                     // default width/precision 
1841                     m_format 
= _T("%f"); 
1845                     m_format
.Printf(_T("%%.%df"), m_precision
); 
1848             else if ( m_precision 
== -1 ) 
1850                 // default precision 
1851                 m_format
.Printf(_T("%%%d.f"), m_width
); 
1855                 m_format
.Printf(_T("%%%d.%df"), m_width
, m_precision
); 
1859         text
.Printf(m_format
, val
); 
1862     //else: text already contains the string 
1867 void wxGridCellFloatRenderer::Draw(wxGrid
& grid
, 
1868                                    wxGridCellAttr
& attr
, 
1870                                    const wxRect
& rectCell
, 
1874     wxGridCellRenderer::Draw(grid
, attr
, dc
, rectCell
, row
, col
, isSelected
); 
1876     SetTextColoursAndFont(grid
, attr
, dc
, isSelected
); 
1878     // draw the text right aligned by default 
1880     attr
.GetAlignment(&hAlign
, &vAlign
); 
1881     hAlign 
= wxALIGN_RIGHT
; 
1883     wxRect rect 
= rectCell
; 
1886     grid
.DrawTextRectangle(dc
, GetString(grid
, row
, col
), rect
, hAlign
, vAlign
); 
1889 wxSize 
wxGridCellFloatRenderer::GetBestSize(wxGrid
& grid
, 
1890                                             wxGridCellAttr
& attr
, 
1894     return DoGetBestSize(attr
, dc
, GetString(grid
, row
, col
)); 
1897 void wxGridCellFloatRenderer::SetParameters(const wxString
& params
) 
1901         // reset to defaults 
1907         wxString tmp 
= params
.BeforeFirst(_T(',')); 
1911             if ( tmp
.ToLong(&width
) ) 
1913                 SetWidth((int)width
); 
1917                 wxLogDebug(_T("Invalid wxGridCellFloatRenderer width parameter string '%s ignored"), params
.c_str()); 
1921                 tmp 
= params
.AfterFirst(_T(',')); 
1925             if ( tmp
.ToLong(&precision
) ) 
1927                 SetPrecision((int)precision
); 
1931                 wxLogDebug(_T("Invalid wxGridCellFloatRenderer precision parameter string '%s ignored"), params
.c_str()); 
1939 // ---------------------------------------------------------------------------- 
1940 // wxGridCellBoolRenderer 
1941 // ---------------------------------------------------------------------------- 
1943 wxSize 
wxGridCellBoolRenderer::ms_sizeCheckMark
; 
1945 // FIXME these checkbox size calculations are really ugly... 
1947 // between checkmark and box 
1948 static const wxCoord wxGRID_CHECKMARK_MARGIN 
= 2; 
1950 wxSize 
wxGridCellBoolRenderer::GetBestSize(wxGrid
& grid
, 
1951                                            wxGridCellAttr
& WXUNUSED(attr
), 
1956     // compute it only once (no locks for MT safeness in GUI thread...) 
1957     if ( !ms_sizeCheckMark
.x 
) 
1959         // get checkbox size 
1960         wxCoord checkSize 
= 0; 
1961         wxCheckBox 
*checkbox 
= new wxCheckBox(&grid
, -1, wxEmptyString
); 
1962         wxSize size 
= checkbox
->GetBestSize(); 
1963         checkSize 
= size
.y 
+ 2*wxGRID_CHECKMARK_MARGIN
; 
1965         // FIXME wxGTK::wxCheckBox::GetBestSize() gives "wrong" result 
1966 #if defined(__WXGTK__) || defined(__WXMOTIF__) 
1967         checkSize 
-= size
.y 
/ 2; 
1972         ms_sizeCheckMark
.x 
= ms_sizeCheckMark
.y 
= checkSize
; 
1975     return ms_sizeCheckMark
; 
1978 void wxGridCellBoolRenderer::Draw(wxGrid
& grid
, 
1979                                   wxGridCellAttr
& attr
, 
1985     wxGridCellRenderer::Draw(grid
, attr
, dc
, rect
, row
, col
, isSelected
); 
1987     // draw a check mark in the centre (ignoring alignment - TODO) 
1988     wxSize size 
= GetBestSize(grid
, attr
, dc
, row
, col
); 
1990     // don't draw outside the cell 
1991     wxCoord minSize 
= wxMin(rect
.width
, rect
.height
); 
1992     if ( size
.x 
>= minSize 
|| size
.y 
>= minSize 
) 
1994         // and even leave (at least) 1 pixel margin 
1995         size
.x 
= size
.y 
= minSize 
- 2; 
1998     // draw a border around checkmark 
2000     attr
.GetAlignment(& hAlign
, &vAlign
); 
2003     if (hAlign 
== wxALIGN_CENTRE
) 
2005         rectBorder
.x 
= rect
.x 
+ rect
.width
/2 - size
.x
/2; 
2006         rectBorder
.y 
= rect
.y 
+ rect
.height
/2 - size
.y
/2; 
2007         rectBorder
.width 
= size
.x
; 
2008         rectBorder
.height 
= size
.y
; 
2010     else if (hAlign 
== wxALIGN_LEFT
) 
2012         rectBorder
.x 
= rect
.x 
+ 2; 
2013         rectBorder
.y 
= rect
.y 
+ rect
.height
/2 - size
.y
/2; 
2014         rectBorder
.width 
= size
.x
; 
2015         rectBorder
.height 
= size
.y
; 
2017     else if (hAlign 
== wxALIGN_RIGHT
) 
2019         rectBorder
.x 
= rect
.x 
+ rect
.width 
- size
.x 
- 2; 
2020         rectBorder
.y 
= rect
.y 
+ rect
.height
/2 - size
.y
/2; 
2021         rectBorder
.width 
= size
.x
; 
2022         rectBorder
.height 
= size
.y
; 
2026     if ( grid
.GetTable()->CanGetValueAs(row
, col
, wxGRID_VALUE_BOOL
) ) 
2027         value 
= grid
.GetTable()->GetValueAsBool(row
, col
); 
2030         wxString 
cellval( grid
.GetTable()->GetValue(row
, col
) ); 
2031         value 
= !( !cellval 
|| (cellval 
== wxT("0")) ); 
2036         wxRect rectMark 
= rectBorder
; 
2038         // MSW DrawCheckMark() is weird (and should probably be changed...) 
2039         rectMark
.Inflate(-wxGRID_CHECKMARK_MARGIN
/2); 
2043         rectMark
.Inflate(-wxGRID_CHECKMARK_MARGIN
); 
2046         dc
.SetTextForeground(attr
.GetTextColour()); 
2047         dc
.DrawCheckMark(rectMark
); 
2050     dc
.SetBrush(*wxTRANSPARENT_BRUSH
); 
2051     dc
.SetPen(wxPen(attr
.GetTextColour(), 1, wxSOLID
)); 
2052     dc
.DrawRectangle(rectBorder
); 
2055 // ---------------------------------------------------------------------------- 
2057 // ---------------------------------------------------------------------------- 
2059 void wxGridCellAttr::Init(wxGridCellAttr 
*attrDefault
) 
2063     m_isReadOnly 
= Unset
; 
2068     m_attrkind 
= wxGridCellAttr::Cell
; 
2070     m_sizeRows 
= m_sizeCols 
= 1; 
2071     m_overflow 
= UnsetOverflow
; 
2073     SetDefAttr(attrDefault
); 
2076 wxGridCellAttr 
*wxGridCellAttr::Clone() const 
2078     wxGridCellAttr 
*attr 
= new wxGridCellAttr(m_defGridAttr
); 
2080     if ( HasTextColour() ) 
2081         attr
->SetTextColour(GetTextColour()); 
2082     if ( HasBackgroundColour() ) 
2083         attr
->SetBackgroundColour(GetBackgroundColour()); 
2085         attr
->SetFont(GetFont()); 
2086     if ( HasAlignment() ) 
2087         attr
->SetAlignment(m_hAlign
, m_vAlign
); 
2089     attr
->SetSize( m_sizeRows
, m_sizeCols 
); 
2093         attr
->SetRenderer(m_renderer
); 
2094         m_renderer
->IncRef(); 
2098         attr
->SetEditor(m_editor
); 
2103         attr
->SetReadOnly(); 
2105     attr
->SetKind( m_attrkind 
); 
2110 void wxGridCellAttr::MergeWith(wxGridCellAttr 
*mergefrom
) 
2112     if ( !HasTextColour() && mergefrom
->HasTextColour() ) 
2113         SetTextColour(mergefrom
->GetTextColour()); 
2114     if ( !HasBackgroundColour() && mergefrom
->HasBackgroundColour() ) 
2115         SetBackgroundColour(mergefrom
->GetBackgroundColour()); 
2116     if ( !HasFont() && mergefrom
->HasFont() ) 
2117         SetFont(mergefrom
->GetFont()); 
2118     if ( !HasAlignment() && mergefrom
->HasAlignment() ){ 
2120         mergefrom
->GetAlignment( &hAlign
, &vAlign
); 
2121         SetAlignment(hAlign
, vAlign
); 
2124     mergefrom
->GetSize( &m_sizeRows
, &m_sizeCols 
); 
2126     // Directly access member functions as GetRender/Editor don't just return 
2127     // m_renderer/m_editor 
2129     // Maybe add support for merge of Render and Editor? 
2130     if (!HasRenderer() && mergefrom
->HasRenderer() ) 
2132         m_renderer 
= mergefrom
->m_renderer
; 
2133         m_renderer
->IncRef(); 
2135     if ( !HasEditor() && mergefrom
->HasEditor() ) 
2137         m_editor 
=  mergefrom
->m_editor
; 
2140     if ( !HasReadWriteMode()  && mergefrom
->HasReadWriteMode() ) 
2141         SetReadOnly(mergefrom
->IsReadOnly()); 
2143     if (!HasOverflowMode()  && mergefrom
->HasOverflowMode() ) 
2144         SetOverflow(mergefrom
->GetOverflow()); 
2146     SetDefAttr(mergefrom
->m_defGridAttr
); 
2149 void wxGridCellAttr::SetSize(int num_rows
, int num_cols
) 
2151     // The size of a cell is normally 1,1 
2153     // If this cell is larger (2,2) then this is the top left cell 
2154     // the other cells that will be covered (lower right cells) must be 
2155     // set to negative or zero values such that 
2156     // row + num_rows of the covered cell points to the larger cell (this cell) 
2157     // same goes for the col + num_cols. 
2159     // Size of 0,0 is NOT valid, neither is <=0 and any positive value 
2161     wxASSERT_MSG( (!((num_rows
>0)&&(num_cols
<=0)) || 
2162                   !((num_rows
<=0)&&(num_cols
>0)) || 
2163                   !((num_rows
==0)&&(num_cols
==0))), 
2164                   wxT("wxGridCellAttr::SetSize only takes two postive values or negative/zero values")); 
2166     m_sizeRows 
= num_rows
; 
2167     m_sizeCols 
= num_cols
; 
2170 const wxColour
& wxGridCellAttr::GetTextColour() const 
2172     if (HasTextColour()) 
2176     else if (m_defGridAttr 
&& m_defGridAttr 
!= this) 
2178         return m_defGridAttr
->GetTextColour(); 
2182         wxFAIL_MSG(wxT("Missing default cell attribute")); 
2183         return wxNullColour
; 
2188 const wxColour
& wxGridCellAttr::GetBackgroundColour() const 
2190     if (HasBackgroundColour()) 
2192     else if (m_defGridAttr 
&& m_defGridAttr 
!= this) 
2193         return m_defGridAttr
->GetBackgroundColour(); 
2196         wxFAIL_MSG(wxT("Missing default cell attribute")); 
2197         return wxNullColour
; 
2202 const wxFont
& wxGridCellAttr::GetFont() const 
2206     else if (m_defGridAttr 
&& m_defGridAttr 
!= this) 
2207         return m_defGridAttr
->GetFont(); 
2210         wxFAIL_MSG(wxT("Missing default cell attribute")); 
2216 void wxGridCellAttr::GetAlignment(int *hAlign
, int *vAlign
) const 
2220         if ( hAlign 
) *hAlign 
= m_hAlign
; 
2221         if ( vAlign 
) *vAlign 
= m_vAlign
; 
2223     else if (m_defGridAttr 
&& m_defGridAttr 
!= this) 
2224         m_defGridAttr
->GetAlignment(hAlign
, vAlign
); 
2227         wxFAIL_MSG(wxT("Missing default cell attribute")); 
2231 void wxGridCellAttr::GetSize( int *num_rows
, int *num_cols 
) const 
2233     if ( num_rows 
) *num_rows 
= m_sizeRows
; 
2234     if ( num_cols 
) *num_cols 
= m_sizeCols
; 
2237 // GetRenderer and GetEditor use a slightly different decision path about 
2238 // which attribute to use.  If a non-default attr object has one then it is 
2239 // used, otherwise the default editor or renderer is fetched from the grid and 
2240 // used.  It should be the default for the data type of the cell.  If it is 
2241 // NULL (because the table has a type that the grid does not have in its 
2242 // registry,) then the grid's default editor or renderer is used. 
2244 wxGridCellRenderer
* wxGridCellAttr::GetRenderer(wxGrid
* grid
, int row
, int col
) const 
2246     wxGridCellRenderer 
*renderer
; 
2248     if ( m_renderer 
&& this != m_defGridAttr 
) 
2250         // use the cells renderer if it has one 
2251         renderer 
= m_renderer
; 
2254     else // no non default cell renderer 
2256         // get default renderer for the data type 
2259             // GetDefaultRendererForCell() will do IncRef() for us 
2260             renderer 
= grid
->GetDefaultRendererForCell(row
, col
); 
2269             if (m_defGridAttr 
&&  this != m_defGridAttr 
) 
2271                 // if we still don't have one then use the grid default 
2272                 // (no need for IncRef() here neither) 
2273                 renderer 
= m_defGridAttr
->GetRenderer(NULL
, 0, 0); 
2275             else // default grid attr 
2277                 // use m_renderer which we had decided not to use initially 
2278                 renderer 
= m_renderer
; 
2285     // we're supposed to always find something 
2286     wxASSERT_MSG(renderer
, wxT("Missing default cell renderer")); 
2291 // same as above, except for s/renderer/editor/g 
2292 wxGridCellEditor
* wxGridCellAttr::GetEditor(wxGrid
* grid
, int row
, int col
) const 
2294     wxGridCellEditor 
*editor
; 
2296     if ( m_editor 
&& this != m_defGridAttr 
) 
2298         // use the cells editor if it has one 
2302     else // no non default cell editor 
2304         // get default editor for the data type 
2307             // GetDefaultEditorForCell() will do IncRef() for us 
2308             editor 
= grid
->GetDefaultEditorForCell(row
, col
); 
2317             if ( m_defGridAttr 
&& this != m_defGridAttr 
) 
2319                 // if we still don't have one then use the grid default 
2320                 // (no need for IncRef() here neither) 
2321                 editor 
= m_defGridAttr
->GetEditor(NULL
, 0, 0); 
2323             else // default grid attr 
2325                 // use m_editor which we had decided not to use initially 
2333     // we're supposed to always find something 
2334     wxASSERT_MSG(editor
, wxT("Missing default cell editor")); 
2339 // ---------------------------------------------------------------------------- 
2340 // wxGridCellAttrData 
2341 // ---------------------------------------------------------------------------- 
2343 void wxGridCellAttrData::SetAttr(wxGridCellAttr 
*attr
, int row
, int col
) 
2345     int n 
= FindIndex(row
, col
); 
2346     if ( n 
== wxNOT_FOUND 
) 
2348         // add the attribute 
2349         m_attrs
.Add(new wxGridCellWithAttr(row
, col
, attr
)); 
2353         // free the old attribute 
2354         m_attrs
[(size_t)n
].attr
->DecRef(); 
2358             // change the attribute 
2359             m_attrs
[(size_t)n
].attr 
= attr
; 
2363             // remove this attribute 
2364             m_attrs
.RemoveAt((size_t)n
); 
2369 wxGridCellAttr 
*wxGridCellAttrData::GetAttr(int row
, int col
) const 
2371     wxGridCellAttr 
*attr 
= (wxGridCellAttr 
*)NULL
; 
2373     int n 
= FindIndex(row
, col
); 
2374     if ( n 
!= wxNOT_FOUND 
) 
2376         attr 
= m_attrs
[(size_t)n
].attr
; 
2383 void wxGridCellAttrData::UpdateAttrRows( size_t pos
, int numRows 
) 
2385     size_t count 
= m_attrs
.GetCount(); 
2386     for ( size_t n 
= 0; n 
< count
; n
++ ) 
2388         wxGridCellCoords
& coords 
= m_attrs
[n
].coords
; 
2389         wxCoord row 
= coords
.GetRow(); 
2390         if ((size_t)row 
>= pos
) 
2394                 // If rows inserted, include row counter where necessary 
2395                 coords
.SetRow(row 
+ numRows
); 
2397             else if (numRows 
< 0) 
2399                 // If rows deleted ... 
2400                 if ((size_t)row 
>= pos 
- numRows
) 
2402                     // ...either decrement row counter (if row still exists)... 
2403                     coords
.SetRow(row 
+ numRows
); 
2407                     // ...or remove the attribute 
2408                     m_attrs
.RemoveAt((size_t)n
); 
2416 void wxGridCellAttrData::UpdateAttrCols( size_t pos
, int numCols 
) 
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 col 
= coords
.GetCol(); 
2423         if ( (size_t)col 
>= pos 
) 
2427                 // If rows inserted, include row counter where necessary 
2428                 coords
.SetCol(col 
+ numCols
); 
2430             else if (numCols 
< 0) 
2432                 // If rows deleted ... 
2433                 if ((size_t)col 
>= pos 
- numCols
) 
2435                     // ...either decrement row counter (if row still exists)... 
2436                     coords
.SetCol(col 
+ numCols
); 
2440                     // ...or remove the attribute 
2441                     m_attrs
.RemoveAt((size_t)n
); 
2449 int wxGridCellAttrData::FindIndex(int row
, int col
) const 
2451     size_t count 
= m_attrs
.GetCount(); 
2452     for ( size_t n 
= 0; n 
< count
; n
++ ) 
2454         const wxGridCellCoords
& coords 
= m_attrs
[n
].coords
; 
2455         if ( (coords
.GetRow() == row
) && (coords
.GetCol() == col
) ) 
2464 // ---------------------------------------------------------------------------- 
2465 // wxGridRowOrColAttrData 
2466 // ---------------------------------------------------------------------------- 
2468 wxGridRowOrColAttrData::~wxGridRowOrColAttrData() 
2470     size_t count 
= m_attrs
.Count(); 
2471     for ( size_t n 
= 0; n 
< count
; n
++ ) 
2473         m_attrs
[n
]->DecRef(); 
2477 wxGridCellAttr 
*wxGridRowOrColAttrData::GetAttr(int rowOrCol
) const 
2479     wxGridCellAttr 
*attr 
= (wxGridCellAttr 
*)NULL
; 
2481     int n 
= m_rowsOrCols
.Index(rowOrCol
); 
2482     if ( n 
!= wxNOT_FOUND 
) 
2484         attr 
= m_attrs
[(size_t)n
]; 
2491 void wxGridRowOrColAttrData::SetAttr(wxGridCellAttr 
*attr
, int rowOrCol
) 
2493     int i 
= m_rowsOrCols
.Index(rowOrCol
); 
2494     if ( i 
== wxNOT_FOUND 
) 
2496         // add the attribute 
2497         m_rowsOrCols
.Add(rowOrCol
); 
2502         size_t n 
= (size_t)i
; 
2505             // change the attribute 
2506             m_attrs
[n
]->DecRef(); 
2511             // remove this attribute 
2512             m_attrs
[n
]->DecRef(); 
2513             m_rowsOrCols
.RemoveAt(n
); 
2514             m_attrs
.RemoveAt(n
); 
2519 void wxGridRowOrColAttrData::UpdateAttrRowsOrCols( size_t pos
, int numRowsOrCols 
) 
2521     size_t count 
= m_attrs
.GetCount(); 
2522     for ( size_t n 
= 0; n 
< count
; n
++ ) 
2524         int & rowOrCol 
= m_rowsOrCols
[n
]; 
2525         if ( (size_t)rowOrCol 
>= pos 
) 
2527             if ( numRowsOrCols 
> 0 ) 
2529                 // If rows inserted, include row counter where necessary 
2530                 rowOrCol 
+= numRowsOrCols
; 
2532             else if ( numRowsOrCols 
< 0) 
2534                 // If rows deleted, either decrement row counter (if row still exists) 
2535                 if ((size_t)rowOrCol 
>= pos 
- numRowsOrCols
) 
2536                     rowOrCol 
+= numRowsOrCols
; 
2539                     m_rowsOrCols
.RemoveAt((size_t)n
); 
2540                     m_attrs
.RemoveAt((size_t)n
); 
2548 // ---------------------------------------------------------------------------- 
2549 // wxGridCellAttrProvider 
2550 // ---------------------------------------------------------------------------- 
2552 wxGridCellAttrProvider::wxGridCellAttrProvider() 
2554     m_data 
= (wxGridCellAttrProviderData 
*)NULL
; 
2557 wxGridCellAttrProvider::~wxGridCellAttrProvider() 
2562 void wxGridCellAttrProvider::InitData() 
2564     m_data 
= new wxGridCellAttrProviderData
; 
2567 wxGridCellAttr 
*wxGridCellAttrProvider::GetAttr(int row
, int col
, 
2568                                                 wxGridCellAttr::wxAttrKind  kind 
) const 
2570     wxGridCellAttr 
*attr 
= (wxGridCellAttr 
*)NULL
; 
2575             case (wxGridCellAttr::Any
): 
2576                 //Get cached merge attributes. 
2577                 // Currenlty not used as no cache implemented as not mutiable 
2578                 // attr = m_data->m_mergeAttr.GetAttr(row, col); 
2581                     //Basicaly implement old version. 
2582                     //Also check merge cache, so we don't have to re-merge every time.. 
2583                     wxGridCellAttr 
*attrcell 
= (wxGridCellAttr 
*)NULL
, 
2584                                    *attrrow 
= (wxGridCellAttr 
*)NULL
, 
2585                                    *attrcol 
= (wxGridCellAttr 
*)NULL
; 
2587                     attrcell 
= m_data
->m_cellAttrs
.GetAttr(row
, col
); 
2588                     attrcol 
= m_data
->m_colAttrs
.GetAttr(col
); 
2589                     attrrow 
= m_data
->m_rowAttrs
.GetAttr(row
); 
2591                     if((attrcell 
!= attrrow
) && (attrrow 
!=attrcol
) && (attrcell 
!= attrcol
)){ 
2592                         // Two or move are non NULL 
2593                         attr 
= new wxGridCellAttr
; 
2594                         attr
->SetKind(wxGridCellAttr::Merged
); 
2598                             attr
->MergeWith(attrcell
); 
2602                             attr
->MergeWith(attrcol
); 
2606                             attr
->MergeWith(attrrow
); 
2609                         //store merge attr if cache implemented 
2611                         //m_data->m_mergeAttr.SetAttr(attr, row, col); 
2615                         // one or none is non null return it or null. 
2616                         if(attrrow
) attr 
= attrrow
; 
2617                         if(attrcol
) attr 
= attrcol
; 
2618                         if(attrcell
) attr 
= attrcell
; 
2622             case (wxGridCellAttr::Cell
): 
2623                 attr 
= m_data
->m_cellAttrs
.GetAttr(row
, col
); 
2625             case (wxGridCellAttr::Col
): 
2626                  attr 
= m_data
->m_colAttrs
.GetAttr(col
); 
2628             case (wxGridCellAttr::Row
): 
2629             attr 
= m_data
->m_rowAttrs
.GetAttr(row
); 
2633                 // (wxGridCellAttr::Default): 
2634                 // (wxGridCellAttr::Merged): 
2641 void wxGridCellAttrProvider::SetAttr(wxGridCellAttr 
*attr
, 
2647     m_data
->m_cellAttrs
.SetAttr(attr
, row
, col
); 
2650 void wxGridCellAttrProvider::SetRowAttr(wxGridCellAttr 
*attr
, int row
) 
2655     m_data
->m_rowAttrs
.SetAttr(attr
, row
); 
2658 void wxGridCellAttrProvider::SetColAttr(wxGridCellAttr 
*attr
, int col
) 
2663     m_data
->m_colAttrs
.SetAttr(attr
, col
); 
2666 void wxGridCellAttrProvider::UpdateAttrRows( size_t pos
, int numRows 
) 
2670         m_data
->m_cellAttrs
.UpdateAttrRows( pos
, numRows 
); 
2672         m_data
->m_rowAttrs
.UpdateAttrRowsOrCols( pos
, numRows 
); 
2676 void wxGridCellAttrProvider::UpdateAttrCols( size_t pos
, int numCols 
) 
2680         m_data
->m_cellAttrs
.UpdateAttrCols( pos
, numCols 
); 
2682         m_data
->m_colAttrs
.UpdateAttrRowsOrCols( pos
, numCols 
); 
2686 // ---------------------------------------------------------------------------- 
2687 // wxGridTypeRegistry 
2688 // ---------------------------------------------------------------------------- 
2690 wxGridTypeRegistry::~wxGridTypeRegistry() 
2692     size_t count 
= m_typeinfo
.Count(); 
2693     for ( size_t i 
= 0; i 
< count
; i
++ ) 
2694         delete m_typeinfo
[i
]; 
2698 void wxGridTypeRegistry::RegisterDataType(const wxString
& typeName
, 
2699                                           wxGridCellRenderer
* renderer
, 
2700                                           wxGridCellEditor
* editor
) 
2702     wxGridDataTypeInfo
* info 
= new wxGridDataTypeInfo(typeName
, renderer
, editor
); 
2704     // is it already registered? 
2705     int loc 
= FindRegisteredDataType(typeName
); 
2706     if ( loc 
!= wxNOT_FOUND 
) 
2708         delete m_typeinfo
[loc
]; 
2709         m_typeinfo
[loc
] = info
; 
2713         m_typeinfo
.Add(info
); 
2717 int wxGridTypeRegistry::FindRegisteredDataType(const wxString
& typeName
) 
2719     size_t count 
= m_typeinfo
.GetCount(); 
2720     for ( size_t i 
= 0; i 
< count
; i
++ ) 
2722         if ( typeName 
== m_typeinfo
[i
]->m_typeName 
) 
2731 int wxGridTypeRegistry::FindDataType(const wxString
& typeName
) 
2733     int index 
= FindRegisteredDataType(typeName
); 
2734     if ( index 
== wxNOT_FOUND 
) 
2736         // check whether this is one of the standard ones, in which case 
2737         // register it "on the fly" 
2739         if ( typeName 
== wxGRID_VALUE_STRING 
) 
2741             RegisterDataType(wxGRID_VALUE_STRING
, 
2742                              new wxGridCellStringRenderer
, 
2743                              new wxGridCellTextEditor
); 
2745 #endif // wxUSE_TEXTCTRL 
2747         if ( typeName 
== wxGRID_VALUE_BOOL 
) 
2749             RegisterDataType(wxGRID_VALUE_BOOL
, 
2750                              new wxGridCellBoolRenderer
, 
2751                              new wxGridCellBoolEditor
); 
2753 #endif // wxUSE_CHECKBOX 
2755         if ( typeName 
== wxGRID_VALUE_NUMBER 
) 
2757             RegisterDataType(wxGRID_VALUE_NUMBER
, 
2758                              new wxGridCellNumberRenderer
, 
2759                              new wxGridCellNumberEditor
); 
2761         else if ( typeName 
== wxGRID_VALUE_FLOAT 
) 
2763             RegisterDataType(wxGRID_VALUE_FLOAT
, 
2764                              new wxGridCellFloatRenderer
, 
2765                              new wxGridCellFloatEditor
); 
2767 #endif // wxUSE_TEXTCTRL 
2769         if ( typeName 
== wxGRID_VALUE_CHOICE 
) 
2771             RegisterDataType(wxGRID_VALUE_CHOICE
, 
2772                              new wxGridCellStringRenderer
, 
2773                              new wxGridCellChoiceEditor
); 
2775 #endif // wxUSE_COMBOBOX 
2780         // we get here only if just added the entry for this type, so return 
2782         index 
= m_typeinfo
.GetCount() - 1; 
2788 int wxGridTypeRegistry::FindOrCloneDataType(const wxString
& typeName
) 
2790     int index 
= FindDataType(typeName
); 
2791     if ( index 
== wxNOT_FOUND 
) 
2793         // the first part of the typename is the "real" type, anything after ':' 
2794         // are the parameters for the renderer 
2795         index 
= FindDataType(typeName
.BeforeFirst(_T(':'))); 
2796         if ( index 
== wxNOT_FOUND 
) 
2801         wxGridCellRenderer 
*renderer 
= GetRenderer(index
); 
2802         wxGridCellRenderer 
*rendererOld 
= renderer
; 
2803         renderer 
= renderer
->Clone(); 
2804         rendererOld
->DecRef(); 
2806         wxGridCellEditor 
*editor 
= GetEditor(index
); 
2807         wxGridCellEditor 
*editorOld 
= editor
; 
2808         editor 
= editor
->Clone(); 
2809         editorOld
->DecRef(); 
2811         // do it even if there are no parameters to reset them to defaults 
2812         wxString params 
= typeName
.AfterFirst(_T(':')); 
2813         renderer
->SetParameters(params
); 
2814         editor
->SetParameters(params
); 
2816         // register the new typename 
2817         RegisterDataType(typeName
, renderer
, editor
); 
2819         // we just registered it, it's the last one 
2820         index 
= m_typeinfo
.GetCount() - 1; 
2826 wxGridCellRenderer
* wxGridTypeRegistry::GetRenderer(int index
) 
2828     wxGridCellRenderer
* renderer 
= m_typeinfo
[index
]->m_renderer
; 
2834 wxGridCellEditor
* wxGridTypeRegistry::GetEditor(int index
) 
2836     wxGridCellEditor
* editor 
= m_typeinfo
[index
]->m_editor
; 
2842 // ---------------------------------------------------------------------------- 
2844 // ---------------------------------------------------------------------------- 
2846 IMPLEMENT_ABSTRACT_CLASS( wxGridTableBase
, wxObject 
) 
2849 wxGridTableBase::wxGridTableBase() 
2851     m_view 
= (wxGrid 
*) NULL
; 
2852     m_attrProvider 
= (wxGridCellAttrProvider 
*) NULL
; 
2855 wxGridTableBase::~wxGridTableBase() 
2857     delete m_attrProvider
; 
2860 void wxGridTableBase::SetAttrProvider(wxGridCellAttrProvider 
*attrProvider
) 
2862     delete m_attrProvider
; 
2863     m_attrProvider 
= attrProvider
; 
2866 bool wxGridTableBase::CanHaveAttributes() 
2868     if ( ! GetAttrProvider() ) 
2870         // use the default attr provider by default 
2871         SetAttrProvider(new wxGridCellAttrProvider
); 
2876 wxGridCellAttr 
*wxGridTableBase::GetAttr(int row
, int col
, wxGridCellAttr::wxAttrKind  kind
) 
2878     if ( m_attrProvider 
) 
2879         return m_attrProvider
->GetAttr(row
, col
, kind
); 
2881         return (wxGridCellAttr 
*)NULL
; 
2884 void wxGridTableBase::SetAttr(wxGridCellAttr
* attr
, int row
, int col
) 
2886     if ( m_attrProvider 
) 
2888         attr
->SetKind(wxGridCellAttr::Cell
); 
2889         m_attrProvider
->SetAttr(attr
, row
, col
); 
2893         // as we take ownership of the pointer and don't store it, we must 
2899 void wxGridTableBase::SetRowAttr(wxGridCellAttr 
*attr
, int row
) 
2901     if ( m_attrProvider 
) 
2903         attr
->SetKind(wxGridCellAttr::Row
); 
2904         m_attrProvider
->SetRowAttr(attr
, row
); 
2908         // as we take ownership of the pointer and don't store it, we must 
2914 void wxGridTableBase::SetColAttr(wxGridCellAttr 
*attr
, int col
) 
2916     if ( m_attrProvider 
) 
2918         attr
->SetKind(wxGridCellAttr::Col
); 
2919         m_attrProvider
->SetColAttr(attr
, col
); 
2923         // as we take ownership of the pointer and don't store it, we must 
2929 bool wxGridTableBase::InsertRows( size_t WXUNUSED(pos
), 
2930                                   size_t WXUNUSED(numRows
) ) 
2932     wxFAIL_MSG( wxT("Called grid table class function InsertRows\nbut your derived table class does not override this function") ); 
2937 bool wxGridTableBase::AppendRows( size_t WXUNUSED(numRows
) ) 
2939     wxFAIL_MSG( wxT("Called grid table class function AppendRows\nbut your derived table class does not override this function")); 
2944 bool wxGridTableBase::DeleteRows( size_t WXUNUSED(pos
), 
2945                                   size_t WXUNUSED(numRows
) ) 
2947     wxFAIL_MSG( wxT("Called grid table class function DeleteRows\nbut your derived table class does not override this function")); 
2952 bool wxGridTableBase::InsertCols( size_t WXUNUSED(pos
), 
2953                                   size_t WXUNUSED(numCols
) ) 
2955     wxFAIL_MSG( wxT("Called grid table class function InsertCols\nbut your derived table class does not override this function")); 
2960 bool wxGridTableBase::AppendCols( size_t WXUNUSED(numCols
) ) 
2962     wxFAIL_MSG(wxT("Called grid table class function AppendCols\nbut your derived table class does not override this function")); 
2967 bool wxGridTableBase::DeleteCols( size_t WXUNUSED(pos
), 
2968                                   size_t WXUNUSED(numCols
) ) 
2970     wxFAIL_MSG( wxT("Called grid table class function DeleteCols\nbut your derived table class does not override this function")); 
2976 wxString 
wxGridTableBase::GetRowLabelValue( int row 
) 
2979     s 
<< row 
+ 1; // RD: Starting the rows at zero confuses users, no matter 
2980                   //     how much it makes sense to us geeks. 
2984 wxString 
wxGridTableBase::GetColLabelValue( int col 
) 
2986     // default col labels are: 
2987     //   cols 0 to 25   : A-Z 
2988     //   cols 26 to 675 : AA-ZZ 
2993     for ( n 
= 1; ; n
++ ) 
2995         s 
+= (_T('A') + (wxChar
)( col%26 
)); 
2997         if ( col 
< 0 ) break; 
3000     // reverse the string... 
3002     for ( i 
= 0;  i 
< n
;  i
++ ) 
3011 wxString 
wxGridTableBase::GetTypeName( int WXUNUSED(row
), int WXUNUSED(col
) ) 
3013     return wxGRID_VALUE_STRING
; 
3016 bool wxGridTableBase::CanGetValueAs( int WXUNUSED(row
), int WXUNUSED(col
), 
3017                                      const wxString
& typeName 
) 
3019     return typeName 
== wxGRID_VALUE_STRING
; 
3022 bool wxGridTableBase::CanSetValueAs( int row
, int col
, const wxString
& typeName 
) 
3024     return CanGetValueAs(row
, col
, typeName
); 
3027 long wxGridTableBase::GetValueAsLong( int WXUNUSED(row
), int WXUNUSED(col
) ) 
3032 double wxGridTableBase::GetValueAsDouble( int WXUNUSED(row
), int WXUNUSED(col
) ) 
3037 bool wxGridTableBase::GetValueAsBool( int WXUNUSED(row
), int WXUNUSED(col
) ) 
3042 void wxGridTableBase::SetValueAsLong( int WXUNUSED(row
), int WXUNUSED(col
), 
3043                                       long WXUNUSED(value
) ) 
3047 void wxGridTableBase::SetValueAsDouble( int WXUNUSED(row
), int WXUNUSED(col
), 
3048                                         double WXUNUSED(value
) ) 
3052 void wxGridTableBase::SetValueAsBool( int WXUNUSED(row
), int WXUNUSED(col
), 
3053                                       bool WXUNUSED(value
) ) 
3058 void* wxGridTableBase::GetValueAsCustom( int WXUNUSED(row
), int WXUNUSED(col
), 
3059                                          const wxString
& WXUNUSED(typeName
) ) 
3064 void  wxGridTableBase::SetValueAsCustom( int WXUNUSED(row
), int WXUNUSED(col
), 
3065                                          const wxString
& WXUNUSED(typeName
), 
3066                                          void* WXUNUSED(value
) ) 
3070 ////////////////////////////////////////////////////////////////////// 
3072 // Message class for the grid table to send requests and notifications 
3076 wxGridTableMessage::wxGridTableMessage() 
3078     m_table 
= (wxGridTableBase 
*) NULL
; 
3084 wxGridTableMessage::wxGridTableMessage( wxGridTableBase 
*table
, int id
, 
3085                                         int commandInt1
, int commandInt2 
) 
3089     m_comInt1 
= commandInt1
; 
3090     m_comInt2 
= commandInt2
; 
3095 ////////////////////////////////////////////////////////////////////// 
3097 // A basic grid table for string data. An object of this class will 
3098 // created by wxGrid if you don't specify an alternative table class. 
3101 WX_DEFINE_OBJARRAY(wxGridStringArray
) 
3103 IMPLEMENT_DYNAMIC_CLASS( wxGridStringTable
, wxGridTableBase 
) 
3105 wxGridStringTable::wxGridStringTable() 
3110 wxGridStringTable::wxGridStringTable( int numRows
, int numCols 
) 
3113     m_data
.Alloc( numRows 
); 
3116     sa
.Alloc( numCols 
); 
3117     sa
.Add( wxEmptyString
, numCols 
); 
3119     m_data
.Add( sa
, numRows 
); 
3122 wxGridStringTable::~wxGridStringTable() 
3126 int wxGridStringTable::GetNumberRows() 
3128     return m_data
.GetCount(); 
3131 int wxGridStringTable::GetNumberCols() 
3133     if ( m_data
.GetCount() > 0 ) 
3134         return m_data
[0].GetCount(); 
3139 wxString 
wxGridStringTable::GetValue( int row
, int col 
) 
3141     wxASSERT_MSG( (row 
< GetNumberRows()) && (col 
< GetNumberCols()), 
3142                   _T("invalid row or column index in wxGridStringTable") ); 
3144     return m_data
[row
][col
]; 
3147 void wxGridStringTable::SetValue( int row
, int col
, const wxString
& value 
) 
3149     wxASSERT_MSG( (row 
< GetNumberRows()) && (col 
< GetNumberCols()), 
3150                   _T("invalid row or column index in wxGridStringTable") ); 
3152     m_data
[row
][col
] = value
; 
3155 bool wxGridStringTable::IsEmptyCell( int row
, int col 
) 
3157     wxASSERT_MSG( (row 
< GetNumberRows()) && (col 
< GetNumberCols()), 
3158                   _T("invalid row or column index in wxGridStringTable") ); 
3160     return (m_data
[row
][col
] == wxEmptyString
); 
3163 void wxGridStringTable::Clear() 
3166     int numRows
, numCols
; 
3168     numRows 
= m_data
.GetCount(); 
3171         numCols 
= m_data
[0].GetCount(); 
3173         for ( row 
= 0;  row 
< numRows
;  row
++ ) 
3175             for ( col 
= 0;  col 
< numCols
;  col
++ ) 
3177                 m_data
[row
][col
] = wxEmptyString
; 
3184 bool wxGridStringTable::InsertRows( size_t pos
, size_t numRows 
) 
3186     size_t curNumRows 
= m_data
.GetCount(); 
3187     size_t curNumCols 
= ( curNumRows 
> 0 ? m_data
[0].GetCount() : 
3188                           ( GetView() ? GetView()->GetNumberCols() : 0 ) ); 
3190     if ( pos 
>= curNumRows 
) 
3192         return AppendRows( numRows 
); 
3196     sa
.Alloc( curNumCols 
); 
3197     sa
.Add( wxEmptyString
, curNumCols 
); 
3198     m_data
.Insert( sa
, pos
, numRows 
); 
3201         wxGridTableMessage 
msg( this, 
3202                                 wxGRIDTABLE_NOTIFY_ROWS_INSERTED
, 
3206         GetView()->ProcessTableMessage( msg 
); 
3212 bool wxGridStringTable::AppendRows( size_t numRows 
) 
3214     size_t curNumRows 
= m_data
.GetCount(); 
3215     size_t curNumCols 
= ( curNumRows 
> 0 ? m_data
[0].GetCount() : 
3216                           ( GetView() ? GetView()->GetNumberCols() : 0 ) ); 
3219     if ( curNumCols 
> 0 ) 
3221         sa
.Alloc( curNumCols 
); 
3222         sa
.Add( wxEmptyString
, curNumCols 
); 
3225     m_data
.Add( sa
, numRows 
); 
3229         wxGridTableMessage 
msg( this, 
3230                                 wxGRIDTABLE_NOTIFY_ROWS_APPENDED
, 
3233         GetView()->ProcessTableMessage( msg 
); 
3239 bool wxGridStringTable::DeleteRows( size_t pos
, size_t numRows 
) 
3241     size_t curNumRows 
= m_data
.GetCount(); 
3243     if ( pos 
>= curNumRows 
) 
3245         wxFAIL_MSG( wxString::Format
 
3247                         wxT("Called wxGridStringTable::DeleteRows(pos=%lu, N=%lu)\nPos value is invalid for present table with %lu rows"), 
3249                         (unsigned long)numRows
, 
3250                         (unsigned long)curNumRows
 
3256     if ( numRows 
> curNumRows 
- pos 
) 
3258         numRows 
= curNumRows 
- pos
; 
3261     if ( numRows 
>= curNumRows 
) 
3267         m_data
.RemoveAt( pos
, numRows 
); 
3271         wxGridTableMessage 
msg( this, 
3272                                 wxGRIDTABLE_NOTIFY_ROWS_DELETED
, 
3276         GetView()->ProcessTableMessage( msg 
); 
3282 bool wxGridStringTable::InsertCols( size_t pos
, size_t numCols 
) 
3286     size_t curNumRows 
= m_data
.GetCount(); 
3287     size_t curNumCols 
= ( curNumRows 
> 0 ? m_data
[0].GetCount() : 
3288                           ( GetView() ? GetView()->GetNumberCols() : 0 ) ); 
3290     if ( pos 
>= curNumCols 
) 
3292         return AppendCols( numCols 
); 
3295     for ( row 
= 0;  row 
< curNumRows
;  row
++ ) 
3297         for ( col 
= pos
;  col 
< pos 
+ numCols
;  col
++ ) 
3299             m_data
[row
].Insert( wxEmptyString
, col 
); 
3304         wxGridTableMessage 
msg( this, 
3305                                 wxGRIDTABLE_NOTIFY_COLS_INSERTED
, 
3309         GetView()->ProcessTableMessage( msg 
); 
3315 bool wxGridStringTable::AppendCols( size_t numCols 
) 
3319     size_t curNumRows 
= m_data
.GetCount(); 
3323         // TODO: something better than this ? 
3325         wxFAIL_MSG( wxT("Unable to append cols to a grid table with no rows.\nCall AppendRows() first") ); 
3330     for ( row 
= 0;  row 
< curNumRows
;  row
++ ) 
3332         m_data
[row
].Add( wxEmptyString
, numCols 
); 
3337         wxGridTableMessage 
msg( this, 
3338                                 wxGRIDTABLE_NOTIFY_COLS_APPENDED
, 
3341         GetView()->ProcessTableMessage( msg 
); 
3347 bool wxGridStringTable::DeleteCols( size_t pos
, size_t numCols 
) 
3351     size_t curNumRows 
= m_data
.GetCount(); 
3352     size_t curNumCols 
= ( curNumRows 
> 0 ? m_data
[0].GetCount() : 
3353                           ( GetView() ? GetView()->GetNumberCols() : 0 ) ); 
3355     if ( pos 
>= curNumCols 
) 
3357         wxFAIL_MSG( wxString::Format
 
3359                         wxT("Called wxGridStringTable::DeleteCols(pos=%lu, N=%lu)\nPos value is invalid for present table with %lu cols"), 
3361                         (unsigned long)numCols
, 
3362                         (unsigned long)curNumCols
 
3367     if ( numCols 
> curNumCols 
- pos 
) 
3369         numCols 
= curNumCols 
- pos
; 
3372     for ( row 
= 0;  row 
< curNumRows
;  row
++ ) 
3374         if ( numCols 
>= curNumCols 
) 
3376             m_data
[row
].Clear(); 
3380             m_data
[row
].RemoveAt( pos
, numCols 
); 
3385         wxGridTableMessage 
msg( this, 
3386                                 wxGRIDTABLE_NOTIFY_COLS_DELETED
, 
3390         GetView()->ProcessTableMessage( msg 
); 
3396 wxString 
wxGridStringTable::GetRowLabelValue( int row 
) 
3398     if ( row 
> (int)(m_rowLabels
.GetCount()) - 1 ) 
3400         // using default label 
3402         return wxGridTableBase::GetRowLabelValue( row 
); 
3406         return m_rowLabels
[ row 
]; 
3410 wxString 
wxGridStringTable::GetColLabelValue( int col 
) 
3412     if ( col 
> (int)(m_colLabels
.GetCount()) - 1 ) 
3414         // using default label 
3416         return wxGridTableBase::GetColLabelValue( col 
); 
3420         return m_colLabels
[ col 
]; 
3424 void wxGridStringTable::SetRowLabelValue( int row
, const wxString
& value 
) 
3426     if ( row 
> (int)(m_rowLabels
.GetCount()) - 1 ) 
3428         int n 
= m_rowLabels
.GetCount(); 
3430         for ( i 
= n
;  i 
<= row
;  i
++ ) 
3432             m_rowLabels
.Add( wxGridTableBase::GetRowLabelValue(i
) ); 
3436     m_rowLabels
[row
] = value
; 
3439 void wxGridStringTable::SetColLabelValue( int col
, const wxString
& value 
) 
3441     if ( col 
> (int)(m_colLabels
.GetCount()) - 1 ) 
3443         int n 
= m_colLabels
.GetCount(); 
3445         for ( i 
= n
;  i 
<= col
;  i
++ ) 
3447             m_colLabels
.Add( wxGridTableBase::GetColLabelValue(i
) ); 
3451     m_colLabels
[col
] = value
; 
3456 ////////////////////////////////////////////////////////////////////// 
3457 ////////////////////////////////////////////////////////////////////// 
3459 IMPLEMENT_DYNAMIC_CLASS( wxGridRowLabelWindow
, wxWindow 
) 
3461 BEGIN_EVENT_TABLE( wxGridRowLabelWindow
, wxWindow 
) 
3462     EVT_PAINT( wxGridRowLabelWindow::OnPaint 
) 
3463     EVT_MOUSEWHEEL( wxGridRowLabelWindow::OnMouseWheel
) 
3464     EVT_MOUSE_EVENTS( wxGridRowLabelWindow::OnMouseEvent 
) 
3465     EVT_KEY_DOWN( wxGridRowLabelWindow::OnKeyDown 
) 
3466     EVT_KEY_UP( wxGridRowLabelWindow::OnKeyUp 
) 
3469 wxGridRowLabelWindow::wxGridRowLabelWindow( wxGrid 
*parent
, 
3471                                             const wxPoint 
&pos
, const wxSize 
&size 
) 
3472   : wxWindow( parent
, id
, pos
, size
, wxWANTS_CHARS
|wxBORDER_NONE 
) 
3477 void wxGridRowLabelWindow::OnPaint( wxPaintEvent
& WXUNUSED(event
) ) 
3481     // NO - don't do this because it will set both the x and y origin 
3482     // coords to match the parent scrolled window and we just want to 
3483     // set the y coord  - MB 
3485     // m_owner->PrepareDC( dc ); 
3488     m_owner
->CalcUnscrolledPosition( 0, 0, &x
, &y 
); 
3489     dc
.SetDeviceOrigin( 0, -y 
); 
3491     wxArrayInt rows 
= m_owner
->CalcRowLabelsExposed( GetUpdateRegion() ); 
3492     m_owner
->DrawRowLabels( dc 
, rows 
); 
3496 void wxGridRowLabelWindow::OnMouseEvent( wxMouseEvent
& event 
) 
3498     m_owner
->ProcessRowLabelMouseEvent( event 
); 
3502 void wxGridRowLabelWindow::OnMouseWheel( wxMouseEvent
& event 
) 
3504     m_owner
->GetEventHandler()->ProcessEvent(event
); 
3508 // This seems to be required for wxMotif otherwise the mouse 
3509 // cursor must be in the cell edit control to get key events 
3511 void wxGridRowLabelWindow::OnKeyDown( wxKeyEvent
& event 
) 
3513     if ( !m_owner
->GetEventHandler()->ProcessEvent( event 
) ) event
.Skip(); 
3516 void wxGridRowLabelWindow::OnKeyUp( wxKeyEvent
& event 
) 
3518     if ( !m_owner
->GetEventHandler()->ProcessEvent( event 
) ) event
.Skip(); 
3523 ////////////////////////////////////////////////////////////////////// 
3525 IMPLEMENT_DYNAMIC_CLASS( wxGridColLabelWindow
, wxWindow 
) 
3527 BEGIN_EVENT_TABLE( wxGridColLabelWindow
, wxWindow 
) 
3528     EVT_PAINT( wxGridColLabelWindow::OnPaint 
) 
3529     EVT_MOUSEWHEEL( wxGridColLabelWindow::OnMouseWheel
) 
3530     EVT_MOUSE_EVENTS( wxGridColLabelWindow::OnMouseEvent 
) 
3531     EVT_KEY_DOWN( wxGridColLabelWindow::OnKeyDown 
) 
3532     EVT_KEY_UP( wxGridColLabelWindow::OnKeyUp 
) 
3535 wxGridColLabelWindow::wxGridColLabelWindow( wxGrid 
*parent
, 
3537                                             const wxPoint 
&pos
, const wxSize 
&size 
) 
3538   : wxWindow( parent
, id
, pos
, size
, wxWANTS_CHARS
|wxBORDER_NONE 
) 
3543 void wxGridColLabelWindow::OnPaint( wxPaintEvent
& WXUNUSED(event
) ) 
3547     // NO - don't do this because it will set both the x and y origin 
3548     // coords to match the parent scrolled window and we just want to 
3549     // set the x coord  - MB 
3551     // m_owner->PrepareDC( dc ); 
3554     m_owner
->CalcUnscrolledPosition( 0, 0, &x
, &y 
); 
3555     dc
.SetDeviceOrigin( -x
, 0 ); 
3557     wxArrayInt cols 
= m_owner
->CalcColLabelsExposed( GetUpdateRegion() ); 
3558     m_owner
->DrawColLabels( dc 
, cols 
); 
3562 void wxGridColLabelWindow::OnMouseEvent( wxMouseEvent
& event 
) 
3564     m_owner
->ProcessColLabelMouseEvent( event 
); 
3567 void wxGridColLabelWindow::OnMouseWheel( wxMouseEvent
& event 
) 
3569     m_owner
->GetEventHandler()->ProcessEvent(event
); 
3573 // This seems to be required for wxMotif otherwise the mouse 
3574 // cursor must be in the cell edit control to get key events 
3576 void wxGridColLabelWindow::OnKeyDown( wxKeyEvent
& event 
) 
3578     if ( !m_owner
->GetEventHandler()->ProcessEvent( event 
) ) event
.Skip(); 
3581 void wxGridColLabelWindow::OnKeyUp( wxKeyEvent
& event 
) 
3583     if ( !m_owner
->GetEventHandler()->ProcessEvent( event 
) ) event
.Skip(); 
3588 ////////////////////////////////////////////////////////////////////// 
3590 IMPLEMENT_DYNAMIC_CLASS( wxGridCornerLabelWindow
, wxWindow 
) 
3592 BEGIN_EVENT_TABLE( wxGridCornerLabelWindow
, wxWindow 
) 
3593     EVT_MOUSEWHEEL( wxGridCornerLabelWindow::OnMouseWheel
) 
3594     EVT_MOUSE_EVENTS( wxGridCornerLabelWindow::OnMouseEvent 
) 
3595     EVT_PAINT( wxGridCornerLabelWindow::OnPaint
) 
3596     EVT_KEY_DOWN( wxGridCornerLabelWindow::OnKeyDown 
) 
3597     EVT_KEY_UP( wxGridCornerLabelWindow::OnKeyUp 
) 
3600 wxGridCornerLabelWindow::wxGridCornerLabelWindow( wxGrid 
*parent
, 
3602                                                   const wxPoint 
&pos
, const wxSize 
&size 
) 
3603   : wxWindow( parent
, id
, pos
, size
, wxWANTS_CHARS
|wxBORDER_NONE 
) 
3608 void wxGridCornerLabelWindow::OnPaint( wxPaintEvent
& WXUNUSED(event
) ) 
3612     int client_height 
= 0; 
3613     int client_width 
= 0; 
3614     GetClientSize( &client_width
, &client_height 
); 
3616     dc
.SetPen( wxPen(wxSystemSettings::GetColour(wxSYS_COLOUR_3DDKSHADOW
),1, wxSOLID
) ); 
3617     dc
.DrawLine( client_width
-1, client_height
-1, client_width
-1, 0 ); 
3618     dc
.DrawLine( client_width
-1, client_height
-1, 0, client_height
-1 ); 
3619     dc
.DrawLine( 0, 0, client_width
, 0 ); 
3620     dc
.DrawLine( 0, 0, 0, client_height 
); 
3622     dc
.SetPen( *wxWHITE_PEN 
); 
3623     dc
.DrawLine( 1, 1, client_width
-1, 1 ); 
3624     dc
.DrawLine( 1, 1, 1, client_height
-1 ); 
3628 void wxGridCornerLabelWindow::OnMouseEvent( wxMouseEvent
& event 
) 
3630     m_owner
->ProcessCornerLabelMouseEvent( event 
); 
3634 void wxGridCornerLabelWindow::OnMouseWheel( wxMouseEvent
& event 
) 
3636     m_owner
->GetEventHandler()->ProcessEvent(event
); 
3639 // This seems to be required for wxMotif otherwise the mouse 
3640 // cursor must be in the cell edit control to get key events 
3642 void wxGridCornerLabelWindow::OnKeyDown( wxKeyEvent
& event 
) 
3644     if ( !m_owner
->GetEventHandler()->ProcessEvent( event 
) ) event
.Skip(); 
3647 void wxGridCornerLabelWindow::OnKeyUp( wxKeyEvent
& event 
) 
3649     if ( !m_owner
->GetEventHandler()->ProcessEvent( event 
) ) event
.Skip(); 
3654 ////////////////////////////////////////////////////////////////////// 
3656 IMPLEMENT_DYNAMIC_CLASS( wxGridWindow
, wxWindow 
) 
3658 BEGIN_EVENT_TABLE( wxGridWindow
, wxWindow 
) 
3659     EVT_PAINT( wxGridWindow::OnPaint 
) 
3660     EVT_MOUSEWHEEL( wxGridWindow::OnMouseWheel
) 
3661     EVT_MOUSE_EVENTS( wxGridWindow::OnMouseEvent 
) 
3662     EVT_KEY_DOWN( wxGridWindow::OnKeyDown 
) 
3663     EVT_KEY_UP( wxGridWindow::OnKeyUp 
) 
3664     EVT_ERASE_BACKGROUND( wxGridWindow::OnEraseBackground 
) 
3667 wxGridWindow::wxGridWindow( wxGrid 
*parent
, 
3668                             wxGridRowLabelWindow 
*rowLblWin
, 
3669                             wxGridColLabelWindow 
*colLblWin
, 
3672                             const wxSize 
&size 
) 
3673             : wxWindow( parent
, id
, pos
, size
, wxWANTS_CHARS 
| wxBORDER_NONE 
| wxCLIP_CHILDREN
, 
3674                         wxT("grid window") ) 
3678     m_rowLabelWin 
= rowLblWin
; 
3679     m_colLabelWin 
= colLblWin
; 
3680     SetBackgroundColour(_T("WHITE")); 
3684 wxGridWindow::~wxGridWindow() 
3689 void wxGridWindow::OnPaint( wxPaintEvent 
&WXUNUSED(event
) ) 
3691     wxPaintDC 
dc( this ); 
3692     m_owner
->PrepareDC( dc 
); 
3693     wxRegion reg 
= GetUpdateRegion(); 
3694     wxGridCellCoordsArray DirtyCells 
= m_owner
->CalcCellsExposed( reg 
); 
3695     m_owner
->DrawGridCellArea( dc 
, DirtyCells
); 
3696 #if WXGRID_DRAW_LINES 
3697     m_owner
->DrawAllGridLines( dc
, reg 
); 
3699     m_owner
->DrawGridSpace( dc 
); 
3700     m_owner
->DrawHighlight( dc 
, DirtyCells 
); 
3704 void wxGridWindow::ScrollWindow( int dx
, int dy
, const wxRect 
*rect 
) 
3706     wxWindow::ScrollWindow( dx
, dy
, rect 
); 
3707     m_rowLabelWin
->ScrollWindow( 0, dy
, rect 
); 
3708     m_colLabelWin
->ScrollWindow( dx
, 0, rect 
); 
3712 void wxGridWindow::OnMouseEvent( wxMouseEvent
& event 
) 
3714     m_owner
->ProcessGridCellMouseEvent( event 
); 
3717 void wxGridWindow::OnMouseWheel( wxMouseEvent
& event 
) 
3719     m_owner
->GetEventHandler()->ProcessEvent(event
); 
3722 // This seems to be required for wxMotif/wxGTK otherwise the mouse 
3723 // cursor must be in the cell edit control to get key events 
3725 void wxGridWindow::OnKeyDown( wxKeyEvent
& event 
) 
3727     if ( !m_owner
->GetEventHandler()->ProcessEvent( event 
) ) event
.Skip(); 
3730 void wxGridWindow::OnKeyUp( wxKeyEvent
& event 
) 
3732     if ( !m_owner
->GetEventHandler()->ProcessEvent( event 
) ) event
.Skip(); 
3735 void wxGridWindow::OnEraseBackground( wxEraseEvent
& WXUNUSED(event
) ) 
3740 ////////////////////////////////////////////////////////////////////// 
3742 // Internal Helper function for computing row or column from some 
3743 // (unscrolled) coordinate value, using either 
3744 // m_defaultRowHeight/m_defaultColWidth or binary search on array 
3745 // of m_rowBottoms/m_ColRights to speed up the search! 
3747 // Internal helper macros for simpler use of that function 
3749 static int CoordToRowOrCol(int coord
, int defaultDist
, int minDist
, 
3750                            const wxArrayInt
& BorderArray
, int nMax
, 
3753 #define internalXToCol(x) CoordToRowOrCol(x, m_defaultColWidth, \ 
3754                                           m_minAcceptableColWidth, \ 
3755                                           m_colRights, m_numCols, TRUE) 
3756 #define internalYToRow(y) CoordToRowOrCol(y, m_defaultRowHeight, \ 
3757                                           m_minAcceptableRowHeight, \ 
3758                                           m_rowBottoms, m_numRows, TRUE) 
3759 ///////////////////////////////////////////////////////////////////// 
3761 IMPLEMENT_DYNAMIC_CLASS( wxGrid
, wxScrolledWindow 
) 
3763 BEGIN_EVENT_TABLE( wxGrid
, wxScrolledWindow 
) 
3764     EVT_PAINT( wxGrid::OnPaint 
) 
3765     EVT_SIZE( wxGrid::OnSize 
) 
3766     EVT_KEY_DOWN( wxGrid::OnKeyDown 
) 
3767     EVT_KEY_UP( wxGrid::OnKeyUp 
) 
3768     EVT_ERASE_BACKGROUND( wxGrid::OnEraseBackground 
) 
3771 wxGrid::wxGrid( wxWindow 
*parent
, 
3776                  const wxString
& name 
) 
3777   : wxScrolledWindow( parent
, id
, pos
, size
, (style 
| wxWANTS_CHARS
), name 
), 
3778     m_colMinWidths(GRID_HASH_SIZE
), 
3779     m_rowMinHeights(GRID_HASH_SIZE
) 
3787     // Must do this or ~wxScrollHelper will pop the wrong event handler 
3788     SetTargetWindow(this); 
3790     wxSafeDecRef(m_defaultCellAttr
); 
3792 #ifdef DEBUG_ATTR_CACHE 
3793     size_t total 
= gs_nAttrCacheHits 
+ gs_nAttrCacheMisses
; 
3794     wxPrintf(_T("wxGrid attribute cache statistics: " 
3795                 "total: %u, hits: %u (%u%%)\n"), 
3796              total
, gs_nAttrCacheHits
, 
3797              total 
? (gs_nAttrCacheHits
*100) / total 
: 0); 
3803     delete m_typeRegistry
; 
3809 // ----- internal init and update functions 
3812 void wxGrid::Create() 
3814     m_created 
= FALSE
;    // set to TRUE by CreateGrid 
3816     m_table        
= (wxGridTableBase 
*) NULL
; 
3819     m_cellEditCtrlEnabled 
= FALSE
; 
3821     m_defaultCellAttr 
= new wxGridCellAttr(); 
3823     // Set default cell attributes 
3824     m_defaultCellAttr
->SetDefAttr(m_defaultCellAttr
); 
3825     m_defaultCellAttr
->SetKind(wxGridCellAttr::Default
); 
3826     m_defaultCellAttr
->SetFont(GetFont()); 
3827     m_defaultCellAttr
->SetAlignment(wxALIGN_LEFT
, wxALIGN_TOP
); 
3828     m_defaultCellAttr
->SetTextColour( 
3829         wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT
)); 
3830     m_defaultCellAttr
->SetBackgroundColour( 
3831         wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW
)); 
3832     m_defaultCellAttr
->SetRenderer(new wxGridCellStringRenderer
); 
3833     m_defaultCellAttr
->SetEditor(new wxGridCellTextEditor
); 
3838     m_currentCellCoords 
= wxGridNoCellCoords
; 
3840     m_rowLabelWidth 
= WXGRID_DEFAULT_ROW_LABEL_WIDTH
; 
3841     m_colLabelHeight 
= WXGRID_DEFAULT_COL_LABEL_HEIGHT
; 
3843     // create the type registry 
3844     m_typeRegistry 
= new wxGridTypeRegistry
; 
3847     // subwindow components that make up the wxGrid 
3848     m_cornerLabelWin 
= new wxGridCornerLabelWindow( this, 
3853     m_rowLabelWin 
= new wxGridRowLabelWindow( this, 
3858     m_colLabelWin 
= new wxGridColLabelWindow( this, 
3863     m_gridWin 
= new wxGridWindow( this, 
3870     SetTargetWindow( m_gridWin 
); 
3876 bool wxGrid::CreateGrid( int numRows
, int numCols
, 
3877                          wxGrid::wxGridSelectionModes selmode 
) 
3879     wxCHECK_MSG( !m_created
, 
3881                  wxT("wxGrid::CreateGrid or wxGrid::SetTable called more than once") ); 
3883     m_numRows 
= numRows
; 
3884     m_numCols 
= numCols
; 
3886     m_table 
= new wxGridStringTable( m_numRows
, m_numCols 
); 
3887     m_table
->SetView( this ); 
3889     m_selection 
= new wxGridSelection( this, selmode 
); 
3898 void wxGrid::SetSelectionMode(wxGrid::wxGridSelectionModes selmode
) 
3900     wxCHECK_RET( m_created
, 
3901                  wxT("Called wxGrid::SetSelectionMode() before calling CreateGrid()") ); 
3903     m_selection
->SetSelectionMode( selmode 
); 
3906 wxGrid::wxGridSelectionModes 
wxGrid::GetSelectionMode() const 
3908     wxCHECK_MSG( m_created
, wxGrid::wxGridSelectCells
, 
3909                  wxT("Called wxGrid::GetSelectionMode() before calling CreateGrid()") ); 
3911     return m_selection
->GetSelectionMode(); 
3914 bool wxGrid::SetTable( wxGridTableBase 
*table
, bool takeOwnership
, 
3915                        wxGrid::wxGridSelectionModes selmode 
) 
3919         // stop all processing  
3924             wxGridTableBase 
*t
=m_table
; 
3937         m_numRows 
= table
->GetNumberRows(); 
3938         m_numCols 
= table
->GetNumberCols(); 
3941         m_table
->SetView( this ); 
3944         m_selection 
= new wxGridSelection( this, selmode 
); 
3957     m_rowLabelWidth  
= WXGRID_DEFAULT_ROW_LABEL_WIDTH
; 
3958     m_colLabelHeight 
= WXGRID_DEFAULT_COL_LABEL_HEIGHT
; 
3960     if ( m_rowLabelWin 
) 
3962         m_labelBackgroundColour 
= m_rowLabelWin
->GetBackgroundColour(); 
3966         m_labelBackgroundColour 
= wxColour( _T("WHITE") ); 
3969     m_labelTextColour 
= wxColour( _T("BLACK") ); 
3972     m_attrCache
.row 
= -1; 
3973     m_attrCache
.col 
= -1; 
3974     m_attrCache
.attr 
= NULL
; 
3976     // TODO: something better than this ? 
3978     m_labelFont 
= this->GetFont(); 
3979     m_labelFont
.SetWeight( wxBOLD 
); 
3981     m_rowLabelHorizAlign 
= wxALIGN_CENTRE
; 
3982     m_rowLabelVertAlign  
= wxALIGN_CENTRE
; 
3984     m_colLabelHorizAlign 
= wxALIGN_CENTRE
; 
3985     m_colLabelVertAlign  
= wxALIGN_CENTRE
; 
3986     m_colLabelTextOrientation 
= wxHORIZONTAL
; 
3988     m_defaultColWidth  
= WXGRID_DEFAULT_COL_WIDTH
; 
3989     m_defaultRowHeight 
= m_gridWin
->GetCharHeight(); 
3991     m_minAcceptableColWidth  
= WXGRID_MIN_COL_WIDTH
; 
3992     m_minAcceptableRowHeight 
= WXGRID_MIN_ROW_HEIGHT
; 
3994 #if defined(__WXMOTIF__) || defined(__WXGTK__)  // see also text ctrl sizing in ShowCellEditControl() 
3995     m_defaultRowHeight 
+= 8; 
3997     m_defaultRowHeight 
+= 4; 
4000     m_gridLineColour 
= wxColour( 192,192,192 ); 
4001     m_gridLinesEnabled 
= TRUE
; 
4002     m_cellHighlightColour 
= *wxBLACK
; 
4003     m_cellHighlightPenWidth 
= 2; 
4004     m_cellHighlightROPenWidth 
= 1; 
4006     m_cursorMode  
= WXGRID_CURSOR_SELECT_CELL
; 
4007     m_winCapture 
= (wxWindow 
*)NULL
; 
4008     m_canDragRowSize 
= TRUE
; 
4009     m_canDragColSize 
= TRUE
; 
4010     m_canDragGridSize 
= TRUE
; 
4012     m_dragRowOrCol 
= -1; 
4013     m_isDragging 
= FALSE
; 
4014     m_startDragPos 
= wxDefaultPosition
; 
4016     m_waitForSlowClick 
= FALSE
; 
4018     m_rowResizeCursor 
= wxCursor( wxCURSOR_SIZENS 
); 
4019     m_colResizeCursor 
= wxCursor( wxCURSOR_SIZEWE 
); 
4021     m_currentCellCoords 
= wxGridNoCellCoords
; 
4023     m_selectingTopLeft 
= wxGridNoCellCoords
; 
4024     m_selectingBottomRight 
= wxGridNoCellCoords
; 
4025     m_selectionBackground 
= wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT
); 
4026     m_selectionForeground 
= wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHTTEXT
); 
4028     m_editable 
= TRUE
;  // default for whole grid 
4030     m_inOnKeyDown 
= FALSE
; 
4037 // ---------------------------------------------------------------------------- 
4038 // the idea is to call these functions only when necessary because they create 
4039 // quite big arrays which eat memory mostly unnecessary - in particular, if 
4040 // default widths/heights are used for all rows/columns, we may not use these 
4043 // with some extra code, it should be possible to only store the 
4044 // widths/heights different from default ones but this will be done later... 
4045 // ---------------------------------------------------------------------------- 
4047 void wxGrid::InitRowHeights() 
4049     m_rowHeights
.Empty(); 
4050     m_rowBottoms
.Empty(); 
4052     m_rowHeights
.Alloc( m_numRows 
); 
4053     m_rowBottoms
.Alloc( m_numRows 
); 
4057     m_rowHeights
.Add( m_defaultRowHeight
, m_numRows 
); 
4059     for ( int i 
= 0;  i 
< m_numRows
;  i
++ ) 
4061         rowBottom 
+= m_defaultRowHeight
; 
4062         m_rowBottoms
.Add( rowBottom 
); 
4066 void wxGrid::InitColWidths() 
4068     m_colWidths
.Empty(); 
4069     m_colRights
.Empty(); 
4071     m_colWidths
.Alloc( m_numCols 
); 
4072     m_colRights
.Alloc( m_numCols 
); 
4075     m_colWidths
.Add( m_defaultColWidth
, m_numCols 
); 
4077     for ( int i 
= 0;  i 
< m_numCols
;  i
++ ) 
4079         colRight 
+= m_defaultColWidth
; 
4080         m_colRights
.Add( colRight 
); 
4084 int wxGrid::GetColWidth(int col
) const 
4086     return m_colWidths
.IsEmpty() ? m_defaultColWidth 
: m_colWidths
[col
]; 
4089 int wxGrid::GetColLeft(int col
) const 
4091     return m_colRights
.IsEmpty() ? col 
* m_defaultColWidth
 
4092                                  : m_colRights
[col
] - m_colWidths
[col
]; 
4095 int wxGrid::GetColRight(int col
) const 
4097     return m_colRights
.IsEmpty() ? (col 
+ 1) * m_defaultColWidth
 
4101 int wxGrid::GetRowHeight(int row
) const 
4103     return m_rowHeights
.IsEmpty() ? m_defaultRowHeight 
: m_rowHeights
[row
]; 
4106 int wxGrid::GetRowTop(int row
) const 
4108     return m_rowBottoms
.IsEmpty() ? row 
* m_defaultRowHeight
 
4109                                   : m_rowBottoms
[row
] - m_rowHeights
[row
]; 
4112 int wxGrid::GetRowBottom(int row
) const 
4114     return m_rowBottoms
.IsEmpty() ? (row 
+ 1) * m_defaultRowHeight
 
4115                                   : m_rowBottoms
[row
]; 
4118 void wxGrid::CalcDimensions() 
4121     GetClientSize( &cw
, &ch 
); 
4123     if ( m_rowLabelWin
->IsShown() ) 
4124         cw 
-= m_rowLabelWidth
; 
4125     if ( m_colLabelWin
->IsShown() ) 
4126         ch 
-= m_colLabelHeight
; 
4129     int w 
= m_numCols 
> 0 ? GetColRight(m_numCols 
- 1) + m_extraWidth 
+ 1 : 0; 
4130     int h 
= m_numRows 
> 0 ? GetRowBottom(m_numRows 
- 1) + m_extraHeight 
+ 1 : 0; 
4132     // take into account editor if shown 
4133     if( IsCellEditControlShown() ) 
4136       int r 
= m_currentCellCoords
.GetRow(); 
4137       int c 
= m_currentCellCoords
.GetCol(); 
4138       int x 
= GetColLeft(c
); 
4139       int y 
= GetRowTop(r
); 
4141       // how big is the editor 
4142       wxGridCellAttr
* attr 
= GetCellAttr(r
, c
); 
4143       wxGridCellEditor
* editor 
= attr
->GetEditor(this, r
, c
); 
4144       editor
->GetControl()->GetSize(&w2
, &h2
); 
4147       if( w2 
> w 
) w 
= w2
; 
4148       if( h2 
> h 
) h 
= h2
; 
4153     // preserve (more or less) the previous position 
4155     GetViewStart( &x
, &y 
); 
4157     // maybe we don't need scrollbars at all? 
4159     // also adjust the position to be valid for the new scroll rangs 
4180     // do set scrollbar parameters 
4181     SetScrollbars( GRID_SCROLL_LINE_X
, GRID_SCROLL_LINE_Y
, 
4182                    GetScrollX(w
), GetScrollY(h
), x
, y
, 
4183                    GetBatchCount() != 0); 
4185     // if our OnSize() hadn't been called (it would if we have scrollbars), we 
4186     // still must reposition the children 
4191 void wxGrid::CalcWindowSizes() 
4194     GetClientSize( &cw
, &ch 
); 
4196     if ( m_cornerLabelWin
->IsShown() ) 
4197         m_cornerLabelWin
->SetSize( 0, 0, m_rowLabelWidth
, m_colLabelHeight 
); 
4199     if ( m_colLabelWin
->IsShown() ) 
4200         m_colLabelWin
->SetSize( m_rowLabelWidth
, 0, cw
-m_rowLabelWidth
, m_colLabelHeight
); 
4202     if ( m_rowLabelWin
->IsShown() ) 
4203         m_rowLabelWin
->SetSize( 0, m_colLabelHeight
, m_rowLabelWidth
, ch
-m_colLabelHeight
); 
4205     if ( m_gridWin
->IsShown() ) 
4206         m_gridWin
->SetSize( m_rowLabelWidth
, m_colLabelHeight
, cw
-m_rowLabelWidth
, ch
-m_colLabelHeight
); 
4210 // this is called when the grid table sends a message to say that it 
4211 // has been redimensioned 
4213 bool wxGrid::Redimension( wxGridTableMessage
& msg 
) 
4216     bool result 
= FALSE
; 
4218     // Clear the attribute cache as the attribute might refer to a different 
4219     // cell than stored in the cache after adding/removing rows/columns. 
4221     // By the same reasoning, the editor should be dismissed if columns are 
4222     // added or removed. And for consistency, it should IMHO always be 
4223     // removed, not only if the cell "underneath" it actually changes. 
4224     // For now, I intentionally do not save the editor's content as the 
4225     // cell it might want to save that stuff to might no longer exist. 
4226     HideCellEditControl(); 
4228     // if we were using the default widths/heights so far, we must change them 
4230     if ( m_colWidths
.IsEmpty() ) 
4235     if ( m_rowHeights
.IsEmpty() ) 
4241     switch ( msg
.GetId() ) 
4243         case wxGRIDTABLE_NOTIFY_ROWS_INSERTED
: 
4245             size_t pos 
= msg
.GetCommandInt(); 
4246             int numRows 
= msg
.GetCommandInt2(); 
4248             m_numRows 
+= numRows
; 
4250             if ( !m_rowHeights
.IsEmpty() ) 
4252                 m_rowHeights
.Insert( m_defaultRowHeight
, pos
, numRows 
); 
4253                 m_rowBottoms
.Insert( 0, pos
, numRows 
); 
4256                 if ( pos 
> 0 ) bottom 
= m_rowBottoms
[pos
-1]; 
4258                 for ( i 
= pos
;  i 
< m_numRows
;  i
++ ) 
4260                     bottom 
+= m_rowHeights
[i
]; 
4261                     m_rowBottoms
[i
] = bottom
; 
4264             if ( m_currentCellCoords 
== wxGridNoCellCoords 
) 
4266                 // if we have just inserted cols into an empty grid the current 
4267                 // cell will be undefined... 
4269                 SetCurrentCell( 0, 0 ); 
4273                 m_selection
->UpdateRows( pos
, numRows 
); 
4274             wxGridCellAttrProvider 
* attrProvider 
= m_table
->GetAttrProvider(); 
4276                 attrProvider
->UpdateAttrRows( pos
, numRows 
); 
4278             if ( !GetBatchCount() ) 
4281                 m_rowLabelWin
->Refresh(); 
4287         case wxGRIDTABLE_NOTIFY_ROWS_APPENDED
: 
4289             int numRows 
= msg
.GetCommandInt(); 
4290             int oldNumRows 
= m_numRows
; 
4291             m_numRows 
+= numRows
; 
4293             if ( !m_rowHeights
.IsEmpty() ) 
4295                 m_rowHeights
.Add( m_defaultRowHeight
, numRows 
); 
4296                 m_rowBottoms
.Add( 0, numRows 
); 
4299                 if ( oldNumRows 
> 0 ) bottom 
= m_rowBottoms
[oldNumRows
-1]; 
4301                 for ( i 
= oldNumRows
;  i 
< m_numRows
;  i
++ ) 
4303                     bottom 
+= m_rowHeights
[i
]; 
4304                     m_rowBottoms
[i
] = bottom
; 
4307             if ( m_currentCellCoords 
== wxGridNoCellCoords 
) 
4309                 // if we have just inserted cols into an empty grid the current 
4310                 // cell will be undefined... 
4312                 SetCurrentCell( 0, 0 ); 
4314             if ( !GetBatchCount() ) 
4317                 m_rowLabelWin
->Refresh(); 
4323         case wxGRIDTABLE_NOTIFY_ROWS_DELETED
: 
4325             size_t pos 
= msg
.GetCommandInt(); 
4326             int numRows 
= msg
.GetCommandInt2(); 
4327             m_numRows 
-= numRows
; 
4329             if ( !m_rowHeights
.IsEmpty() ) 
4331                 m_rowHeights
.RemoveAt( pos
, numRows 
); 
4332                 m_rowBottoms
.RemoveAt( pos
, numRows 
); 
4335                 for ( i 
= 0;  i 
< m_numRows
;  i
++ ) 
4337                     h 
+= m_rowHeights
[i
]; 
4338                     m_rowBottoms
[i
] = h
; 
4343                 m_currentCellCoords 
= wxGridNoCellCoords
; 
4347                 if ( m_currentCellCoords
.GetRow() >= m_numRows 
) 
4348                     m_currentCellCoords
.Set( 0, 0 ); 
4352                 m_selection
->UpdateRows( pos
, -((int)numRows
) ); 
4353             wxGridCellAttrProvider 
* attrProvider 
= m_table
->GetAttrProvider(); 
4355                 attrProvider
->UpdateAttrRows( pos
, -((int)numRows
) ); 
4356 // ifdef'd out following patch from Paul Gammans 
4358                 // No need to touch column attributes, unless we 
4359                 // removed _all_ rows, in this case, we remove 
4360                 // all column attributes. 
4361                 // I hate to do this here, but the 
4362                 // needed data is not available inside UpdateAttrRows. 
4363                 if ( !GetNumberRows() ) 
4364                     attrProvider
->UpdateAttrCols( 0, -GetNumberCols() ); 
4367             if ( !GetBatchCount() ) 
4370                 m_rowLabelWin
->Refresh(); 
4376         case wxGRIDTABLE_NOTIFY_COLS_INSERTED
: 
4378             size_t pos 
= msg
.GetCommandInt(); 
4379             int numCols 
= msg
.GetCommandInt2(); 
4380             m_numCols 
+= numCols
; 
4382             if ( !m_colWidths
.IsEmpty() ) 
4384                 m_colWidths
.Insert( m_defaultColWidth
, pos
, numCols 
); 
4385                 m_colRights
.Insert( 0, pos
, numCols 
); 
4388                 if ( pos 
> 0 ) right 
= m_colRights
[pos
-1]; 
4390                 for ( i 
= pos
;  i 
< m_numCols
;  i
++ ) 
4392                     right 
+= m_colWidths
[i
]; 
4393                     m_colRights
[i
] = right
; 
4396             if ( m_currentCellCoords 
== wxGridNoCellCoords 
) 
4398                 // if we have just inserted cols into an empty grid the current 
4399                 // cell will be undefined... 
4401                 SetCurrentCell( 0, 0 ); 
4405                 m_selection
->UpdateCols( pos
, numCols 
); 
4406             wxGridCellAttrProvider 
* attrProvider 
= m_table
->GetAttrProvider(); 
4408                 attrProvider
->UpdateAttrCols( pos
, numCols 
); 
4409             if ( !GetBatchCount() ) 
4412                 m_colLabelWin
->Refresh(); 
4419         case wxGRIDTABLE_NOTIFY_COLS_APPENDED
: 
4421             int numCols 
= msg
.GetCommandInt(); 
4422             int oldNumCols 
= m_numCols
; 
4423             m_numCols 
+= numCols
; 
4424             if ( !m_colWidths
.IsEmpty() ) 
4426                 m_colWidths
.Add( m_defaultColWidth
, numCols 
); 
4427                 m_colRights
.Add( 0, numCols 
); 
4430                 if ( oldNumCols 
> 0 ) right 
= m_colRights
[oldNumCols
-1]; 
4432                 for ( i 
= oldNumCols
;  i 
< m_numCols
;  i
++ ) 
4434                     right 
+= m_colWidths
[i
]; 
4435                     m_colRights
[i
] = right
; 
4438             if ( m_currentCellCoords 
== wxGridNoCellCoords 
) 
4440                 // if we have just inserted cols into an empty grid the current 
4441                 // cell will be undefined... 
4443                 SetCurrentCell( 0, 0 ); 
4445             if ( !GetBatchCount() ) 
4448                 m_colLabelWin
->Refresh(); 
4454         case wxGRIDTABLE_NOTIFY_COLS_DELETED
: 
4456             size_t pos 
= msg
.GetCommandInt(); 
4457             int numCols 
= msg
.GetCommandInt2(); 
4458             m_numCols 
-= numCols
; 
4460             if ( !m_colWidths
.IsEmpty() ) 
4462                 m_colWidths
.RemoveAt( pos
, numCols 
); 
4463                 m_colRights
.RemoveAt( pos
, numCols 
); 
4466                 for ( i 
= 0;  i 
< m_numCols
;  i
++ ) 
4468                     w 
+= m_colWidths
[i
]; 
4474                 m_currentCellCoords 
= wxGridNoCellCoords
; 
4478                 if ( m_currentCellCoords
.GetCol() >= m_numCols 
) 
4479                   m_currentCellCoords
.Set( 0, 0 ); 
4483                 m_selection
->UpdateCols( pos
, -((int)numCols
) ); 
4484             wxGridCellAttrProvider 
* attrProvider 
= m_table
->GetAttrProvider(); 
4486                 attrProvider
->UpdateAttrCols( pos
, -((int)numCols
) ); 
4487 // ifdef'd out following patch from Paul Gammans 
4489                 // No need to touch row attributes, unless we 
4490                 // removed _all_ columns, in this case, we remove 
4491                 // all row attributes. 
4492                 // I hate to do this here, but the 
4493                 // needed data is not available inside UpdateAttrCols. 
4494                 if ( !GetNumberCols() ) 
4495                     attrProvider
->UpdateAttrRows( 0, -GetNumberRows() ); 
4498             if ( !GetBatchCount() ) 
4501                 m_colLabelWin
->Refresh(); 
4508     if (result 
&& !GetBatchCount() ) 
4509         m_gridWin
->Refresh(); 
4514 wxArrayInt 
wxGrid::CalcRowLabelsExposed( const wxRegion
& reg 
) 
4516     wxRegionIterator 
iter( reg 
); 
4519     wxArrayInt  rowlabels
; 
4526         // TODO: remove this when we can... 
4527         // There is a bug in wxMotif that gives garbage update 
4528         // rectangles if you jump-scroll a long way by clicking the 
4529         // scrollbar with middle button.  This is a work-around 
4531 #if defined(__WXMOTIF__) 
4533         m_gridWin
->GetClientSize( &cw
, &ch 
); 
4534         if ( r
.GetTop() > ch 
) r
.SetTop( 0 ); 
4535         r
.SetBottom( wxMin( r
.GetBottom(), ch 
) ); 
4538         // logical bounds of update region 
4541         CalcUnscrolledPosition( 0, r
.GetTop(), &dummy
, &top 
); 
4542         CalcUnscrolledPosition( 0, r
.GetBottom(), &dummy
, &bottom 
); 
4544         // find the row labels within these bounds 
4547         for ( row 
= internalYToRow(top
);  row 
< m_numRows
;  row
++ ) 
4549             if ( GetRowBottom(row
) < top 
) 
4552             if ( GetRowTop(row
) > bottom 
) 
4555             rowlabels
.Add( row 
); 
4565 wxArrayInt 
wxGrid::CalcColLabelsExposed( const wxRegion
& reg 
) 
4567     wxRegionIterator 
iter( reg 
); 
4570     wxArrayInt colLabels
; 
4577         // TODO: remove this when we can... 
4578         // There is a bug in wxMotif that gives garbage update 
4579         // rectangles if you jump-scroll a long way by clicking the 
4580         // scrollbar with middle button.  This is a work-around 
4582 #if defined(__WXMOTIF__) 
4584         m_gridWin
->GetClientSize( &cw
, &ch 
); 
4585         if ( r
.GetLeft() > cw 
) r
.SetLeft( 0 ); 
4586         r
.SetRight( wxMin( r
.GetRight(), cw 
) ); 
4589         // logical bounds of update region 
4592         CalcUnscrolledPosition( r
.GetLeft(), 0, &left
, &dummy 
); 
4593         CalcUnscrolledPosition( r
.GetRight(), 0, &right
, &dummy 
); 
4595         // find the cells within these bounds 
4598         for ( col 
= internalXToCol(left
);  col 
< m_numCols
;  col
++ ) 
4600             if ( GetColRight(col
) < left 
) 
4603             if ( GetColLeft(col
) > right 
) 
4606             colLabels
.Add( col 
); 
4615 wxGridCellCoordsArray 
wxGrid::CalcCellsExposed( const wxRegion
& reg 
) 
4617     wxRegionIterator 
iter( reg 
); 
4620     wxGridCellCoordsArray  cellsExposed
; 
4622     int left
, top
, right
, bottom
; 
4627         // TODO: remove this when we can... 
4628         // There is a bug in wxMotif that gives garbage update 
4629         // rectangles if you jump-scroll a long way by clicking the 
4630         // scrollbar with middle button.  This is a work-around 
4632 #if defined(__WXMOTIF__) 
4634         m_gridWin
->GetClientSize( &cw
, &ch 
); 
4635         if ( r
.GetTop() > ch 
) r
.SetTop( 0 ); 
4636         if ( r
.GetLeft() > cw 
) r
.SetLeft( 0 ); 
4637         r
.SetRight( wxMin( r
.GetRight(), cw 
) ); 
4638         r
.SetBottom( wxMin( r
.GetBottom(), ch 
) ); 
4641         // logical bounds of update region 
4643         CalcUnscrolledPosition( r
.GetLeft(), r
.GetTop(), &left
, &top 
); 
4644         CalcUnscrolledPosition( r
.GetRight(), r
.GetBottom(), &right
, &bottom 
); 
4646         // find the cells within these bounds 
4649         for ( row 
= internalYToRow(top
);  row 
< m_numRows
;  row
++ ) 
4651             if ( GetRowBottom(row
) <= top 
) 
4654             if ( GetRowTop(row
) > bottom 
) 
4657             for ( col 
= internalXToCol(left
);  col 
< m_numCols
;  col
++ ) 
4659                 if ( GetColRight(col
) <= left 
) 
4662                 if ( GetColLeft(col
) > right 
) 
4665                 cellsExposed
.Add( wxGridCellCoords( row
, col 
) ); 
4672     return cellsExposed
; 
4676 void wxGrid::ProcessRowLabelMouseEvent( wxMouseEvent
& event 
) 
4679     wxPoint 
pos( event
.GetPosition() ); 
4680     CalcUnscrolledPosition( pos
.x
, pos
.y
, &x
, &y 
); 
4682     if ( event
.Dragging() ) 
4686             m_isDragging 
= TRUE
; 
4687             m_rowLabelWin
->CaptureMouse(); 
4690         if ( event
.LeftIsDown() ) 
4692             switch( m_cursorMode 
) 
4694                 case WXGRID_CURSOR_RESIZE_ROW
: 
4696                     int cw
, ch
, left
, dummy
; 
4697                     m_gridWin
->GetClientSize( &cw
, &ch 
); 
4698                     CalcUnscrolledPosition( 0, 0, &left
, &dummy 
); 
4700                     wxClientDC 
dc( m_gridWin 
); 
4703                                GetRowTop(m_dragRowOrCol
) + 
4704                                GetRowMinimalHeight(m_dragRowOrCol
) ); 
4705                     dc
.SetLogicalFunction(wxINVERT
); 
4706                     if ( m_dragLastPos 
>= 0 ) 
4708                         dc
.DrawLine( left
, m_dragLastPos
, left
+cw
, m_dragLastPos 
); 
4710                     dc
.DrawLine( left
, y
, left
+cw
, y 
); 
4715                 case WXGRID_CURSOR_SELECT_ROW
: 
4716                     if ( (row 
= YToRow( y 
)) >= 0 ) 
4720                             m_selection
->SelectRow( row
, 
4721                                                     event
.ControlDown(), 
4728                 // default label to suppress warnings about "enumeration value 
4729                 // 'xxx' not handled in switch 
4737     if ( m_isDragging 
&& (event
.Entering() || event
.Leaving()) ) 
4742         if (m_rowLabelWin
->HasCapture()) m_rowLabelWin
->ReleaseMouse(); 
4743         m_isDragging 
= FALSE
; 
4746     // ------------ Entering or leaving the window 
4748     if ( event
.Entering() || event
.Leaving() ) 
4750         ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
, m_rowLabelWin
); 
4754     // ------------ Left button pressed 
4756     else if ( event
.LeftDown() ) 
4758         // don't send a label click event for a hit on the 
4759         // edge of the row label - this is probably the user 
4760         // wanting to resize the row 
4762         if ( YToEdgeOfRow(y
) < 0 ) 
4766                  !SendEvent( wxEVT_GRID_LABEL_LEFT_CLICK
, row
, -1, event 
) ) 
4768                 if ( !event
.ShiftDown() && !event
.ControlDown() ) 
4772                     if ( event
.ShiftDown() ) 
4774                         m_selection
->SelectBlock( m_currentCellCoords
.GetRow(), 
4777                                                   GetNumberCols() - 1, 
4778                                                   event
.ControlDown(), 
4785                         m_selection
->SelectRow( row
, 
4786                                                 event
.ControlDown(), 
4793                 ChangeCursorMode(WXGRID_CURSOR_SELECT_ROW
, m_rowLabelWin
); 
4798             // starting to drag-resize a row 
4800             if ( CanDragRowSize() ) 
4801                 ChangeCursorMode(WXGRID_CURSOR_RESIZE_ROW
, m_rowLabelWin
); 
4806     // ------------ Left double click 
4808     else if (event
.LeftDClick() ) 
4810         int row 
= YToEdgeOfRow(y
); 
4815                  !SendEvent( wxEVT_GRID_LABEL_LEFT_DCLICK
, row
, -1, event 
) ) 
4817                 // no default action at the moment 
4822             // adjust row height depending on label text 
4823             AutoSizeRowLabelSize( row 
); 
4825             ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
, m_colLabelWin
); 
4831     // ------------ Left button released 
4833     else if ( event
.LeftUp() ) 
4835         if ( m_cursorMode 
== WXGRID_CURSOR_RESIZE_ROW 
) 
4837             DoEndDragResizeRow(); 
4839             // Note: we are ending the event *after* doing 
4840             // default processing in this case 
4842             SendEvent( wxEVT_GRID_ROW_SIZE
, m_dragRowOrCol
, -1, event 
); 
4845         ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
, m_rowLabelWin
); 
4850     // ------------ Right button down 
4852     else if ( event
.RightDown() ) 
4856             !SendEvent( wxEVT_GRID_LABEL_RIGHT_CLICK
, row
, -1, event 
) ) 
4858             // no default action at the moment 
4863     // ------------ Right double click 
4865     else if ( event
.RightDClick() ) 
4869              !SendEvent( wxEVT_GRID_LABEL_RIGHT_DCLICK
, row
, -1, event 
) ) 
4871             // no default action at the moment 
4876     // ------------ No buttons down and mouse moving 
4878     else if ( event
.Moving() ) 
4880         m_dragRowOrCol 
= YToEdgeOfRow( y 
); 
4881         if ( m_dragRowOrCol 
>= 0 ) 
4883             if ( m_cursorMode 
== WXGRID_CURSOR_SELECT_CELL 
) 
4885                 // don't capture the mouse yet 
4886                 if ( CanDragRowSize() ) 
4887                     ChangeCursorMode(WXGRID_CURSOR_RESIZE_ROW
, m_rowLabelWin
, FALSE
); 
4890         else if ( m_cursorMode 
!= WXGRID_CURSOR_SELECT_CELL 
) 
4892             ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
, m_rowLabelWin
, FALSE
); 
4898 void wxGrid::ProcessColLabelMouseEvent( wxMouseEvent
& event 
) 
4901     wxPoint 
pos( event
.GetPosition() ); 
4902     CalcUnscrolledPosition( pos
.x
, pos
.y
, &x
, &y 
); 
4904     if ( event
.Dragging() ) 
4908             m_isDragging 
= TRUE
; 
4909             m_colLabelWin
->CaptureMouse(); 
4912         if ( event
.LeftIsDown() ) 
4914             switch( m_cursorMode 
) 
4916                 case WXGRID_CURSOR_RESIZE_COL
: 
4918                     int cw
, ch
, dummy
, top
; 
4919                     m_gridWin
->GetClientSize( &cw
, &ch 
); 
4920                     CalcUnscrolledPosition( 0, 0, &dummy
, &top 
); 
4922                     wxClientDC 
dc( m_gridWin 
); 
4925                     x 
= wxMax( x
, GetColLeft(m_dragRowOrCol
) + 
4926                                   GetColMinimalWidth(m_dragRowOrCol
)); 
4927                     dc
.SetLogicalFunction(wxINVERT
); 
4928                     if ( m_dragLastPos 
>= 0 ) 
4930                         dc
.DrawLine( m_dragLastPos
, top
, m_dragLastPos
, top
+ch 
); 
4932                     dc
.DrawLine( x
, top
, x
, top
+ch 
); 
4937                 case WXGRID_CURSOR_SELECT_COL
: 
4938                     if ( (col 
= XToCol( x 
)) >= 0 ) 
4942                             m_selection
->SelectCol( col
, 
4943                                                     event
.ControlDown(), 
4950                 // default label to suppress warnings about "enumeration value 
4951                 // 'xxx' not handled in switch 
4959     if ( m_isDragging 
&& (event
.Entering() || event
.Leaving()) ) 
4964         if (m_colLabelWin
->HasCapture()) m_colLabelWin
->ReleaseMouse(); 
4965         m_isDragging 
= FALSE
; 
4968     // ------------ Entering or leaving the window 
4970     if ( event
.Entering() || event
.Leaving() ) 
4972         ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
, m_colLabelWin
); 
4976     // ------------ Left button pressed 
4978     else if ( event
.LeftDown() ) 
4980         // don't send a label click event for a hit on the 
4981         // edge of the col label - this is probably the user 
4982         // wanting to resize the col 
4984         if ( XToEdgeOfCol(x
) < 0 ) 
4988                  !SendEvent( wxEVT_GRID_LABEL_LEFT_CLICK
, -1, col
, event 
) ) 
4990                 if ( !event
.ShiftDown() && !event
.ControlDown() ) 
4994                     if ( event
.ShiftDown() ) 
4996                         m_selection
->SelectBlock( 0, 
4997                                                   m_currentCellCoords
.GetCol(), 
4998                                                   GetNumberRows() - 1, col
, 
4999                                                   event
.ControlDown(), 
5006                         m_selection
->SelectCol( col
, 
5007                                                 event
.ControlDown(), 
5014                 ChangeCursorMode(WXGRID_CURSOR_SELECT_COL
, m_colLabelWin
); 
5019             // starting to drag-resize a col 
5021             if ( CanDragColSize() ) 
5022                 ChangeCursorMode(WXGRID_CURSOR_RESIZE_COL
, m_colLabelWin
); 
5027     // ------------ Left double click 
5029     if ( event
.LeftDClick() ) 
5031         int col 
= XToEdgeOfCol(x
); 
5036                  ! SendEvent( wxEVT_GRID_LABEL_LEFT_DCLICK
, -1, col
, event 
) ) 
5038                 // no default action at the moment 
5043             // adjust column width depending on label text 
5044             AutoSizeColLabelSize( col 
); 
5046             ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
, m_colLabelWin
); 
5052     // ------------ Left button released 
5054     else if ( event
.LeftUp() ) 
5056         if ( m_cursorMode 
== WXGRID_CURSOR_RESIZE_COL 
) 
5058             DoEndDragResizeCol(); 
5060             // Note: we are ending the event *after* doing 
5061             // default processing in this case 
5063             SendEvent( wxEVT_GRID_COL_SIZE
, -1, m_dragRowOrCol
, event 
); 
5066         ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
, m_colLabelWin
); 
5071     // ------------ Right button down 
5073     else if ( event
.RightDown() ) 
5077              !SendEvent( wxEVT_GRID_LABEL_RIGHT_CLICK
, -1, col
, event 
) ) 
5079             // no default action at the moment 
5084     // ------------ Right double click 
5086     else if ( event
.RightDClick() ) 
5090              !SendEvent( wxEVT_GRID_LABEL_RIGHT_DCLICK
, -1, col
, event 
) ) 
5092             // no default action at the moment 
5097     // ------------ No buttons down and mouse moving 
5099     else if ( event
.Moving() ) 
5101         m_dragRowOrCol 
= XToEdgeOfCol( x 
); 
5102         if ( m_dragRowOrCol 
>= 0 ) 
5104             if ( m_cursorMode 
== WXGRID_CURSOR_SELECT_CELL 
) 
5106                 // don't capture the cursor yet 
5107                 if ( CanDragColSize() ) 
5108                     ChangeCursorMode(WXGRID_CURSOR_RESIZE_COL
, m_colLabelWin
, FALSE
); 
5111         else if ( m_cursorMode 
!= WXGRID_CURSOR_SELECT_CELL 
) 
5113             ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
, m_colLabelWin
, FALSE
); 
5119 void wxGrid::ProcessCornerLabelMouseEvent( wxMouseEvent
& event 
) 
5121     if ( event
.LeftDown() ) 
5123         // indicate corner label by having both row and 
5126         if ( !SendEvent( wxEVT_GRID_LABEL_LEFT_CLICK
, -1, -1, event 
) ) 
5132     else if ( event
.LeftDClick() ) 
5134         SendEvent( wxEVT_GRID_LABEL_LEFT_DCLICK
, -1, -1, event 
); 
5137     else if ( event
.RightDown() ) 
5139         if ( !SendEvent( wxEVT_GRID_LABEL_RIGHT_CLICK
, -1, -1, event 
) ) 
5141             // no default action at the moment 
5145     else if ( event
.RightDClick() ) 
5147         if ( !SendEvent( wxEVT_GRID_LABEL_RIGHT_DCLICK
, -1, -1, event 
) ) 
5149             // no default action at the moment 
5154 void wxGrid::ChangeCursorMode(CursorMode mode
, 
5159     static const wxChar 
*cursorModes
[] = 
5168     wxLogTrace(_T("grid"), 
5169                _T("wxGrid cursor mode (mouse capture for %s): %s -> %s"), 
5170                win 
== m_colLabelWin 
? _T("colLabelWin") 
5171                                     : win 
? _T("rowLabelWin") 
5173                cursorModes
[m_cursorMode
], cursorModes
[mode
]); 
5174 #endif // __WXDEBUG__ 
5176     if ( mode 
== m_cursorMode 
&& 
5177          win 
== m_winCapture 
&& 
5178          captureMouse 
== (m_winCapture 
!= NULL
)) 
5183         // by default use the grid itself 
5189         if (m_winCapture
->HasCapture()) m_winCapture
->ReleaseMouse(); 
5190         m_winCapture 
= (wxWindow 
*)NULL
; 
5193     m_cursorMode 
= mode
; 
5195     switch ( m_cursorMode 
) 
5197         case WXGRID_CURSOR_RESIZE_ROW
: 
5198             win
->SetCursor( m_rowResizeCursor 
); 
5201         case WXGRID_CURSOR_RESIZE_COL
: 
5202             win
->SetCursor( m_colResizeCursor 
); 
5206             win
->SetCursor( *wxSTANDARD_CURSOR 
); 
5209     // we need to capture mouse when resizing 
5210     bool resize 
= m_cursorMode 
== WXGRID_CURSOR_RESIZE_ROW 
|| 
5211                   m_cursorMode 
== WXGRID_CURSOR_RESIZE_COL
; 
5213     if ( captureMouse 
&& resize 
) 
5215         win
->CaptureMouse(); 
5220 void wxGrid::ProcessGridCellMouseEvent( wxMouseEvent
& event 
) 
5223     wxPoint 
pos( event
.GetPosition() ); 
5224     CalcUnscrolledPosition( pos
.x
, pos
.y
, &x
, &y 
); 
5226     wxGridCellCoords coords
; 
5227     XYToCell( x
, y
, coords 
); 
5229     int cell_rows
, cell_cols
; 
5230     GetCellSize( coords
.GetRow(), coords
.GetCol(), &cell_rows
, &cell_cols 
); 
5231     if ((cell_rows 
< 0) || (cell_cols 
< 0)) 
5233         coords
.SetRow(coords
.GetRow() + cell_rows
); 
5234         coords
.SetCol(coords
.GetCol() + cell_cols
); 
5237     if ( event
.Dragging() ) 
5239         //wxLogDebug("pos(%d, %d) coords(%d, %d)", pos.x, pos.y, coords.GetRow(), coords.GetCol()); 
5241         // Don't start doing anything until the mouse has been drug at 
5242         // least 3 pixels in any direction... 
5245             if (m_startDragPos 
== wxDefaultPosition
) 
5247                 m_startDragPos 
= pos
; 
5250             if (abs(m_startDragPos
.x 
- pos
.x
) < 4 && abs(m_startDragPos
.y 
- pos
.y
) < 4) 
5254         m_isDragging 
= TRUE
; 
5255         if ( m_cursorMode 
== WXGRID_CURSOR_SELECT_CELL 
) 
5257             // Hide the edit control, so it 
5258             // won't interfer with drag-shrinking. 
5259             if ( IsCellEditControlShown() ) 
5261                 HideCellEditControl(); 
5262                 SaveEditControlValue(); 
5265             // Have we captured the mouse yet? 
5268                 m_winCapture 
= m_gridWin
; 
5269                 m_winCapture
->CaptureMouse(); 
5272             if ( coords 
!= wxGridNoCellCoords 
) 
5274                 if ( event
.ControlDown() ) 
5276                     if ( m_selectingKeyboard 
== wxGridNoCellCoords
) 
5277                         m_selectingKeyboard 
= coords
; 
5278                     HighlightBlock ( m_selectingKeyboard
, coords 
); 
5282                     if ( !IsSelection() ) 
5284                         HighlightBlock( coords
, coords 
); 
5288                         HighlightBlock( m_currentCellCoords
, coords 
); 
5292                 if (! IsVisible(coords
)) 
5294                     MakeCellVisible(coords
); 
5295                     // TODO: need to introduce a delay or something here.  The 
5296                     // scrolling is way to fast, at least on MSW - also on GTK. 
5300         else if ( m_cursorMode 
== WXGRID_CURSOR_RESIZE_ROW 
) 
5302             int cw
, ch
, left
, dummy
; 
5303             m_gridWin
->GetClientSize( &cw
, &ch 
); 
5304             CalcUnscrolledPosition( 0, 0, &left
, &dummy 
); 
5306             wxClientDC 
dc( m_gridWin 
); 
5308             y 
= wxMax( y
, GetRowTop(m_dragRowOrCol
) + 
5309                           GetRowMinimalHeight(m_dragRowOrCol
) ); 
5310             dc
.SetLogicalFunction(wxINVERT
); 
5311             if ( m_dragLastPos 
>= 0 ) 
5313                 dc
.DrawLine( left
, m_dragLastPos
, left
+cw
, m_dragLastPos 
); 
5315             dc
.DrawLine( left
, y
, left
+cw
, y 
); 
5318         else if ( m_cursorMode 
== WXGRID_CURSOR_RESIZE_COL 
) 
5320             int cw
, ch
, dummy
, top
; 
5321             m_gridWin
->GetClientSize( &cw
, &ch 
); 
5322             CalcUnscrolledPosition( 0, 0, &dummy
, &top 
); 
5324             wxClientDC 
dc( m_gridWin 
); 
5326             x 
= wxMax( x
, GetColLeft(m_dragRowOrCol
) + 
5327                           GetColMinimalWidth(m_dragRowOrCol
) ); 
5328             dc
.SetLogicalFunction(wxINVERT
); 
5329             if ( m_dragLastPos 
>= 0 ) 
5331                 dc
.DrawLine( m_dragLastPos
, top
, m_dragLastPos
, top
+ch 
); 
5333             dc
.DrawLine( x
, top
, x
, top
+ch 
); 
5340     m_isDragging 
= FALSE
; 
5341     m_startDragPos 
= wxDefaultPosition
; 
5343     // VZ: if we do this, the mode is reset to WXGRID_CURSOR_SELECT_CELL 
5344     //     immediately after it becomes WXGRID_CURSOR_RESIZE_ROW/COL under 
5347     if ( event
.Entering() || event
.Leaving() ) 
5349         ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
); 
5350         m_gridWin
->SetCursor( *wxSTANDARD_CURSOR 
); 
5355     // ------------ Left button pressed 
5357     if ( event
.LeftDown() && coords 
!= wxGridNoCellCoords 
) 
5359         if ( !SendEvent( wxEVT_GRID_CELL_LEFT_CLICK
, 
5364             if ( !event
.ControlDown() ) 
5366             if ( event
.ShiftDown() ) 
5370                     m_selection
->SelectBlock( m_currentCellCoords
.GetRow(), 
5371                                               m_currentCellCoords
.GetCol(), 
5374                                               event
.ControlDown(), 
5380             else if ( XToEdgeOfCol(x
) < 0  && 
5381                       YToEdgeOfRow(y
) < 0 ) 
5383                 DisableCellEditControl(); 
5384                 MakeCellVisible( coords 
); 
5386                 if ( event
.ControlDown() ) 
5390                         m_selection
->ToggleCellSelection( coords
.GetRow(), 
5392                                                           event
.ControlDown(), 
5397                     m_selectingTopLeft 
= wxGridNoCellCoords
; 
5398                     m_selectingBottomRight 
= wxGridNoCellCoords
; 
5399                     m_selectingKeyboard 
= coords
; 
5403                     m_waitForSlowClick 
= m_currentCellCoords 
== coords 
&& coords 
!= wxGridNoCellCoords
; 
5404                     SetCurrentCell( coords 
); 
5407                         if ( m_selection
->GetSelectionMode() != 
5408                                 wxGrid::wxGridSelectCells 
) 
5410                             HighlightBlock( coords
, coords 
); 
5419     // ------------ Left double click 
5421     else if ( event
.LeftDClick() && coords 
!= wxGridNoCellCoords 
) 
5423         DisableCellEditControl(); 
5425         if ( XToEdgeOfCol(x
) < 0  &&  YToEdgeOfRow(y
) < 0 ) 
5427             SendEvent( wxEVT_GRID_CELL_LEFT_DCLICK
, 
5435     // ------------ Left button released 
5437     else if ( event
.LeftUp() ) 
5439         if ( m_cursorMode 
== WXGRID_CURSOR_SELECT_CELL 
) 
5443                 if (m_winCapture
->HasCapture()) m_winCapture
->ReleaseMouse(); 
5444                 m_winCapture 
= NULL
; 
5447             if ( coords 
== m_currentCellCoords 
&& m_waitForSlowClick 
&& CanEnableCellControl()) 
5450                 EnableCellEditControl(); 
5452                 wxGridCellAttr
* attr 
= GetCellAttr(coords
); 
5453                 wxGridCellEditor 
*editor 
= attr
->GetEditor(this, coords
.GetRow(), coords
.GetCol()); 
5454                 editor
->StartingClick(); 
5458                 m_waitForSlowClick 
= FALSE
; 
5460             else if ( m_selectingTopLeft 
!= wxGridNoCellCoords 
&& 
5461                  m_selectingBottomRight 
!= wxGridNoCellCoords 
) 
5465                     m_selection
->SelectBlock( m_selectingTopLeft
.GetRow(), 
5466                                               m_selectingTopLeft
.GetCol(), 
5467                                               m_selectingBottomRight
.GetRow(), 
5468                                               m_selectingBottomRight
.GetCol(), 
5469                                               event
.ControlDown(), 
5475                 m_selectingTopLeft 
= wxGridNoCellCoords
; 
5476                 m_selectingBottomRight 
= wxGridNoCellCoords
; 
5478                 // Show the edit control, if it has been hidden for 
5480                 ShowCellEditControl(); 
5483         else if ( m_cursorMode 
== WXGRID_CURSOR_RESIZE_ROW 
) 
5485             ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
); 
5486             DoEndDragResizeRow(); 
5488             // Note: we are ending the event *after* doing 
5489             // default processing in this case 
5491             SendEvent( wxEVT_GRID_ROW_SIZE
, m_dragRowOrCol
, -1, event 
); 
5493         else if ( m_cursorMode 
== WXGRID_CURSOR_RESIZE_COL 
) 
5495             ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
); 
5496             DoEndDragResizeCol(); 
5498             // Note: we are ending the event *after* doing 
5499             // default processing in this case 
5501             SendEvent( wxEVT_GRID_COL_SIZE
, -1, m_dragRowOrCol
, event 
); 
5508     // ------------ Right button down 
5510     else if ( event
.RightDown() && coords 
!= wxGridNoCellCoords 
) 
5512         DisableCellEditControl(); 
5513         if ( !SendEvent( wxEVT_GRID_CELL_RIGHT_CLICK
, 
5518             // no default action at the moment 
5523     // ------------ Right double click 
5525     else if ( event
.RightDClick() && coords 
!= wxGridNoCellCoords 
) 
5527         DisableCellEditControl(); 
5528         if ( !SendEvent( wxEVT_GRID_CELL_RIGHT_DCLICK
, 
5533             // no default action at the moment 
5537     // ------------ Moving and no button action 
5539     else if ( event
.Moving() && !event
.IsButton() ) 
5541         if( coords
.GetRow() < 0 || coords
.GetCol() < 0 ) 
5543             // out of grid cell area 
5544             ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
); 
5548         int dragRow 
= YToEdgeOfRow( y 
); 
5549         int dragCol 
= XToEdgeOfCol( x 
); 
5551         // Dragging on the corner of a cell to resize in both 
5552         // directions is not implemented yet... 
5554         if ( dragRow 
>= 0  &&  dragCol 
>= 0 ) 
5556             ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
); 
5562             m_dragRowOrCol 
= dragRow
; 
5564             if ( m_cursorMode 
== WXGRID_CURSOR_SELECT_CELL 
) 
5566                 if ( CanDragRowSize() && CanDragGridSize() ) 
5567                     ChangeCursorMode(WXGRID_CURSOR_RESIZE_ROW
); 
5572                 m_dragRowOrCol 
= dragCol
; 
5580             m_dragRowOrCol 
= dragCol
; 
5582             if ( m_cursorMode 
== WXGRID_CURSOR_SELECT_CELL 
) 
5584                 if ( CanDragColSize() && CanDragGridSize() ) 
5585                     ChangeCursorMode(WXGRID_CURSOR_RESIZE_COL
); 
5591         // Neither on a row or col edge 
5593         if ( m_cursorMode 
!= WXGRID_CURSOR_SELECT_CELL 
) 
5595             ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
); 
5601 void wxGrid::DoEndDragResizeRow() 
5603     if ( m_dragLastPos 
>= 0 ) 
5605         // erase the last line and resize the row 
5607         int cw
, ch
, left
, dummy
; 
5608         m_gridWin
->GetClientSize( &cw
, &ch 
); 
5609         CalcUnscrolledPosition( 0, 0, &left
, &dummy 
); 
5611         wxClientDC 
dc( m_gridWin 
); 
5613         dc
.SetLogicalFunction( wxINVERT 
); 
5614         dc
.DrawLine( left
, m_dragLastPos
, left
+cw
, m_dragLastPos 
); 
5615         HideCellEditControl(); 
5616         SaveEditControlValue(); 
5618         int rowTop 
= GetRowTop(m_dragRowOrCol
); 
5619         SetRowSize( m_dragRowOrCol
, 
5620                     wxMax( m_dragLastPos 
- rowTop
, m_minAcceptableRowHeight 
) ); 
5622         if ( !GetBatchCount() ) 
5624             // Only needed to get the correct rect.y: 
5625             wxRect 
rect ( CellToRect( m_dragRowOrCol
, 0 ) ); 
5627             CalcScrolledPosition(0, rect
.y
, &dummy
, &rect
.y
); 
5628             rect
.width 
= m_rowLabelWidth
; 
5629             rect
.height 
= ch 
- rect
.y
; 
5630             m_rowLabelWin
->Refresh( TRUE
, &rect 
); 
5632             // if there is a multicell block, paint all of it 
5635                 int i
, cell_rows
, cell_cols
, subtract_rows 
= 0; 
5636                 int leftCol 
= XToCol(left
); 
5637                 int rightCol 
= internalXToCol(left
+cw
); 
5640                     for (i
=leftCol
; i
<rightCol
; i
++) 
5642                         GetCellSize(m_dragRowOrCol
, i
, &cell_rows
, &cell_cols
); 
5643                         if (cell_rows 
< subtract_rows
) 
5644                             subtract_rows 
= cell_rows
; 
5646                     rect
.y 
= GetRowTop(m_dragRowOrCol 
+ subtract_rows
); 
5647                     CalcScrolledPosition(0, rect
.y
, &dummy
, &rect
.y
); 
5648                     rect
.height 
= ch 
- rect
.y
; 
5651             m_gridWin
->Refresh( FALSE
, &rect 
); 
5654         ShowCellEditControl(); 
5659 void wxGrid::DoEndDragResizeCol() 
5661     if ( m_dragLastPos 
>= 0 ) 
5663         // erase the last line and resize the col 
5665         int cw
, ch
, dummy
, top
; 
5666         m_gridWin
->GetClientSize( &cw
, &ch 
); 
5667         CalcUnscrolledPosition( 0, 0, &dummy
, &top 
); 
5669         wxClientDC 
dc( m_gridWin 
); 
5671         dc
.SetLogicalFunction( wxINVERT 
); 
5672         dc
.DrawLine( m_dragLastPos
, top
, m_dragLastPos
, top
+ch 
); 
5673         HideCellEditControl(); 
5674         SaveEditControlValue(); 
5676         int colLeft 
= GetColLeft(m_dragRowOrCol
); 
5677         SetColSize( m_dragRowOrCol
, 
5678                     wxMax( m_dragLastPos 
- colLeft
, 
5679                            GetColMinimalWidth(m_dragRowOrCol
) ) ); 
5681         if ( !GetBatchCount() ) 
5683             // Only needed to get the correct rect.x: 
5684             wxRect 
rect ( CellToRect( 0, m_dragRowOrCol 
) ); 
5686             CalcScrolledPosition(rect
.x
, 0, &rect
.x
, &dummy
); 
5687             rect
.width 
= cw 
- rect
.x
; 
5688             rect
.height 
= m_colLabelHeight
; 
5689             m_colLabelWin
->Refresh( TRUE
, &rect 
); 
5691             // if there is a multicell block, paint all of it 
5694                 int i
, cell_rows
, cell_cols
, subtract_cols 
= 0; 
5695                 int topRow 
= YToRow(top
); 
5696                 int bottomRow 
= internalYToRow(top
+cw
); 
5699                     for (i
=topRow
; i
<bottomRow
; i
++) 
5701                         GetCellSize(i
, m_dragRowOrCol
, &cell_rows
, &cell_cols
); 
5702                         if (cell_cols 
< subtract_cols
) 
5703                             subtract_cols 
= cell_cols
; 
5705                     rect
.x 
= GetColLeft(m_dragRowOrCol 
+ subtract_cols
); 
5706                     CalcScrolledPosition(rect
.x
, 0, &rect
.x
, &dummy
); 
5707                     rect
.width 
= cw 
- rect
.x
; 
5710             m_gridWin
->Refresh( FALSE
, &rect 
); 
5713         ShowCellEditControl(); 
5720 // ------ interaction with data model 
5722 bool wxGrid::ProcessTableMessage( wxGridTableMessage
& msg 
) 
5724     switch ( msg
.GetId() ) 
5726         case wxGRIDTABLE_REQUEST_VIEW_GET_VALUES
: 
5727             return GetModelValues(); 
5729         case wxGRIDTABLE_REQUEST_VIEW_SEND_VALUES
: 
5730             return SetModelValues(); 
5732         case wxGRIDTABLE_NOTIFY_ROWS_INSERTED
: 
5733         case wxGRIDTABLE_NOTIFY_ROWS_APPENDED
: 
5734         case wxGRIDTABLE_NOTIFY_ROWS_DELETED
: 
5735         case wxGRIDTABLE_NOTIFY_COLS_INSERTED
: 
5736         case wxGRIDTABLE_NOTIFY_COLS_APPENDED
: 
5737         case wxGRIDTABLE_NOTIFY_COLS_DELETED
: 
5738             return Redimension( msg 
); 
5747 // The behaviour of this function depends on the grid table class 
5748 // Clear() function.  For the default wxGridStringTable class the 
5749 // behavious is to replace all cell contents with wxEmptyString but 
5750 // not to change the number of rows or cols. 
5752 void wxGrid::ClearGrid() 
5756         if (IsCellEditControlEnabled()) 
5757             DisableCellEditControl(); 
5760         if ( !GetBatchCount() ) m_gridWin
->Refresh(); 
5765 bool wxGrid::InsertRows( int pos
, int numRows
, bool WXUNUSED(updateLabels
) ) 
5767     // TODO: something with updateLabels flag 
5771         wxFAIL_MSG( wxT("Called wxGrid::InsertRows() before calling CreateGrid()") ); 
5777         if (IsCellEditControlEnabled()) 
5778             DisableCellEditControl(); 
5780         bool done 
= m_table
->InsertRows( pos
, numRows 
); 
5783         // the table will have sent the results of the insert row 
5784         // operation to this view object as a grid table message 
5790 bool wxGrid::AppendRows( int numRows
, bool WXUNUSED(updateLabels
) ) 
5792     // TODO: something with updateLabels flag 
5796         wxFAIL_MSG( wxT("Called wxGrid::AppendRows() before calling CreateGrid()") ); 
5802         bool done 
= m_table 
&& m_table
->AppendRows( numRows 
); 
5804         // the table will have sent the results of the append row 
5805         // operation to this view object as a grid table message 
5811 bool wxGrid::DeleteRows( int pos
, int numRows
, bool WXUNUSED(updateLabels
) ) 
5813     // TODO: something with updateLabels flag 
5817         wxFAIL_MSG( wxT("Called wxGrid::DeleteRows() before calling CreateGrid()") ); 
5823         if (IsCellEditControlEnabled()) 
5824             DisableCellEditControl(); 
5826         bool done 
= m_table
->DeleteRows( pos
, numRows 
); 
5828         // the table will have sent the results of the delete row 
5829         // operation to this view object as a grid table message 
5835 bool wxGrid::InsertCols( int pos
, int numCols
, bool WXUNUSED(updateLabels
) ) 
5837     // TODO: something with updateLabels flag 
5841         wxFAIL_MSG( wxT("Called wxGrid::InsertCols() before calling CreateGrid()") ); 
5847         if (IsCellEditControlEnabled()) 
5848             DisableCellEditControl(); 
5850         bool done 
= m_table
->InsertCols( pos
, numCols 
); 
5852         // the table will have sent the results of the insert col 
5853         // operation to this view object as a grid table message 
5859 bool wxGrid::AppendCols( int numCols
, bool WXUNUSED(updateLabels
) ) 
5861     // TODO: something with updateLabels flag 
5865         wxFAIL_MSG( wxT("Called wxGrid::AppendCols() before calling CreateGrid()") ); 
5871         bool done 
= m_table
->AppendCols( numCols 
); 
5873         // the table will have sent the results of the append col 
5874         // operation to this view object as a grid table message 
5880 bool wxGrid::DeleteCols( int pos
, int numCols
, bool WXUNUSED(updateLabels
) ) 
5882     // TODO: something with updateLabels flag 
5886         wxFAIL_MSG( wxT("Called wxGrid::DeleteCols() before calling CreateGrid()") ); 
5892         if (IsCellEditControlEnabled()) 
5893             DisableCellEditControl(); 
5895         bool done 
= m_table
->DeleteCols( pos
, numCols 
); 
5897         // the table will have sent the results of the delete col 
5898         // operation to this view object as a grid table message 
5906 // ----- event handlers 
5909 // Generate a grid event based on a mouse event and 
5910 // return the result of ProcessEvent() 
5912 int wxGrid::SendEvent( const wxEventType type
, 
5914                         wxMouseEvent
& mouseEv 
) 
5919    if ( type 
== wxEVT_GRID_ROW_SIZE 
|| type 
== wxEVT_GRID_COL_SIZE 
) 
5921        int rowOrCol 
= (row 
== -1 ? col 
: row
); 
5923        wxGridSizeEvent 
gridEvt( GetId(), 
5927                mouseEv
.GetX() + GetRowLabelSize(), 
5928                mouseEv
.GetY() + GetColLabelSize(), 
5929                mouseEv
.ControlDown(), 
5930                mouseEv
.ShiftDown(), 
5932                mouseEv
.MetaDown() ); 
5934        claimed 
= GetEventHandler()->ProcessEvent(gridEvt
); 
5935        vetoed 
= !gridEvt
.IsAllowed(); 
5937    else if ( type 
== wxEVT_GRID_RANGE_SELECT 
) 
5939        // Right now, it should _never_ end up here! 
5940        wxGridRangeSelectEvent 
gridEvt( GetId(), 
5944                m_selectingBottomRight
, 
5946                mouseEv
.ControlDown(), 
5947                mouseEv
.ShiftDown(), 
5949                mouseEv
.MetaDown() ); 
5951        claimed 
= GetEventHandler()->ProcessEvent(gridEvt
); 
5952        vetoed 
= !gridEvt
.IsAllowed(); 
5956        wxGridEvent 
gridEvt( GetId(), 
5960                mouseEv
.GetX() + GetRowLabelSize(), 
5961                mouseEv
.GetY() + GetColLabelSize(), 
5963                mouseEv
.ControlDown(), 
5964                mouseEv
.ShiftDown(), 
5966                mouseEv
.MetaDown() ); 
5967        claimed 
= GetEventHandler()->ProcessEvent(gridEvt
); 
5968        vetoed 
= !gridEvt
.IsAllowed(); 
5971    // A Veto'd event may not be `claimed' so test this first 
5972    if (vetoed
) return -1; 
5973    return claimed 
? 1 : 0; 
5977 // Generate a grid event of specified type and return the result 
5978 // of ProcessEvent(). 
5980 int wxGrid::SendEvent( const wxEventType type
, 
5986     if ( type 
== wxEVT_GRID_ROW_SIZE 
|| type 
== wxEVT_GRID_COL_SIZE 
) 
5988         int rowOrCol 
= (row 
== -1 ? col 
: row
); 
5990         wxGridSizeEvent 
gridEvt( GetId(), 
5995         claimed 
= GetEventHandler()->ProcessEvent(gridEvt
); 
5996         vetoed  
= !gridEvt
.IsAllowed(); 
6000         wxGridEvent 
gridEvt( GetId(), 
6005         claimed 
= GetEventHandler()->ProcessEvent(gridEvt
); 
6006         vetoed  
= !gridEvt
.IsAllowed(); 
6009     // A Veto'd event may not be `claimed' so test this first 
6010     if (vetoed
) return -1; 
6011     return claimed 
? 1 : 0; 
6015 void wxGrid::OnPaint( wxPaintEvent
& WXUNUSED(event
) ) 
6017     wxPaintDC 
dc(this);  // needed to prevent zillions of paint events on MSW 
6020 void wxGrid::Refresh(bool eraseb
, const wxRect
* rect
) 
6022     // Don't do anything if between Begin/EndBatch... 
6023     // EndBatch() will do all this on the last nested one anyway. 
6024     if (! GetBatchCount()) 
6026         // Refresh to get correct scrolled position: 
6027         wxScrolledWindow::Refresh(eraseb
,rect
); 
6031             int rect_x
, rect_y
, rectWidth
, rectHeight
; 
6032             int width_label
, width_cell
, height_label
, height_cell
; 
6035             //Copy rectangle can get scroll offsets.. 
6036             rect_x 
= rect
->GetX(); 
6037             rect_y 
= rect
->GetY(); 
6038             rectWidth 
= rect
->GetWidth(); 
6039             rectHeight 
= rect
->GetHeight(); 
6041             width_label 
= m_rowLabelWidth 
- rect_x
; 
6042             if (width_label 
> rectWidth
) width_label 
= rectWidth
; 
6044             height_label 
= m_colLabelHeight 
- rect_y
; 
6045             if (height_label 
> rectHeight
) height_label 
= rectHeight
; 
6047             if (rect_x 
> m_rowLabelWidth
) 
6049                 x 
= rect_x 
- m_rowLabelWidth
; 
6050                 width_cell 
= rectWidth
; 
6055                 width_cell 
= rectWidth 
- (m_rowLabelWidth 
- rect_x
); 
6058             if (rect_y 
> m_colLabelHeight
) 
6060                 y 
= rect_y 
- m_colLabelHeight
; 
6061                 height_cell 
= rectHeight
; 
6066                 height_cell 
= rectHeight 
- (m_colLabelHeight 
- rect_y
); 
6069             // Paint corner label part intersecting rect. 
6070             if ( width_label 
> 0 && height_label 
> 0 ) 
6072                 wxRect 
anotherrect(rect_x
, rect_y
, width_label
, height_label
); 
6073                 m_cornerLabelWin
->Refresh(eraseb
, &anotherrect
); 
6076             // Paint col labels part intersecting rect. 
6077             if ( width_cell 
> 0 && height_label 
> 0 ) 
6079                 wxRect 
anotherrect(x
, rect_y
, width_cell
, height_label
); 
6080                 m_colLabelWin
->Refresh(eraseb
, &anotherrect
); 
6083             // Paint row labels part intersecting rect. 
6084             if ( width_label 
> 0 && height_cell 
> 0 ) 
6086                 wxRect 
anotherrect(rect_x
, y
, width_label
, height_cell
); 
6087                 m_rowLabelWin
->Refresh(eraseb
, &anotherrect
); 
6090             // Paint cell area part intersecting rect. 
6091             if ( width_cell 
> 0 && height_cell 
> 0 ) 
6093                 wxRect 
anotherrect(x
, y
, width_cell
, height_cell
); 
6094                 m_gridWin
->Refresh(eraseb
, &anotherrect
); 
6099             m_cornerLabelWin
->Refresh(eraseb
, NULL
); 
6100             m_colLabelWin
->Refresh(eraseb
, NULL
); 
6101             m_rowLabelWin
->Refresh(eraseb
, NULL
); 
6102             m_gridWin
->Refresh(eraseb
, NULL
); 
6107 void wxGrid::OnSize( wxSizeEvent
& event 
) 
6109     // position the child windows 
6112     // don't call CalcDimensions() from here, the base class handles the size 
6118 void wxGrid::OnKeyDown( wxKeyEvent
& event 
) 
6120     if ( m_inOnKeyDown 
) 
6122         // shouldn't be here - we are going round in circles... 
6124         wxFAIL_MSG( wxT("wxGrid::OnKeyDown called while already active") ); 
6127     m_inOnKeyDown 
= TRUE
; 
6129     // propagate the event up and see if it gets processed 
6131     wxWindow 
*parent 
= GetParent(); 
6132     wxKeyEvent 
keyEvt( event 
); 
6133     keyEvt
.SetEventObject( parent 
); 
6135     if ( !parent
->GetEventHandler()->ProcessEvent( keyEvt 
) ) 
6138         // try local handlers 
6140         switch ( event
.GetKeyCode() ) 
6143                 if ( event
.ControlDown() ) 
6145                     MoveCursorUpBlock( event
.ShiftDown() ); 
6149                     MoveCursorUp( event
.ShiftDown() ); 
6154                 if ( event
.ControlDown() ) 
6156                     MoveCursorDownBlock( event
.ShiftDown() ); 
6160                     MoveCursorDown( event
.ShiftDown() ); 
6165                 if ( event
.ControlDown() ) 
6167                     MoveCursorLeftBlock( event
.ShiftDown() ); 
6171                     MoveCursorLeft( event
.ShiftDown() ); 
6176                 if ( event
.ControlDown() ) 
6178                     MoveCursorRightBlock( event
.ShiftDown() ); 
6182                     MoveCursorRight( event
.ShiftDown() ); 
6187             case WXK_NUMPAD_ENTER
: 
6188                 if ( event
.ControlDown() ) 
6190                     event
.Skip();  // to let the edit control have the return 
6194                     if ( GetGridCursorRow() < GetNumberRows()-1 ) 
6196                         MoveCursorDown( event
.ShiftDown() ); 
6200                         // at the bottom of a column 
6201                         HideCellEditControl(); 
6202                         SaveEditControlValue(); 
6212                 if (event
.ShiftDown()) 
6214                     if ( GetGridCursorCol() > 0 ) 
6216                         MoveCursorLeft( FALSE 
); 
6221                         HideCellEditControl(); 
6222                         SaveEditControlValue(); 
6227                     if ( GetGridCursorCol() < GetNumberCols()-1 ) 
6229                         MoveCursorRight( FALSE 
); 
6234                         HideCellEditControl(); 
6235                         SaveEditControlValue(); 
6241                 if ( event
.ControlDown() ) 
6243                     MakeCellVisible( 0, 0 ); 
6244                     SetCurrentCell( 0, 0 ); 
6253                 if ( event
.ControlDown() ) 
6255                     MakeCellVisible( m_numRows
-1, m_numCols
-1 ); 
6256                     SetCurrentCell( m_numRows
-1, m_numCols
-1 ); 
6273                 if ( event
.ControlDown() ) 
6277                         m_selection
->ToggleCellSelection( m_currentCellCoords
.GetRow(), 
6278                                                           m_currentCellCoords
.GetCol(), 
6279                                                           event
.ControlDown(), 
6286                 if ( !IsEditable() ) 
6288                     MoveCursorRight( FALSE 
); 
6291                 // Otherwise fall through to default 
6294                 // is it possible to edit the current cell at all? 
6295                 if ( !IsCellEditControlEnabled() && CanEnableCellControl() ) 
6297                     // yes, now check whether the cells editor accepts the key 
6298                     int row 
= m_currentCellCoords
.GetRow(); 
6299                     int col 
= m_currentCellCoords
.GetCol(); 
6300                     wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
6301                     wxGridCellEditor 
*editor 
= attr
->GetEditor(this, row
, col
); 
6303                     // <F2> is special and will always start editing, for 
6304                     // other keys - ask the editor itself 
6305                     if ( (event
.GetKeyCode() == WXK_F2 
&& !event
.HasModifiers()) 
6306                          || editor
->IsAcceptedKey(event
) ) 
6308                         // ensure cell is visble 
6309                         MakeCellVisible(row
, col
); 
6310                         EnableCellEditControl(); 
6312                         // a problem can arise if the cell is not completely 
6313                         // visible (even after calling MakeCellVisible the 
6314                         // control is not created and calling StartingKey will 
6316                         if( editor
->IsCreated() && m_cellEditCtrlEnabled 
) editor
->StartingKey(event
); 
6328                     // let others process char events with modifiers or all 
6329                     // char events for readonly cells 
6336     m_inOnKeyDown 
= FALSE
; 
6339 void wxGrid::OnKeyUp( wxKeyEvent
& event 
) 
6341     // try local handlers 
6343     if ( event
.GetKeyCode() == WXK_SHIFT 
) 
6345         if ( m_selectingTopLeft 
!= wxGridNoCellCoords 
&& 
6346              m_selectingBottomRight 
!= wxGridNoCellCoords 
) 
6350                 m_selection
->SelectBlock( m_selectingTopLeft
.GetRow(), 
6351                                           m_selectingTopLeft
.GetCol(), 
6352                                           m_selectingBottomRight
.GetRow(), 
6353                                           m_selectingBottomRight
.GetCol(), 
6354                                           event
.ControlDown(), 
6361         m_selectingTopLeft 
= wxGridNoCellCoords
; 
6362         m_selectingBottomRight 
= wxGridNoCellCoords
; 
6363         m_selectingKeyboard 
= wxGridNoCellCoords
; 
6367 void wxGrid::OnEraseBackground(wxEraseEvent
&) 
6371 void wxGrid::SetCurrentCell( const wxGridCellCoords
& coords 
) 
6373     if ( SendEvent( wxEVT_GRID_SELECT_CELL
, coords
.GetRow(), coords
.GetCol() ) ) 
6375         // the event has been intercepted - do nothing 
6379     wxClientDC 
dc(m_gridWin
); 
6382     if ( m_currentCellCoords 
!= wxGridNoCellCoords 
) 
6384         HideCellEditControl(); 
6385         DisableCellEditControl(); 
6387         if ( IsVisible( m_currentCellCoords
, FALSE 
) ) 
6390             r 
= BlockToDeviceRect(m_currentCellCoords
, m_currentCellCoords
); 
6391             if ( !m_gridLinesEnabled 
) 
6399             wxGridCellCoordsArray cells 
= CalcCellsExposed( r 
); 
6401             // Otherwise refresh redraws the highlight! 
6402             m_currentCellCoords 
= coords
; 
6404             DrawGridCellArea(dc
,cells
); 
6405             DrawAllGridLines( dc
, r 
); 
6409     m_currentCellCoords 
= coords
; 
6411     wxGridCellAttr
* attr 
= GetCellAttr(coords
); 
6412     DrawCellHighlight(dc
, attr
); 
6417 void wxGrid::HighlightBlock( int topRow
, int leftCol
, int bottomRow
, int rightCol 
) 
6420     wxGridCellCoords updateTopLeft
, updateBottomRight
; 
6424         if ( m_selection
->GetSelectionMode() == wxGrid::wxGridSelectRows 
) 
6427             rightCol 
= GetNumberCols() - 1; 
6429         else if ( m_selection
->GetSelectionMode() == wxGrid::wxGridSelectColumns 
) 
6432             bottomRow 
= GetNumberRows() - 1; 
6436     if ( topRow 
> bottomRow 
) 
6443     if ( leftCol 
> rightCol 
) 
6450     updateTopLeft 
= wxGridCellCoords( topRow
, leftCol 
); 
6451     updateBottomRight 
= wxGridCellCoords( bottomRow
, rightCol 
); 
6453     // First the case that we selected a completely new area 
6454     if ( m_selectingTopLeft 
== wxGridNoCellCoords 
|| 
6455          m_selectingBottomRight 
== wxGridNoCellCoords 
) 
6458         rect 
= BlockToDeviceRect( wxGridCellCoords ( topRow
, leftCol 
), 
6459                                   wxGridCellCoords ( bottomRow
, rightCol 
) ); 
6460         m_gridWin
->Refresh( FALSE
, &rect 
); 
6462     // Now handle changing an existing selection area. 
6463     else if ( m_selectingTopLeft 
!= updateTopLeft 
|| 
6464               m_selectingBottomRight 
!= updateBottomRight 
) 
6466         // Compute two optimal update rectangles: 
6467         // Either one rectangle is a real subset of the 
6468         // other, or they are (almost) disjoint! 
6470         bool    need_refresh
[4]; 
6474         need_refresh
[3] = FALSE
; 
6477         // Store intermediate values 
6478         wxCoord oldLeft   
= m_selectingTopLeft
.GetCol(); 
6479         wxCoord oldTop    
= m_selectingTopLeft
.GetRow(); 
6480         wxCoord oldRight  
= m_selectingBottomRight
.GetCol(); 
6481         wxCoord oldBottom 
= m_selectingBottomRight
.GetRow(); 
6483         // Determine the outer/inner coordinates. 
6484         if (oldLeft 
> leftCol
) 
6490         if (oldTop 
> topRow 
) 
6496         if (oldRight 
< rightCol 
) 
6499             oldRight 
= rightCol
; 
6502         if (oldBottom 
< bottomRow
) 
6505             oldBottom 
= bottomRow
; 
6509         // Now, either the stuff marked old is the outer 
6510         // rectangle or we don't have a situation where one 
6511         // is contained in the other. 
6513         if ( oldLeft 
< leftCol 
) 
6515             // Refresh the newly selected or deselected 
6516             // area to the left of the old or new selection. 
6517             need_refresh
[0] = TRUE
; 
6518             rect
[0] = BlockToDeviceRect( wxGridCellCoords ( oldTop
, 
6520                                          wxGridCellCoords ( oldBottom
, 
6524         if ( oldTop  
< topRow 
) 
6526             // Refresh the newly selected or deselected 
6527             // area above the old or new selection. 
6528             need_refresh
[1] = TRUE
; 
6529             rect
[1] = BlockToDeviceRect( wxGridCellCoords ( oldTop
, 
6531                                          wxGridCellCoords ( topRow 
- 1, 
6535         if ( oldRight 
> rightCol 
) 
6537             // Refresh the newly selected or deselected 
6538             // area to the right of the old or new selection. 
6539             need_refresh
[2] = TRUE
; 
6540             rect
[2] = BlockToDeviceRect( wxGridCellCoords ( oldTop
, 
6542                                          wxGridCellCoords ( oldBottom
, 
6546         if ( oldBottom 
> bottomRow 
) 
6548             // Refresh the newly selected or deselected 
6549             // area below the old or new selection. 
6550             need_refresh
[3] = TRUE
; 
6551             rect
[3] = BlockToDeviceRect( wxGridCellCoords ( bottomRow 
+ 1, 
6553                                          wxGridCellCoords ( oldBottom
, 
6557         // various Refresh() calls 
6558         for (i 
= 0; i 
< 4; i
++ ) 
6559             if ( need_refresh
[i
] && rect
[i
] != wxGridNoCellRect 
) 
6560                 m_gridWin
->Refresh( FALSE
, &(rect
[i
]) ); 
6563     m_selectingTopLeft 
= updateTopLeft
; 
6564     m_selectingBottomRight 
= updateBottomRight
; 
6568 // ------ functions to get/send data (see also public functions) 
6571 bool wxGrid::GetModelValues() 
6573     // Hide the editor, so it won't hide a changed value. 
6574     HideCellEditControl(); 
6578         // all we need to do is repaint the grid 
6580         m_gridWin
->Refresh(); 
6588 bool wxGrid::SetModelValues() 
6592     // Disable the editor, so it won't hide a changed value. 
6593     // Do we also want to save the current value of the editor first? 
6595     DisableCellEditControl(); 
6599         for ( row 
= 0;  row 
< m_numRows
;  row
++ ) 
6601             for ( col 
= 0;  col 
< m_numCols
;  col
++ ) 
6603                 m_table
->SetValue( row
, col
, GetCellValue(row
, col
) ); 
6615 // Note - this function only draws cells that are in the list of 
6616 // exposed cells (usually set from the update region by 
6617 // CalcExposedCells) 
6619 void wxGrid::DrawGridCellArea( wxDC
& dc
, const wxGridCellCoordsArray
& cells 
) 
6621     if ( !m_numRows 
|| !m_numCols 
) return; 
6623     int i
, numCells 
= cells
.GetCount(); 
6624     int row
, col
, cell_rows
, cell_cols
; 
6625     wxGridCellCoordsArray redrawCells
; 
6627     for ( i 
= numCells
-1; i 
>= 0;  i
-- ) 
6629         row 
= cells
[i
].GetRow(); 
6630         col 
= cells
[i
].GetCol(); 
6631         GetCellSize( row
, col
, &cell_rows
, &cell_cols 
); 
6633         // If this cell is part of a multicell block, find owner for repaint 
6634         if ( cell_rows 
<= 0 || cell_cols 
<= 0 ) 
6636             wxGridCellCoords 
cell(row
+cell_rows
, col
+cell_cols
); 
6637             bool marked 
= FALSE
; 
6638             for ( int j 
= 0;  j 
< numCells
;  j
++ ) 
6640                 if ( cell 
== cells
[j
] ) 
6648                 int count 
= redrawCells
.GetCount(); 
6649                 for (int j 
= 0; j 
< count
; j
++) 
6651                     if ( cell 
== redrawCells
[j
] ) 
6657                 if (!marked
) redrawCells
.Add( cell 
); 
6659             continue; // don't bother drawing this cell 
6662         // If this cell is empty, find cell to left that might want to overflow 
6663         if (m_table 
&& m_table
->IsEmptyCell(row
, col
)) 
6665             for ( int l 
= 0; l 
< cell_rows
; l
++ ) 
6667                 // find a cell in this row to left alreay marked for repaint 
6669                 for (int k 
= 0; k 
< int(redrawCells
.GetCount()); k
++) 
6670                     if ((redrawCells
[k
].GetCol() < left
) && 
6671                         (redrawCells
[k
].GetRow() == row
)) 
6672                         left
=redrawCells
[k
].GetCol(); 
6674                 if (left 
== col
) left 
= 0; // oh well 
6676                 for (int j 
= col
-1; j 
>= left
; j
--) 
6678                     if (!m_table
->IsEmptyCell(row
+l
, j
)) 
6680                         if (GetCellOverflow(row
+l
, j
)) 
6682                             wxGridCellCoords 
cell(row
+l
, j
); 
6683                             bool marked 
= FALSE
; 
6685                             for (int k 
= 0; k 
< numCells
; k
++) 
6687                                 if ( cell 
== cells
[k
] ) 
6695                                 int count 
= redrawCells
.GetCount(); 
6696                                 for (int k 
= 0; k 
< count
; k
++) 
6698                                     if ( cell 
== redrawCells
[k
] ) 
6704                                 if (!marked
) redrawCells
.Add( cell 
); 
6712         DrawCell( dc
, cells
[i
] ); 
6715     numCells 
= redrawCells
.GetCount(); 
6717     for ( i 
= numCells 
- 1; i 
>= 0;  i
-- ) 
6719         DrawCell( dc
, redrawCells
[i
] ); 
6724 void wxGrid::DrawGridSpace( wxDC
& dc 
) 
6727   m_gridWin
->GetClientSize( &cw
, &ch 
); 
6730   CalcUnscrolledPosition( cw
, ch
, &right
, &bottom 
); 
6732   int rightCol 
= m_numCols 
> 0 ? GetColRight(m_numCols 
- 1) : 0; 
6733   int bottomRow 
= m_numRows 
> 0 ? GetRowBottom(m_numRows 
- 1) : 0 ; 
6735   if ( right 
> rightCol 
|| bottom 
> bottomRow 
) 
6738       CalcUnscrolledPosition( 0, 0, &left
, &top 
); 
6740       dc
.SetBrush( wxBrush(GetDefaultCellBackgroundColour(), wxSOLID
) ); 
6741       dc
.SetPen( *wxTRANSPARENT_PEN 
); 
6743       if ( right 
> rightCol 
) 
6745           dc
.DrawRectangle( rightCol
, top
, right 
- rightCol
, ch
); 
6748       if ( bottom 
> bottomRow 
) 
6750           dc
.DrawRectangle( left
, bottomRow
, cw
, bottom 
- bottomRow
); 
6756 void wxGrid::DrawCell( wxDC
& dc
, const wxGridCellCoords
& coords 
) 
6758     int row 
= coords
.GetRow(); 
6759     int col 
= coords
.GetCol(); 
6761     if ( GetColWidth(col
) <= 0 || GetRowHeight(row
) <= 0 ) 
6764     // we draw the cell border ourselves 
6765 #if !WXGRID_DRAW_LINES 
6766     if ( m_gridLinesEnabled 
) 
6767         DrawCellBorder( dc
, coords 
); 
6770     wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
6772     bool isCurrent 
= coords 
== m_currentCellCoords
; 
6774     wxRect rect 
= CellToRect( row
, col 
); 
6776     // if the editor is shown, we should use it and not the renderer 
6777     // Note: However, only if it is really _shown_, i.e. not hidden! 
6778     if ( isCurrent 
&& IsCellEditControlShown() ) 
6780         wxGridCellEditor 
*editor 
= attr
->GetEditor(this, row
, col
); 
6781         editor
->PaintBackground(rect
, attr
); 
6786         // but all the rest is drawn by the cell renderer and hence may be 
6788         wxGridCellRenderer 
*renderer 
= attr
->GetRenderer(this, row
, col
); 
6789         renderer
->Draw(*this, *attr
, dc
, rect
, row
, col
, IsInSelection(coords
)); 
6796 void wxGrid::DrawCellHighlight( wxDC
& dc
, const wxGridCellAttr 
*attr 
) 
6798     int row 
= m_currentCellCoords
.GetRow(); 
6799     int col 
= m_currentCellCoords
.GetCol(); 
6801     if ( GetColWidth(col
) <= 0 || GetRowHeight(row
) <= 0 ) 
6804     wxRect rect 
= CellToRect(row
, col
); 
6806     // hmmm... what could we do here to show that the cell is disabled? 
6807     // for now, I just draw a thinner border than for the other ones, but 
6808     // it doesn't look really good 
6810     int penWidth 
= attr
->IsReadOnly() ? m_cellHighlightROPenWidth 
: m_cellHighlightPenWidth
; 
6814         // The center of th drawn line is where the position/width/height of 
6815         // the rectangle is actually at, (on wxMSW atr least,) so we will 
6816         // reduce the size of the rectangle to compensate for the thickness of 
6817         // the line.  If this is too strange on non wxMSW platforms then 
6818         // please #ifdef this appropriately. 
6819         rect
.x 
+= penWidth
/2; 
6820         rect
.y 
+= penWidth
/2; 
6821         rect
.width 
-= penWidth
-1; 
6822         rect
.height 
-= penWidth
-1; 
6825         // Now draw the rectangle 
6826         // use the cellHighlightColour if the cell is inside a selection, this 
6827         // will ensure the cell is always visible. 
6828         dc
.SetPen(wxPen(IsInSelection(row
,col
)?m_selectionForeground
:m_cellHighlightColour
, penWidth
, wxSOLID
)); 
6829         dc
.SetBrush(*wxTRANSPARENT_BRUSH
); 
6830         dc
.DrawRectangle(rect
); 
6834         // VZ: my experiments with 3d borders... 
6836         // how to properly set colours for arbitrary bg? 
6837         wxCoord x1 
= rect
.x
, 
6839                 x2 
= rect
.x 
+ rect
.width 
-1, 
6840                 y2 
= rect
.y 
+ rect
.height 
-1; 
6842         dc
.SetPen(*wxWHITE_PEN
); 
6843         dc
.DrawLine(x1
, y1
, x2
, y1
); 
6844         dc
.DrawLine(x1
, y1
, x1
, y2
); 
6846         dc
.DrawLine(x1 
+ 1, y2 
- 1, x2 
- 1, y2 
- 1); 
6847         dc
.DrawLine(x2 
- 1, y1 
+ 1, x2 
- 1, y2 
); 
6849         dc
.SetPen(*wxBLACK_PEN
); 
6850         dc
.DrawLine(x1
, y2
, x2
, y2
); 
6851         dc
.DrawLine(x2
, y1
, x2
, y2
+1); 
6856 void wxGrid::DrawCellBorder( wxDC
& dc
, const wxGridCellCoords
& coords 
) 
6858     int row 
= coords
.GetRow(); 
6859     int col 
= coords
.GetCol(); 
6860     if ( GetColWidth(col
) <= 0 || GetRowHeight(row
) <= 0 ) 
6863     dc
.SetPen( wxPen(GetGridLineColour(), 1, wxSOLID
) ); 
6865     wxRect rect 
= CellToRect( row
, col 
); 
6867     // right hand border 
6869     dc
.DrawLine( rect
.x 
+ rect
.width
, rect
.y
, 
6870                  rect
.x 
+ rect
.width
, rect
.y 
+ rect
.height 
+ 1 ); 
6874     dc
.DrawLine( rect
.x
,              rect
.y 
+ rect
.height
, 
6875                  rect
.x 
+ rect
.width
, rect
.y 
+ rect
.height
); 
6878 void wxGrid::DrawHighlight(wxDC
& dc
,const  wxGridCellCoordsArray
& cells
) 
6880     // This if block was previously in wxGrid::OnPaint but that doesn't 
6881     // seem to get called under wxGTK - MB 
6883     if ( m_currentCellCoords 
== wxGridNoCellCoords  
&& 
6884          m_numRows 
&& m_numCols 
) 
6886         m_currentCellCoords
.Set(0, 0); 
6889     if ( IsCellEditControlShown() ) 
6891         // don't show highlight when the edit control is shown 
6895     // if the active cell was repainted, repaint its highlight too because it 
6896     // might have been damaged by the grid lines 
6897     size_t count 
= cells
.GetCount(); 
6898     for ( size_t n 
= 0; n 
< count
; n
++ ) 
6900         if ( cells
[n
] == m_currentCellCoords 
) 
6902             wxGridCellAttr
* attr 
= GetCellAttr(m_currentCellCoords
); 
6903             DrawCellHighlight(dc
, attr
); 
6911 // TODO: remove this ??? 
6912 // This is used to redraw all grid lines e.g. when the grid line colour 
6915 void wxGrid::DrawAllGridLines( wxDC
& dc
, const wxRegion 
& WXUNUSED(reg
) ) 
6917 #if !WXGRID_DRAW_LINES 
6921     if ( !m_gridLinesEnabled 
|| 
6923          !m_numCols 
) return; 
6925     int top
, bottom
, left
, right
; 
6927 #if 0  //#ifndef __WXGTK__ 
6931       m_gridWin
->GetClientSize(&cw
, &ch
); 
6933       // virtual coords of visible area 
6935       CalcUnscrolledPosition( 0, 0, &left
, &top 
); 
6936       CalcUnscrolledPosition( cw
, ch
, &right
, &bottom 
); 
6941       reg
.GetBox(x
, y
, w
, h
); 
6942       CalcUnscrolledPosition( x
, y
, &left
, &top 
); 
6943       CalcUnscrolledPosition( x 
+ w
, y 
+ h
, &right
, &bottom 
); 
6947       m_gridWin
->GetClientSize(&cw
, &ch
); 
6948       CalcUnscrolledPosition( 0, 0, &left
, &top 
); 
6949       CalcUnscrolledPosition( cw
, ch
, &right
, &bottom 
); 
6952     // avoid drawing grid lines past the last row and col 
6954     right 
= wxMin( right
, GetColRight(m_numCols 
- 1) ); 
6955     bottom 
= wxMin( bottom
, GetRowBottom(m_numRows 
- 1) ); 
6957     // no gridlines inside multicells, clip them out 
6958     int leftCol   
= internalXToCol(left
); 
6959     int topRow    
= internalYToRow(top
); 
6960     int rightCol  
= internalXToCol(right
); 
6961     int bottomRow 
= internalYToRow(bottom
); 
6962     wxRegion 
clippedcells(0, 0, cw
, ch
); 
6965     int i
, j
, cell_rows
, cell_cols
; 
6968     for (j
=topRow
; j
<bottomRow
; j
++) 
6970         for (i
=leftCol
; i
<rightCol
; i
++) 
6972             GetCellSize( j
, i
, &cell_rows
, &cell_cols 
); 
6973             if ((cell_rows 
> 1) || (cell_cols 
> 1)) 
6975                 rect 
= CellToRect(j
,i
); 
6976                 CalcScrolledPosition( rect
.x
, rect
.y
, &rect
.x
, &rect
.y 
); 
6977                 clippedcells
.Subtract(rect
); 
6979             else if ((cell_rows 
< 0) || (cell_cols 
< 0)) 
6981                 rect 
= CellToRect(j
+cell_rows
, i
+cell_cols
); 
6982                 CalcScrolledPosition( rect
.x
, rect
.y
, &rect
.x
, &rect
.y 
); 
6983                 clippedcells
.Subtract(rect
); 
6987     dc
.SetClippingRegion( clippedcells 
); 
6989     dc
.SetPen( wxPen(GetGridLineColour(), 1, wxSOLID
) ); 
6991     // horizontal grid lines 
6993     // already declared above - int i; 
6994     for ( i 
= internalYToRow(top
); i 
< m_numRows
; i
++ ) 
6996         int bot 
= GetRowBottom(i
) - 1; 
7005             dc
.DrawLine( left
, bot
, right
, bot 
); 
7010     // vertical grid lines 
7012     for ( i 
= internalXToCol(left
); i 
< m_numCols
; i
++ ) 
7014         int colRight 
= GetColRight(i
) - 1; 
7015         if ( colRight 
> right 
) 
7020         if ( colRight 
>= left 
) 
7022             dc
.DrawLine( colRight
, top
, colRight
, bottom 
); 
7025     dc
.DestroyClippingRegion(); 
7029 void wxGrid::DrawRowLabels( wxDC
& dc 
,const wxArrayInt
& rows
) 
7031     if ( !m_numRows 
) return; 
7034     size_t numLabels 
= rows
.GetCount(); 
7036     for ( i 
= 0;  i 
< numLabels
;  i
++ ) 
7038         DrawRowLabel( dc
, rows
[i
] ); 
7043 void wxGrid::DrawRowLabel( wxDC
& dc
, int row 
) 
7045     if ( GetRowHeight(row
) <= 0 ) 
7048     int rowTop 
= GetRowTop(row
), 
7049         rowBottom 
= GetRowBottom(row
) - 1; 
7051     dc
.SetPen( wxPen(wxSystemSettings::GetColour(wxSYS_COLOUR_3DDKSHADOW
),1, wxSOLID
) ); 
7052     dc
.DrawLine( m_rowLabelWidth
-1, rowTop
, 
7053                  m_rowLabelWidth
-1, rowBottom 
); 
7055     dc
.DrawLine( 0, rowTop
, 0, rowBottom 
); 
7057     dc
.DrawLine( 0, rowBottom
, m_rowLabelWidth
, rowBottom 
); 
7059     dc
.SetPen( *wxWHITE_PEN 
); 
7060     dc
.DrawLine( 1, rowTop
, 1, rowBottom 
); 
7061     dc
.DrawLine( 1, rowTop
, m_rowLabelWidth
-1, rowTop 
); 
7063     dc
.SetBackgroundMode( wxTRANSPARENT 
); 
7064     dc
.SetTextForeground( GetLabelTextColour() ); 
7065     dc
.SetFont( GetLabelFont() ); 
7068     GetRowLabelAlignment( &hAlign
, &vAlign 
); 
7072     rect
.SetY( GetRowTop(row
) + 2 ); 
7073     rect
.SetWidth( m_rowLabelWidth 
- 4 ); 
7074     rect
.SetHeight( GetRowHeight(row
) - 4 ); 
7075     DrawTextRectangle( dc
, GetRowLabelValue( row 
), rect
, hAlign
, vAlign 
); 
7079 void wxGrid::DrawColLabels( wxDC
& dc
,const wxArrayInt
& cols 
) 
7081     if ( !m_numCols 
) return; 
7084     size_t numLabels 
= cols
.GetCount(); 
7086     for ( i 
= 0;  i 
< numLabels
;  i
++ ) 
7088         DrawColLabel( dc
, cols
[i
] ); 
7093 void wxGrid::DrawColLabel( wxDC
& dc
, int col 
) 
7095     if ( GetColWidth(col
) <= 0 ) 
7098     int colLeft 
= GetColLeft(col
), 
7099         colRight 
= GetColRight(col
) - 1; 
7101     dc
.SetPen( wxPen(wxSystemSettings::GetColour(wxSYS_COLOUR_3DDKSHADOW
),1, wxSOLID
) ); 
7102     dc
.DrawLine( colRight
, 0, 
7103                  colRight
, m_colLabelHeight
-1 ); 
7105     dc
.DrawLine( colLeft
, 0, colRight
, 0 ); 
7107     dc
.DrawLine( colLeft
, m_colLabelHeight
-1, 
7108                  colRight
+1, m_colLabelHeight
-1 ); 
7110     dc
.SetPen( *wxWHITE_PEN 
); 
7111     dc
.DrawLine( colLeft
, 1, colLeft
, m_colLabelHeight
-1 ); 
7112     dc
.DrawLine( colLeft
, 1, colRight
, 1 ); 
7114     dc
.SetBackgroundMode( wxTRANSPARENT 
); 
7115     dc
.SetTextForeground( GetLabelTextColour() ); 
7116     dc
.SetFont( GetLabelFont() ); 
7118     int hAlign
, vAlign
, orient
; 
7119     GetColLabelAlignment( &hAlign
, &vAlign 
); 
7120     orient 
= GetColLabelTextOrientation(); 
7123     rect
.SetX( colLeft 
+ 2 ); 
7125     rect
.SetWidth( GetColWidth(col
) - 4 ); 
7126     rect
.SetHeight( m_colLabelHeight 
- 4 ); 
7127     DrawTextRectangle( dc
, GetColLabelValue( col 
), rect
, hAlign
, vAlign
, orient 
); 
7130 void wxGrid::DrawTextRectangle( wxDC
& dc
, 
7131                                 const wxString
& value
, 
7135                                 int textOrientation 
) 
7137     wxArrayString lines
; 
7139     StringToLines( value
, lines 
); 
7142     //Forward to new API. 
7143     DrawTextRectangle(  dc
, 
7152 void wxGrid::DrawTextRectangle( wxDC
& dc
, 
7153                                const wxArrayString
& lines
, 
7157                                int textOrientation 
) 
7159     long textWidth
, textHeight
; 
7160     long lineWidth
, lineHeight
; 
7163     dc
.SetClippingRegion( rect 
); 
7165     nLines 
= lines
.GetCount(); 
7169         float x 
= 0.0, y 
= 0.0; 
7171         if( textOrientation 
== wxHORIZONTAL 
) 
7172             GetTextBoxSize(dc
, lines
, &textWidth
, &textHeight
); 
7174             GetTextBoxSize( dc
, lines
, &textHeight
, &textWidth 
); 
7178         case wxALIGN_BOTTOM
: 
7179             if( textOrientation 
== wxHORIZONTAL 
) 
7180                 y 
= rect
.y 
+ (rect
.height 
- textHeight 
- 1); 
7182                 x 
= rect
.x 
+ rect
.width 
- textWidth
; 
7185         case wxALIGN_CENTRE
: 
7186             if( textOrientation 
== wxHORIZONTAL 
) 
7187                 y 
= rect
.y 
+ ((rect
.height 
- textHeight
)/2); 
7189                 x 
= rect
.x 
+ ((rect
.width 
- textWidth
)/2); 
7194             if( textOrientation 
== wxHORIZONTAL 
) 
7201         // Align each line of a multi-line label 
7202         for( l 
= 0; l 
< nLines
; l
++ ) 
7204             dc
.GetTextExtent(lines
[l
], &lineWidth
, &lineHeight
); 
7206             switch( horizAlign 
) 
7209                 if( textOrientation 
== wxHORIZONTAL 
) 
7210                     x 
= rect
.x 
+ (rect
.width 
- lineWidth 
- 1); 
7212                     y 
= rect
.y 
+ lineWidth 
+ 1; 
7215             case wxALIGN_CENTRE
: 
7216                 if( textOrientation 
== wxHORIZONTAL 
) 
7217                     x 
= rect
.x 
+ ((rect
.width 
- lineWidth
)/2); 
7219                     y 
= rect
.y 
+ rect
.height 
- ((rect
.height 
- lineWidth
)/2); 
7224                 if( textOrientation 
== wxHORIZONTAL 
) 
7227                     y 
= rect
.y 
+ rect
.height 
- 1; 
7231             if( textOrientation 
== wxHORIZONTAL 
) 
7233                 dc
.DrawText( lines
[l
], (int)x
, (int)y 
); 
7238                 dc
.DrawRotatedText( lines
[l
], (int)x
, (int)y
, 90.0 ); 
7243     dc
.DestroyClippingRegion(); 
7247 // Split multi line text up into an array of strings.  Any existing 
7248 // contents of the string array are preserved. 
7250 void wxGrid::StringToLines( const wxString
& value
, wxArrayString
& lines 
) 
7254     wxString eol 
= wxTextFile::GetEOL( wxTextFileType_Unix 
); 
7255     wxString tVal 
= wxTextFile::Translate( value
, wxTextFileType_Unix 
); 
7257     while ( startPos 
< (int)tVal
.Length() ) 
7259         pos 
= tVal
.Mid(startPos
).Find( eol 
); 
7264         else if ( pos 
== 0 ) 
7266             lines
.Add( wxEmptyString 
); 
7270             lines
.Add( value
.Mid(startPos
, pos
) ); 
7274     if ( startPos 
< (int)value
.Length() ) 
7276         lines
.Add( value
.Mid( startPos 
) ); 
7281 void wxGrid::GetTextBoxSize( wxDC
& dc
, 
7282                              const wxArrayString
& lines
, 
7283                              long *width
, long *height 
) 
7290     for ( i 
= 0;  i 
< lines
.GetCount();  i
++ ) 
7292         dc
.GetTextExtent( lines
[i
], &lineW
, &lineH 
); 
7293         w 
= wxMax( w
, lineW 
); 
7302 // ------ Batch processing. 
7304 void wxGrid::EndBatch() 
7306     if ( m_batchCount 
> 0 ) 
7309         if ( !m_batchCount 
) 
7312             m_rowLabelWin
->Refresh(); 
7313             m_colLabelWin
->Refresh(); 
7314             m_cornerLabelWin
->Refresh(); 
7315             m_gridWin
->Refresh(); 
7320 // Use this, rather than wxWindow::Refresh(), to force an immediate 
7321 // repainting of the grid. Has no effect if you are already inside a 
7322 // BeginBatch / EndBatch block. 
7324 void wxGrid::ForceRefresh() 
7332 // ------ Edit control functions 
7336 void wxGrid::EnableEditing( bool edit 
) 
7338     // TODO: improve this ? 
7340     if ( edit 
!= m_editable 
) 
7342         if(!edit
) EnableCellEditControl(edit
); 
7348 void wxGrid::EnableCellEditControl( bool enable 
) 
7353     if ( m_currentCellCoords 
== wxGridNoCellCoords 
) 
7354         SetCurrentCell( 0, 0 ); 
7356     if ( enable 
!= m_cellEditCtrlEnabled 
) 
7360             if (SendEvent( wxEVT_GRID_EDITOR_SHOWN
) <0) 
7363             // this should be checked by the caller! 
7364             wxASSERT_MSG( CanEnableCellControl(), 
7365                           _T("can't enable editing for this cell!") ); 
7367             // do it before ShowCellEditControl() 
7368             m_cellEditCtrlEnabled 
= enable
; 
7370             ShowCellEditControl(); 
7374             //FIXME:add veto support 
7375             SendEvent( wxEVT_GRID_EDITOR_HIDDEN
); 
7377             HideCellEditControl(); 
7378             SaveEditControlValue(); 
7380             // do it after HideCellEditControl() 
7381             m_cellEditCtrlEnabled 
= enable
; 
7386 bool wxGrid::IsCurrentCellReadOnly() const 
7389     wxGridCellAttr
* attr 
= ((wxGrid 
*)this)->GetCellAttr(m_currentCellCoords
); 
7390     bool readonly 
= attr
->IsReadOnly(); 
7396 bool wxGrid::CanEnableCellControl() const 
7398     return m_editable 
&& !IsCurrentCellReadOnly(); 
7401 bool wxGrid::IsCellEditControlEnabled() const 
7403     // the cell edit control might be disable for all cells or just for the 
7404     // current one if it's read only 
7405     return m_cellEditCtrlEnabled 
? !IsCurrentCellReadOnly() : FALSE
; 
7408 bool wxGrid::IsCellEditControlShown() const 
7410     bool isShown 
= FALSE
; 
7412     if ( m_cellEditCtrlEnabled 
) 
7414         int row 
= m_currentCellCoords
.GetRow(); 
7415         int col 
= m_currentCellCoords
.GetCol(); 
7416         wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
7417         wxGridCellEditor
* editor 
= attr
->GetEditor((wxGrid
*) this, row
, col
); 
7422             if ( editor
->IsCreated() ) 
7424                 isShown 
= editor
->GetControl()->IsShown(); 
7434 void wxGrid::ShowCellEditControl() 
7436     if ( IsCellEditControlEnabled() ) 
7438         if ( !IsVisible( m_currentCellCoords 
) ) 
7440             m_cellEditCtrlEnabled 
= FALSE
; 
7445             wxRect rect 
= CellToRect( m_currentCellCoords 
); 
7446             int row 
= m_currentCellCoords
.GetRow(); 
7447             int col 
= m_currentCellCoords
.GetCol(); 
7449             // if this is part of a multicell, find owner (topleft) 
7450             int cell_rows
, cell_cols
; 
7451             GetCellSize( row
, col
, &cell_rows
, &cell_cols 
); 
7452             if ( cell_rows 
<= 0 || cell_cols 
<= 0 ) 
7456                 m_currentCellCoords
.SetRow( row 
); 
7457                 m_currentCellCoords
.SetCol( col 
); 
7460             // convert to scrolled coords 
7462             CalcScrolledPosition( rect
.x
, rect
.y
, &rect
.x
, &rect
.y 
); 
7464             // done in PaintBackground() 
7466             // erase the highlight and the cell contents because the editor 
7467             // might not cover the entire cell 
7468             wxClientDC 
dc( m_gridWin 
); 
7470             dc
.SetBrush(*wxLIGHT_GREY_BRUSH
); //wxBrush(attr->GetBackgroundColour(), wxSOLID)); 
7471             dc
.SetPen(*wxTRANSPARENT_PEN
); 
7472             dc
.DrawRectangle(rect
); 
7475             // cell is shifted by one pixel 
7476             // However, don't allow x or y to become negative 
7477             // since the SetSize() method interprets that as 
7484             wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
7485             wxGridCellEditor
* editor 
= attr
->GetEditor(this, row
, col
); 
7486             if ( !editor
->IsCreated() ) 
7488                 editor
->Create(m_gridWin
, -1, 
7489                                new wxGridCellEditorEvtHandler(this, editor
)); 
7491                 wxGridEditorCreatedEvent 
evt(GetId(), 
7492                                              wxEVT_GRID_EDITOR_CREATED
, 
7496                                              editor
->GetControl()); 
7497                 GetEventHandler()->ProcessEvent(evt
); 
7501             // resize editor to overflow into righthand cells if allowed 
7502             int maxWidth 
= rect
.width
; 
7503             wxString value 
= GetCellValue(row
, col
); 
7504             if ( (value 
!= wxEmptyString
) && (attr
->GetOverflow()) ) 
7507                 GetTextExtent(value
, &maxWidth
, &y
, 
7508                         NULL
, NULL
, &attr
->GetFont()); 
7509                 if (maxWidth 
< rect
.width
) maxWidth 
= rect
.width
; 
7511             int client_right 
= m_gridWin
->GetClientSize().GetWidth(); 
7512             if (rect
.x
+maxWidth 
> client_right
) 
7513                 maxWidth 
= client_right 
- rect
.x
; 
7515             if ((maxWidth 
> rect
.width
) && (col 
< m_numCols
) && m_table
) 
7517                 GetCellSize( row
, col
, &cell_rows
, &cell_cols 
); 
7518                 // may have changed earlier 
7519                 for (int i 
= col
+cell_cols
; i 
< m_numCols
; i
++) 
7522                     GetCellSize( row
, i
, &c_rows
, &c_cols 
); 
7523                     // looks weird going over a multicell 
7524                     if (m_table
->IsEmptyCell(row
,i
) && 
7525                             (rect
.width 
< maxWidth
) && (c_rows 
== 1)) 
7526                         rect
.width 
+= GetColWidth(i
); 
7530                 if (rect
.GetRight() > client_right
) 
7531                     rect
.SetRight(client_right
-1); 
7534             editor
->SetCellAttr(attr
); 
7535             editor
->SetSize( rect 
); 
7536             editor
->Show( TRUE
, attr 
); 
7538             // recalc dimensions in case we need to 
7539             // expand the scrolled window to account for editor 
7542             editor
->BeginEdit(row
, col
, this); 
7543             editor
->SetCellAttr(NULL
); 
7552 void wxGrid::HideCellEditControl() 
7554     if ( IsCellEditControlEnabled() ) 
7556         int row 
= m_currentCellCoords
.GetRow(); 
7557         int col 
= m_currentCellCoords
.GetCol(); 
7559         wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
7560         wxGridCellEditor 
*editor 
= attr
->GetEditor(this, row
, col
); 
7561         editor
->Show( FALSE 
); 
7564         m_gridWin
->SetFocus(); 
7565         // refresh whole row to the right 
7566         wxRect 
rect( CellToRect(row
, col
) ); 
7567         CalcScrolledPosition(rect
.x
, rect
.y
, &rect
.x
, &rect
.y 
); 
7568         rect
.width 
= m_gridWin
->GetClientSize().GetWidth() - rect
.x
; 
7569         m_gridWin
->Refresh( FALSE
, &rect 
); 
7574 void wxGrid::SaveEditControlValue() 
7576     if ( IsCellEditControlEnabled() ) 
7578         int row 
= m_currentCellCoords
.GetRow(); 
7579         int col 
= m_currentCellCoords
.GetCol(); 
7581         wxString oldval 
= GetCellValue(row
,col
); 
7583         wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
7584         wxGridCellEditor
* editor 
= attr
->GetEditor(this, row
, col
); 
7585         bool changed 
= editor
->EndEdit(row
, col
, this); 
7592             if ( SendEvent( wxEVT_GRID_CELL_CHANGE
, 
7593                        m_currentCellCoords
.GetRow(), 
7594                        m_currentCellCoords
.GetCol() ) < 0 ) { 
7596                 // Event has been vetoed, set the data back. 
7597                 SetCellValue(row
,col
,oldval
); 
7605 // ------ Grid location functions 
7606 //  Note that all of these functions work with the logical coordinates of 
7607 //  grid cells and labels so you will need to convert from device 
7608 //  coordinates for mouse events etc. 
7611 void wxGrid::XYToCell( int x
, int y
, wxGridCellCoords
& coords 
) 
7613     int row 
= YToRow(y
); 
7614     int col 
= XToCol(x
); 
7616     if ( row 
== -1  ||  col 
== -1 ) 
7618         coords 
= wxGridNoCellCoords
; 
7622         coords
.Set( row
, col 
); 
7627 // Internal Helper function for computing row or column from some 
7628 // (unscrolled) coordinate value, using either 
7629 // m_defaultRowHeight/m_defaultColWidth or binary search on array 
7630 // of m_rowBottoms/m_ColRights to speed up the search! 
7632 static int CoordToRowOrCol(int coord
, int defaultDist
, int minDist
, 
7633                            const wxArrayInt
& BorderArray
, int nMax
, 
7638         return clipToMinMax 
&& (nMax 
> 0) ? 0 : -1; 
7644     size_t i_max 
= coord 
/ defaultDist
, 
7647     if (BorderArray
.IsEmpty()) 
7649         if((int) i_max 
< nMax
) 
7651         return clipToMinMax 
? nMax 
- 1 : -1; 
7654     if ( i_max 
>= BorderArray
.GetCount()) 
7655         i_max 
= BorderArray
.GetCount() - 1; 
7658         if ( coord 
>= BorderArray
[i_max
]) 
7661             i_max 
= coord 
/ minDist
; 
7663         if ( i_max 
>= BorderArray
.GetCount()) 
7664             i_max 
= BorderArray
.GetCount() - 1; 
7666     if ( coord 
>= BorderArray
[i_max
]) 
7667         return clipToMinMax 
? (int)i_max 
: -1; 
7668     if ( coord 
< BorderArray
[0] ) 
7671     while ( i_max 
- i_min 
> 0 ) 
7673         wxCHECK_MSG(BorderArray
[i_min
] <= coord 
&& coord 
< BorderArray
[i_max
], 
7674                     0, _T("wxGrid: internal error in CoordToRowOrCol")); 
7675         if (coord 
>=  BorderArray
[ i_max 
- 1]) 
7679         int median 
= i_min 
+ (i_max 
- i_min 
+ 1) / 2; 
7680         if (coord 
< BorderArray
[median
]) 
7688 int wxGrid::YToRow( int y 
) 
7690     return CoordToRowOrCol(y
, m_defaultRowHeight
, 
7691                            m_minAcceptableRowHeight
, m_rowBottoms
, m_numRows
, FALSE
); 
7695 int wxGrid::XToCol( int x 
) 
7697     return CoordToRowOrCol(x
, m_defaultColWidth
, 
7698                            m_minAcceptableColWidth
, m_colRights
, m_numCols
, FALSE
); 
7702 // return the row number that that the y coord is near the edge of, or 
7703 // -1 if not near an edge 
7705 int wxGrid::YToEdgeOfRow( int y 
) 
7708     i 
= internalYToRow(y
); 
7710     if ( GetRowHeight(i
) > WXGRID_LABEL_EDGE_ZONE 
) 
7712         // We know that we are in row i, test whether we are 
7713         // close enough to lower or upper border, respectively. 
7714         if ( abs(GetRowBottom(i
) - y
) < WXGRID_LABEL_EDGE_ZONE 
) 
7716         else if( i 
> 0 && y 
- GetRowTop(i
) < WXGRID_LABEL_EDGE_ZONE 
) 
7724 // return the col number that that the x coord is near the edge of, or 
7725 // -1 if not near an edge 
7727 int wxGrid::XToEdgeOfCol( int x 
) 
7730     i 
= internalXToCol(x
); 
7732     if ( GetColWidth(i
) > WXGRID_LABEL_EDGE_ZONE 
) 
7734         // We know that we are in column i,  test whether we are 
7735         // close enough to right or left border, respectively. 
7736         if ( abs(GetColRight(i
) - x
) < WXGRID_LABEL_EDGE_ZONE 
) 
7738         else if( i 
> 0 && x 
- GetColLeft(i
) < WXGRID_LABEL_EDGE_ZONE 
) 
7746 wxRect 
wxGrid::CellToRect( int row
, int col 
) 
7748     wxRect 
rect( -1, -1, -1, -1 ); 
7750     if ( row 
>= 0  &&  row 
< m_numRows  
&& 
7751          col 
>= 0  &&  col 
< m_numCols 
) 
7753         int i
, cell_rows
, cell_cols
; 
7754         rect
.width 
= rect
.height 
= 0; 
7755         GetCellSize( row
, col
, &cell_rows
, &cell_cols 
); 
7756         // if negative then find multicell owner 
7757         if (cell_rows 
< 0) row 
+= cell_rows
; 
7758         if (cell_cols 
< 0) col 
+= cell_cols
; 
7759         GetCellSize( row
, col
, &cell_rows
, &cell_cols 
); 
7761         rect
.x 
= GetColLeft(col
); 
7762         rect
.y 
= GetRowTop(row
); 
7763         for (i
=col
; i
<col
+cell_cols
; i
++) 
7764             rect
.width  
+= GetColWidth(i
); 
7765         for (i
=row
; i
<row
+cell_rows
; i
++) 
7766             rect
.height 
+= GetRowHeight(i
); 
7769     // if grid lines are enabled, then the area of the cell is a bit smaller 
7770     if (m_gridLinesEnabled
) { 
7778 bool wxGrid::IsVisible( int row
, int col
, bool wholeCellVisible 
) 
7780     // get the cell rectangle in logical coords 
7782     wxRect 
r( CellToRect( row
, col 
) ); 
7784     // convert to device coords 
7786     int left
, top
, right
, bottom
; 
7787     CalcScrolledPosition( r
.GetLeft(), r
.GetTop(), &left
, &top 
); 
7788     CalcScrolledPosition( r
.GetRight(), r
.GetBottom(), &right
, &bottom 
); 
7790     // check against the client area of the grid window 
7793     m_gridWin
->GetClientSize( &cw
, &ch 
); 
7795     if ( wholeCellVisible 
) 
7797         // is the cell wholly visible ? 
7799         return ( left 
>= 0  &&  right 
<= cw  
&& 
7800                  top 
>= 0  &&  bottom 
<= ch 
); 
7804         // is the cell partly visible ? 
7806         return ( ((left 
>=0 && left 
< cw
) || (right 
> 0 && right 
<= cw
))  && 
7807                  ((top 
>=0 && top 
< ch
) || (bottom 
> 0 && bottom 
<= ch
)) ); 
7812 // make the specified cell location visible by doing a minimal amount 
7815 void wxGrid::MakeCellVisible( int row
, int col 
) 
7819     int xpos 
= -1, ypos 
= -1; 
7821     if ( row 
>= 0  &&  row 
< m_numRows  
&& 
7822          col 
>= 0  &&  col 
< m_numCols 
) 
7824         // get the cell rectangle in logical coords 
7826         wxRect 
r( CellToRect( row
, col 
) ); 
7828         // convert to device coords 
7830         int left
, top
, right
, bottom
; 
7831         CalcScrolledPosition( r
.GetLeft(), r
.GetTop(), &left
, &top 
); 
7832         CalcScrolledPosition( r
.GetRight(), r
.GetBottom(), &right
, &bottom 
); 
7835         m_gridWin
->GetClientSize( &cw
, &ch 
); 
7841         else if ( bottom 
> ch 
) 
7843             int h 
= r
.GetHeight(); 
7845             for ( i 
= row
-1;  i 
>= 0;  i
-- ) 
7847                 int rowHeight 
= GetRowHeight(i
); 
7848                 if ( h 
+ rowHeight 
> ch 
) 
7855             // we divide it later by GRID_SCROLL_LINE, make sure that we don't 
7856             // have rounding errors (this is important, because if we do, we 
7857             // might not scroll at all and some cells won't be redrawn) 
7859             // Sometimes GRID_SCROLL_LINE/2 is not enough, so just add a full 
7861             ypos 
+= GRID_SCROLL_LINE_Y
; 
7868         else if ( right 
> cw 
) 
7870             // position the view so that the cell is on the right 
7872             CalcUnscrolledPosition(0, 0, &x0
, &y0
); 
7873             xpos 
= x0 
+ (right 
- cw
); 
7875             // see comment for ypos above 
7876             xpos 
+= GRID_SCROLL_LINE_X
; 
7879         if ( xpos 
!= -1  ||  ypos 
!= -1 ) 
7882                 xpos 
/= GRID_SCROLL_LINE_X
; 
7884                 ypos 
/= GRID_SCROLL_LINE_Y
; 
7885             Scroll( xpos
, ypos 
); 
7893 // ------ Grid cursor movement functions 
7896 bool wxGrid::MoveCursorUp( bool expandSelection 
) 
7898     if ( m_currentCellCoords 
!= wxGridNoCellCoords  
&& 
7899          m_currentCellCoords
.GetRow() >= 0 ) 
7901         if ( expandSelection
) 
7903             if ( m_selectingKeyboard 
== wxGridNoCellCoords 
) 
7904                 m_selectingKeyboard 
= m_currentCellCoords
; 
7905             if ( m_selectingKeyboard
.GetRow() > 0 ) 
7907                 m_selectingKeyboard
.SetRow( m_selectingKeyboard
.GetRow() - 1 ); 
7908                 MakeCellVisible( m_selectingKeyboard
.GetRow(), 
7909                                  m_selectingKeyboard
.GetCol() ); 
7910                 HighlightBlock( m_currentCellCoords
, m_selectingKeyboard 
); 
7913         else if ( m_currentCellCoords
.GetRow() > 0 ) 
7916             MakeCellVisible( m_currentCellCoords
.GetRow() - 1, 
7917                              m_currentCellCoords
.GetCol() ); 
7918             SetCurrentCell( m_currentCellCoords
.GetRow() - 1, 
7919                             m_currentCellCoords
.GetCol() ); 
7930 bool wxGrid::MoveCursorDown( bool expandSelection 
) 
7932     if ( m_currentCellCoords 
!= wxGridNoCellCoords  
&& 
7933          m_currentCellCoords
.GetRow() < m_numRows 
) 
7935         if ( expandSelection 
) 
7937             if ( m_selectingKeyboard 
== wxGridNoCellCoords 
) 
7938                 m_selectingKeyboard 
= m_currentCellCoords
; 
7939             if ( m_selectingKeyboard
.GetRow() < m_numRows
-1 ) 
7941                 m_selectingKeyboard
.SetRow( m_selectingKeyboard
.GetRow() + 1 ); 
7942                 MakeCellVisible( m_selectingKeyboard
.GetRow(), 
7943                         m_selectingKeyboard
.GetCol() ); 
7944                 HighlightBlock( m_currentCellCoords
, m_selectingKeyboard 
); 
7947         else if ( m_currentCellCoords
.GetRow() < m_numRows 
- 1 ) 
7950             MakeCellVisible( m_currentCellCoords
.GetRow() + 1, 
7951                              m_currentCellCoords
.GetCol() ); 
7952             SetCurrentCell( m_currentCellCoords
.GetRow() + 1, 
7953                             m_currentCellCoords
.GetCol() ); 
7964 bool wxGrid::MoveCursorLeft( bool expandSelection 
) 
7966     if ( m_currentCellCoords 
!= wxGridNoCellCoords  
&& 
7967          m_currentCellCoords
.GetCol() >= 0 ) 
7969         if ( expandSelection 
) 
7971             if ( m_selectingKeyboard 
== wxGridNoCellCoords 
) 
7972                 m_selectingKeyboard 
= m_currentCellCoords
; 
7973             if ( m_selectingKeyboard
.GetCol() > 0 ) 
7975                 m_selectingKeyboard
.SetCol( m_selectingKeyboard
.GetCol() - 1 ); 
7976                 MakeCellVisible( m_selectingKeyboard
.GetRow(), 
7977                         m_selectingKeyboard
.GetCol() ); 
7978                 HighlightBlock( m_currentCellCoords
, m_selectingKeyboard 
); 
7981         else if ( m_currentCellCoords
.GetCol() > 0 ) 
7984             MakeCellVisible( m_currentCellCoords
.GetRow(), 
7985                              m_currentCellCoords
.GetCol() - 1 ); 
7986             SetCurrentCell( m_currentCellCoords
.GetRow(), 
7987                             m_currentCellCoords
.GetCol() - 1 ); 
7998 bool wxGrid::MoveCursorRight( bool expandSelection 
) 
8000     if ( m_currentCellCoords 
!= wxGridNoCellCoords  
&& 
8001          m_currentCellCoords
.GetCol() < m_numCols 
) 
8003         if ( expandSelection 
) 
8005             if ( m_selectingKeyboard 
== wxGridNoCellCoords 
) 
8006                 m_selectingKeyboard 
= m_currentCellCoords
; 
8007             if ( m_selectingKeyboard
.GetCol() < m_numCols 
- 1 ) 
8009                 m_selectingKeyboard
.SetCol( m_selectingKeyboard
.GetCol() + 1 ); 
8010                 MakeCellVisible( m_selectingKeyboard
.GetRow(), 
8011                         m_selectingKeyboard
.GetCol() ); 
8012                 HighlightBlock( m_currentCellCoords
, m_selectingKeyboard 
); 
8015         else if ( m_currentCellCoords
.GetCol() < m_numCols 
- 1 ) 
8018             MakeCellVisible( m_currentCellCoords
.GetRow(), 
8019                              m_currentCellCoords
.GetCol() + 1 ); 
8020             SetCurrentCell( m_currentCellCoords
.GetRow(), 
8021                             m_currentCellCoords
.GetCol() + 1 ); 
8032 bool wxGrid::MovePageUp() 
8034     if ( m_currentCellCoords 
== wxGridNoCellCoords 
) return FALSE
; 
8036     int row 
= m_currentCellCoords
.GetRow(); 
8040         m_gridWin
->GetClientSize( &cw
, &ch 
); 
8042         int y 
= GetRowTop(row
); 
8043         int newRow 
= internalYToRow( y 
- ch 
+ 1 ); 
8045         if ( newRow 
== row 
) 
8047             //row > 0 , so newrow can never be less than 0 here. 
8051         MakeCellVisible( newRow
, m_currentCellCoords
.GetCol() ); 
8052         SetCurrentCell( newRow
, m_currentCellCoords
.GetCol() ); 
8060 bool wxGrid::MovePageDown() 
8062     if ( m_currentCellCoords 
== wxGridNoCellCoords 
) return FALSE
; 
8064     int row 
= m_currentCellCoords
.GetRow(); 
8065     if ( (row
+1) < m_numRows 
) 
8068         m_gridWin
->GetClientSize( &cw
, &ch 
); 
8070         int y 
= GetRowTop(row
); 
8071         int newRow 
= internalYToRow( y 
+ ch 
); 
8072         if ( newRow 
== row 
) 
8074             // row < m_numRows , so newrow can't overflow here. 
8078         MakeCellVisible( newRow
, m_currentCellCoords
.GetCol() ); 
8079         SetCurrentCell( newRow
, m_currentCellCoords
.GetCol() ); 
8087 bool wxGrid::MoveCursorUpBlock( bool expandSelection 
) 
8090          m_currentCellCoords 
!= wxGridNoCellCoords  
&& 
8091          m_currentCellCoords
.GetRow() > 0 ) 
8093         int row 
= m_currentCellCoords
.GetRow(); 
8094         int col 
= m_currentCellCoords
.GetCol(); 
8096         if ( m_table
->IsEmptyCell(row
, col
) ) 
8098             // starting in an empty cell: find the next block of 
8104                 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break; 
8107         else if ( m_table
->IsEmptyCell(row
-1, col
) ) 
8109             // starting at the top of a block: find the next block 
8115                 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break; 
8120             // starting within a block: find the top of the block 
8125                 if ( m_table
->IsEmptyCell(row
, col
) ) 
8133         MakeCellVisible( row
, col 
); 
8134         if ( expandSelection 
) 
8136             m_selectingKeyboard 
= wxGridCellCoords( row
, col 
); 
8137             HighlightBlock( m_currentCellCoords
, m_selectingKeyboard 
); 
8142             SetCurrentCell( row
, col 
); 
8150 bool wxGrid::MoveCursorDownBlock( bool expandSelection 
) 
8153          m_currentCellCoords 
!= wxGridNoCellCoords  
&& 
8154          m_currentCellCoords
.GetRow() < m_numRows
-1 ) 
8156         int row 
= m_currentCellCoords
.GetRow(); 
8157         int col 
= m_currentCellCoords
.GetCol(); 
8159         if ( m_table
->IsEmptyCell(row
, col
) ) 
8161             // starting in an empty cell: find the next block of 
8164             while ( row 
< m_numRows
-1 ) 
8167                 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break; 
8170         else if ( m_table
->IsEmptyCell(row
+1, col
) ) 
8172             // starting at the bottom of a block: find the next block 
8175             while ( row 
< m_numRows
-1 ) 
8178                 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break; 
8183             // starting within a block: find the bottom of the block 
8185             while ( row 
< m_numRows
-1 ) 
8188                 if ( m_table
->IsEmptyCell(row
, col
) ) 
8196         MakeCellVisible( row
, col 
); 
8197         if ( expandSelection 
) 
8199             m_selectingKeyboard 
= wxGridCellCoords( row
, col 
); 
8200             HighlightBlock( m_currentCellCoords
, m_selectingKeyboard 
); 
8205             SetCurrentCell( row
, col 
); 
8214 bool wxGrid::MoveCursorLeftBlock( bool expandSelection 
) 
8217          m_currentCellCoords 
!= wxGridNoCellCoords  
&& 
8218          m_currentCellCoords
.GetCol() > 0 ) 
8220         int row 
= m_currentCellCoords
.GetRow(); 
8221         int col 
= m_currentCellCoords
.GetCol(); 
8223         if ( m_table
->IsEmptyCell(row
, col
) ) 
8225             // starting in an empty cell: find the next block of 
8231                 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break; 
8234         else if ( m_table
->IsEmptyCell(row
, col
-1) ) 
8236             // starting at the left of a block: find the next block 
8242                 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break; 
8247             // starting within a block: find the left of the block 
8252                 if ( m_table
->IsEmptyCell(row
, col
) ) 
8260         MakeCellVisible( row
, col 
); 
8261         if ( expandSelection 
) 
8263             m_selectingKeyboard 
= wxGridCellCoords( row
, col 
); 
8264             HighlightBlock( m_currentCellCoords
, m_selectingKeyboard 
); 
8269             SetCurrentCell( row
, col 
); 
8278 bool wxGrid::MoveCursorRightBlock( bool expandSelection 
) 
8281          m_currentCellCoords 
!= wxGridNoCellCoords  
&& 
8282          m_currentCellCoords
.GetCol() < m_numCols
-1 ) 
8284         int row 
= m_currentCellCoords
.GetRow(); 
8285         int col 
= m_currentCellCoords
.GetCol(); 
8287         if ( m_table
->IsEmptyCell(row
, col
) ) 
8289             // starting in an empty cell: find the next block of 
8292             while ( col 
< m_numCols
-1 ) 
8295                 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break; 
8298         else if ( m_table
->IsEmptyCell(row
, col
+1) ) 
8300             // starting at the right of a block: find the next block 
8303             while ( col 
< m_numCols
-1 ) 
8306                 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break; 
8311             // starting within a block: find the right of the block 
8313             while ( col 
< m_numCols
-1 ) 
8316                 if ( m_table
->IsEmptyCell(row
, col
) ) 
8324         MakeCellVisible( row
, col 
); 
8325         if ( expandSelection 
) 
8327             m_selectingKeyboard 
= wxGridCellCoords( row
, col 
); 
8328             HighlightBlock( m_currentCellCoords
, m_selectingKeyboard 
); 
8333             SetCurrentCell( row
, col 
); 
8345 // ------ Label values and formatting 
8348 void wxGrid::GetRowLabelAlignment( int *horiz
, int *vert 
) 
8350     *horiz 
= m_rowLabelHorizAlign
; 
8351     *vert  
= m_rowLabelVertAlign
; 
8354 void wxGrid::GetColLabelAlignment( int *horiz
, int *vert 
) 
8356     *horiz 
= m_colLabelHorizAlign
; 
8357     *vert  
= m_colLabelVertAlign
; 
8360 int wxGrid::GetColLabelTextOrientation() 
8362     return m_colLabelTextOrientation
; 
8365 wxString 
wxGrid::GetRowLabelValue( int row 
) 
8369         return m_table
->GetRowLabelValue( row 
); 
8379 wxString 
wxGrid::GetColLabelValue( int col 
) 
8383         return m_table
->GetColLabelValue( col 
); 
8394 void wxGrid::SetRowLabelSize( int width 
) 
8396     width 
= wxMax( width
, 0 ); 
8397     if ( width 
!= m_rowLabelWidth 
) 
8401             m_rowLabelWin
->Show( FALSE 
); 
8402             m_cornerLabelWin
->Show( FALSE 
); 
8404         else if ( m_rowLabelWidth 
== 0 ) 
8406             m_rowLabelWin
->Show( TRUE 
); 
8407             if ( m_colLabelHeight 
> 0 ) m_cornerLabelWin
->Show( TRUE 
); 
8410         m_rowLabelWidth 
= width
; 
8412         wxScrolledWindow::Refresh( TRUE 
); 
8417 void wxGrid::SetColLabelSize( int height 
) 
8419     height 
= wxMax( height
, 0 ); 
8420     if ( height 
!= m_colLabelHeight 
) 
8424             m_colLabelWin
->Show( FALSE 
); 
8425             m_cornerLabelWin
->Show( FALSE 
); 
8427         else if ( m_colLabelHeight 
== 0 ) 
8429             m_colLabelWin
->Show( TRUE 
); 
8430             if ( m_rowLabelWidth 
> 0 ) m_cornerLabelWin
->Show( TRUE 
); 
8433         m_colLabelHeight 
= height
; 
8435         wxScrolledWindow::Refresh( TRUE 
); 
8440 void wxGrid::SetLabelBackgroundColour( const wxColour
& colour 
) 
8442     if ( m_labelBackgroundColour 
!= colour 
) 
8444         m_labelBackgroundColour 
= colour
; 
8445         m_rowLabelWin
->SetBackgroundColour( colour 
); 
8446         m_colLabelWin
->SetBackgroundColour( colour 
); 
8447         m_cornerLabelWin
->SetBackgroundColour( colour 
); 
8449         if ( !GetBatchCount() ) 
8451             m_rowLabelWin
->Refresh(); 
8452             m_colLabelWin
->Refresh(); 
8453             m_cornerLabelWin
->Refresh(); 
8458 void wxGrid::SetLabelTextColour( const wxColour
& colour 
) 
8460     if ( m_labelTextColour 
!= colour 
) 
8462         m_labelTextColour 
= colour
; 
8463         if ( !GetBatchCount() ) 
8465             m_rowLabelWin
->Refresh(); 
8466             m_colLabelWin
->Refresh(); 
8471 void wxGrid::SetLabelFont( const wxFont
& font 
) 
8474     if ( !GetBatchCount() ) 
8476         m_rowLabelWin
->Refresh(); 
8477         m_colLabelWin
->Refresh(); 
8481 void wxGrid::SetRowLabelAlignment( int horiz
, int vert 
) 
8483     // allow old (incorrect) defs to be used 
8486         case wxLEFT
:   horiz 
= wxALIGN_LEFT
; break; 
8487         case wxRIGHT
:  horiz 
= wxALIGN_RIGHT
; break; 
8488         case wxCENTRE
: horiz 
= wxALIGN_CENTRE
; break; 
8493         case wxTOP
:    vert 
= wxALIGN_TOP
;    break; 
8494         case wxBOTTOM
: vert 
= wxALIGN_BOTTOM
; break; 
8495         case wxCENTRE
: vert 
= wxALIGN_CENTRE
; break; 
8498     if ( horiz 
== wxALIGN_LEFT 
|| horiz 
== wxALIGN_CENTRE 
|| horiz 
== wxALIGN_RIGHT 
) 
8500         m_rowLabelHorizAlign 
= horiz
; 
8503     if ( vert 
== wxALIGN_TOP 
|| vert 
== wxALIGN_CENTRE 
|| vert 
== wxALIGN_BOTTOM 
) 
8505         m_rowLabelVertAlign 
= vert
; 
8508     if ( !GetBatchCount() ) 
8510         m_rowLabelWin
->Refresh(); 
8514 void wxGrid::SetColLabelAlignment( int horiz
, int vert 
) 
8516     // allow old (incorrect) defs to be used 
8519         case wxLEFT
:   horiz 
= wxALIGN_LEFT
; break; 
8520         case wxRIGHT
:  horiz 
= wxALIGN_RIGHT
; break; 
8521         case wxCENTRE
: horiz 
= wxALIGN_CENTRE
; break; 
8526         case wxTOP
:    vert 
= wxALIGN_TOP
;    break; 
8527         case wxBOTTOM
: vert 
= wxALIGN_BOTTOM
; break; 
8528         case wxCENTRE
: vert 
= wxALIGN_CENTRE
; break; 
8531     if ( horiz 
== wxALIGN_LEFT 
|| horiz 
== wxALIGN_CENTRE 
|| horiz 
== wxALIGN_RIGHT 
) 
8533         m_colLabelHorizAlign 
= horiz
; 
8536     if ( vert 
== wxALIGN_TOP 
|| vert 
== wxALIGN_CENTRE 
|| vert 
== wxALIGN_BOTTOM 
) 
8538         m_colLabelVertAlign 
= vert
; 
8541     if ( !GetBatchCount() ) 
8543         m_colLabelWin
->Refresh(); 
8547 // Note:        under MSW, the default column label font must be changed because it 
8548 //                              does not support vertical printing 
8550 // Example: wxFont font(9, wxSWISS, wxNORMAL, wxBOLD); 
8551 //                              pGrid->SetLabelFont(font); 
8552 //              pGrid->SetColLabelTextOrientation(wxVERTICAL); 
8554 void wxGrid::SetColLabelTextOrientation( int textOrientation 
) 
8556     if( textOrientation 
== wxHORIZONTAL 
|| textOrientation 
== wxVERTICAL 
) 
8558         m_colLabelTextOrientation 
= textOrientation
; 
8561     if ( !GetBatchCount() ) 
8563         m_colLabelWin
->Refresh(); 
8567 void wxGrid::SetRowLabelValue( int row
, const wxString
& s 
) 
8571         m_table
->SetRowLabelValue( row
, s 
); 
8572         if ( !GetBatchCount() ) 
8574             wxRect rect 
= CellToRect( row
, 0); 
8575             if ( rect
.height 
> 0 ) 
8577                 CalcScrolledPosition(0, rect
.y
, &rect
.x
, &rect
.y
); 
8579                 rect
.width 
= m_rowLabelWidth
; 
8580                 m_rowLabelWin
->Refresh( TRUE
, &rect 
); 
8586 void wxGrid::SetColLabelValue( int col
, const wxString
& s 
) 
8590         m_table
->SetColLabelValue( col
, s 
); 
8591         if ( !GetBatchCount() ) 
8593             wxRect rect 
= CellToRect( 0, col 
); 
8594             if ( rect
.width 
> 0 ) 
8596                 CalcScrolledPosition(rect
.x
, 0, &rect
.x
, &rect
.y
); 
8598                 rect
.height 
= m_colLabelHeight
; 
8599                 m_colLabelWin
->Refresh( TRUE
, &rect 
); 
8605 void wxGrid::SetGridLineColour( const wxColour
& colour 
) 
8607     if ( m_gridLineColour 
!= colour 
) 
8609         m_gridLineColour 
= colour
; 
8611         wxClientDC 
dc( m_gridWin 
); 
8613         DrawAllGridLines( dc
, wxRegion() ); 
8618 void wxGrid::SetCellHighlightColour( const wxColour
& colour 
) 
8620     if ( m_cellHighlightColour 
!= colour 
) 
8622         m_cellHighlightColour 
= colour
; 
8624         wxClientDC 
dc( m_gridWin 
); 
8626         wxGridCellAttr
* attr 
= GetCellAttr(m_currentCellCoords
); 
8627         DrawCellHighlight(dc
, attr
); 
8632 void wxGrid::SetCellHighlightPenWidth(int width
) 
8634     if (m_cellHighlightPenWidth 
!= width
) { 
8635         m_cellHighlightPenWidth 
= width
; 
8637         // Just redrawing the cell highlight is not enough since that won't 
8638         // make any visible change if the the thickness is getting smaller. 
8639         int row 
= m_currentCellCoords
.GetRow(); 
8640         int col 
= m_currentCellCoords
.GetCol(); 
8641         if ( GetColWidth(col
) <= 0 || GetRowHeight(row
) <= 0 ) 
8643         wxRect rect 
= CellToRect(row
, col
); 
8644         m_gridWin
->Refresh(TRUE
, &rect
); 
8648 void wxGrid::SetCellHighlightROPenWidth(int width
) 
8650     if (m_cellHighlightROPenWidth 
!= width
) { 
8651         m_cellHighlightROPenWidth 
= width
; 
8653         // Just redrawing the cell highlight is not enough since that won't 
8654         // make any visible change if the the thickness is getting smaller. 
8655         int row 
= m_currentCellCoords
.GetRow(); 
8656         int col 
= m_currentCellCoords
.GetCol(); 
8657         if ( GetColWidth(col
) <= 0 || GetRowHeight(row
) <= 0 ) 
8659         wxRect rect 
= CellToRect(row
, col
); 
8660         m_gridWin
->Refresh(TRUE
, &rect
); 
8664 void wxGrid::EnableGridLines( bool enable 
) 
8666     if ( enable 
!= m_gridLinesEnabled 
) 
8668         m_gridLinesEnabled 
= enable
; 
8670         if ( !GetBatchCount() ) 
8674                 wxClientDC 
dc( m_gridWin 
); 
8676                 DrawAllGridLines( dc
, wxRegion() ); 
8680                 m_gridWin
->Refresh(); 
8687 int wxGrid::GetDefaultRowSize() 
8689     return m_defaultRowHeight
; 
8692 int wxGrid::GetRowSize( int row 
) 
8694     wxCHECK_MSG( row 
>= 0 && row 
< m_numRows
, 0, _T("invalid row index") ); 
8696     return GetRowHeight(row
); 
8699 int wxGrid::GetDefaultColSize() 
8701     return m_defaultColWidth
; 
8704 int wxGrid::GetColSize( int col 
) 
8706     wxCHECK_MSG( col 
>= 0 && col 
< m_numCols
, 0, _T("invalid column index") ); 
8708     return GetColWidth(col
); 
8711 // ============================================================================ 
8712 // access to the grid attributes: each of them has a default value in the grid 
8713 // itself and may be overidden on a per-cell basis 
8714 // ============================================================================ 
8716 // ---------------------------------------------------------------------------- 
8717 // setting default attributes 
8718 // ---------------------------------------------------------------------------- 
8720 void wxGrid::SetDefaultCellBackgroundColour( const wxColour
& col 
) 
8722     m_defaultCellAttr
->SetBackgroundColour(col
); 
8724     m_gridWin
->SetBackgroundColour(col
); 
8728 void wxGrid::SetDefaultCellTextColour( const wxColour
& col 
) 
8730     m_defaultCellAttr
->SetTextColour(col
); 
8733 void wxGrid::SetDefaultCellAlignment( int horiz
, int vert 
) 
8735     m_defaultCellAttr
->SetAlignment(horiz
, vert
); 
8738 void wxGrid::SetDefaultCellOverflow( bool allow 
) 
8740     m_defaultCellAttr
->SetOverflow(allow
); 
8743 void wxGrid::SetDefaultCellFont( const wxFont
& font 
) 
8745     m_defaultCellAttr
->SetFont(font
); 
8748 void wxGrid::SetDefaultRenderer(wxGridCellRenderer 
*renderer
) 
8750     m_defaultCellAttr
->SetRenderer(renderer
); 
8753 void wxGrid::SetDefaultEditor(wxGridCellEditor 
*editor
) 
8755     m_defaultCellAttr
->SetEditor(editor
); 
8758 // ---------------------------------------------------------------------------- 
8759 // access to the default attrbiutes 
8760 // ---------------------------------------------------------------------------- 
8762 wxColour 
wxGrid::GetDefaultCellBackgroundColour() 
8764     return m_defaultCellAttr
->GetBackgroundColour(); 
8767 wxColour 
wxGrid::GetDefaultCellTextColour() 
8769     return m_defaultCellAttr
->GetTextColour(); 
8772 wxFont 
wxGrid::GetDefaultCellFont() 
8774     return m_defaultCellAttr
->GetFont(); 
8777 void wxGrid::GetDefaultCellAlignment( int *horiz
, int *vert 
) 
8779     m_defaultCellAttr
->GetAlignment(horiz
, vert
); 
8782 bool wxGrid::GetDefaultCellOverflow() 
8784     return m_defaultCellAttr
->GetOverflow(); 
8787 wxGridCellRenderer 
*wxGrid::GetDefaultRenderer() const 
8789     return m_defaultCellAttr
->GetRenderer(NULL
, 0, 0); 
8792 wxGridCellEditor 
*wxGrid::GetDefaultEditor() const 
8794     return m_defaultCellAttr
->GetEditor(NULL
,0,0); 
8797 // ---------------------------------------------------------------------------- 
8798 // access to cell attributes 
8799 // ---------------------------------------------------------------------------- 
8801 wxColour 
wxGrid::GetCellBackgroundColour(int row
, int col
) 
8803     wxGridCellAttr 
*attr 
= GetCellAttr(row
, col
); 
8804     wxColour colour 
= attr
->GetBackgroundColour(); 
8809 wxColour 
wxGrid::GetCellTextColour( int row
, int col 
) 
8811     wxGridCellAttr 
*attr 
= GetCellAttr(row
, col
); 
8812     wxColour colour 
= attr
->GetTextColour(); 
8817 wxFont 
wxGrid::GetCellFont( int row
, int col 
) 
8819     wxGridCellAttr 
*attr 
= GetCellAttr(row
, col
); 
8820     wxFont font 
= attr
->GetFont(); 
8825 void wxGrid::GetCellAlignment( int row
, int col
, int *horiz
, int *vert 
) 
8827     wxGridCellAttr 
*attr 
= GetCellAttr(row
, col
); 
8828     attr
->GetAlignment(horiz
, vert
); 
8832 bool wxGrid::GetCellOverflow( int row
, int col 
) 
8834     wxGridCellAttr 
*attr 
= GetCellAttr(row
, col
); 
8835     bool allow 
= attr
->GetOverflow(); 
8840 void wxGrid::GetCellSize( int row
, int col
, int *num_rows
, int *num_cols 
) 
8842     wxGridCellAttr 
*attr 
= GetCellAttr(row
, col
); 
8843     attr
->GetSize( num_rows
, num_cols 
); 
8847 wxGridCellRenderer
* wxGrid::GetCellRenderer(int row
, int col
) 
8849     wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
8850     wxGridCellRenderer
* renderer 
= attr
->GetRenderer(this, row
, col
); 
8856 wxGridCellEditor
* wxGrid::GetCellEditor(int row
, int col
) 
8858     wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
8859     wxGridCellEditor
* editor 
= attr
->GetEditor(this, row
, col
); 
8865 bool wxGrid::IsReadOnly(int row
, int col
) const 
8867     wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
8868     bool isReadOnly 
= attr
->IsReadOnly(); 
8873 // ---------------------------------------------------------------------------- 
8874 // attribute support: cache, automatic provider creation, ... 
8875 // ---------------------------------------------------------------------------- 
8877 bool wxGrid::CanHaveAttributes() 
8884     return m_table
->CanHaveAttributes(); 
8887 void wxGrid::ClearAttrCache() 
8889     if ( m_attrCache
.row 
!= -1 ) 
8891         wxSafeDecRef(m_attrCache
.attr
); 
8892         m_attrCache
.attr 
= NULL
; 
8893         m_attrCache
.row 
= -1; 
8897 void wxGrid::CacheAttr(int row
, int col
, wxGridCellAttr 
*attr
) const 
8901         wxGrid 
*self 
= (wxGrid 
*)this;  // const_cast 
8903         self
->ClearAttrCache(); 
8904         self
->m_attrCache
.row 
= row
; 
8905         self
->m_attrCache
.col 
= col
; 
8906         self
->m_attrCache
.attr 
= attr
; 
8911 bool wxGrid::LookupAttr(int row
, int col
, wxGridCellAttr 
**attr
) const 
8913     if ( row 
== m_attrCache
.row 
&& col 
== m_attrCache
.col 
) 
8915         *attr 
= m_attrCache
.attr
; 
8916         wxSafeIncRef(m_attrCache
.attr
); 
8918 #ifdef DEBUG_ATTR_CACHE 
8919         gs_nAttrCacheHits
++; 
8926 #ifdef DEBUG_ATTR_CACHE 
8927         gs_nAttrCacheMisses
++; 
8933 wxGridCellAttr 
*wxGrid::GetCellAttr(int row
, int col
) const 
8935     wxGridCellAttr 
*attr 
= NULL
; 
8936     // Additional test to avoid looking at the cache e.g. for 
8937     // wxNoCellCoords, as this will confuse memory management. 
8940         if ( !LookupAttr(row
, col
, &attr
) ) 
8942             attr 
= m_table 
? m_table
->GetAttr(row
, col 
, wxGridCellAttr::Any
) 
8943                            : (wxGridCellAttr 
*)NULL
; 
8944             CacheAttr(row
, col
, attr
); 
8949         attr
->SetDefAttr(m_defaultCellAttr
); 
8953         attr 
= m_defaultCellAttr
; 
8960 wxGridCellAttr 
*wxGrid::GetOrCreateCellAttr(int row
, int col
) const 
8962     wxGridCellAttr 
*attr 
= (wxGridCellAttr 
*)NULL
; 
8964     wxCHECK_MSG( m_table
, attr
, 
8965                   _T("we may only be called if CanHaveAttributes() returned TRUE and then m_table should be !NULL") ); 
8967     attr 
= m_table
->GetAttr(row
, col
, wxGridCellAttr::Cell
); 
8970         attr 
= new wxGridCellAttr(m_defaultCellAttr
); 
8972         // artificially inc the ref count to match DecRef() in caller 
8974         m_table
->SetAttr(attr
, row
, col
); 
8980 // ---------------------------------------------------------------------------- 
8981 // setting column attributes (wrappers around SetColAttr) 
8982 // ---------------------------------------------------------------------------- 
8984 void wxGrid::SetColFormatBool(int col
) 
8986     SetColFormatCustom(col
, wxGRID_VALUE_BOOL
); 
8989 void wxGrid::SetColFormatNumber(int col
) 
8991     SetColFormatCustom(col
, wxGRID_VALUE_NUMBER
); 
8994 void wxGrid::SetColFormatFloat(int col
, int width
, int precision
) 
8996     wxString typeName 
= wxGRID_VALUE_FLOAT
; 
8997     if ( (width 
!= -1) || (precision 
!= -1) ) 
8999         typeName 
<< _T(':') << width 
<< _T(',') << precision
; 
9002     SetColFormatCustom(col
, typeName
); 
9005 void wxGrid::SetColFormatCustom(int col
, const wxString
& typeName
) 
9007     wxGridCellAttr 
*attr 
= (wxGridCellAttr 
*)NULL
; 
9009     attr 
= m_table
->GetAttr(-1, col
, wxGridCellAttr::Col 
); 
9011         attr 
= new wxGridCellAttr
; 
9012     wxGridCellRenderer 
*renderer 
= GetDefaultRendererForType(typeName
); 
9013     attr
->SetRenderer(renderer
); 
9015     SetColAttr(col
, attr
); 
9019 // ---------------------------------------------------------------------------- 
9020 // setting cell attributes: this is forwarded to the table 
9021 // ---------------------------------------------------------------------------- 
9023 void wxGrid::SetAttr(int row
, int col
, wxGridCellAttr 
*attr
) 
9025     if ( CanHaveAttributes() ) 
9027         m_table
->SetAttr(attr
, row
, col
); 
9036 void wxGrid::SetRowAttr(int row
, wxGridCellAttr 
*attr
) 
9038     if ( CanHaveAttributes() ) 
9040         m_table
->SetRowAttr(attr
, row
); 
9049 void wxGrid::SetColAttr(int col
, wxGridCellAttr 
*attr
) 
9051     if ( CanHaveAttributes() ) 
9053         m_table
->SetColAttr(attr
, col
); 
9062 void wxGrid::SetCellBackgroundColour( int row
, int col
, const wxColour
& colour 
) 
9064     if ( CanHaveAttributes() ) 
9066         wxGridCellAttr 
*attr 
= GetOrCreateCellAttr(row
, col
); 
9067         attr
->SetBackgroundColour(colour
); 
9072 void wxGrid::SetCellTextColour( int row
, int col
, const wxColour
& colour 
) 
9074     if ( CanHaveAttributes() ) 
9076         wxGridCellAttr 
*attr 
= GetOrCreateCellAttr(row
, col
); 
9077         attr
->SetTextColour(colour
); 
9082 void wxGrid::SetCellFont( int row
, int col
, const wxFont
& font 
) 
9084     if ( CanHaveAttributes() ) 
9086         wxGridCellAttr 
*attr 
= GetOrCreateCellAttr(row
, col
); 
9087         attr
->SetFont(font
); 
9092 void wxGrid::SetCellAlignment( int row
, int col
, int horiz
, int vert 
) 
9094     if ( CanHaveAttributes() ) 
9096         wxGridCellAttr 
*attr 
= GetOrCreateCellAttr(row
, col
); 
9097         attr
->SetAlignment(horiz
, vert
); 
9102 void wxGrid::SetCellOverflow( int row
, int col
, bool allow 
) 
9104     if ( CanHaveAttributes() ) 
9106         wxGridCellAttr 
*attr 
= GetOrCreateCellAttr(row
, col
); 
9107         attr
->SetOverflow(allow
); 
9112 void wxGrid::SetCellSize( int row
, int col
, int num_rows
, int num_cols 
) 
9114     if ( CanHaveAttributes() ) 
9116         int cell_rows
, cell_cols
; 
9118         wxGridCellAttr 
*attr 
= GetOrCreateCellAttr(row
, col
); 
9119         attr
->GetSize(&cell_rows
, &cell_cols
); 
9120         attr
->SetSize(num_rows
, num_cols
); 
9123         // Cannot set the size of a cell to 0 or negative values 
9124         // While it is perfectly legal to do that, this function cannot 
9125         // handle all the possibilies, do it by hand by getting the CellAttr. 
9126         // You can only set the size of a cell to 1,1 or greater with this fn 
9127         wxASSERT_MSG( !((cell_rows 
< 1) || (cell_cols 
< 1)), 
9128                       wxT("wxGrid::SetCellSize setting cell size that is already part of another cell")); 
9129         wxASSERT_MSG( !((num_rows 
< 1) || (num_cols 
< 1)), 
9130                       wxT("wxGrid::SetCellSize setting cell size to < 1")); 
9132         // if this was already a multicell then "turn off" the other cells first 
9133         if ((cell_rows 
> 1) || (cell_rows 
> 1)) 
9136             for (j
=row
; j
<row
+cell_rows
; j
++) 
9138                 for (i
=col
; i
<col
+cell_cols
; i
++) 
9140                     if ((i 
!= col
) || (j 
!= row
)) 
9142                         wxGridCellAttr 
*attr_stub 
= GetOrCreateCellAttr(j
, i
); 
9143                         attr_stub
->SetSize( 1, 1 ); 
9144                         attr_stub
->DecRef(); 
9150         // mark the cells that will be covered by this cell to 
9151         // negative or zero values to point back at this cell 
9152         if (((num_rows 
> 1) || (num_cols 
> 1)) && (num_rows 
>= 1) && (num_cols 
>= 1)) 
9155             for (j
=row
; j
<row
+num_rows
; j
++) 
9157                 for (i
=col
; i
<col
+num_cols
; i
++) 
9159                     if ((i 
!= col
) || (j 
!= row
)) 
9161                         wxGridCellAttr 
*attr_stub 
= GetOrCreateCellAttr(j
, i
); 
9162                         attr_stub
->SetSize( row
-j
, col
-i 
); 
9163                         attr_stub
->DecRef(); 
9171 void wxGrid::SetCellRenderer(int row
, int col
, wxGridCellRenderer 
*renderer
) 
9173     if ( CanHaveAttributes() ) 
9175         wxGridCellAttr 
*attr 
= GetOrCreateCellAttr(row
, col
); 
9176         attr
->SetRenderer(renderer
); 
9181 void wxGrid::SetCellEditor(int row
, int col
, wxGridCellEditor
* editor
) 
9183     if ( CanHaveAttributes() ) 
9185         wxGridCellAttr 
*attr 
= GetOrCreateCellAttr(row
, col
); 
9186         attr
->SetEditor(editor
); 
9191 void wxGrid::SetReadOnly(int row
, int col
, bool isReadOnly
) 
9193     if ( CanHaveAttributes() ) 
9195         wxGridCellAttr 
*attr 
= GetOrCreateCellAttr(row
, col
); 
9196         attr
->SetReadOnly(isReadOnly
); 
9201 // ---------------------------------------------------------------------------- 
9202 // Data type registration 
9203 // ---------------------------------------------------------------------------- 
9205 void wxGrid::RegisterDataType(const wxString
& typeName
, 
9206                               wxGridCellRenderer
* renderer
, 
9207                               wxGridCellEditor
* editor
) 
9209     m_typeRegistry
->RegisterDataType(typeName
, renderer
, editor
); 
9213 wxGridCellEditor
* wxGrid::GetDefaultEditorForCell(int row
, int col
) const 
9215     wxString typeName 
= m_table
->GetTypeName(row
, col
); 
9216     return GetDefaultEditorForType(typeName
); 
9219 wxGridCellRenderer
* wxGrid::GetDefaultRendererForCell(int row
, int col
) const 
9221     wxString typeName 
= m_table
->GetTypeName(row
, col
); 
9222     return GetDefaultRendererForType(typeName
); 
9226 wxGrid::GetDefaultEditorForType(const wxString
& typeName
) const 
9228     int index 
= m_typeRegistry
->FindOrCloneDataType(typeName
); 
9229     if ( index 
== wxNOT_FOUND 
) 
9231         wxFAIL_MSG(wxT("Unknown data type name")); 
9236     return m_typeRegistry
->GetEditor(index
); 
9240 wxGrid::GetDefaultRendererForType(const wxString
& typeName
) const 
9242     int index 
= m_typeRegistry
->FindOrCloneDataType(typeName
); 
9243     if ( index 
== wxNOT_FOUND 
) 
9245         wxFAIL_MSG(wxT("Unknown data type name")); 
9250     return m_typeRegistry
->GetRenderer(index
); 
9254 // ---------------------------------------------------------------------------- 
9256 // ---------------------------------------------------------------------------- 
9258 void wxGrid::EnableDragRowSize( bool enable 
) 
9260     m_canDragRowSize 
= enable
; 
9264 void wxGrid::EnableDragColSize( bool enable 
) 
9266     m_canDragColSize 
= enable
; 
9269 void wxGrid::EnableDragGridSize( bool enable 
) 
9271     m_canDragGridSize 
= enable
; 
9275 void wxGrid::SetDefaultRowSize( int height
, bool resizeExistingRows 
) 
9277     m_defaultRowHeight 
= wxMax( height
, m_minAcceptableRowHeight 
); 
9279     if ( resizeExistingRows 
) 
9281         // since we are resizing all rows to the default row size, 
9282         // we can simply clear the row heights and row bottoms 
9283         // arrays (which also allows us to take advantage of 
9284         // some speed optimisations) 
9285         m_rowHeights
.Empty(); 
9286         m_rowBottoms
.Empty(); 
9287         if ( !GetBatchCount() ) 
9292 void wxGrid::SetRowSize( int row
, int height 
) 
9294     wxCHECK_RET( row 
>= 0 && row 
< m_numRows
, _T("invalid row index") ); 
9296     // See comment in SetColSize 
9297     if ( height 
< GetRowMinimalAcceptableHeight()) { return; } 
9299     if ( m_rowHeights
.IsEmpty() ) 
9301         // need to really create the array 
9305     int h 
= wxMax( 0, height 
); 
9306     int diff 
= h 
- m_rowHeights
[row
]; 
9308     m_rowHeights
[row
] = h
; 
9310     for ( i 
= row
;  i 
< m_numRows
;  i
++ ) 
9312         m_rowBottoms
[i
] += diff
; 
9314     if ( !GetBatchCount() ) 
9318 void wxGrid::SetDefaultColSize( int width
, bool resizeExistingCols 
) 
9320     m_defaultColWidth 
= wxMax( width
, m_minAcceptableColWidth 
); 
9322     if ( resizeExistingCols 
) 
9324         // since we are resizing all columns to the default column size, 
9325         // we can simply clear the col widths and col rights 
9326         // arrays (which also allows us to take advantage of 
9327         // some speed optimisations) 
9328         m_colWidths
.Empty(); 
9329         m_colRights
.Empty(); 
9330         if ( !GetBatchCount() ) 
9335 void wxGrid::SetColSize( int col
, int width 
) 
9337     wxCHECK_RET( col 
>= 0 && col 
< m_numCols
, _T("invalid column index") ); 
9339     // should we check that it's bigger than GetColMinimalWidth(col) here? 
9341     // No, because it is reasonable to assume the library user know's 
9342     // what he is doing. However whe should test against the weaker  
9343     // constariant of minimalAcceptableWidth, as this breaks rendering 
9345     // This test then fixes sf.net bug #645734 
9347     if ( width 
< GetColMinimalAcceptableWidth()) { return; } 
9349     if ( m_colWidths
.IsEmpty() ) 
9351         // need to really create the array 
9355     // if < 0 calc new width from label 
9359       wxArrayString lines
; 
9360       wxClientDC 
dc(m_colLabelWin
); 
9361       dc
.SetFont(GetLabelFont()); 
9362       StringToLines(GetColLabelValue(col
), lines
); 
9363       GetTextBoxSize(dc
, lines
, &w
, &h
); 
9366     int w 
= wxMax( 0, width 
); 
9367     int diff 
= w 
- m_colWidths
[col
]; 
9368     m_colWidths
[col
] = w
; 
9371     for ( i 
= col
;  i 
< m_numCols
;  i
++ ) 
9373         m_colRights
[i
] += diff
; 
9375     if ( !GetBatchCount() ) 
9380 void wxGrid::SetColMinimalWidth( int col
, int width 
) 
9382     if (width 
> GetColMinimalAcceptableWidth()) { 
9383         m_colMinWidths
[col
] = width
; 
9387 void wxGrid::SetRowMinimalHeight( int row
, int width 
) 
9389     if (width 
> GetRowMinimalAcceptableHeight()) { 
9390        m_rowMinHeights
[row
] = width
; 
9394 int wxGrid::GetColMinimalWidth(int col
) const 
9396     wxLongToLongHashMap::const_iterator it 
= m_colMinWidths
.find(col
); 
9397     return it 
!= m_colMinWidths
.end() ? (int)it
->second 
: m_minAcceptableColWidth
; 
9400 int wxGrid::GetRowMinimalHeight(int row
) const 
9402     wxLongToLongHashMap::const_iterator it 
= m_rowMinHeights
.find(row
); 
9403     return it 
!= m_rowMinHeights
.end() ? (int)it
->second 
: m_minAcceptableRowHeight
; 
9406 void wxGrid::SetColMinimalAcceptableWidth( int width 
) 
9410     m_minAcceptableColWidth 
= width
; 
9413 void wxGrid::SetRowMinimalAcceptableHeight( int height 
) 
9417     m_minAcceptableRowHeight 
= height
; 
9420 int  wxGrid::GetColMinimalAcceptableWidth() const 
9422     return m_minAcceptableColWidth
; 
9425 int  wxGrid::GetRowMinimalAcceptableHeight() const 
9427     return m_minAcceptableRowHeight
; 
9430 // ---------------------------------------------------------------------------- 
9432 // ---------------------------------------------------------------------------- 
9434 void wxGrid::AutoSizeColOrRow( int colOrRow
, bool setAsMin
, bool column 
) 
9436     wxClientDC 
dc(m_gridWin
); 
9438     // init both of them to avoid compiler warnings, even if weo nly need one 
9446     wxCoord extent
, extentMax 
= 0; 
9447     int max 
= column 
? m_numRows 
: m_numCols
; 
9448     for ( int rowOrCol 
= 0; rowOrCol 
< max
; rowOrCol
++ ) 
9455         wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
9456         wxGridCellRenderer
* renderer 
= attr
->GetRenderer(this, row
, col
); 
9459             wxSize size 
= renderer
->GetBestSize(*this, *attr
, dc
, row
, col
); 
9460             extent 
= column 
? size
.x 
: size
.y
; 
9461             if ( extent 
> extentMax 
) 
9472     // now also compare with the column label extent 
9474     dc
.SetFont( GetLabelFont() ); 
9478         dc
.GetTextExtent( GetColLabelValue(col
), &w
, &h 
); 
9479         if( GetColLabelTextOrientation() == wxVERTICAL 
) 
9483         dc
.GetTextExtent( GetRowLabelValue(row
), &w
, &h 
); 
9485     extent 
= column 
? w 
: h
; 
9486     if ( extent 
> extentMax 
) 
9493         // empty column - give default extent (notice that if extentMax is less 
9494         // than default extent but != 0, it's ok) 
9495         extentMax 
= column 
? m_defaultColWidth 
: m_defaultRowHeight
; 
9501             // leave some space around text 
9512         SetColSize(col
, extentMax
); 
9513         if ( !GetBatchCount() ) 
9516             m_gridWin
->GetClientSize( &cw
, &ch 
); 
9517             wxRect 
rect ( CellToRect( 0, col 
) ); 
9519             CalcScrolledPosition(rect
.x
, 0, &rect
.x
, &dummy
); 
9520             rect
.width 
= cw 
- rect
.x
; 
9521             rect
.height 
= m_colLabelHeight
; 
9522             m_colLabelWin
->Refresh( TRUE
, &rect 
); 
9527         SetRowSize(row
, extentMax
); 
9528         if ( !GetBatchCount() ) 
9531             m_gridWin
->GetClientSize( &cw
, &ch 
); 
9532             wxRect 
rect ( CellToRect( row
, 0 ) ); 
9534             CalcScrolledPosition(0, rect
.y
, &dummy
, &rect
.y
); 
9535             rect
.width 
= m_rowLabelWidth
; 
9536             rect
.height 
= ch 
- rect
.y
; 
9537             m_rowLabelWin
->Refresh( TRUE
, &rect 
); 
9543             SetColMinimalWidth(col
, extentMax
); 
9545             SetRowMinimalHeight(row
, extentMax
); 
9549 int wxGrid::SetOrCalcColumnSizes(bool calcOnly
, bool setAsMin
) 
9551     int width 
= m_rowLabelWidth
; 
9556     for ( int col 
= 0; col 
< m_numCols
; col
++ ) 
9560             AutoSizeColumn(col
, setAsMin
); 
9563         width 
+= GetColWidth(col
); 
9572 int wxGrid::SetOrCalcRowSizes(bool calcOnly
, bool setAsMin
) 
9574     int height 
= m_colLabelHeight
; 
9579     for ( int row 
= 0; row 
< m_numRows
; row
++ ) 
9583             AutoSizeRow(row
, setAsMin
); 
9586         height 
+= GetRowHeight(row
); 
9595 void wxGrid::AutoSize() 
9599     wxSize 
size(SetOrCalcColumnSizes(FALSE
), SetOrCalcRowSizes(FALSE
)); 
9601     // round up the size to a multiple of scroll step - this ensures that we 
9602     // won't get the scrollbars if we're sized exactly to this width 
9603     // CalcDimension adds m_extraWidth + 1 etc. to calculate the necessary 
9605     wxSize 
sizeFit(GetScrollX(size
.x 
+ m_extraWidth 
+ 1) * GRID_SCROLL_LINE_X
, 
9606                    GetScrollY(size
.y 
+ m_extraHeight 
+ 1) * GRID_SCROLL_LINE_Y
); 
9608     // distribute the extra space between the columns/rows to avoid having 
9609     // extra white space 
9611     // Remove the extra m_extraWidth + 1 added above 
9612     wxCoord diff 
= sizeFit
.x 
- size
.x 
+ (m_extraWidth 
+ 1); 
9613     if ( diff 
&& m_numCols 
) 
9615         // try to resize the columns uniformly 
9616         wxCoord diffPerCol 
= diff 
/ m_numCols
; 
9619             for ( int col 
= 0; col 
< m_numCols
; col
++ ) 
9621                 SetColSize(col
, GetColWidth(col
) + diffPerCol
); 
9625         // add remaining amount to the last columns 
9626         diff 
-= diffPerCol 
* m_numCols
; 
9629             for ( int col 
= m_numCols 
- 1; col 
>= m_numCols 
- diff
; col
-- ) 
9631                 SetColSize(col
, GetColWidth(col
) + 1); 
9637     diff 
= sizeFit
.y 
- size
.y 
- (m_extraHeight 
+ 1); 
9638     if ( diff 
&& m_numRows 
) 
9640         // try to resize the columns uniformly 
9641         wxCoord diffPerRow 
= diff 
/ m_numRows
; 
9644             for ( int row 
= 0; row 
< m_numRows
; row
++ ) 
9646                 SetRowSize(row
, GetRowHeight(row
) + diffPerRow
); 
9650         // add remaining amount to the last rows 
9651         diff 
-= diffPerRow 
* m_numRows
; 
9654             for ( int row 
= m_numRows 
- 1; row 
>= m_numRows 
- diff
; row
-- ) 
9656                 SetRowSize(row
, GetRowHeight(row
) + 1); 
9663     SetClientSize(sizeFit
); 
9666 void wxGrid::AutoSizeRowLabelSize( int row 
) 
9668     wxArrayString lines
; 
9671     // Hide the edit control, so it 
9672     // won't interfer with drag-shrinking. 
9673     if( IsCellEditControlShown() ) 
9675         HideCellEditControl(); 
9676         SaveEditControlValue(); 
9679     // autosize row height depending on label text 
9680     StringToLines( GetRowLabelValue( row 
), lines 
); 
9681     wxClientDC 
dc( m_rowLabelWin 
); 
9682     GetTextBoxSize( dc
, lines
, &w
, &h
); 
9683     if( h 
< m_defaultRowHeight 
) 
9684         h 
= m_defaultRowHeight
; 
9689 void wxGrid::AutoSizeColLabelSize( int col 
) 
9691     wxArrayString lines
; 
9694     // Hide the edit control, so it 
9695     // won't interfer with drag-shrinking. 
9696     if( IsCellEditControlShown() ) 
9698         HideCellEditControl(); 
9699         SaveEditControlValue(); 
9702     // autosize column width depending on label text 
9703     StringToLines( GetColLabelValue( col 
), lines 
); 
9704     wxClientDC 
dc( m_colLabelWin 
); 
9705     if( GetColLabelTextOrientation() == wxHORIZONTAL 
) 
9706         GetTextBoxSize( dc
, lines
, &w
, &h
); 
9708         GetTextBoxSize( dc
, lines
, &h
, &w
); 
9709     if( w 
< m_defaultColWidth 
) 
9710         w 
= m_defaultColWidth
; 
9715 wxSize 
wxGrid::DoGetBestSize() const 
9717     // don't set sizes, only calculate them 
9718     wxGrid 
*self 
= (wxGrid 
*)this;  // const_cast 
9721     width 
= self
->SetOrCalcColumnSizes(TRUE
); 
9722     height 
= self
->SetOrCalcRowSizes(TRUE
); 
9724     int maxwidth
, maxheight
; 
9725     wxDisplaySize( & maxwidth
, & maxheight 
); 
9727     if ( width 
> maxwidth 
) width 
= maxwidth
; 
9728     if ( height 
> maxheight 
) height 
= maxheight
; 
9730     return wxSize( width
, height 
); 
9739 wxPen
& wxGrid::GetDividerPen() const 
9744 // ---------------------------------------------------------------------------- 
9745 // cell value accessor functions 
9746 // ---------------------------------------------------------------------------- 
9748 void wxGrid::SetCellValue( int row
, int col
, const wxString
& s 
) 
9752         m_table
->SetValue( row
, col
, s 
); 
9753         if ( !GetBatchCount() ) 
9756             wxRect 
rect( CellToRect( row
, col 
) ); 
9758             rect
.width 
= m_gridWin
->GetClientSize().GetWidth(); 
9759             CalcScrolledPosition(0, rect
.y
, &dummy
, &rect
.y
); 
9760             m_gridWin
->Refresh( FALSE
, &rect 
); 
9763         if ( m_currentCellCoords
.GetRow() == row 
&& 
9764              m_currentCellCoords
.GetCol() == col 
&& 
9765              IsCellEditControlShown()) 
9766              // Note: If we are using IsCellEditControlEnabled, 
9767              // this interacts badly with calling SetCellValue from 
9768              // an EVT_GRID_CELL_CHANGE handler. 
9770             HideCellEditControl(); 
9771             ShowCellEditControl(); // will reread data from table 
9778 // ------ Block, row and col selection 
9781 void wxGrid::SelectRow( int row
, bool addToSelected 
) 
9783     if ( IsSelection() && !addToSelected 
) 
9787         m_selection
->SelectRow( row
, FALSE
, addToSelected 
); 
9791 void wxGrid::SelectCol( int col
, bool addToSelected 
) 
9793     if ( IsSelection() && !addToSelected 
) 
9797         m_selection
->SelectCol( col
, FALSE
, addToSelected 
); 
9801 void wxGrid::SelectBlock( int topRow
, int leftCol
, int bottomRow
, int rightCol
, 
9802                           bool addToSelected 
) 
9804     if ( IsSelection() && !addToSelected 
) 
9808         m_selection
->SelectBlock( topRow
, leftCol
, bottomRow
, rightCol
, 
9809                                   FALSE
, addToSelected 
); 
9813 void wxGrid::SelectAll() 
9815     if ( m_numRows 
> 0 && m_numCols 
> 0 ) 
9818             m_selection
->SelectBlock( 0, 0, m_numRows
-1, m_numCols
-1 ); 
9823 // ------ Cell, row and col deselection 
9826 void wxGrid::DeselectRow( int row 
) 
9831     if ( m_selection
->GetSelectionMode() == wxGrid::wxGridSelectRows 
) 
9833         if ( m_selection
->IsInSelection(row
, 0 ) ) 
9834             m_selection
->ToggleCellSelection( row
, 0); 
9838         int nCols 
= GetNumberCols(); 
9839         for ( int i 
= 0; i 
< nCols 
; i
++ ) 
9841             if ( m_selection
->IsInSelection(row
, i 
) ) 
9842                 m_selection
->ToggleCellSelection( row
, i
); 
9847 void wxGrid::DeselectCol( int col 
) 
9852     if ( m_selection
->GetSelectionMode() == wxGrid::wxGridSelectColumns 
) 
9854         if ( m_selection
->IsInSelection(0, col 
) ) 
9855             m_selection
->ToggleCellSelection( 0, col
); 
9859         int nRows 
= GetNumberRows(); 
9860         for ( int i 
= 0; i 
< nRows 
; i
++ ) 
9862             if ( m_selection
->IsInSelection(i
, col 
) ) 
9863                 m_selection
->ToggleCellSelection(i
, col
); 
9868 void wxGrid::DeselectCell( int row
, int col 
) 
9870     if ( m_selection 
&& m_selection
->IsInSelection(row
, col
) ) 
9871         m_selection
->ToggleCellSelection(row
, col
); 
9874 bool wxGrid::IsSelection() 
9876     return ( m_selection 
&& (m_selection
->IsSelection() || 
9877              ( m_selectingTopLeft 
!= wxGridNoCellCoords 
&& 
9878                m_selectingBottomRight 
!= wxGridNoCellCoords
) ) ); 
9881 bool wxGrid::IsInSelection( int row
, int col 
) const 
9883     return ( m_selection 
&& (m_selection
->IsInSelection( row
, col 
) || 
9884              ( row 
>= m_selectingTopLeft
.GetRow() && 
9885                col 
>= m_selectingTopLeft
.GetCol() && 
9886                row 
<= m_selectingBottomRight
.GetRow() && 
9887                col 
<= m_selectingBottomRight
.GetCol() )) ); 
9890 wxGridCellCoordsArray 
wxGrid::GetSelectedCells() const 
9892     if (!m_selection
) { wxGridCellCoordsArray a
; return a
; } 
9893     return m_selection
->m_cellSelection
; 
9895 wxGridCellCoordsArray 
wxGrid::GetSelectionBlockTopLeft() const 
9897     if (!m_selection
) { wxGridCellCoordsArray a
; return a
; } 
9898     return m_selection
->m_blockSelectionTopLeft
; 
9900 wxGridCellCoordsArray 
wxGrid::GetSelectionBlockBottomRight() const 
9902     if (!m_selection
) { wxGridCellCoordsArray a
; return a
; } 
9903     return m_selection
->m_blockSelectionBottomRight
; 
9905 wxArrayInt 
wxGrid::GetSelectedRows() const 
9907     if (!m_selection
) { wxArrayInt a
; return a
; } 
9908     return m_selection
->m_rowSelection
; 
9910 wxArrayInt 
wxGrid::GetSelectedCols() const 
9912     if (!m_selection
) { wxArrayInt a
; return a
; } 
9913     return m_selection
->m_colSelection
; 
9917 void wxGrid::ClearSelection() 
9919     m_selectingTopLeft 
= wxGridNoCellCoords
; 
9920     m_selectingBottomRight 
= wxGridNoCellCoords
; 
9922         m_selection
->ClearSelection(); 
9926 // This function returns the rectangle that encloses the given block 
9927 // in device coords clipped to the client size of the grid window. 
9929 wxRect 
wxGrid::BlockToDeviceRect( const wxGridCellCoords 
&topLeft
, 
9930                                   const wxGridCellCoords 
&bottomRight 
) 
9932     wxRect 
rect( wxGridNoCellRect 
); 
9935     cellRect 
= CellToRect( topLeft 
); 
9936     if ( cellRect 
!= wxGridNoCellRect 
) 
9942         rect 
= wxRect( 0, 0, 0, 0 ); 
9945     cellRect 
= CellToRect( bottomRight 
); 
9946     if ( cellRect 
!= wxGridNoCellRect 
) 
9952         return wxGridNoCellRect
; 
9956     int left 
= rect
.GetLeft(); 
9957     int top 
= rect
.GetTop(); 
9958     int right 
= rect
.GetRight(); 
9959     int bottom 
= rect
.GetBottom(); 
9961     int leftCol 
= topLeft
.GetCol(); 
9962     int topRow 
= topLeft
.GetRow(); 
9963     int rightCol 
= bottomRight
.GetCol(); 
9964     int bottomRow 
= bottomRight
.GetRow(); 
9987     for ( j 
= topRow
; j 
<= bottomRow
; j
++ ) 
9989         for ( i 
= leftCol
; i 
<= rightCol
; i
++ ) 
9991             if ((j
==topRow
) || (j
==bottomRow
) || (i
==leftCol
) || (i
==rightCol
)) 
9993                 cellRect 
= CellToRect( j
, i 
); 
9995                 if (cellRect
.x 
< left
) 
9997                 if (cellRect
.y 
< top
) 
9999                 if (cellRect
.x 
+ cellRect
.width 
> right
) 
10000                     right 
= cellRect
.x 
+ cellRect
.width
; 
10001                 if (cellRect
.y 
+ cellRect
.height 
> bottom
) 
10002                     bottom 
= cellRect
.y 
+ cellRect
.height
; 
10004             else i 
= rightCol
; // jump over inner cells. 
10008     // convert to scrolled coords 
10010     CalcScrolledPosition( left
, top
, &left
, &top 
); 
10011     CalcScrolledPosition( right
, bottom
, &right
, &bottom 
); 
10014     m_gridWin
->GetClientSize( &cw
, &ch 
); 
10016     if (right 
< 0 || bottom 
< 0 || left 
> cw 
|| top 
> ch
) 
10017         return wxRect( 0, 0, 0, 0); 
10019     rect
.SetLeft( wxMax(0, left
) ); 
10020     rect
.SetTop( wxMax(0, top
) ); 
10021     rect
.SetRight( wxMin(cw
, right
) ); 
10022     rect
.SetBottom( wxMin(ch
, bottom
) ); 
10028 // ------ Grid event classes 
10031 IMPLEMENT_DYNAMIC_CLASS( wxGridEvent
, wxNotifyEvent 
) 
10033 wxGridEvent::wxGridEvent( int id
, wxEventType type
, wxObject
* obj
, 
10034                           int row
, int col
, int x
, int y
, bool sel
, 
10035                           bool control
, bool shift
, bool alt
, bool meta 
) 
10036         : wxNotifyEvent( type
, id 
) 
10043     m_control 
= control
; 
10048     SetEventObject(obj
); 
10052 IMPLEMENT_DYNAMIC_CLASS( wxGridSizeEvent
, wxNotifyEvent 
) 
10054 wxGridSizeEvent::wxGridSizeEvent( int id
, wxEventType type
, wxObject
* obj
, 
10055                                   int rowOrCol
, int x
, int y
, 
10056                                   bool control
, bool shift
, bool alt
, bool meta 
) 
10057         : wxNotifyEvent( type
, id 
) 
10059     m_rowOrCol 
= rowOrCol
; 
10062     m_control 
= control
; 
10067     SetEventObject(obj
); 
10071 IMPLEMENT_DYNAMIC_CLASS( wxGridRangeSelectEvent
, wxNotifyEvent 
) 
10073 wxGridRangeSelectEvent::wxGridRangeSelectEvent(int id
, wxEventType type
, wxObject
* obj
, 
10074                                                const wxGridCellCoords
& topLeft
, 
10075                                                const wxGridCellCoords
& bottomRight
, 
10076                                                bool sel
, bool control
, 
10077                                                bool shift
, bool alt
, bool meta 
) 
10078         : wxNotifyEvent( type
, id 
) 
10080     m_topLeft     
= topLeft
; 
10081     m_bottomRight 
= bottomRight
; 
10083     m_control     
= control
; 
10088     SetEventObject(obj
); 
10092 IMPLEMENT_DYNAMIC_CLASS(wxGridEditorCreatedEvent
, wxCommandEvent
) 
10094 wxGridEditorCreatedEvent::wxGridEditorCreatedEvent(int id
, wxEventType type
, 
10095                                                    wxObject
* obj
, int row
, 
10096                                                    int col
, wxControl
* ctrl
) 
10097     : wxCommandEvent(type
, id
) 
10099     SetEventObject(obj
); 
10105 #endif // wxUSE_GRID