1 /////////////////////////////////////////////////////////////////////////// 
   2 // Name:        generic/grid.cpp 
   3 // Purpose:     wxGrid and related classes 
   4 // Author:      Michael Bedward (based on code by Julian Smart, Robin Dunn) 
   8 // Copyright:   (c) Michael Bedward (mbedward@ozemail.com.au) 
   9 // Licence:     wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////////// 
  12 // ============================================================================ 
  14 // ============================================================================ 
  16 // ---------------------------------------------------------------------------- 
  18 // ---------------------------------------------------------------------------- 
  21     #pragma implementation "grid.h" 
  24 // For compilers that support precompilatixon, includes "wx/wx.h". 
  25 #include "wx/wxprec.h" 
  33 #if !defined(wxUSE_NEW_GRID) || !(wxUSE_NEW_GRID) 
  39     #include "wx/dcclient.h" 
  40     #include "wx/settings.h" 
  42     #include "wx/textctrl.h" 
  43     #include "wx/checkbox.h" 
  44     #include "wx/combobox.h" 
  45     #include "wx/valtext.h" 
  48 #include "wx/textfile.h" 
  49 #include "wx/spinctrl.h" 
  50 #include "wx/tokenzr.h" 
  53 #include "wx/generic/gridsel.h" 
  55 #if defined(__WXMOTIF__) 
  56     #define WXUNUSED_MOTIF(identifier)  WXUNUSED(identifier) 
  58     #define WXUNUSED_MOTIF(identifier)  identifier 
  61 #if defined(__WXGTK__) 
  62     #define WXUNUSED_GTK(identifier)    WXUNUSED(identifier) 
  64     #define WXUNUSED_GTK(identifier)    identifier 
  67 // Required for wxIs... functions 
  70 // ---------------------------------------------------------------------------- 
  72 // ---------------------------------------------------------------------------- 
  74 WX_DEFINE_EXPORTED_ARRAY(wxGridCellAttr 
*, wxArrayAttrs
); 
  76 struct wxGridCellWithAttr
 
  78     wxGridCellWithAttr(int row
, int col
, wxGridCellAttr 
*attr_
) 
  79         : coords(row
, col
), attr(attr_
) 
  88     wxGridCellCoords coords
; 
  92 WX_DECLARE_EXPORTED_OBJARRAY(wxGridCellWithAttr
, wxGridCellWithAttrArray
); 
  94 #include "wx/arrimpl.cpp" 
  96 WX_DEFINE_OBJARRAY(wxGridCellCoordsArray
) 
  97 WX_DEFINE_OBJARRAY(wxGridCellWithAttrArray
) 
  99 // ---------------------------------------------------------------------------- 
 101 // ---------------------------------------------------------------------------- 
 103 class WXDLLEXPORT wxGridRowLabelWindow 
: public wxWindow
 
 106     wxGridRowLabelWindow() { m_owner 
= (wxGrid 
*)NULL
; } 
 107     wxGridRowLabelWindow( wxGrid 
*parent
, wxWindowID id
, 
 108                           const wxPoint 
&pos
, const wxSize 
&size 
); 
 113     void OnPaint( wxPaintEvent
& event 
); 
 114     void OnMouseEvent( wxMouseEvent
& event 
); 
 115     void OnKeyDown( wxKeyEvent
& event 
); 
 116     void OnKeyUp( wxKeyEvent
& ); 
 118     DECLARE_DYNAMIC_CLASS(wxGridRowLabelWindow
) 
 119     DECLARE_EVENT_TABLE() 
 123 class WXDLLEXPORT wxGridColLabelWindow 
: public wxWindow
 
 126     wxGridColLabelWindow() { m_owner 
= (wxGrid 
*)NULL
; } 
 127     wxGridColLabelWindow( wxGrid 
*parent
, wxWindowID id
, 
 128                           const wxPoint 
&pos
, const wxSize 
&size 
); 
 133     void OnPaint( wxPaintEvent 
&event 
); 
 134     void OnMouseEvent( wxMouseEvent
& event 
); 
 135     void OnKeyDown( wxKeyEvent
& event 
); 
 136     void OnKeyUp( wxKeyEvent
& ); 
 138     DECLARE_DYNAMIC_CLASS(wxGridColLabelWindow
) 
 139     DECLARE_EVENT_TABLE() 
 143 class WXDLLEXPORT wxGridCornerLabelWindow 
: public wxWindow
 
 146     wxGridCornerLabelWindow() { m_owner 
= (wxGrid 
*)NULL
; } 
 147     wxGridCornerLabelWindow( wxGrid 
*parent
, wxWindowID id
, 
 148                              const wxPoint 
&pos
, const wxSize 
&size 
); 
 153     void OnMouseEvent( wxMouseEvent
& event 
); 
 154     void OnKeyDown( wxKeyEvent
& event 
); 
 155     void OnKeyUp( wxKeyEvent
& ); 
 156     void OnPaint( wxPaintEvent
& event 
); 
 158     DECLARE_DYNAMIC_CLASS(wxGridCornerLabelWindow
) 
 159     DECLARE_EVENT_TABLE() 
 162 class WXDLLEXPORT wxGridWindow 
: public wxPanel
 
 167         m_owner 
= (wxGrid 
*)NULL
; 
 168         m_rowLabelWin 
= (wxGridRowLabelWindow 
*)NULL
; 
 169         m_colLabelWin 
= (wxGridColLabelWindow 
*)NULL
; 
 172     wxGridWindow( wxGrid 
*parent
, 
 173                   wxGridRowLabelWindow 
*rowLblWin
, 
 174                   wxGridColLabelWindow 
*colLblWin
, 
 175                   wxWindowID id
, const wxPoint 
&pos
, const wxSize 
&size 
); 
 178     void ScrollWindow( int dx
, int dy
, const wxRect 
*rect 
); 
 182     wxGridRowLabelWindow     
*m_rowLabelWin
; 
 183     wxGridColLabelWindow     
*m_colLabelWin
; 
 185     void OnPaint( wxPaintEvent 
&event 
); 
 186     void OnMouseEvent( wxMouseEvent
& event 
); 
 187     void OnKeyDown( wxKeyEvent
& ); 
 188     void OnKeyUp( wxKeyEvent
& ); 
 189     void OnEraseBackground( wxEraseEvent
& ); 
 192     DECLARE_DYNAMIC_CLASS(wxGridWindow
) 
 193     DECLARE_EVENT_TABLE() 
 198 class wxGridCellEditorEvtHandler 
: public wxEvtHandler
 
 201     wxGridCellEditorEvtHandler() 
 202         : m_grid(0), m_editor(0) 
 204     wxGridCellEditorEvtHandler(wxGrid
* grid
, wxGridCellEditor
* editor
) 
 205         : m_grid(grid
), m_editor(editor
) 
 208     void OnKeyDown(wxKeyEvent
& event
); 
 209     void OnChar(wxKeyEvent
& event
); 
 213     wxGridCellEditor
*   m_editor
; 
 214     DECLARE_DYNAMIC_CLASS(wxGridCellEditorEvtHandler
) 
 215     DECLARE_EVENT_TABLE() 
 219 IMPLEMENT_DYNAMIC_CLASS( wxGridCellEditorEvtHandler
, wxEvtHandler 
) 
 220 BEGIN_EVENT_TABLE( wxGridCellEditorEvtHandler
, wxEvtHandler 
) 
 221     EVT_KEY_DOWN( wxGridCellEditorEvtHandler::OnKeyDown 
) 
 222     EVT_CHAR( wxGridCellEditorEvtHandler::OnChar 
) 
 227 // ---------------------------------------------------------------------------- 
 228 // the internal data representation used by wxGridCellAttrProvider 
 229 // ---------------------------------------------------------------------------- 
 231 // this class stores attributes set for cells 
 232 class WXDLLEXPORT wxGridCellAttrData
 
 235     void SetAttr(wxGridCellAttr 
*attr
, int row
, int col
); 
 236     wxGridCellAttr 
*GetAttr(int row
, int col
) const; 
 237     void UpdateAttrRows( size_t pos
, int numRows 
); 
 238     void UpdateAttrCols( size_t pos
, int numCols 
); 
 241     // searches for the attr for given cell, returns wxNOT_FOUND if not found 
 242     int FindIndex(int row
, int col
) const; 
 244     wxGridCellWithAttrArray m_attrs
; 
 247 // this class stores attributes set for rows or columns 
 248 class WXDLLEXPORT wxGridRowOrColAttrData
 
 251     // empty ctor to suppress warnings 
 252     wxGridRowOrColAttrData() { } 
 253     ~wxGridRowOrColAttrData(); 
 255     void SetAttr(wxGridCellAttr 
*attr
, int rowOrCol
); 
 256     wxGridCellAttr 
*GetAttr(int rowOrCol
) const; 
 257     void UpdateAttrRowsOrCols( size_t pos
, int numRowsOrCols 
); 
 260     wxArrayInt m_rowsOrCols
; 
 261     wxArrayAttrs m_attrs
; 
 264 // NB: this is just a wrapper around 3 objects: one which stores cell 
 265 //     attributes, and 2 others for row/col ones 
 266 class WXDLLEXPORT wxGridCellAttrProviderData
 
 269     wxGridCellAttrData m_cellAttrs
; 
 270     wxGridRowOrColAttrData m_rowAttrs
, 
 275 // ---------------------------------------------------------------------------- 
 276 // data structures used for the data type registry 
 277 // ---------------------------------------------------------------------------- 
 279 struct wxGridDataTypeInfo
 
 281     wxGridDataTypeInfo(const wxString
& typeName
, 
 282                        wxGridCellRenderer
* renderer
, 
 283                        wxGridCellEditor
* editor
) 
 284         : m_typeName(typeName
), m_renderer(renderer
), m_editor(editor
) 
 287     ~wxGridDataTypeInfo() 
 289         wxSafeDecRef(m_renderer
); 
 290         wxSafeDecRef(m_editor
); 
 294     wxGridCellRenderer
* m_renderer
; 
 295     wxGridCellEditor
*   m_editor
; 
 299 WX_DEFINE_EXPORTED_ARRAY(wxGridDataTypeInfo
*, wxGridDataTypeInfoArray
); 
 302 class WXDLLEXPORT wxGridTypeRegistry
 
 305   wxGridTypeRegistry() {} 
 306     ~wxGridTypeRegistry(); 
 308     void RegisterDataType(const wxString
& typeName
, 
 309                      wxGridCellRenderer
* renderer
, 
 310                      wxGridCellEditor
* editor
); 
 312     // find one of already registered data types 
 313     int FindRegisteredDataType(const wxString
& typeName
); 
 315     // try to FindRegisteredDataType(), if this fails and typeName is one of 
 316     // standard typenames, register it and return its index 
 317     int FindDataType(const wxString
& typeName
); 
 319     // try to FindDataType(), if it fails see if it is not one of already 
 320     // registered data types with some params in which case clone the 
 321     // registered data type and set params for it 
 322     int FindOrCloneDataType(const wxString
& typeName
); 
 324     wxGridCellRenderer
* GetRenderer(int index
); 
 325     wxGridCellEditor
*   GetEditor(int index
); 
 328     wxGridDataTypeInfoArray m_typeinfo
; 
 331 // ---------------------------------------------------------------------------- 
 332 // conditional compilation 
 333 // ---------------------------------------------------------------------------- 
 335 #ifndef WXGRID_DRAW_LINES 
 336 #define WXGRID_DRAW_LINES 1 
 339 // ---------------------------------------------------------------------------- 
 341 // ---------------------------------------------------------------------------- 
 343 //#define DEBUG_ATTR_CACHE 
 344 #ifdef DEBUG_ATTR_CACHE 
 345     static size_t gs_nAttrCacheHits 
= 0; 
 346     static size_t gs_nAttrCacheMisses 
= 0; 
 347 #endif // DEBUG_ATTR_CACHE 
 349 // ---------------------------------------------------------------------------- 
 351 // ---------------------------------------------------------------------------- 
 353 wxGridCellCoords 
wxGridNoCellCoords( -1, -1 ); 
 354 wxRect           
wxGridNoCellRect( -1, -1, -1, -1 ); 
 357 // TODO: fixed so far - make configurable later (and also different for x/y) 
 358 static const size_t GRID_SCROLL_LINE 
= 10; 
 360 // the size of hash tables used a bit everywhere (the max number of elements 
 361 // in these hash tables is the number of rows/columns) 
 362 static const int GRID_HASH_SIZE 
= 100; 
 364 // ============================================================================ 
 366 // ============================================================================ 
 368 // ---------------------------------------------------------------------------- 
 370 // ---------------------------------------------------------------------------- 
 372 wxGridCellEditor::wxGridCellEditor() 
 378 wxGridCellEditor::~wxGridCellEditor() 
 383 void wxGridCellEditor::Create(wxWindow
* WXUNUSED(parent
), 
 384                               wxWindowID 
WXUNUSED(id
), 
 385                               wxEvtHandler
* evtHandler
) 
 388         m_control
->PushEventHandler(evtHandler
); 
 391 void wxGridCellEditor::PaintBackground(const wxRect
& rectCell
, 
 392                                        wxGridCellAttr 
*attr
) 
 394     // erase the background because we might not fill the cell 
 395     wxClientDC 
dc(m_control
->GetParent()); 
 396     dc
.SetPen(*wxTRANSPARENT_PEN
); 
 397     dc
.SetBrush(wxBrush(attr
->GetBackgroundColour(), wxSOLID
)); 
 398     dc
.DrawRectangle(rectCell
); 
 400     // redraw the control we just painted over 
 401     m_control
->Refresh(); 
 404 void wxGridCellEditor::Destroy() 
 408         m_control
->PopEventHandler(TRUE 
/* delete it*/); 
 410         m_control
->Destroy(); 
 415 void wxGridCellEditor::Show(bool show
, wxGridCellAttr 
*attr
) 
 417     wxASSERT_MSG(m_control
, 
 418                  wxT("The wxGridCellEditor must be Created first!")); 
 419     m_control
->Show(show
); 
 423         // set the colours/fonts if we have any 
 426             m_colFgOld 
= m_control
->GetForegroundColour(); 
 427             m_control
->SetForegroundColour(attr
->GetTextColour()); 
 429             m_colBgOld 
= m_control
->GetBackgroundColour(); 
 430             m_control
->SetBackgroundColour(attr
->GetBackgroundColour()); 
 432             m_fontOld 
= m_control
->GetFont(); 
 433             m_control
->SetFont(attr
->GetFont()); 
 435             // can't do anything more in the base class version, the other 
 436             // attributes may only be used by the derived classes 
 441         // restore the standard colours fonts 
 442         if ( m_colFgOld
.Ok() ) 
 444             m_control
->SetForegroundColour(m_colFgOld
); 
 445             m_colFgOld 
= wxNullColour
; 
 448         if ( m_colBgOld
.Ok() ) 
 450             m_control
->SetBackgroundColour(m_colBgOld
); 
 451             m_colBgOld 
= wxNullColour
; 
 454         if ( m_fontOld
.Ok() ) 
 456             m_control
->SetFont(m_fontOld
); 
 457             m_fontOld 
= wxNullFont
; 
 462 void wxGridCellEditor::SetSize(const wxRect
& rect
) 
 464     wxASSERT_MSG(m_control
, 
 465                  wxT("The wxGridCellEditor must be Created first!")); 
 466     m_control
->SetSize(rect
, wxSIZE_ALLOW_MINUS_ONE
); 
 469 void wxGridCellEditor::HandleReturn(wxKeyEvent
& event
) 
 474 bool wxGridCellEditor::IsAcceptedKey(wxKeyEvent
& event
) 
 476     // accept the simple key presses, not anything with Ctrl/Alt/Meta 
 477     return !event
.HasModifiers(); 
 480 void wxGridCellEditor::StartingKey(wxKeyEvent
& event
) 
 485 void wxGridCellEditor::StartingClick() 
 489 // ---------------------------------------------------------------------------- 
 490 // wxGridCellTextEditor 
 491 // ---------------------------------------------------------------------------- 
 493 wxGridCellTextEditor::wxGridCellTextEditor() 
 498 void wxGridCellTextEditor::Create(wxWindow
* parent
, 
 500                                   wxEvtHandler
* evtHandler
) 
 502     m_control 
= new wxTextCtrl(parent
, id
, wxEmptyString
, 
 503                                wxDefaultPosition
, wxDefaultSize
 
 504 #if defined(__WXMSW__) 
 505                                , wxTE_MULTILINE 
| wxTE_NO_VSCROLL 
| wxTE_AUTO_SCROLL
 
 509     // TODO: use m_maxChars 
 511     wxGridCellEditor::Create(parent
, id
, evtHandler
); 
 514 void wxGridCellTextEditor::PaintBackground(const wxRect
& WXUNUSED(rectCell
), 
 515                                            wxGridCellAttr 
* WXUNUSED(attr
)) 
 517     // as we fill the entire client area, don't do anything here to minimize 
 521 void wxGridCellTextEditor::SetSize(const wxRect
& rectOrig
) 
 523     wxRect 
rect(rectOrig
); 
 525     // Make the edit control large enough to allow for internal 
 528     // TODO: remove this if the text ctrl sizing is improved esp. for 
 531 #if defined(__WXGTK__) 
 540     int extra_x 
= ( rect
.x 
> 2 )? 2 : 1; 
 542 // MB: treat MSW separately here otherwise the caret doesn't show  
 543 // when the editor is in the first row.  
 544 #if defined(__WXMSW__) 
 547     int extra_y 
= ( rect
.y 
> 2 )? 2 : 1; 
 550 #if defined(__WXMOTIF__) 
 554     rect
.SetLeft( wxMax(0, rect
.x 
- extra_x
) ); 
 555     rect
.SetTop( wxMax(0, rect
.y 
- extra_y
) ); 
 556     rect
.SetRight( rect
.GetRight() + 2*extra_x 
); 
 557     rect
.SetBottom( rect
.GetBottom() + 2*extra_y 
); 
 560     wxGridCellEditor::SetSize(rect
); 
 563 void wxGridCellTextEditor::BeginEdit(int row
, int col
, wxGrid
* grid
) 
 565     wxASSERT_MSG(m_control
, 
 566                  wxT("The wxGridCellEditor must be Created first!")); 
 568     m_startValue 
= grid
->GetTable()->GetValue(row
, col
); 
 570     DoBeginEdit(m_startValue
); 
 573 void wxGridCellTextEditor::DoBeginEdit(const wxString
& startValue
) 
 575     Text()->SetValue(startValue
); 
 576     Text()->SetInsertionPointEnd(); 
 580 bool wxGridCellTextEditor::EndEdit(int row
, int col
, 
 583     wxASSERT_MSG(m_control
, 
 584                  wxT("The wxGridCellEditor must be Created first!")); 
 586     bool changed 
= FALSE
; 
 587     wxString value 
= Text()->GetValue(); 
 588     if (value 
!= m_startValue
) 
 592         grid
->GetTable()->SetValue(row
, col
, value
); 
 594     m_startValue 
= wxEmptyString
; 
 595     Text()->SetValue(m_startValue
); 
 601 void wxGridCellTextEditor::Reset() 
 603     wxASSERT_MSG(m_control
, 
 604                  wxT("The wxGridCellEditor must be Created first!")); 
 606     DoReset(m_startValue
); 
 609 void wxGridCellTextEditor::DoReset(const wxString
& startValue
) 
 611     Text()->SetValue(startValue
); 
 612     Text()->SetInsertionPointEnd(); 
 615 bool wxGridCellTextEditor::IsAcceptedKey(wxKeyEvent
& event
) 
 617     if ( wxGridCellEditor::IsAcceptedKey(event
) ) 
 619         int keycode 
= event
.GetKeyCode(); 
 633             case WXK_NUMPAD_MULTIPLY
: 
 637             case WXK_NUMPAD_SUBTRACT
: 
 639             case WXK_NUMPAD_DECIMAL
: 
 641             case WXK_NUMPAD_DIVIDE
: 
 645                 // accept 8 bit chars too if isprint() agrees 
 646                 if ( (keycode 
< 255) && (isprint(keycode
)) ) 
 654 void wxGridCellTextEditor::StartingKey(wxKeyEvent
& event
) 
 656     // we don't check for !HasModifiers() because IsAcceptedKey() did it 
 658     // insert the key in the control 
 660     int keycode 
= event
.GetKeyCode(); 
 673             ch 
= _T('0') + keycode 
- WXK_NUMPAD0
; 
 677         case WXK_NUMPAD_MULTIPLY
: 
 687         case WXK_NUMPAD_SUBTRACT
: 
 692         case WXK_NUMPAD_DECIMAL
: 
 697         case WXK_NUMPAD_DIVIDE
: 
 702             if ( keycode 
< 256 && keycode 
>= 0 && isprint(keycode
) ) 
 704                 // FIXME this is not going to work for non letters... 
 705                 if ( !event
.ShiftDown() ) 
 707                     keycode 
= tolower(keycode
); 
 710                 ch 
= (wxChar
)keycode
; 
 720         Text()->AppendText(ch
); 
 728 void wxGridCellTextEditor::HandleReturn( wxKeyEvent
& 
 729                                          WXUNUSED_GTK(WXUNUSED_MOTIF(event
)) ) 
 731 #if defined(__WXMOTIF__) || defined(__WXGTK__) 
 732     // wxMotif needs a little extra help... 
 733     size_t pos 
= (size_t)( Text()->GetInsertionPoint() ); 
 734     wxString 
s( Text()->GetValue() ); 
 735     s 
= s
.Left(pos
) + "\n" + s
.Mid(pos
); 
 737     Text()->SetInsertionPoint( pos 
); 
 739     // the other ports can handle a Return key press 
 745 void wxGridCellTextEditor::SetParameters(const wxString
& params
) 
 755         if ( !params
.ToLong(&tmp
) ) 
 757             wxLogDebug(_T("Invalid wxGridCellTextEditor parameter string '%s' ignored"), params
.c_str()); 
 761             m_maxChars 
= (size_t)tmp
; 
 766 // ---------------------------------------------------------------------------- 
 767 // wxGridCellNumberEditor 
 768 // ---------------------------------------------------------------------------- 
 770 wxGridCellNumberEditor::wxGridCellNumberEditor(int min
, int max
) 
 776 void wxGridCellNumberEditor::Create(wxWindow
* parent
, 
 778                                     wxEvtHandler
* evtHandler
) 
 782         // create a spin ctrl 
 783         m_control 
= new wxSpinCtrl(parent
, -1, wxEmptyString
, 
 784                                    wxDefaultPosition
, wxDefaultSize
, 
 788         wxGridCellEditor::Create(parent
, id
, evtHandler
); 
 792         // just a text control 
 793         wxGridCellTextEditor::Create(parent
, id
, evtHandler
); 
 796         Text()->SetValidator(wxTextValidator(wxFILTER_NUMERIC
)); 
 797 #endif // wxUSE_VALIDATORS 
 801 void wxGridCellNumberEditor::BeginEdit(int row
, int col
, wxGrid
* grid
) 
 803     // first get the value 
 804     wxGridTableBase 
*table 
= grid
->GetTable(); 
 805     if ( table
->CanGetValueAs(row
, col
, wxGRID_VALUE_NUMBER
) ) 
 807         m_valueOld 
= table
->GetValueAsLong(row
, col
); 
 811         wxString sValue 
= table
->GetValue(row
, col
); 
 812         if (! sValue
.ToLong(&m_valueOld
)) 
 814             wxFAIL_MSG( _T("this cell doesn't have numeric value") ); 
 821         Spin()->SetValue((int)m_valueOld
); 
 826         DoBeginEdit(GetString()); 
 830 bool wxGridCellNumberEditor::EndEdit(int row
, int col
, 
 838         value 
= Spin()->GetValue(); 
 839         changed 
= value 
!= m_valueOld
; 
 843         changed 
= Text()->GetValue().ToLong(&value
) && (value 
!= m_valueOld
); 
 848         if (grid
->GetTable()->CanSetValueAs(row
, col
, wxGRID_VALUE_NUMBER
)) 
 849             grid
->GetTable()->SetValueAsLong(row
, col
, value
); 
 851             grid
->GetTable()->SetValue(row
, col
, wxString::Format(wxT("%ld"), value
)); 
 857 void wxGridCellNumberEditor::Reset() 
 861         Spin()->SetValue((int)m_valueOld
); 
 865         DoReset(GetString()); 
 869 bool wxGridCellNumberEditor::IsAcceptedKey(wxKeyEvent
& event
) 
 871     if ( wxGridCellEditor::IsAcceptedKey(event
) ) 
 873         int keycode 
= event
.GetKeyCode(); 
 889             case WXK_NUMPAD_SUBTRACT
: 
 895                 if ( (keycode 
< 128) && isdigit(keycode
) ) 
 903 void wxGridCellNumberEditor::StartingKey(wxKeyEvent
& event
) 
 907         int keycode 
= (int) event
.KeyCode(); 
 908         if ( isdigit(keycode
) || keycode 
== '+' || keycode 
== '-' ) 
 910             wxGridCellTextEditor::StartingKey(event
); 
 920 void wxGridCellNumberEditor::SetParameters(const wxString
& params
) 
 931         if ( params
.BeforeFirst(_T(',')).ToLong(&tmp
) ) 
 935             if ( params
.AfterFirst(_T(',')).ToLong(&tmp
) ) 
 939                 // skip the error message below 
 944         wxLogDebug(_T("Invalid wxGridCellNumberEditor parameter string '%s' ignored"), params
.c_str()); 
 948 // ---------------------------------------------------------------------------- 
 949 // wxGridCellFloatEditor 
 950 // ---------------------------------------------------------------------------- 
 952 wxGridCellFloatEditor::wxGridCellFloatEditor(int width
, int precision
) 
 955     m_precision 
= precision
; 
 958 void wxGridCellFloatEditor::Create(wxWindow
* parent
, 
 960                                    wxEvtHandler
* evtHandler
) 
 962     wxGridCellTextEditor::Create(parent
, id
, evtHandler
); 
 965     Text()->SetValidator(wxTextValidator(wxFILTER_NUMERIC
)); 
 966 #endif // wxUSE_VALIDATORS 
 969 void wxGridCellFloatEditor::BeginEdit(int row
, int col
, wxGrid
* grid
) 
 971     // first get the value 
 972     wxGridTableBase 
*table 
= grid
->GetTable(); 
 973     if ( table
->CanGetValueAs(row
, col
, wxGRID_VALUE_FLOAT
) ) 
 975         m_valueOld 
= table
->GetValueAsDouble(row
, col
); 
 979         wxString sValue 
= table
->GetValue(row
, col
); 
 980         if (! sValue
.ToDouble(&m_valueOld
)) 
 982             wxFAIL_MSG( _T("this cell doesn't have float value") ); 
 987     DoBeginEdit(GetString()); 
 990 bool wxGridCellFloatEditor::EndEdit(int row
, int col
, 
 994     if ( Text()->GetValue().ToDouble(&value
) && (value 
!= m_valueOld
) ) 
 996         if (grid
->GetTable()->CanSetValueAs(row
, col
, wxGRID_VALUE_FLOAT
)) 
 997             grid
->GetTable()->SetValueAsDouble(row
, col
, value
); 
 999             grid
->GetTable()->SetValue(row
, col
, wxString::Format(wxT("%f"), value
)); 
1009 void wxGridCellFloatEditor::Reset() 
1011     DoReset(GetString()); 
1014 void wxGridCellFloatEditor::StartingKey(wxKeyEvent
& event
) 
1016     int keycode 
= (int)event
.KeyCode(); 
1017     if ( isdigit(keycode
) || 
1018          keycode 
== '+' || keycode 
== '-' || keycode 
== '.' ) 
1020         wxGridCellTextEditor::StartingKey(event
); 
1022         // skip Skip() below 
1029 void wxGridCellFloatEditor::SetParameters(const wxString
& params
) 
1040         if ( params
.BeforeFirst(_T(',')).ToLong(&tmp
) ) 
1044             if ( params
.AfterFirst(_T(',')).ToLong(&tmp
) ) 
1046                 m_precision 
= (int)tmp
; 
1048                 // skip the error message below 
1053         wxLogDebug(_T("Invalid wxGridCellFloatEditor parameter string '%s' ignored"), params
.c_str()); 
1057 wxString 
wxGridCellFloatEditor::GetString() const 
1060     if ( m_width 
== -1 ) 
1062         // default width/precision 
1065     else if ( m_precision 
== -1 ) 
1067         // default precision 
1068         fmt
.Printf(_T("%%%d.g"), m_width
); 
1072         fmt
.Printf(_T("%%%d.%dg"), m_width
, m_precision
); 
1075     return wxString::Format(fmt
, m_valueOld
); 
1078 bool wxGridCellFloatEditor::IsAcceptedKey(wxKeyEvent
& event
) 
1080     if ( wxGridCellEditor::IsAcceptedKey(event
) ) 
1082         int keycode 
= event
.GetKeyCode(); 
1096             case WXK_NUMPAD_ADD
: 
1098             case WXK_NUMPAD_SUBTRACT
: 
1100             case WXK_NUMPAD_DECIMAL
: 
1104                 // additionally accept 'e' as in '1e+6' 
1105                 if ( (keycode 
< 128) && 
1106                      (isdigit(keycode
) || tolower(keycode
) == 'e') ) 
1114 // ---------------------------------------------------------------------------- 
1115 // wxGridCellBoolEditor 
1116 // ---------------------------------------------------------------------------- 
1118 void wxGridCellBoolEditor::Create(wxWindow
* parent
, 
1120                                   wxEvtHandler
* evtHandler
) 
1122     m_control 
= new wxCheckBox(parent
, id
, wxEmptyString
, 
1123                                wxDefaultPosition
, wxDefaultSize
, 
1126     wxGridCellEditor::Create(parent
, id
, evtHandler
); 
1129 void wxGridCellBoolEditor::SetSize(const wxRect
& r
) 
1131     bool resize 
= FALSE
; 
1132     wxSize size 
= m_control
->GetSize(); 
1133     wxCoord minSize 
= wxMin(r
.width
, r
.height
); 
1135     // check if the checkbox is not too big/small for this cell 
1136     wxSize sizeBest 
= m_control
->GetBestSize(); 
1137     if ( !(size 
== sizeBest
) ) 
1139         // reset to default size if it had been made smaller 
1145     if ( size
.x 
>= minSize 
|| size
.y 
>= minSize 
) 
1147         // leave 1 pixel margin 
1148         size
.x 
= size
.y 
= minSize 
- 2; 
1155         m_control
->SetSize(size
); 
1158     // position it in the centre of the rectangle (TODO: support alignment?) 
1160 #if defined(__WXGTK__) || defined (__WXMOTIF__) 
1161     // the checkbox without label still has some space to the right in wxGTK, 
1162     // so shift it to the right 
1164 #elif defined(__WXMSW__) 
1165     // here too, but in other way 
1170     m_control
->Move(r
.x 
+ r
.width
/2 - size
.x
/2, r
.y 
+ r
.height
/2 - size
.y
/2); 
1173 void wxGridCellBoolEditor::Show(bool show
, wxGridCellAttr 
*attr
) 
1175     m_control
->Show(show
); 
1179         wxColour colBg 
= attr 
? attr
->GetBackgroundColour() : *wxLIGHT_GREY
; 
1180         CBox()->SetBackgroundColour(colBg
); 
1184 void wxGridCellBoolEditor::BeginEdit(int row
, int col
, wxGrid
* grid
) 
1186     wxASSERT_MSG(m_control
, 
1187                  wxT("The wxGridCellEditor must be Created first!")); 
1189     if (grid
->GetTable()->CanGetValueAs(row
, col
, wxGRID_VALUE_BOOL
)) 
1190         m_startValue 
= grid
->GetTable()->GetValueAsBool(row
, col
); 
1193         wxString 
cellval( grid
->GetTable()->GetValue(row
, col
) ); 
1194         m_startValue 
= !( !cellval 
|| (cellval 
== "0") ); 
1196     CBox()->SetValue(m_startValue
); 
1200 bool wxGridCellBoolEditor::EndEdit(int row
, int col
, 
1203     wxASSERT_MSG(m_control
, 
1204                  wxT("The wxGridCellEditor must be Created first!")); 
1206     bool changed 
= FALSE
; 
1207     bool value 
= CBox()->GetValue(); 
1208     if ( value 
!= m_startValue 
) 
1213         if (grid
->GetTable()->CanGetValueAs(row
, col
, wxGRID_VALUE_BOOL
)) 
1214             grid
->GetTable()->SetValueAsBool(row
, col
, value
); 
1216             grid
->GetTable()->SetValue(row
, col
, value 
? _T("1") : wxEmptyString
); 
1222 void wxGridCellBoolEditor::Reset() 
1224     wxASSERT_MSG(m_control
, 
1225                  wxT("The wxGridCellEditor must be Created first!")); 
1227     CBox()->SetValue(m_startValue
); 
1230 void wxGridCellBoolEditor::StartingClick() 
1232     CBox()->SetValue(!CBox()->GetValue()); 
1235 bool wxGridCellBoolEditor::IsAcceptedKey(wxKeyEvent
& event
) 
1237     if ( wxGridCellEditor::IsAcceptedKey(event
) ) 
1239         int keycode 
= event
.GetKeyCode(); 
1243             case WXK_NUMPAD_MULTIPLY
: 
1245             case WXK_NUMPAD_ADD
: 
1247             case WXK_NUMPAD_SUBTRACT
: 
1258 // ---------------------------------------------------------------------------- 
1259 // wxGridCellChoiceEditor 
1260 // ---------------------------------------------------------------------------- 
1262 wxGridCellChoiceEditor::wxGridCellChoiceEditor(size_t count
, 
1263                                                const wxString choices
[], 
1265                       : m_allowOthers(allowOthers
) 
1269         m_choices
.Alloc(count
); 
1270         for ( size_t n 
= 0; n 
< count
; n
++ ) 
1272             m_choices
.Add(choices
[n
]); 
1277 wxGridCellEditor 
*wxGridCellChoiceEditor::Clone() const 
1279     wxGridCellChoiceEditor 
*editor 
= new wxGridCellChoiceEditor
; 
1280     editor
->m_allowOthers 
= m_allowOthers
; 
1281     editor
->m_choices 
= m_choices
; 
1286 void wxGridCellChoiceEditor::Create(wxWindow
* parent
, 
1288                                     wxEvtHandler
* evtHandler
) 
1290     size_t count 
= m_choices
.GetCount(); 
1291     wxString 
*choices 
= new wxString
[count
]; 
1292     for ( size_t n 
= 0; n 
< count
; n
++ ) 
1294         choices
[n
] = m_choices
[n
]; 
1297     m_control 
= new wxComboBox(parent
, id
, wxEmptyString
, 
1298                                wxDefaultPosition
, wxDefaultSize
, 
1300                                m_allowOthers 
? 0 : wxCB_READONLY
); 
1304     wxGridCellEditor::Create(parent
, id
, evtHandler
); 
1307 void wxGridCellChoiceEditor::PaintBackground(const wxRect
& rectCell
, 
1308                                              wxGridCellAttr 
* attr
) 
1310     // as we fill the entire client area, don't do anything here to minimize 
1313     // TODO: It doesn't actually fill the client area since the height of a 
1314     // combo always defaults to the standard...  Until someone has time to 
1315     // figure out the right rectangle to paint, just do it the normal way... 
1316     wxGridCellEditor::PaintBackground(rectCell
, attr
); 
1319 void wxGridCellChoiceEditor::BeginEdit(int row
, int col
, wxGrid
* grid
) 
1321     wxASSERT_MSG(m_control
, 
1322                  wxT("The wxGridCellEditor must be Created first!")); 
1324     m_startValue 
= grid
->GetTable()->GetValue(row
, col
); 
1326     Combo()->SetValue(m_startValue
); 
1327     size_t count 
= m_choices
.GetCount(); 
1328     for (size_t i
=0; i
<count
; i
++) 
1330         if (m_startValue 
== m_choices
[i
]) 
1332             Combo()->SetSelection(i
); 
1336     Combo()->SetInsertionPointEnd(); 
1337     Combo()->SetFocus(); 
1340 bool wxGridCellChoiceEditor::EndEdit(int row
, int col
, 
1343     wxString value 
= Combo()->GetValue(); 
1344     bool changed 
= value 
!= m_startValue
; 
1347         grid
->GetTable()->SetValue(row
, col
, value
); 
1349     m_startValue 
= wxEmptyString
; 
1350     Combo()->SetValue(m_startValue
); 
1355 void wxGridCellChoiceEditor::Reset() 
1357     Combo()->SetValue(m_startValue
); 
1358     Combo()->SetInsertionPointEnd(); 
1361 void wxGridCellChoiceEditor::SetParameters(const wxString
& params
) 
1371     wxStringTokenizer 
tk(params
, _T(',')); 
1372     while ( tk
.HasMoreTokens() ) 
1374         m_choices
.Add(tk
.GetNextToken()); 
1378 // ---------------------------------------------------------------------------- 
1379 // wxGridCellEditorEvtHandler 
1380 // ---------------------------------------------------------------------------- 
1382 void wxGridCellEditorEvtHandler::OnKeyDown(wxKeyEvent
& event
) 
1384     switch ( event
.KeyCode() ) 
1388             m_grid
->DisableCellEditControl(); 
1392             event
.Skip( m_grid
->ProcessEvent( event 
) ); 
1396             if (!m_grid
->ProcessEvent(event
)) 
1397                 m_editor
->HandleReturn(event
); 
1406 void wxGridCellEditorEvtHandler::OnChar(wxKeyEvent
& event
) 
1408     switch ( event
.KeyCode() ) 
1420 // ---------------------------------------------------------------------------- 
1421 // wxGridCellWorker is an (almost) empty common base class for 
1422 // wxGridCellRenderer and wxGridCellEditor managing ref counting 
1423 // ---------------------------------------------------------------------------- 
1425 void wxGridCellWorker::SetParameters(const wxString
& WXUNUSED(params
)) 
1430 wxGridCellWorker::~wxGridCellWorker() 
1434 // ============================================================================ 
1436 // ============================================================================ 
1438 // ---------------------------------------------------------------------------- 
1439 // wxGridCellRenderer 
1440 // ---------------------------------------------------------------------------- 
1442 void wxGridCellRenderer::Draw(wxGrid
& grid
, 
1443                               wxGridCellAttr
& attr
, 
1446                               int WXUNUSED(row
), int WXUNUSED(col
), 
1449     dc
.SetBackgroundMode( wxSOLID 
); 
1453         dc
.SetBrush( wxBrush(grid
.GetSelectionBackground(), wxSOLID
) ); 
1457         dc
.SetBrush( wxBrush(attr
.GetBackgroundColour(), wxSOLID
) ); 
1460     dc
.SetPen( *wxTRANSPARENT_PEN 
); 
1461     dc
.DrawRectangle(rect
); 
1464 // ---------------------------------------------------------------------------- 
1465 // wxGridCellStringRenderer 
1466 // ---------------------------------------------------------------------------- 
1468 void wxGridCellStringRenderer::SetTextColoursAndFont(wxGrid
& grid
, 
1469                                                      wxGridCellAttr
& attr
, 
1473     dc
.SetBackgroundMode( wxTRANSPARENT 
); 
1475     // TODO some special colours for attr.IsReadOnly() case? 
1479         dc
.SetTextBackground( grid
.GetSelectionBackground() ); 
1480         dc
.SetTextForeground( grid
.GetSelectionForeground() ); 
1484         dc
.SetTextBackground( attr
.GetBackgroundColour() ); 
1485         dc
.SetTextForeground( attr
.GetTextColour() ); 
1488     dc
.SetFont( attr
.GetFont() ); 
1491 wxSize 
wxGridCellStringRenderer::DoGetBestSize(wxGridCellAttr
& attr
, 
1493                                                const wxString
& text
) 
1495     wxCoord x 
= 0, y 
= 0, max_x 
= 0; 
1496     dc
.SetFont(attr
.GetFont()); 
1497     wxStringTokenizer 
tk(text
, _T('\n')); 
1498     while ( tk
.HasMoreTokens() ) 
1500         dc
.GetTextExtent(tk
.GetNextToken(), &x
, &y
); 
1501         max_x 
= wxMax(max_x
, x
); 
1504     y 
*= 1 + text
.Freq(wxT('\n')); // multiply by the number of lines. 
1506     return wxSize(max_x
, y
); 
1509 wxSize 
wxGridCellStringRenderer::GetBestSize(wxGrid
& grid
, 
1510                                              wxGridCellAttr
& attr
, 
1514     return DoGetBestSize(attr
, dc
, grid
.GetCellValue(row
, col
)); 
1517 void wxGridCellStringRenderer::Draw(wxGrid
& grid
, 
1518                                     wxGridCellAttr
& attr
, 
1520                                     const wxRect
& rectCell
, 
1524     wxGridCellRenderer::Draw(grid
, attr
, dc
, rectCell
, row
, col
, isSelected
); 
1526     // now we only have to draw the text 
1527     SetTextColoursAndFont(grid
, attr
, dc
, isSelected
); 
1530     attr
.GetAlignment(&hAlign
, &vAlign
); 
1532     wxRect rect 
= rectCell
; 
1535     grid
.DrawTextRectangle(dc
, grid
.GetCellValue(row
, col
), 
1536                            rect
, hAlign
, vAlign
); 
1539 // ---------------------------------------------------------------------------- 
1540 // wxGridCellNumberRenderer 
1541 // ---------------------------------------------------------------------------- 
1543 wxString 
wxGridCellNumberRenderer::GetString(wxGrid
& grid
, int row
, int col
) 
1545     wxGridTableBase 
*table 
= grid
.GetTable(); 
1547     if ( table
->CanGetValueAs(row
, col
, wxGRID_VALUE_NUMBER
) ) 
1549         text
.Printf(_T("%ld"), table
->GetValueAsLong(row
, col
)); 
1553         text 
= table
->GetValue(row
, col
); 
1559 void wxGridCellNumberRenderer::Draw(wxGrid
& grid
, 
1560                                     wxGridCellAttr
& attr
, 
1562                                     const wxRect
& rectCell
, 
1566     wxGridCellRenderer::Draw(grid
, attr
, dc
, rectCell
, row
, col
, isSelected
); 
1568     SetTextColoursAndFont(grid
, attr
, dc
, isSelected
); 
1570     // draw the text right aligned by default 
1572     attr
.GetAlignment(&hAlign
, &vAlign
); 
1573     hAlign 
= wxALIGN_RIGHT
; 
1575     wxRect rect 
= rectCell
; 
1578     grid
.DrawTextRectangle(dc
, GetString(grid
, row
, col
), rect
, hAlign
, vAlign
); 
1581 wxSize 
wxGridCellNumberRenderer::GetBestSize(wxGrid
& grid
, 
1582                                              wxGridCellAttr
& attr
, 
1586     return DoGetBestSize(attr
, dc
, GetString(grid
, row
, col
)); 
1589 // ---------------------------------------------------------------------------- 
1590 // wxGridCellFloatRenderer 
1591 // ---------------------------------------------------------------------------- 
1593 wxGridCellFloatRenderer::wxGridCellFloatRenderer(int width
, int precision
) 
1596     SetPrecision(precision
); 
1599 wxGridCellRenderer 
*wxGridCellFloatRenderer::Clone() const 
1601     wxGridCellFloatRenderer 
*renderer 
= new wxGridCellFloatRenderer
; 
1602     renderer
->m_width 
= m_width
; 
1603     renderer
->m_precision 
= m_precision
; 
1604     renderer
->m_format 
= m_format
; 
1609 wxString 
wxGridCellFloatRenderer::GetString(wxGrid
& grid
, int row
, int col
) 
1611     wxGridTableBase 
*table 
= grid
.GetTable(); 
1616     if ( table
->CanGetValueAs(row
, col
, wxGRID_VALUE_FLOAT
) ) 
1618         val 
= table
->GetValueAsDouble(row
, col
); 
1623         text 
= table
->GetValue(row
, col
); 
1624         hasDouble 
= text
.ToDouble(&val
); 
1631             if ( m_width 
== -1 ) 
1633                 // default width/precision 
1634                 m_format 
= _T("%f"); 
1636             else if ( m_precision 
== -1 ) 
1638                 // default precision 
1639                 m_format
.Printf(_T("%%%d.f"), m_width
); 
1643                 m_format
.Printf(_T("%%%d.%df"), m_width
, m_precision
); 
1647         text
.Printf(m_format
, val
); 
1649     //else: text already contains the string 
1654 void wxGridCellFloatRenderer::Draw(wxGrid
& grid
, 
1655                                    wxGridCellAttr
& attr
, 
1657                                    const wxRect
& rectCell
, 
1661     wxGridCellRenderer::Draw(grid
, attr
, dc
, rectCell
, row
, col
, isSelected
); 
1663     SetTextColoursAndFont(grid
, attr
, dc
, isSelected
); 
1665     // draw the text right aligned by default 
1667     attr
.GetAlignment(&hAlign
, &vAlign
); 
1668     hAlign 
= wxALIGN_RIGHT
; 
1670     wxRect rect 
= rectCell
; 
1673     grid
.DrawTextRectangle(dc
, GetString(grid
, row
, col
), rect
, hAlign
, vAlign
); 
1676 wxSize 
wxGridCellFloatRenderer::GetBestSize(wxGrid
& grid
, 
1677                                             wxGridCellAttr
& attr
, 
1681     return DoGetBestSize(attr
, dc
, GetString(grid
, row
, col
)); 
1684 void wxGridCellFloatRenderer::SetParameters(const wxString
& params
) 
1690         // reset to defaults 
1696         wxString tmp 
= params
.BeforeFirst(_T(',')); 
1700             if ( !tmp
.ToLong(&width
) ) 
1706                 SetWidth((int)width
); 
1708                 tmp 
= params
.AfterFirst(_T(',')); 
1712                     if ( !tmp
.ToLong(&precision
) ) 
1718                         SetPrecision((int)precision
); 
1726             wxLogDebug(_T("Invalid wxGridCellFloatRenderer parameter string '%s ignored"), params
.c_str()); 
1731 // ---------------------------------------------------------------------------- 
1732 // wxGridCellBoolRenderer 
1733 // ---------------------------------------------------------------------------- 
1735 wxSize 
wxGridCellBoolRenderer::ms_sizeCheckMark
; 
1737 // FIXME these checkbox size calculations are really ugly... 
1739 // between checkmark and box 
1740 static const wxCoord wxGRID_CHECKMARK_MARGIN 
= 2; 
1742 wxSize 
wxGridCellBoolRenderer::GetBestSize(wxGrid
& grid
, 
1743                                            wxGridCellAttr
& WXUNUSED(attr
), 
1748     // compute it only once (no locks for MT safeness in GUI thread...) 
1749     if ( !ms_sizeCheckMark
.x 
) 
1751         // get checkbox size 
1752         wxCoord checkSize 
= 0; 
1753         wxCheckBox 
*checkbox 
= new wxCheckBox(&grid
, -1, wxEmptyString
); 
1754         wxSize size 
= checkbox
->GetBestSize(); 
1755         checkSize 
= size
.y 
+ 2*wxGRID_CHECKMARK_MARGIN
; 
1757         // FIXME wxGTK::wxCheckBox::GetBestSize() gives "wrong" result 
1758 #if defined(__WXGTK__) || defined(__WXMOTIF__) 
1759         checkSize 
-= size
.y 
/ 2; 
1764         ms_sizeCheckMark
.x 
= ms_sizeCheckMark
.y 
= checkSize
; 
1767     return ms_sizeCheckMark
; 
1770 void wxGridCellBoolRenderer::Draw(wxGrid
& grid
, 
1771                                   wxGridCellAttr
& attr
, 
1777     wxGridCellRenderer::Draw(grid
, attr
, dc
, rect
, row
, col
, isSelected
); 
1779     // draw a check mark in the centre (ignoring alignment - TODO) 
1780     wxSize size 
= GetBestSize(grid
, attr
, dc
, row
, col
); 
1782     // don't draw outside the cell 
1783     wxCoord minSize 
= wxMin(rect
.width
, rect
.height
); 
1784     if ( size
.x 
>= minSize 
|| size
.y 
>= minSize 
) 
1786         // and even leave (at least) 1 pixel margin 
1787         size
.x 
= size
.y 
= minSize 
- 2; 
1790     // draw a border around checkmark 
1792     rectBorder
.x 
= rect
.x 
+ rect
.width
/2 - size
.x
/2; 
1793     rectBorder
.y 
= rect
.y 
+ rect
.height
/2 - size
.y
/2; 
1794     rectBorder
.width 
= size
.x
; 
1795     rectBorder
.height 
= size
.y
; 
1798     if ( grid
.GetTable()->CanGetValueAs(row
, col
, wxGRID_VALUE_BOOL
) ) 
1799         value 
= grid
.GetTable()->GetValueAsBool(row
, col
); 
1802         wxString 
cellval( grid
.GetTable()->GetValue(row
, col
) ); 
1803         value 
= !( !cellval 
|| (cellval 
== "0") ); 
1808         wxRect rectMark 
= rectBorder
; 
1810         // MSW DrawCheckMark() is weird (and should probably be changed...) 
1811         rectMark
.Inflate(-wxGRID_CHECKMARK_MARGIN
/2); 
1815         rectMark
.Inflate(-wxGRID_CHECKMARK_MARGIN
); 
1818         dc
.SetTextForeground(attr
.GetTextColour()); 
1819         dc
.DrawCheckMark(rectMark
); 
1822     dc
.SetBrush(*wxTRANSPARENT_BRUSH
); 
1823     dc
.SetPen(wxPen(attr
.GetTextColour(), 1, wxSOLID
)); 
1824     dc
.DrawRectangle(rectBorder
); 
1827 // ---------------------------------------------------------------------------- 
1829 // ---------------------------------------------------------------------------- 
1831 wxGridCellAttr 
*wxGridCellAttr::Clone() const 
1833     wxGridCellAttr 
*attr 
= new wxGridCellAttr
; 
1834     if ( HasTextColour() ) 
1835         attr
->SetTextColour(GetTextColour()); 
1836     if ( HasBackgroundColour() ) 
1837         attr
->SetBackgroundColour(GetBackgroundColour()); 
1839         attr
->SetFont(GetFont()); 
1840     if ( HasAlignment() ) 
1841         attr
->SetAlignment(m_hAlign
, m_vAlign
); 
1845         attr
->SetRenderer(m_renderer
); 
1846         m_renderer
->IncRef(); 
1850         attr
->SetEditor(m_editor
); 
1855         attr
->SetReadOnly(); 
1857     attr
->SetDefAttr(m_defGridAttr
); 
1862 const wxColour
& wxGridCellAttr::GetTextColour() const 
1864     if (HasTextColour()) 
1868     else if (m_defGridAttr 
!= this) 
1870         return m_defGridAttr
->GetTextColour(); 
1874         wxFAIL_MSG(wxT("Missing default cell attribute")); 
1875         return wxNullColour
; 
1880 const wxColour
& wxGridCellAttr::GetBackgroundColour() const 
1882     if (HasBackgroundColour()) 
1884     else if (m_defGridAttr 
!= this) 
1885         return m_defGridAttr
->GetBackgroundColour(); 
1888         wxFAIL_MSG(wxT("Missing default cell attribute")); 
1889         return wxNullColour
; 
1894 const wxFont
& wxGridCellAttr::GetFont() const 
1898     else if (m_defGridAttr 
!= this) 
1899         return m_defGridAttr
->GetFont(); 
1902         wxFAIL_MSG(wxT("Missing default cell attribute")); 
1908 void wxGridCellAttr::GetAlignment(int *hAlign
, int *vAlign
) const 
1912         if ( hAlign 
) *hAlign 
= m_hAlign
; 
1913         if ( vAlign 
) *vAlign 
= m_vAlign
; 
1915     else if (m_defGridAttr 
!= this) 
1916         m_defGridAttr
->GetAlignment(hAlign
, vAlign
); 
1919         wxFAIL_MSG(wxT("Missing default cell attribute")); 
1924 // GetRenderer and GetEditor use a slightly different decision path about 
1925 // which attribute to use.  If a non-default attr object has one then it is 
1926 // used, otherwise the default editor or renderer is fetched from the grid and 
1927 // used.  It should be the default for the data type of the cell.  If it is 
1928 // NULL (because the table has a type that the grid does not have in its 
1929 // registry,) then the grid's default editor or renderer is used. 
1931 wxGridCellRenderer
* wxGridCellAttr::GetRenderer(wxGrid
* grid
, int row
, int col
) const 
1933     wxGridCellRenderer
* renderer 
= NULL
; 
1935     if ( m_defGridAttr 
!= this || grid 
== NULL 
) 
1937         renderer 
= m_renderer
;      // use local attribute 
1942     if ( !renderer 
&& grid 
)        // get renderer for the data type 
1944         // GetDefaultRendererForCell() will do IncRef() for us 
1945         renderer 
= grid
->GetDefaultRendererForCell(row
, col
); 
1950         // if we still don't have one then use the grid default 
1951         // (no need for IncRef() here neither) 
1952         renderer 
= m_defGridAttr
->GetRenderer(NULL
,0,0); 
1957         wxFAIL_MSG(wxT("Missing default cell attribute")); 
1963 wxGridCellEditor
* wxGridCellAttr::GetEditor(wxGrid
* grid
, int row
, int col
) const 
1965     wxGridCellEditor
* editor 
= NULL
; 
1967     if ( m_defGridAttr 
!= this || grid 
== NULL 
) 
1969         editor 
= m_editor
;      // use local attribute 
1974     if ( !editor 
&& grid 
)                   // get renderer for the data type 
1975         editor 
= grid
->GetDefaultEditorForCell(row
, col
); 
1978         // if we still don't have one then use the grid default 
1979         editor 
= m_defGridAttr
->GetEditor(NULL
,0,0); 
1983         wxFAIL_MSG(wxT("Missing default cell attribute")); 
1989 // ---------------------------------------------------------------------------- 
1990 // wxGridCellAttrData 
1991 // ---------------------------------------------------------------------------- 
1993 void wxGridCellAttrData::SetAttr(wxGridCellAttr 
*attr
, int row
, int col
) 
1995     int n 
= FindIndex(row
, col
); 
1996     if ( n 
== wxNOT_FOUND 
) 
1998         // add the attribute 
1999         m_attrs
.Add(new wxGridCellWithAttr(row
, col
, attr
)); 
2005             // change the attribute 
2006             m_attrs
[(size_t)n
].attr 
= attr
; 
2010             // remove this attribute 
2011             m_attrs
.RemoveAt((size_t)n
); 
2016 wxGridCellAttr 
*wxGridCellAttrData::GetAttr(int row
, int col
) const 
2018     wxGridCellAttr 
*attr 
= (wxGridCellAttr 
*)NULL
; 
2020     int n 
= FindIndex(row
, col
); 
2021     if ( n 
!= wxNOT_FOUND 
) 
2023         attr 
= m_attrs
[(size_t)n
].attr
; 
2030 void wxGridCellAttrData::UpdateAttrRows( size_t pos
, int numRows 
) 
2032     size_t count 
= m_attrs
.GetCount(); 
2033     for ( size_t n 
= 0; n 
< count
; n
++ ) 
2035         wxGridCellCoords
& coords 
= m_attrs
[n
].coords
; 
2036         wxCoord row 
= coords
.GetRow(); 
2037         if ((size_t)row 
>= pos
) 
2041                 // If rows inserted, include row counter where necessary 
2042                 coords
.SetRow(row 
+ numRows
); 
2044             else if (numRows 
< 0) 
2046                 // If rows deleted ... 
2047                 if ((size_t)row 
>= pos 
- numRows
) 
2049                     // ...either decrement row counter (if row still exists)... 
2050                     coords
.SetRow(row 
+ numRows
); 
2054                     // ...or remove the attribute 
2055                     m_attrs
.RemoveAt((size_t)n
); 
2063 void wxGridCellAttrData::UpdateAttrCols( size_t pos
, int numCols 
) 
2065     size_t count 
= m_attrs
.GetCount(); 
2066     for ( size_t n 
= 0; n 
< count
; n
++ ) 
2068         wxGridCellCoords
& coords 
= m_attrs
[n
].coords
; 
2069         wxCoord col 
= coords
.GetCol(); 
2070         if ( (size_t)col 
>= pos 
) 
2074                 // If rows inserted, include row counter where necessary 
2075                 coords
.SetCol(col 
+ numCols
); 
2077             else if (numCols 
< 0) 
2079                 // If rows deleted ... 
2080                 if ((size_t)col 
>= pos 
- numCols
) 
2082                     // ...either decrement row counter (if row still exists)... 
2083                     coords
.SetCol(col 
+ numCols
); 
2087                     // ...or remove the attribute 
2088                     m_attrs
.RemoveAt((size_t)n
); 
2096 int wxGridCellAttrData::FindIndex(int row
, int col
) const 
2098     size_t count 
= m_attrs
.GetCount(); 
2099     for ( size_t n 
= 0; n 
< count
; n
++ ) 
2101         const wxGridCellCoords
& coords 
= m_attrs
[n
].coords
; 
2102         if ( (coords
.GetRow() == row
) && (coords
.GetCol() == col
) ) 
2111 // ---------------------------------------------------------------------------- 
2112 // wxGridRowOrColAttrData 
2113 // ---------------------------------------------------------------------------- 
2115 wxGridRowOrColAttrData::~wxGridRowOrColAttrData() 
2117     size_t count 
= m_attrs
.Count(); 
2118     for ( size_t n 
= 0; n 
< count
; n
++ ) 
2120         m_attrs
[n
]->DecRef(); 
2124 wxGridCellAttr 
*wxGridRowOrColAttrData::GetAttr(int rowOrCol
) const 
2126     wxGridCellAttr 
*attr 
= (wxGridCellAttr 
*)NULL
; 
2128     int n 
= m_rowsOrCols
.Index(rowOrCol
); 
2129     if ( n 
!= wxNOT_FOUND 
) 
2131         attr 
= m_attrs
[(size_t)n
]; 
2138 void wxGridRowOrColAttrData::SetAttr(wxGridCellAttr 
*attr
, int rowOrCol
) 
2140     int i 
= m_rowsOrCols
.Index(rowOrCol
); 
2141     if ( i 
== wxNOT_FOUND 
) 
2143         // add the attribute 
2144         m_rowsOrCols
.Add(rowOrCol
); 
2149         size_t n 
= (size_t)i
; 
2152             // change the attribute 
2153             m_attrs
[n
]->DecRef(); 
2158             // remove this attribute 
2159             m_attrs
[n
]->DecRef(); 
2160             m_rowsOrCols
.RemoveAt(n
); 
2161             m_attrs
.RemoveAt(n
); 
2166 void wxGridRowOrColAttrData::UpdateAttrRowsOrCols( size_t pos
, int numRowsOrCols 
) 
2168     size_t count 
= m_attrs
.GetCount(); 
2169     for ( size_t n 
= 0; n 
< count
; n
++ ) 
2171         int & rowOrCol 
= m_rowsOrCols
[n
]; 
2172         if ( (size_t)rowOrCol 
>= pos 
) 
2174             if ( numRowsOrCols 
> 0 ) 
2176                 // If rows inserted, include row counter where necessary 
2177                 rowOrCol 
+= numRowsOrCols
; 
2179             else if ( numRowsOrCols 
< 0) 
2181                 // If rows deleted, either decrement row counter (if row still exists) 
2182                 if ((size_t)rowOrCol 
>= pos 
- numRowsOrCols
) 
2183                     rowOrCol 
+= numRowsOrCols
; 
2186                     m_rowsOrCols
.RemoveAt((size_t)n
); 
2187                     m_attrs
.RemoveAt((size_t)n
); 
2195 // ---------------------------------------------------------------------------- 
2196 // wxGridCellAttrProvider 
2197 // ---------------------------------------------------------------------------- 
2199 wxGridCellAttrProvider::wxGridCellAttrProvider() 
2201     m_data 
= (wxGridCellAttrProviderData 
*)NULL
; 
2204 wxGridCellAttrProvider::~wxGridCellAttrProvider() 
2209 void wxGridCellAttrProvider::InitData() 
2211     m_data 
= new wxGridCellAttrProviderData
; 
2214 wxGridCellAttr 
*wxGridCellAttrProvider::GetAttr(int row
, int col
) const 
2216     wxGridCellAttr 
*attr 
= (wxGridCellAttr 
*)NULL
; 
2219         // first look for the attribute of this specific cell 
2220         attr 
= m_data
->m_cellAttrs
.GetAttr(row
, col
); 
2224             // then look for the col attr (col attributes are more common than 
2225             // the row ones, hence they have priority) 
2226             attr 
= m_data
->m_colAttrs
.GetAttr(col
); 
2231             // finally try the row attributes 
2232             attr 
= m_data
->m_rowAttrs
.GetAttr(row
); 
2239 void wxGridCellAttrProvider::SetAttr(wxGridCellAttr 
*attr
, 
2245     m_data
->m_cellAttrs
.SetAttr(attr
, row
, col
); 
2248 void wxGridCellAttrProvider::SetRowAttr(wxGridCellAttr 
*attr
, int row
) 
2253     m_data
->m_rowAttrs
.SetAttr(attr
, row
); 
2256 void wxGridCellAttrProvider::SetColAttr(wxGridCellAttr 
*attr
, int col
) 
2261     m_data
->m_colAttrs
.SetAttr(attr
, col
); 
2264 void wxGridCellAttrProvider::UpdateAttrRows( size_t pos
, int numRows 
) 
2268         m_data
->m_cellAttrs
.UpdateAttrRows( pos
, numRows 
); 
2270         m_data
->m_rowAttrs
.UpdateAttrRowsOrCols( pos
, numRows 
); 
2274 void wxGridCellAttrProvider::UpdateAttrCols( size_t pos
, int numCols 
) 
2278         m_data
->m_cellAttrs
.UpdateAttrCols( pos
, numCols 
); 
2280         m_data
->m_colAttrs
.UpdateAttrRowsOrCols( pos
, numCols 
); 
2284 // ---------------------------------------------------------------------------- 
2285 // wxGridTypeRegistry 
2286 // ---------------------------------------------------------------------------- 
2288 wxGridTypeRegistry::~wxGridTypeRegistry() 
2290     size_t count 
= m_typeinfo
.Count(); 
2291     for ( size_t i 
= 0; i 
< count
; i
++ ) 
2292         delete m_typeinfo
[i
]; 
2296 void wxGridTypeRegistry::RegisterDataType(const wxString
& typeName
, 
2297                                           wxGridCellRenderer
* renderer
, 
2298                                           wxGridCellEditor
* editor
) 
2300     wxGridDataTypeInfo
* info 
= new wxGridDataTypeInfo(typeName
, renderer
, editor
); 
2302     // is it already registered? 
2303     int loc 
= FindRegisteredDataType(typeName
); 
2304     if ( loc 
!= wxNOT_FOUND 
) 
2306         delete m_typeinfo
[loc
]; 
2307         m_typeinfo
[loc
] = info
; 
2311         m_typeinfo
.Add(info
); 
2315 int wxGridTypeRegistry::FindRegisteredDataType(const wxString
& typeName
) 
2317     size_t count 
= m_typeinfo
.GetCount(); 
2318     for ( size_t i 
= 0; i 
< count
; i
++ ) 
2320         if ( typeName 
== m_typeinfo
[i
]->m_typeName 
) 
2329 int wxGridTypeRegistry::FindDataType(const wxString
& typeName
) 
2331     int index 
= FindRegisteredDataType(typeName
); 
2332     if ( index 
== wxNOT_FOUND 
) 
2334         // check whether this is one of the standard ones, in which case 
2335         // register it "on the fly" 
2336         if ( typeName 
== wxGRID_VALUE_STRING 
) 
2338             RegisterDataType(wxGRID_VALUE_STRING
, 
2339                              new wxGridCellStringRenderer
, 
2340                              new wxGridCellTextEditor
); 
2342         else if ( typeName 
== wxGRID_VALUE_BOOL 
) 
2344             RegisterDataType(wxGRID_VALUE_BOOL
, 
2345                              new wxGridCellBoolRenderer
, 
2346                              new wxGridCellBoolEditor
); 
2348         else if ( typeName 
== wxGRID_VALUE_NUMBER 
) 
2350             RegisterDataType(wxGRID_VALUE_NUMBER
, 
2351                              new wxGridCellNumberRenderer
, 
2352                              new wxGridCellNumberEditor
); 
2354         else if ( typeName 
== wxGRID_VALUE_FLOAT 
) 
2356             RegisterDataType(wxGRID_VALUE_FLOAT
, 
2357                              new wxGridCellFloatRenderer
, 
2358                              new wxGridCellFloatEditor
); 
2360         else if ( typeName 
== wxGRID_VALUE_CHOICE 
) 
2362             RegisterDataType(wxGRID_VALUE_CHOICE
, 
2363                              new wxGridCellStringRenderer
, 
2364                              new wxGridCellChoiceEditor
); 
2371         // we get here only if just added the entry for this type, so return 
2373         index 
= m_typeinfo
.GetCount() - 1; 
2379 int wxGridTypeRegistry::FindOrCloneDataType(const wxString
& typeName
) 
2381     int index 
= FindDataType(typeName
); 
2382     if ( index 
== wxNOT_FOUND 
) 
2384         // the first part of the typename is the "real" type, anything after ':' 
2385         // are the parameters for the renderer 
2386         index 
= FindDataType(typeName
.BeforeFirst(_T(':'))); 
2387         if ( index 
== wxNOT_FOUND 
) 
2392         wxGridCellRenderer 
*renderer 
= GetRenderer(index
); 
2393         wxGridCellRenderer 
*rendererOld 
= renderer
; 
2394         renderer 
= renderer
->Clone(); 
2395         rendererOld
->DecRef(); 
2397         wxGridCellEditor 
*editor 
= GetEditor(index
); 
2398         wxGridCellEditor 
*editorOld 
= editor
; 
2399         editor 
= editor
->Clone(); 
2400         editorOld
->DecRef(); 
2402         // do it even if there are no parameters to reset them to defaults 
2403         wxString params 
= typeName
.AfterFirst(_T(':')); 
2404         renderer
->SetParameters(params
); 
2405         editor
->SetParameters(params
); 
2407         // register the new typename 
2408         RegisterDataType(typeName
, renderer
, editor
); 
2410         // we just registered it, it's the last one 
2411         index 
= m_typeinfo
.GetCount() - 1; 
2417 wxGridCellRenderer
* wxGridTypeRegistry::GetRenderer(int index
) 
2419     wxGridCellRenderer
* renderer 
= m_typeinfo
[index
]->m_renderer
; 
2424 wxGridCellEditor
* wxGridTypeRegistry::GetEditor(int index
) 
2426     wxGridCellEditor
* editor 
= m_typeinfo
[index
]->m_editor
; 
2431 // ---------------------------------------------------------------------------- 
2433 // ---------------------------------------------------------------------------- 
2435 IMPLEMENT_ABSTRACT_CLASS( wxGridTableBase
, wxObject 
) 
2438 wxGridTableBase::wxGridTableBase() 
2440     m_view 
= (wxGrid 
*) NULL
; 
2441     m_attrProvider 
= (wxGridCellAttrProvider 
*) NULL
; 
2444 wxGridTableBase::~wxGridTableBase() 
2446     delete m_attrProvider
; 
2449 void wxGridTableBase::SetAttrProvider(wxGridCellAttrProvider 
*attrProvider
) 
2451     delete m_attrProvider
; 
2452     m_attrProvider 
= attrProvider
; 
2455 bool wxGridTableBase::CanHaveAttributes() 
2457     if ( ! GetAttrProvider() ) 
2459         // use the default attr provider by default 
2460         SetAttrProvider(new wxGridCellAttrProvider
); 
2465 wxGridCellAttr 
*wxGridTableBase::GetAttr(int row
, int col
) 
2467     if ( m_attrProvider 
) 
2468         return m_attrProvider
->GetAttr(row
, col
); 
2470         return (wxGridCellAttr 
*)NULL
; 
2473 void wxGridTableBase::SetAttr(wxGridCellAttr
* attr
, int row
, int col
) 
2475     if ( m_attrProvider 
) 
2477         m_attrProvider
->SetAttr(attr
, row
, col
); 
2481         // as we take ownership of the pointer and don't store it, we must 
2487 void wxGridTableBase::SetRowAttr(wxGridCellAttr 
*attr
, int row
) 
2489     if ( m_attrProvider 
) 
2491         m_attrProvider
->SetRowAttr(attr
, row
); 
2495         // as we take ownership of the pointer and don't store it, we must 
2501 void wxGridTableBase::SetColAttr(wxGridCellAttr 
*attr
, int col
) 
2503     if ( m_attrProvider 
) 
2505         m_attrProvider
->SetColAttr(attr
, col
); 
2509         // as we take ownership of the pointer and don't store it, we must 
2515 bool wxGridTableBase::InsertRows( size_t WXUNUSED(pos
), 
2516                                   size_t WXUNUSED(numRows
) ) 
2518     wxFAIL_MSG( wxT("Called grid table class function InsertRows\nbut your derived table class does not override this function") ); 
2523 bool wxGridTableBase::AppendRows( size_t WXUNUSED(numRows
) ) 
2525     wxFAIL_MSG( wxT("Called grid table class function AppendRows\nbut your derived table class does not override this function")); 
2530 bool wxGridTableBase::DeleteRows( size_t WXUNUSED(pos
), 
2531                                   size_t WXUNUSED(numRows
) ) 
2533     wxFAIL_MSG( wxT("Called grid table class function DeleteRows\nbut your derived table class does not override this function")); 
2538 bool wxGridTableBase::InsertCols( size_t WXUNUSED(pos
), 
2539                                   size_t WXUNUSED(numCols
) ) 
2541     wxFAIL_MSG( wxT("Called grid table class function InsertCols\nbut your derived table class does not override this function")); 
2546 bool wxGridTableBase::AppendCols( size_t WXUNUSED(numCols
) ) 
2548     wxFAIL_MSG(wxT("Called grid table class function AppendCols\nbut your derived table class does not override this function")); 
2553 bool wxGridTableBase::DeleteCols( size_t WXUNUSED(pos
), 
2554                                   size_t WXUNUSED(numCols
) ) 
2556     wxFAIL_MSG( wxT("Called grid table class function DeleteCols\nbut your derived table class does not override this function")); 
2562 wxString 
wxGridTableBase::GetRowLabelValue( int row 
) 
2565     s 
<< row 
+ 1; // RD: Starting the rows at zero confuses users, no matter 
2566                   //     how much it makes sense to us geeks. 
2570 wxString 
wxGridTableBase::GetColLabelValue( int col 
) 
2572     // default col labels are: 
2573     //   cols 0 to 25   : A-Z 
2574     //   cols 26 to 675 : AA-ZZ 
2579     for ( n 
= 1; ; n
++ ) 
2581         s 
+= (_T('A') + (wxChar
)( col%26 
)); 
2583         if ( col 
< 0 ) break; 
2586     // reverse the string... 
2588     for ( i 
= 0;  i 
< n
;  i
++ ) 
2597 wxString 
wxGridTableBase::GetTypeName( int WXUNUSED(row
), int WXUNUSED(col
) ) 
2599     return wxGRID_VALUE_STRING
; 
2602 bool wxGridTableBase::CanGetValueAs( int WXUNUSED(row
), int WXUNUSED(col
), 
2603                                      const wxString
& typeName 
) 
2605     return typeName 
== wxGRID_VALUE_STRING
; 
2608 bool wxGridTableBase::CanSetValueAs( int row
, int col
, const wxString
& typeName 
) 
2610     return CanGetValueAs(row
, col
, typeName
); 
2613 long wxGridTableBase::GetValueAsLong( int WXUNUSED(row
), int WXUNUSED(col
) ) 
2618 double wxGridTableBase::GetValueAsDouble( int WXUNUSED(row
), int WXUNUSED(col
) ) 
2623 bool wxGridTableBase::GetValueAsBool( int WXUNUSED(row
), int WXUNUSED(col
) ) 
2628 void wxGridTableBase::SetValueAsLong( int WXUNUSED(row
), int WXUNUSED(col
), 
2629                                       long WXUNUSED(value
) ) 
2633 void wxGridTableBase::SetValueAsDouble( int WXUNUSED(row
), int WXUNUSED(col
), 
2634                                         double WXUNUSED(value
) ) 
2638 void wxGridTableBase::SetValueAsBool( int WXUNUSED(row
), int WXUNUSED(col
), 
2639                                       bool WXUNUSED(value
) ) 
2644 void* wxGridTableBase::GetValueAsCustom( int WXUNUSED(row
), int WXUNUSED(col
), 
2645                                          const wxString
& WXUNUSED(typeName
) ) 
2650 void  wxGridTableBase::SetValueAsCustom( int WXUNUSED(row
), int WXUNUSED(col
), 
2651                                          const wxString
& WXUNUSED(typeName
), 
2652                                          void* WXUNUSED(value
) ) 
2656 ////////////////////////////////////////////////////////////////////// 
2658 // Message class for the grid table to send requests and notifications 
2662 wxGridTableMessage::wxGridTableMessage() 
2664     m_table 
= (wxGridTableBase 
*) NULL
; 
2670 wxGridTableMessage::wxGridTableMessage( wxGridTableBase 
*table
, int id
, 
2671                                         int commandInt1
, int commandInt2 
) 
2675     m_comInt1 
= commandInt1
; 
2676     m_comInt2 
= commandInt2
; 
2681 ////////////////////////////////////////////////////////////////////// 
2683 // A basic grid table for string data. An object of this class will 
2684 // created by wxGrid if you don't specify an alternative table class. 
2687 WX_DEFINE_OBJARRAY(wxGridStringArray
) 
2689 IMPLEMENT_DYNAMIC_CLASS( wxGridStringTable
, wxGridTableBase 
) 
2691 wxGridStringTable::wxGridStringTable() 
2696 wxGridStringTable::wxGridStringTable( int numRows
, int numCols 
) 
2701     m_data
.Alloc( numRows 
); 
2704     sa
.Alloc( numCols 
); 
2705     for ( col 
= 0;  col 
< numCols
;  col
++ ) 
2707         sa
.Add( wxEmptyString 
); 
2710     for ( row 
= 0;  row 
< numRows
;  row
++ ) 
2716 wxGridStringTable::~wxGridStringTable() 
2720 int wxGridStringTable::GetNumberRows() 
2722     return m_data
.GetCount(); 
2725 int wxGridStringTable::GetNumberCols() 
2727     if ( m_data
.GetCount() > 0 ) 
2728         return m_data
[0].GetCount(); 
2733 wxString 
wxGridStringTable::GetValue( int row
, int col 
) 
2735     wxASSERT_MSG( (row 
< GetNumberRows()) && (col 
< GetNumberCols()), 
2736                   _T("invalid row or column index in wxGridStringTable") ); 
2738     return m_data
[row
][col
]; 
2741 void wxGridStringTable::SetValue( int row
, int col
, const wxString
& value 
) 
2743     wxASSERT_MSG( (row 
< GetNumberRows()) && (col 
< GetNumberCols()), 
2744                   _T("invalid row or column index in wxGridStringTable") ); 
2746     m_data
[row
][col
] = value
; 
2749 bool wxGridStringTable::IsEmptyCell( int row
, int col 
) 
2751     wxASSERT_MSG( (row 
< GetNumberRows()) && (col 
< GetNumberCols()), 
2752                   _T("invalid row or column index in wxGridStringTable") ); 
2754     return (m_data
[row
][col
] == wxEmptyString
); 
2757 void wxGridStringTable::Clear() 
2760     int numRows
, numCols
; 
2762     numRows 
= m_data
.GetCount(); 
2765         numCols 
= m_data
[0].GetCount(); 
2767         for ( row 
= 0;  row 
< numRows
;  row
++ ) 
2769             for ( col 
= 0;  col 
< numCols
;  col
++ ) 
2771                 m_data
[row
][col
] = wxEmptyString
; 
2778 bool wxGridStringTable::InsertRows( size_t pos
, size_t numRows 
) 
2782     size_t curNumRows 
= m_data
.GetCount(); 
2783     size_t curNumCols 
= ( curNumRows 
> 0 ? m_data
[0].GetCount() : 
2784                           ( GetView() ? GetView()->GetNumberCols() : 0 ) ); 
2786     if ( pos 
>= curNumRows 
) 
2788         return AppendRows( numRows 
); 
2792     sa
.Alloc( curNumCols 
); 
2793     for ( col 
= 0;  col 
< curNumCols
;  col
++ ) 
2795         sa
.Add( wxEmptyString 
); 
2798     for ( row 
= pos
;  row 
< pos 
+ numRows
;  row
++ ) 
2800         m_data
.Insert( sa
, row 
); 
2804         wxGridTableMessage 
msg( this, 
2805                                 wxGRIDTABLE_NOTIFY_ROWS_INSERTED
, 
2809         GetView()->ProcessTableMessage( msg 
); 
2815 bool wxGridStringTable::AppendRows( size_t numRows 
) 
2819     size_t curNumRows 
= m_data
.GetCount(); 
2820     size_t curNumCols 
= ( curNumRows 
> 0 ? m_data
[0].GetCount() : 
2821                           ( GetView() ? GetView()->GetNumberCols() : 0 ) ); 
2824     if ( curNumCols 
> 0 ) 
2826         sa
.Alloc( curNumCols 
); 
2827         for ( col 
= 0;  col 
< curNumCols
;  col
++ ) 
2829             sa
.Add( wxEmptyString 
); 
2833     for ( row 
= 0;  row 
< numRows
;  row
++ ) 
2840         wxGridTableMessage 
msg( this, 
2841                                 wxGRIDTABLE_NOTIFY_ROWS_APPENDED
, 
2844         GetView()->ProcessTableMessage( msg 
); 
2850 bool wxGridStringTable::DeleteRows( size_t pos
, size_t numRows 
) 
2854     size_t curNumRows 
= m_data
.GetCount(); 
2856     if ( pos 
>= curNumRows 
) 
2859         errmsg
.Printf(wxT("Called wxGridStringTable::DeleteRows(pos=%d, N=%d)\nPos value is invalid for present table with %d rows"), 
2860                       pos
, numRows
, curNumRows 
); 
2861         wxFAIL_MSG( errmsg 
); 
2865     if ( numRows 
> curNumRows 
- pos 
) 
2867         numRows 
= curNumRows 
- pos
; 
2870     if ( numRows 
>= curNumRows 
) 
2872         m_data
.Empty();  // don't release memory just yet 
2876         for ( n 
= 0;  n 
< numRows
;  n
++ ) 
2878             m_data
.Remove( pos 
); 
2883         wxGridTableMessage 
msg( this, 
2884                                 wxGRIDTABLE_NOTIFY_ROWS_DELETED
, 
2888         GetView()->ProcessTableMessage( msg 
); 
2894 bool wxGridStringTable::InsertCols( size_t pos
, size_t numCols 
) 
2898     size_t curNumRows 
= m_data
.GetCount(); 
2899     size_t curNumCols 
= ( curNumRows 
> 0 ? m_data
[0].GetCount() : 
2900                           ( GetView() ? GetView()->GetNumberCols() : 0 ) ); 
2902     if ( pos 
>= curNumCols 
) 
2904         return AppendCols( numCols 
); 
2907     for ( row 
= 0;  row 
< curNumRows
;  row
++ ) 
2909         for ( col 
= pos
;  col 
< pos 
+ numCols
;  col
++ ) 
2911             m_data
[row
].Insert( wxEmptyString
, col 
); 
2916         wxGridTableMessage 
msg( this, 
2917                                 wxGRIDTABLE_NOTIFY_COLS_INSERTED
, 
2921         GetView()->ProcessTableMessage( msg 
); 
2927 bool wxGridStringTable::AppendCols( size_t numCols 
) 
2931     size_t curNumRows 
= m_data
.GetCount(); 
2935         // TODO: something better than this ? 
2937         wxFAIL_MSG( wxT("Unable to append cols to a grid table with no rows.\nCall AppendRows() first") ); 
2942     for ( row 
= 0;  row 
< curNumRows
;  row
++ ) 
2944         for ( n 
= 0;  n 
< numCols
;  n
++ ) 
2946             m_data
[row
].Add( wxEmptyString 
); 
2952         wxGridTableMessage 
msg( this, 
2953                                 wxGRIDTABLE_NOTIFY_COLS_APPENDED
, 
2956         GetView()->ProcessTableMessage( msg 
); 
2962 bool wxGridStringTable::DeleteCols( size_t pos
, size_t numCols 
) 
2966     size_t curNumRows 
= m_data
.GetCount(); 
2967     size_t curNumCols 
= ( curNumRows 
> 0 ? m_data
[0].GetCount() : 
2968                           ( GetView() ? GetView()->GetNumberCols() : 0 ) ); 
2970     if ( pos 
>= curNumCols 
) 
2973         errmsg
.Printf( wxT("Called wxGridStringTable::DeleteCols(pos=%d, N=%d)...\nPos value is invalid for present table with %d cols"), 
2974                         pos
, numCols
, curNumCols 
); 
2975         wxFAIL_MSG( errmsg 
); 
2979     if ( numCols 
> curNumCols 
- pos 
) 
2981         numCols 
= curNumCols 
- pos
; 
2984     for ( row 
= 0;  row 
< curNumRows
;  row
++ ) 
2986         if ( numCols 
>= curNumCols 
) 
2988             m_data
[row
].Clear(); 
2992             for ( n 
= 0;  n 
< numCols
;  n
++ ) 
2994                 m_data
[row
].Remove( pos 
); 
3000         wxGridTableMessage 
msg( this, 
3001                                 wxGRIDTABLE_NOTIFY_COLS_DELETED
, 
3005         GetView()->ProcessTableMessage( msg 
); 
3011 wxString 
wxGridStringTable::GetRowLabelValue( int row 
) 
3013     if ( row 
> (int)(m_rowLabels
.GetCount()) - 1 ) 
3015         // using default label 
3017         return wxGridTableBase::GetRowLabelValue( row 
); 
3021         return m_rowLabels
[ row 
]; 
3025 wxString 
wxGridStringTable::GetColLabelValue( int col 
) 
3027     if ( col 
> (int)(m_colLabels
.GetCount()) - 1 ) 
3029         // using default label 
3031         return wxGridTableBase::GetColLabelValue( col 
); 
3035         return m_colLabels
[ col 
]; 
3039 void wxGridStringTable::SetRowLabelValue( int row
, const wxString
& value 
) 
3041     if ( row 
> (int)(m_rowLabels
.GetCount()) - 1 ) 
3043         int n 
= m_rowLabels
.GetCount(); 
3045         for ( i 
= n
;  i 
<= row
;  i
++ ) 
3047             m_rowLabels
.Add( wxGridTableBase::GetRowLabelValue(i
) ); 
3051     m_rowLabels
[row
] = value
; 
3054 void wxGridStringTable::SetColLabelValue( int col
, const wxString
& value 
) 
3056     if ( col 
> (int)(m_colLabels
.GetCount()) - 1 ) 
3058         int n 
= m_colLabels
.GetCount(); 
3060         for ( i 
= n
;  i 
<= col
;  i
++ ) 
3062             m_colLabels
.Add( wxGridTableBase::GetColLabelValue(i
) ); 
3066     m_colLabels
[col
] = value
; 
3071 ////////////////////////////////////////////////////////////////////// 
3072 ////////////////////////////////////////////////////////////////////// 
3074 IMPLEMENT_DYNAMIC_CLASS( wxGridRowLabelWindow
, wxWindow 
) 
3076 BEGIN_EVENT_TABLE( wxGridRowLabelWindow
, wxWindow 
) 
3077     EVT_PAINT( wxGridRowLabelWindow::OnPaint 
) 
3078     EVT_MOUSE_EVENTS( wxGridRowLabelWindow::OnMouseEvent 
) 
3079     EVT_KEY_DOWN( wxGridRowLabelWindow::OnKeyDown 
) 
3080     EVT_KEY_UP( wxGridRowLabelWindow::OnKeyUp 
) 
3083 wxGridRowLabelWindow::wxGridRowLabelWindow( wxGrid 
*parent
, 
3085                                             const wxPoint 
&pos
, const wxSize 
&size 
) 
3086   : wxWindow( parent
, id
, pos
, size
, wxWANTS_CHARS 
) 
3091 void wxGridRowLabelWindow::OnPaint( wxPaintEvent
& WXUNUSED(event
) ) 
3095     // NO - don't do this because it will set both the x and y origin 
3096     // coords to match the parent scrolled window and we just want to 
3097     // set the y coord  - MB 
3099     // m_owner->PrepareDC( dc ); 
3102     m_owner
->CalcUnscrolledPosition( 0, 0, &x
, &y 
); 
3103     dc
.SetDeviceOrigin( 0, -y 
); 
3105     m_owner
->CalcRowLabelsExposed( GetUpdateRegion() ); 
3106     m_owner
->DrawRowLabels( dc 
); 
3110 void wxGridRowLabelWindow::OnMouseEvent( wxMouseEvent
& event 
) 
3112     m_owner
->ProcessRowLabelMouseEvent( event 
); 
3116 // This seems to be required for wxMotif otherwise the mouse 
3117 // cursor must be in the cell edit control to get key events 
3119 void wxGridRowLabelWindow::OnKeyDown( wxKeyEvent
& event 
) 
3121     if ( !m_owner
->ProcessEvent( event 
) ) event
.Skip(); 
3124 void wxGridRowLabelWindow::OnKeyUp( wxKeyEvent
& event 
) 
3126     if ( !m_owner
->ProcessEvent( event 
) ) event
.Skip(); 
3131 ////////////////////////////////////////////////////////////////////// 
3133 IMPLEMENT_DYNAMIC_CLASS( wxGridColLabelWindow
, wxWindow 
) 
3135 BEGIN_EVENT_TABLE( wxGridColLabelWindow
, wxWindow 
) 
3136     EVT_PAINT( wxGridColLabelWindow::OnPaint 
) 
3137     EVT_MOUSE_EVENTS( wxGridColLabelWindow::OnMouseEvent 
) 
3138     EVT_KEY_DOWN( wxGridColLabelWindow::OnKeyDown 
) 
3139     EVT_KEY_UP( wxGridColLabelWindow::OnKeyUp 
) 
3142 wxGridColLabelWindow::wxGridColLabelWindow( wxGrid 
*parent
, 
3144                                             const wxPoint 
&pos
, const wxSize 
&size 
) 
3145   : wxWindow( parent
, id
, pos
, size
, wxWANTS_CHARS 
) 
3150 void wxGridColLabelWindow::OnPaint( wxPaintEvent
& WXUNUSED(event
) ) 
3154     // NO - don't do this because it will set both the x and y origin 
3155     // coords to match the parent scrolled window and we just want to 
3156     // set the x coord  - MB 
3158     // m_owner->PrepareDC( dc ); 
3161     m_owner
->CalcUnscrolledPosition( 0, 0, &x
, &y 
); 
3162     dc
.SetDeviceOrigin( -x
, 0 ); 
3164     m_owner
->CalcColLabelsExposed( GetUpdateRegion() ); 
3165     m_owner
->DrawColLabels( dc 
); 
3169 void wxGridColLabelWindow::OnMouseEvent( wxMouseEvent
& event 
) 
3171     m_owner
->ProcessColLabelMouseEvent( event 
); 
3175 // This seems to be required for wxMotif otherwise the mouse 
3176 // cursor must be in the cell edit control to get key events 
3178 void wxGridColLabelWindow::OnKeyDown( wxKeyEvent
& event 
) 
3180     if ( !m_owner
->ProcessEvent( event 
) ) event
.Skip(); 
3183 void wxGridColLabelWindow::OnKeyUp( wxKeyEvent
& event 
) 
3185     if ( !m_owner
->ProcessEvent( event 
) ) event
.Skip(); 
3190 ////////////////////////////////////////////////////////////////////// 
3192 IMPLEMENT_DYNAMIC_CLASS( wxGridCornerLabelWindow
, wxWindow 
) 
3194 BEGIN_EVENT_TABLE( wxGridCornerLabelWindow
, wxWindow 
) 
3195     EVT_MOUSE_EVENTS( wxGridCornerLabelWindow::OnMouseEvent 
) 
3196     EVT_PAINT( wxGridCornerLabelWindow::OnPaint
) 
3197     EVT_KEY_DOWN( wxGridCornerLabelWindow::OnKeyDown 
) 
3198     EVT_KEY_UP( wxGridCornerLabelWindow::OnKeyUp 
) 
3201 wxGridCornerLabelWindow::wxGridCornerLabelWindow( wxGrid 
*parent
, 
3203                                                   const wxPoint 
&pos
, const wxSize 
&size 
) 
3204   : wxWindow( parent
, id
, pos
, size
, wxWANTS_CHARS 
) 
3209 void wxGridCornerLabelWindow::OnPaint( wxPaintEvent
& WXUNUSED(event
) ) 
3213     int client_height 
= 0; 
3214     int client_width 
= 0; 
3215     GetClientSize( &client_width
, &client_height 
); 
3217     dc
.SetPen( *wxBLACK_PEN 
); 
3218     dc
.DrawLine( client_width
-1, client_height
-1, client_width
-1, 0 ); 
3219     dc
.DrawLine( client_width
-1, client_height
-1, 0, client_height
-1 ); 
3221     dc
.SetPen( *wxWHITE_PEN 
); 
3222     dc
.DrawLine( 0, 0, client_width
, 0 ); 
3223     dc
.DrawLine( 0, 0, 0, client_height 
); 
3227 void wxGridCornerLabelWindow::OnMouseEvent( wxMouseEvent
& event 
) 
3229     m_owner
->ProcessCornerLabelMouseEvent( event 
); 
3233 // This seems to be required for wxMotif otherwise the mouse 
3234 // cursor must be in the cell edit control to get key events 
3236 void wxGridCornerLabelWindow::OnKeyDown( wxKeyEvent
& event 
) 
3238     if ( !m_owner
->ProcessEvent( event 
) ) event
.Skip(); 
3241 void wxGridCornerLabelWindow::OnKeyUp( wxKeyEvent
& event 
) 
3243     if ( !m_owner
->ProcessEvent( event 
) ) event
.Skip(); 
3248 ////////////////////////////////////////////////////////////////////// 
3250 IMPLEMENT_DYNAMIC_CLASS( wxGridWindow
, wxPanel 
) 
3252 BEGIN_EVENT_TABLE( wxGridWindow
, wxPanel 
) 
3253     EVT_PAINT( wxGridWindow::OnPaint 
) 
3254     EVT_MOUSE_EVENTS( wxGridWindow::OnMouseEvent 
) 
3255     EVT_KEY_DOWN( wxGridWindow::OnKeyDown 
) 
3256     EVT_KEY_UP( wxGridWindow::OnKeyUp 
) 
3257     EVT_ERASE_BACKGROUND( wxGridWindow::OnEraseBackground 
) 
3260 wxGridWindow::wxGridWindow( wxGrid 
*parent
, 
3261                             wxGridRowLabelWindow 
*rowLblWin
, 
3262                             wxGridColLabelWindow 
*colLblWin
, 
3263                             wxWindowID id
, const wxPoint 
&pos
, const wxSize 
&size 
) 
3264         : wxPanel( parent
, id
, pos
, size
, wxWANTS_CHARS
, "grid window" ) 
3267     m_rowLabelWin 
= rowLblWin
; 
3268     m_colLabelWin 
= colLblWin
; 
3269     SetBackgroundColour( "WHITE" ); 
3273 wxGridWindow::~wxGridWindow() 
3278 void wxGridWindow::OnPaint( wxPaintEvent 
&WXUNUSED(event
) ) 
3280     wxPaintDC 
dc( this ); 
3281     m_owner
->PrepareDC( dc 
); 
3282     wxRegion reg 
= GetUpdateRegion(); 
3283     m_owner
->CalcCellsExposed( reg 
); 
3284     m_owner
->DrawGridCellArea( dc 
); 
3285 #if WXGRID_DRAW_LINES 
3286     m_owner
->DrawAllGridLines( dc
, reg 
); 
3288     m_owner
->DrawGridSpace( dc 
); 
3289     m_owner
->DrawHighlight( dc 
); 
3293 void wxGridWindow::ScrollWindow( int dx
, int dy
, const wxRect 
*rect 
) 
3295     wxPanel::ScrollWindow( dx
, dy
, rect 
); 
3296     m_rowLabelWin
->ScrollWindow( 0, dy
, rect 
); 
3297     m_colLabelWin
->ScrollWindow( dx
, 0, rect 
); 
3301 void wxGridWindow::OnMouseEvent( wxMouseEvent
& event 
) 
3303     m_owner
->ProcessGridCellMouseEvent( event 
); 
3307 // This seems to be required for wxMotif/wxGTK otherwise the mouse 
3308 // cursor must be in the cell edit control to get key events 
3310 void wxGridWindow::OnKeyDown( wxKeyEvent
& event 
) 
3312     if ( !m_owner
->ProcessEvent( event 
) ) event
.Skip(); 
3315 void wxGridWindow::OnKeyUp( wxKeyEvent
& event 
) 
3317     if ( !m_owner
->ProcessEvent( event 
) ) event
.Skip(); 
3320 void wxGridWindow::OnEraseBackground( wxEraseEvent
& WXUNUSED(event
) ) 
3325 ////////////////////////////////////////////////////////////////////// 
3328 IMPLEMENT_DYNAMIC_CLASS( wxGrid
, wxScrolledWindow 
) 
3330 BEGIN_EVENT_TABLE( wxGrid
, wxScrolledWindow 
) 
3331     EVT_PAINT( wxGrid::OnPaint 
) 
3332     EVT_SIZE( wxGrid::OnSize 
) 
3333     EVT_KEY_DOWN( wxGrid::OnKeyDown 
) 
3334     EVT_KEY_UP( wxGrid::OnKeyUp 
) 
3335     EVT_ERASE_BACKGROUND( wxGrid::OnEraseBackground 
) 
3338 wxGrid::wxGrid( wxWindow 
*parent
, 
3343                  const wxString
& name 
) 
3344   : wxScrolledWindow( parent
, id
, pos
, size
, (style 
| wxWANTS_CHARS
), name 
), 
3345     m_colMinWidths(GRID_HASH_SIZE
), 
3346     m_rowMinHeights(GRID_HASH_SIZE
) 
3355     wxSafeDecRef(m_defaultCellAttr
); 
3357 #ifdef DEBUG_ATTR_CACHE 
3358     size_t total 
= gs_nAttrCacheHits 
+ gs_nAttrCacheMisses
; 
3359     wxPrintf(_T("wxGrid attribute cache statistics: " 
3360                 "total: %u, hits: %u (%u%%)\n"), 
3361              total
, gs_nAttrCacheHits
, 
3362              total 
? (gs_nAttrCacheHits
*100) / total 
: 0); 
3368     delete m_typeRegistry
; 
3374 // ----- internal init and update functions 
3377 void wxGrid::Create() 
3379     m_created 
= FALSE
;    // set to TRUE by CreateGrid 
3381     m_table        
= (wxGridTableBase 
*) NULL
; 
3384     m_cellEditCtrlEnabled 
= FALSE
; 
3386     m_defaultCellAttr 
= new wxGridCellAttr
; 
3387     m_defaultCellAttr
->SetDefAttr(m_defaultCellAttr
); 
3389     // Set default cell attributes 
3390     m_defaultCellAttr
->SetFont(GetFont()); 
3391     m_defaultCellAttr
->SetAlignment(wxALIGN_LEFT
, wxALIGN_TOP
); 
3392     m_defaultCellAttr
->SetTextColour( 
3393         wxSystemSettings::GetSystemColour(wxSYS_COLOUR_WINDOWTEXT
)); 
3394     m_defaultCellAttr
->SetBackgroundColour( 
3395         wxSystemSettings::GetSystemColour(wxSYS_COLOUR_WINDOW
)); 
3396     m_defaultCellAttr
->SetRenderer(new wxGridCellStringRenderer
); 
3397     m_defaultCellAttr
->SetEditor(new wxGridCellTextEditor
); 
3402     m_currentCellCoords 
= wxGridNoCellCoords
; 
3404     m_rowLabelWidth 
= WXGRID_DEFAULT_ROW_LABEL_WIDTH
; 
3405     m_colLabelHeight 
= WXGRID_DEFAULT_COL_LABEL_HEIGHT
; 
3407     // create the type registry 
3408     m_typeRegistry 
= new wxGridTypeRegistry
; 
3410     // subwindow components that make up the wxGrid 
3411     m_cornerLabelWin 
= new wxGridCornerLabelWindow( this, 
3416     m_rowLabelWin 
= new wxGridRowLabelWindow( this, 
3421     m_colLabelWin 
= new wxGridColLabelWindow( this, 
3426     m_gridWin 
= new wxGridWindow( this, 
3433     SetTargetWindow( m_gridWin 
); 
3437 bool wxGrid::CreateGrid( int numRows
, int numCols
, 
3438                          wxGrid::wxGridSelectionModes selmode 
) 
3440     wxCHECK_MSG( !m_created
, 
3442                  wxT("wxGrid::CreateGrid or wxGrid::SetTable called more than once") ); 
3444     m_numRows 
= numRows
; 
3445     m_numCols 
= numCols
; 
3447     m_table 
= new wxGridStringTable( m_numRows
, m_numCols 
); 
3448     m_table
->SetView( this ); 
3450     m_selection 
= new wxGridSelection( this, selmode 
); 
3457 void wxGrid::SetSelectionMode(wxGrid::wxGridSelectionModes selmode
) 
3461         wxFAIL_MSG( wxT("Called wxGrid::SetSelectionMode() before calling CreateGrid()") ); 
3464         m_selection
->SetSelectionMode( selmode 
); 
3467 bool wxGrid::SetTable( wxGridTableBase 
*table
, bool takeOwnership
, 
3468                        wxGrid::wxGridSelectionModes selmode 
) 
3472         // RD: Actually, this should probably be allowed.  I think it would be 
3473         // nice to be able to switch multiple Tables in and out of a single 
3474         // View at runtime.  Is there anything in the implmentation that would 
3477         // At least, you now have to cope with m_selection 
3478         wxFAIL_MSG( wxT("wxGrid::CreateGrid or wxGrid::SetTable called more than once") ); 
3483         m_numRows 
= table
->GetNumberRows(); 
3484         m_numCols 
= table
->GetNumberCols(); 
3487         m_table
->SetView( this ); 
3490         m_selection 
= new wxGridSelection( this, selmode 
); 
3501     m_rowLabelWidth  
= WXGRID_DEFAULT_ROW_LABEL_WIDTH
; 
3502     m_colLabelHeight 
= WXGRID_DEFAULT_COL_LABEL_HEIGHT
; 
3504     if ( m_rowLabelWin 
) 
3506         m_labelBackgroundColour 
= m_rowLabelWin
->GetBackgroundColour(); 
3510         m_labelBackgroundColour 
= wxColour( _T("WHITE") ); 
3513     m_labelTextColour 
= wxColour( _T("BLACK") ); 
3516     m_attrCache
.row 
= -1; 
3518     // TODO: something better than this ? 
3520     m_labelFont 
= this->GetFont(); 
3521     m_labelFont
.SetWeight( m_labelFont
.GetWeight() + 2 ); 
3523     m_rowLabelHorizAlign 
= wxALIGN_LEFT
; 
3524     m_rowLabelVertAlign  
= wxALIGN_CENTRE
; 
3526     m_colLabelHorizAlign 
= wxALIGN_CENTRE
; 
3527     m_colLabelVertAlign  
= wxALIGN_TOP
; 
3529     m_defaultColWidth  
= WXGRID_DEFAULT_COL_WIDTH
; 
3530     m_defaultRowHeight 
= m_gridWin
->GetCharHeight(); 
3532 #if defined(__WXMOTIF__) || defined(__WXGTK__)  // see also text ctrl sizing in ShowCellEditControl() 
3533     m_defaultRowHeight 
+= 8; 
3535     m_defaultRowHeight 
+= 4; 
3538     m_gridLineColour 
= wxColour( 128, 128, 255 ); 
3539     m_gridLinesEnabled 
= TRUE
; 
3540     m_cellHighlightColour 
= m_gridLineColour
; 
3542     m_cursorMode  
= WXGRID_CURSOR_SELECT_CELL
; 
3543     m_winCapture 
= (wxWindow 
*)NULL
; 
3544     m_canDragRowSize 
= TRUE
; 
3545     m_canDragColSize 
= TRUE
; 
3546     m_canDragGridSize 
= TRUE
; 
3548     m_dragRowOrCol 
= -1; 
3549     m_isDragging 
= FALSE
; 
3550     m_startDragPos 
= wxDefaultPosition
; 
3552     m_waitForSlowClick 
= FALSE
; 
3554     m_rowResizeCursor 
= wxCursor( wxCURSOR_SIZENS 
); 
3555     m_colResizeCursor 
= wxCursor( wxCURSOR_SIZEWE 
); 
3557     m_currentCellCoords 
= wxGridNoCellCoords
; 
3559     m_selectingTopLeft 
= wxGridNoCellCoords
; 
3560     m_selectingBottomRight 
= wxGridNoCellCoords
; 
3561     m_selectionBackground 
= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_HIGHLIGHT
); 
3562     m_selectionForeground 
= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_HIGHLIGHTTEXT
); 
3564     m_editable 
= TRUE
;  // default for whole grid 
3566     m_inOnKeyDown 
= FALSE
; 
3575 // ---------------------------------------------------------------------------- 
3576 // the idea is to call these functions only when necessary because they create 
3577 // quite big arrays which eat memory mostly unnecessary - in particular, if 
3578 // default widths/heights are used for all rows/columns, we may not use these 
3581 // with some extra code, it should be possible to only store the 
3582 // widths/heights different from default ones but this will be done later... 
3583 // ---------------------------------------------------------------------------- 
3585 void wxGrid::InitRowHeights() 
3587     m_rowHeights
.Empty(); 
3588     m_rowBottoms
.Empty(); 
3590     m_rowHeights
.Alloc( m_numRows 
); 
3591     m_rowBottoms
.Alloc( m_numRows 
); 
3594     for ( int i 
= 0;  i 
< m_numRows
;  i
++ ) 
3596         m_rowHeights
.Add( m_defaultRowHeight 
); 
3597         rowBottom 
+= m_defaultRowHeight
; 
3598         m_rowBottoms
.Add( rowBottom 
); 
3602 void wxGrid::InitColWidths() 
3604     m_colWidths
.Empty(); 
3605     m_colRights
.Empty(); 
3607     m_colWidths
.Alloc( m_numCols 
); 
3608     m_colRights
.Alloc( m_numCols 
); 
3610     for ( int i 
= 0;  i 
< m_numCols
;  i
++ ) 
3612         m_colWidths
.Add( m_defaultColWidth 
); 
3613         colRight 
+= m_defaultColWidth
; 
3614         m_colRights
.Add( colRight 
); 
3618 int wxGrid::GetColWidth(int col
) const 
3620     return m_colWidths
.IsEmpty() ? m_defaultColWidth 
: m_colWidths
[col
]; 
3623 int wxGrid::GetColLeft(int col
) const 
3625     return m_colRights
.IsEmpty() ? col 
* m_defaultColWidth
 
3626                                  : m_colRights
[col
] - m_colWidths
[col
]; 
3629 int wxGrid::GetColRight(int col
) const 
3631     return m_colRights
.IsEmpty() ? (col 
+ 1) * m_defaultColWidth
 
3635 int wxGrid::GetRowHeight(int row
) const 
3637     return m_rowHeights
.IsEmpty() ? m_defaultRowHeight 
: m_rowHeights
[row
]; 
3640 int wxGrid::GetRowTop(int row
) const 
3642     return m_rowBottoms
.IsEmpty() ? row 
* m_defaultRowHeight
 
3643                                   : m_rowBottoms
[row
] - m_rowHeights
[row
]; 
3646 int wxGrid::GetRowBottom(int row
) const 
3648     return m_rowBottoms
.IsEmpty() ? (row 
+ 1) * m_defaultRowHeight
 
3649                                   : m_rowBottoms
[row
]; 
3652 void wxGrid::CalcDimensions() 
3655     GetClientSize( &cw
, &ch 
); 
3657     if ( m_numRows 
> 0  ||  m_numCols 
> 0 ) 
3659         int right 
= m_numCols 
> 0 ? GetColRight( m_numCols
-1 ) + m_extraWidth 
: 0; 
3660         int bottom 
= m_numRows 
> 0 ? GetRowBottom( m_numRows
-1 ) + m_extraHeight 
: 0; 
3662         // TODO: restore the scroll position that we had before sizing 
3665         GetViewStart( &x
, &y 
); 
3666         SetScrollbars( GRID_SCROLL_LINE
, GRID_SCROLL_LINE
, 
3667                        right
/GRID_SCROLL_LINE
, bottom
/GRID_SCROLL_LINE
, 
3673 void wxGrid::CalcWindowSizes() 
3676     GetClientSize( &cw
, &ch 
); 
3678     if ( m_cornerLabelWin
->IsShown() ) 
3679         m_cornerLabelWin
->SetSize( 0, 0, m_rowLabelWidth
, m_colLabelHeight 
); 
3681     if ( m_colLabelWin
->IsShown() ) 
3682         m_colLabelWin
->SetSize( m_rowLabelWidth
, 0, cw
-m_rowLabelWidth
, m_colLabelHeight
); 
3684     if ( m_rowLabelWin
->IsShown() ) 
3685         m_rowLabelWin
->SetSize( 0, m_colLabelHeight
, m_rowLabelWidth
, ch
-m_colLabelHeight
); 
3687     if ( m_gridWin
->IsShown() ) 
3688         m_gridWin
->SetSize( m_rowLabelWidth
, m_colLabelHeight
, cw
-m_rowLabelWidth
, ch
-m_colLabelHeight
); 
3692 // this is called when the grid table sends a message to say that it 
3693 // has been redimensioned 
3695 bool wxGrid::Redimension( wxGridTableMessage
& msg 
) 
3698     bool result 
= FALSE
; 
3701     // if we were using the default widths/heights so far, we must change them 
3703     if ( m_colWidths
.IsEmpty() ) 
3708     if ( m_rowHeights
.IsEmpty() ) 
3714     switch ( msg
.GetId() ) 
3716         case wxGRIDTABLE_NOTIFY_ROWS_INSERTED
: 
3718             size_t pos 
= msg
.GetCommandInt(); 
3719             int numRows 
= msg
.GetCommandInt2(); 
3721             m_numRows 
+= numRows
; 
3723             if ( !m_rowHeights
.IsEmpty() ) 
3725                 for ( i 
= 0;  i 
< numRows
;  i
++ ) 
3727                     m_rowHeights
.Insert( m_defaultRowHeight
, pos 
); 
3728                     m_rowBottoms
.Insert( 0, pos 
); 
3732                 if ( pos 
> 0 ) bottom 
= m_rowBottoms
[pos
-1]; 
3734                 for ( i 
= pos
;  i 
< m_numRows
;  i
++ ) 
3736                     bottom 
+= m_rowHeights
[i
]; 
3737                     m_rowBottoms
[i
] = bottom
; 
3740             if ( m_currentCellCoords 
== wxGridNoCellCoords 
) 
3742                 // if we have just inserted cols into an empty grid the current 
3743                 // cell will be undefined... 
3745                 SetCurrentCell( 0, 0 ); 
3747             m_selection
->UpdateRows( pos
, numRows 
); 
3748             wxGridCellAttrProvider 
* attrProvider 
= m_table
->GetAttrProvider(); 
3750                 attrProvider
->UpdateAttrRows( pos
, numRows 
); 
3752             if ( !GetBatchCount() ) 
3755                 m_rowLabelWin
->Refresh(); 
3761         case wxGRIDTABLE_NOTIFY_ROWS_APPENDED
: 
3763             int numRows 
= msg
.GetCommandInt(); 
3764             int oldNumRows 
= m_numRows
; 
3765             m_numRows 
+= numRows
; 
3767             if ( !m_rowHeights
.IsEmpty() ) 
3769                 for ( i 
= 0;  i 
< numRows
;  i
++ ) 
3771                     m_rowHeights
.Add( m_defaultRowHeight 
); 
3772                     m_rowBottoms
.Add( 0 ); 
3776                 if ( oldNumRows 
> 0 ) bottom 
= m_rowBottoms
[oldNumRows
-1]; 
3778                 for ( i 
= oldNumRows
;  i 
< m_numRows
;  i
++ ) 
3780                     bottom 
+= m_rowHeights
[i
]; 
3781                     m_rowBottoms
[i
] = bottom
; 
3784             if ( m_currentCellCoords 
== wxGridNoCellCoords 
) 
3786                 // if we have just inserted cols into an empty grid the current 
3787                 // cell will be undefined... 
3789                 SetCurrentCell( 0, 0 ); 
3791             if ( !GetBatchCount() ) 
3794                 m_rowLabelWin
->Refresh(); 
3800         case wxGRIDTABLE_NOTIFY_ROWS_DELETED
: 
3802             size_t pos 
= msg
.GetCommandInt(); 
3803             int numRows 
= msg
.GetCommandInt2(); 
3804             m_numRows 
-= numRows
; 
3806             if ( !m_rowHeights
.IsEmpty() ) 
3808                 for ( i 
= 0;  i 
< numRows
;  i
++ ) 
3810                     m_rowHeights
.Remove( pos 
); 
3811                     m_rowBottoms
.Remove( pos 
); 
3815                 for ( i 
= 0;  i 
< m_numRows
;  i
++ ) 
3817                     h 
+= m_rowHeights
[i
]; 
3818                     m_rowBottoms
[i
] = h
; 
3823                 m_currentCellCoords 
= wxGridNoCellCoords
; 
3827                 if ( m_currentCellCoords
.GetRow() >= m_numRows 
) 
3828                     m_currentCellCoords
.Set( 0, 0 ); 
3830             m_selection
->UpdateRows( pos
, -((int)numRows
) ); 
3831             wxGridCellAttrProvider 
* attrProvider 
= m_table
->GetAttrProvider(); 
3833                 attrProvider
->UpdateAttrRows( pos
, -((int)numRows
) ); 
3834 // ifdef'd out following patch from Paul Gammans                 
3836                 // No need to touch column attributes, unless we 
3837                 // removed _all_ rows, in this case, we remove 
3838                 // all column attributes. 
3839                 // I hate to do this here, but the 
3840                 // needed data is not available inside UpdateAttrRows. 
3841                 if ( !GetNumberRows() ) 
3842                     attrProvider
->UpdateAttrCols( 0, -GetNumberCols() ); 
3845             if ( !GetBatchCount() ) 
3848                 m_rowLabelWin
->Refresh(); 
3854         case wxGRIDTABLE_NOTIFY_COLS_INSERTED
: 
3856             size_t pos 
= msg
.GetCommandInt(); 
3857             int numCols 
= msg
.GetCommandInt2(); 
3858             m_numCols 
+= numCols
; 
3860             if ( !m_colWidths
.IsEmpty() ) 
3862                 for ( i 
= 0;  i 
< numCols
;  i
++ ) 
3864                     m_colWidths
.Insert( m_defaultColWidth
, pos 
); 
3865                     m_colRights
.Insert( 0, pos 
); 
3869                 if ( pos 
> 0 ) right 
= m_colRights
[pos
-1]; 
3871                 for ( i 
= pos
;  i 
< m_numCols
;  i
++ ) 
3873                     right 
+= m_colWidths
[i
]; 
3874                     m_colRights
[i
] = right
; 
3877             if ( m_currentCellCoords 
== wxGridNoCellCoords 
) 
3879                 // if we have just inserted cols into an empty grid the current 
3880                 // cell will be undefined... 
3882                 SetCurrentCell( 0, 0 ); 
3884             m_selection
->UpdateCols( pos
, numCols 
); 
3885             wxGridCellAttrProvider 
* attrProvider 
= m_table
->GetAttrProvider(); 
3887                 attrProvider
->UpdateAttrCols( pos
, numCols 
); 
3888             if ( !GetBatchCount() ) 
3891                 m_colLabelWin
->Refresh(); 
3898         case wxGRIDTABLE_NOTIFY_COLS_APPENDED
: 
3900             int numCols 
= msg
.GetCommandInt(); 
3901             int oldNumCols 
= m_numCols
; 
3902             m_numCols 
+= numCols
; 
3903             if ( !m_colWidths
.IsEmpty() ) 
3905                 for ( i 
= 0;  i 
< numCols
;  i
++ ) 
3907                     m_colWidths
.Add( m_defaultColWidth 
); 
3908                     m_colRights
.Add( 0 ); 
3912                 if ( oldNumCols 
> 0 ) right 
= m_colRights
[oldNumCols
-1]; 
3914                 for ( i 
= oldNumCols
;  i 
< m_numCols
;  i
++ ) 
3916                     right 
+= m_colWidths
[i
]; 
3917                     m_colRights
[i
] = right
; 
3920             if ( m_currentCellCoords 
== wxGridNoCellCoords 
) 
3922                 // if we have just inserted cols into an empty grid the current 
3923                 // cell will be undefined... 
3925                 SetCurrentCell( 0, 0 ); 
3927             if ( !GetBatchCount() ) 
3930                 m_colLabelWin
->Refresh(); 
3936         case wxGRIDTABLE_NOTIFY_COLS_DELETED
: 
3938             size_t pos 
= msg
.GetCommandInt(); 
3939             int numCols 
= msg
.GetCommandInt2(); 
3940             m_numCols 
-= numCols
; 
3942             if ( !m_colWidths
.IsEmpty() ) 
3944                 for ( i 
= 0;  i 
< numCols
;  i
++ ) 
3946                     m_colWidths
.Remove( pos 
); 
3947                     m_colRights
.Remove( pos 
); 
3951                 for ( i 
= 0;  i 
< m_numCols
;  i
++ ) 
3953                     w 
+= m_colWidths
[i
]; 
3959                 m_currentCellCoords 
= wxGridNoCellCoords
; 
3963                 if ( m_currentCellCoords
.GetCol() >= m_numCols 
) 
3964                   m_currentCellCoords
.Set( 0, 0 ); 
3966             m_selection
->UpdateCols( pos
, -((int)numCols
) ); 
3967             wxGridCellAttrProvider 
* attrProvider 
= m_table
->GetAttrProvider(); 
3969                 attrProvider
->UpdateAttrCols( pos
, -((int)numCols
) ); 
3970 // ifdef'd out following patch from Paul Gammans                 
3972                 // No need to touch row attributes, unless we 
3973                 // removed _all_ columns, in this case, we remove 
3974                 // all row attributes. 
3975                 // I hate to do this here, but the 
3976                 // needed data is not available inside UpdateAttrCols. 
3977                 if ( !GetNumberCols() ) 
3978                     attrProvider
->UpdateAttrRows( 0, -GetNumberRows() ); 
3981             if ( !GetBatchCount() ) 
3984                 m_colLabelWin
->Refresh(); 
3989 // There is no path to this code !!!!!! 
3995     if (result 
&& !GetBatchCount() ) 
3996         m_gridWin
->Refresh(); 
4001 void wxGrid::CalcRowLabelsExposed( const wxRegion
& reg 
) 
4003     wxRegionIterator 
iter( reg 
); 
4006     m_rowLabelsExposed
.Empty(); 
4013         // TODO: remove this when we can... 
4014         // There is a bug in wxMotif that gives garbage update 
4015         // rectangles if you jump-scroll a long way by clicking the 
4016         // scrollbar with middle button.  This is a work-around 
4018 #if defined(__WXMOTIF__) 
4020         m_gridWin
->GetClientSize( &cw
, &ch 
); 
4021         if ( r
.GetTop() > ch 
) r
.SetTop( 0 ); 
4022         r
.SetBottom( wxMin( r
.GetBottom(), ch 
) ); 
4025         // logical bounds of update region 
4028         CalcUnscrolledPosition( 0, r
.GetTop(), &dummy
, &top 
); 
4029         CalcUnscrolledPosition( 0, r
.GetBottom(), &dummy
, &bottom 
); 
4031         // find the row labels within these bounds 
4034         for ( row 
= 0;  row 
< m_numRows
;  row
++ ) 
4036             if ( GetRowBottom(row
) < top 
) 
4039             if ( GetRowTop(row
) > bottom 
) 
4042             m_rowLabelsExposed
.Add( row 
); 
4050 void wxGrid::CalcColLabelsExposed( const wxRegion
& reg 
) 
4052     wxRegionIterator 
iter( reg 
); 
4055     m_colLabelsExposed
.Empty(); 
4062         // TODO: remove this when we can... 
4063         // There is a bug in wxMotif that gives garbage update 
4064         // rectangles if you jump-scroll a long way by clicking the 
4065         // scrollbar with middle button.  This is a work-around 
4067 #if defined(__WXMOTIF__) 
4069         m_gridWin
->GetClientSize( &cw
, &ch 
); 
4070         if ( r
.GetLeft() > cw 
) r
.SetLeft( 0 ); 
4071         r
.SetRight( wxMin( r
.GetRight(), cw 
) ); 
4074         // logical bounds of update region 
4077         CalcUnscrolledPosition( r
.GetLeft(), 0, &left
, &dummy 
); 
4078         CalcUnscrolledPosition( r
.GetRight(), 0, &right
, &dummy 
); 
4080         // find the cells within these bounds 
4083         for ( col 
= 0;  col 
< m_numCols
;  col
++ ) 
4085             if ( GetColRight(col
) < left 
) 
4088             if ( GetColLeft(col
) > right 
) 
4091             m_colLabelsExposed
.Add( col 
); 
4099 void wxGrid::CalcCellsExposed( const wxRegion
& reg 
) 
4101     wxRegionIterator 
iter( reg 
); 
4104     m_cellsExposed
.Empty(); 
4105     m_rowsExposed
.Empty(); 
4106     m_colsExposed
.Empty(); 
4108     int left
, top
, right
, bottom
; 
4113         // TODO: remove this when we can... 
4114         // There is a bug in wxMotif that gives garbage update 
4115         // rectangles if you jump-scroll a long way by clicking the 
4116         // scrollbar with middle button.  This is a work-around 
4118 #if defined(__WXMOTIF__) 
4120         m_gridWin
->GetClientSize( &cw
, &ch 
); 
4121         if ( r
.GetTop() > ch 
) r
.SetTop( 0 ); 
4122         if ( r
.GetLeft() > cw 
) r
.SetLeft( 0 ); 
4123         r
.SetRight( wxMin( r
.GetRight(), cw 
) ); 
4124         r
.SetBottom( wxMin( r
.GetBottom(), ch 
) ); 
4127         // logical bounds of update region 
4129         CalcUnscrolledPosition( r
.GetLeft(), r
.GetTop(), &left
, &top 
); 
4130         CalcUnscrolledPosition( r
.GetRight(), r
.GetBottom(), &right
, &bottom 
); 
4132         // find the cells within these bounds 
4135         for ( row 
= 0;  row 
< m_numRows
;  row
++ ) 
4137             if ( GetRowBottom(row
) <= top 
) 
4140             if ( GetRowTop(row
) > bottom 
) 
4143             m_rowsExposed
.Add( row 
); 
4145             for ( col 
= 0;  col 
< m_numCols
;  col
++ ) 
4147                 if ( GetColRight(col
) <= left 
) 
4150                 if ( GetColLeft(col
) > right 
) 
4153                 if ( m_colsExposed
.Index( col 
) == wxNOT_FOUND 
) 
4154                     m_colsExposed
.Add( col 
); 
4155                 m_cellsExposed
.Add( wxGridCellCoords( row
, col 
) ); 
4164 void wxGrid::ProcessRowLabelMouseEvent( wxMouseEvent
& event 
) 
4167     wxPoint 
pos( event
.GetPosition() ); 
4168     CalcUnscrolledPosition( pos
.x
, pos
.y
, &x
, &y 
); 
4170     if ( event
.Dragging() ) 
4172         m_isDragging 
= TRUE
; 
4174         if ( event
.LeftIsDown() ) 
4176             switch( m_cursorMode 
) 
4178                 case WXGRID_CURSOR_RESIZE_ROW
: 
4180                     int cw
, ch
, left
, dummy
; 
4181                     m_gridWin
->GetClientSize( &cw
, &ch 
); 
4182                     CalcUnscrolledPosition( 0, 0, &left
, &dummy 
); 
4184                     wxClientDC 
dc( m_gridWin 
); 
4187                                GetRowTop(m_dragRowOrCol
) + 
4188                                GetRowMinimalHeight(m_dragRowOrCol
) ); 
4189                     dc
.SetLogicalFunction(wxINVERT
); 
4190                     if ( m_dragLastPos 
>= 0 ) 
4192                         dc
.DrawLine( left
, m_dragLastPos
, left
+cw
, m_dragLastPos 
); 
4194                     dc
.DrawLine( left
, y
, left
+cw
, y 
); 
4199                 case WXGRID_CURSOR_SELECT_ROW
: 
4200                     if ( (row 
= YToRow( y 
)) >= 0 ) 
4202                         m_selection
->SelectRow( row
, 
4203                                                 event
.ControlDown(), 
4209                 // default label to suppress warnings about "enumeration value 
4210                 // 'xxx' not handled in switch 
4218     m_isDragging 
= FALSE
; 
4221     // ------------ Entering or leaving the window 
4223     if ( event
.Entering() || event
.Leaving() ) 
4225         ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
, m_rowLabelWin
); 
4229     // ------------ Left button pressed 
4231     else if ( event
.LeftDown() ) 
4233         // don't send a label click event for a hit on the 
4234         // edge of the row label - this is probably the user 
4235         // wanting to resize the row 
4237         if ( YToEdgeOfRow(y
) < 0 ) 
4241                  !SendEvent( wxEVT_GRID_LABEL_LEFT_CLICK
, row
, -1, event 
) ) 
4243                 if ( !event
.ShiftDown() && !event
.ControlDown() ) 
4245                 if ( event
.ShiftDown() ) 
4246                     m_selection
->SelectBlock( m_currentCellCoords
.GetRow(), 
4249                                               GetNumberCols() - 1, 
4250                                               event
.ControlDown(), 
4255                     m_selection
->SelectRow( row
, 
4256                                             event
.ControlDown(), 
4260                 ChangeCursorMode(WXGRID_CURSOR_SELECT_ROW
, m_rowLabelWin
); 
4265             // starting to drag-resize a row 
4267             if ( CanDragRowSize() ) 
4268                 ChangeCursorMode(WXGRID_CURSOR_RESIZE_ROW
, m_rowLabelWin
); 
4273     // ------------ Left double click 
4275     else if (event
.LeftDClick() ) 
4277         if ( YToEdgeOfRow(y
) < 0 ) 
4280             SendEvent( wxEVT_GRID_LABEL_LEFT_DCLICK
, row
, -1, event 
); 
4285     // ------------ Left button released 
4287     else if ( event
.LeftUp() ) 
4289         if ( m_cursorMode 
== WXGRID_CURSOR_RESIZE_ROW 
) 
4291             DoEndDragResizeRow(); 
4293             // Note: we are ending the event *after* doing 
4294             // default processing in this case 
4296             SendEvent( wxEVT_GRID_ROW_SIZE
, m_dragRowOrCol
, -1, event 
); 
4299         ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
, m_rowLabelWin
); 
4304     // ------------ Right button down 
4306     else if ( event
.RightDown() ) 
4309         if ( !SendEvent( wxEVT_GRID_LABEL_RIGHT_CLICK
, row
, -1, event 
) ) 
4311             // no default action at the moment 
4316     // ------------ Right double click 
4318     else if ( event
.RightDClick() ) 
4321         if ( !SendEvent( wxEVT_GRID_LABEL_RIGHT_DCLICK
, row
, -1, event 
) ) 
4323             // no default action at the moment 
4328     // ------------ No buttons down and mouse moving 
4330     else if ( event
.Moving() ) 
4332         m_dragRowOrCol 
= YToEdgeOfRow( y 
); 
4333         if ( m_dragRowOrCol 
>= 0 ) 
4335             if ( m_cursorMode 
== WXGRID_CURSOR_SELECT_CELL 
) 
4337                 // don't capture the mouse yet 
4338                 if ( CanDragRowSize() ) 
4339                     ChangeCursorMode(WXGRID_CURSOR_RESIZE_ROW
, m_rowLabelWin
, FALSE
); 
4342         else if ( m_cursorMode 
!= WXGRID_CURSOR_SELECT_CELL 
) 
4344             ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
, m_rowLabelWin
, FALSE
); 
4350 void wxGrid::ProcessColLabelMouseEvent( wxMouseEvent
& event 
) 
4353     wxPoint 
pos( event
.GetPosition() ); 
4354     CalcUnscrolledPosition( pos
.x
, pos
.y
, &x
, &y 
); 
4356     if ( event
.Dragging() ) 
4358         m_isDragging 
= TRUE
; 
4360         if ( event
.LeftIsDown() ) 
4362             switch( m_cursorMode 
) 
4364                 case WXGRID_CURSOR_RESIZE_COL
: 
4366                     int cw
, ch
, dummy
, top
; 
4367                     m_gridWin
->GetClientSize( &cw
, &ch 
); 
4368                     CalcUnscrolledPosition( 0, 0, &dummy
, &top 
); 
4370                     wxClientDC 
dc( m_gridWin 
); 
4373                     x 
= wxMax( x
, GetColLeft(m_dragRowOrCol
) + 
4374                                   GetColMinimalWidth(m_dragRowOrCol
)); 
4375                     dc
.SetLogicalFunction(wxINVERT
); 
4376                     if ( m_dragLastPos 
>= 0 ) 
4378                         dc
.DrawLine( m_dragLastPos
, top
, m_dragLastPos
, top
+ch 
); 
4380                     dc
.DrawLine( x
, top
, x
, top
+ch 
); 
4385                 case WXGRID_CURSOR_SELECT_COL
: 
4386                     if ( (col 
= XToCol( x 
)) >= 0 ) 
4388                         m_selection
->SelectCol( col
, 
4389                                                 event
.ControlDown(), 
4395                 // default label to suppress warnings about "enumeration value 
4396                 // 'xxx' not handled in switch 
4404     m_isDragging 
= FALSE
; 
4407     // ------------ Entering or leaving the window 
4409     if ( event
.Entering() || event
.Leaving() ) 
4411         ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
, m_colLabelWin
); 
4415     // ------------ Left button pressed 
4417     else if ( event
.LeftDown() ) 
4419         // don't send a label click event for a hit on the 
4420         // edge of the col label - this is probably the user 
4421         // wanting to resize the col 
4423         if ( XToEdgeOfCol(x
) < 0 ) 
4427                  !SendEvent( wxEVT_GRID_LABEL_LEFT_CLICK
, -1, col
, event 
) ) 
4429                 if ( !event
.ShiftDown() && !event
.ControlDown() ) 
4431                 if ( event
.ShiftDown() ) 
4432                     m_selection
->SelectBlock( 0, 
4433                                               m_currentCellCoords
.GetCol(), 
4434                                               GetNumberRows() - 1, col
, 
4435                                               event
.ControlDown(), 
4440                     m_selection
->SelectCol( col
, 
4441                                             event
.ControlDown(), 
4445                 ChangeCursorMode(WXGRID_CURSOR_SELECT_COL
, m_colLabelWin
); 
4450             // starting to drag-resize a col 
4452             if ( CanDragColSize() ) 
4453                 ChangeCursorMode(WXGRID_CURSOR_RESIZE_COL
, m_colLabelWin
); 
4458     // ------------ Left double click 
4460     if ( event
.LeftDClick() ) 
4462         if ( XToEdgeOfCol(x
) < 0 ) 
4465             SendEvent( wxEVT_GRID_LABEL_LEFT_DCLICK
, -1, col
, event 
); 
4470     // ------------ Left button released 
4472     else if ( event
.LeftUp() ) 
4474         if ( m_cursorMode 
== WXGRID_CURSOR_RESIZE_COL 
) 
4476             DoEndDragResizeCol(); 
4478             // Note: we are ending the event *after* doing 
4479             // default processing in this case 
4481             SendEvent( wxEVT_GRID_COL_SIZE
, -1, m_dragRowOrCol
, event 
); 
4484         ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
, m_colLabelWin
); 
4489     // ------------ Right button down 
4491     else if ( event
.RightDown() ) 
4494         if ( !SendEvent( wxEVT_GRID_LABEL_RIGHT_CLICK
, -1, col
, event 
) ) 
4496             // no default action at the moment 
4501     // ------------ Right double click 
4503     else if ( event
.RightDClick() ) 
4506         if ( !SendEvent( wxEVT_GRID_LABEL_RIGHT_DCLICK
, -1, col
, event 
) ) 
4508             // no default action at the moment 
4513     // ------------ No buttons down and mouse moving 
4515     else if ( event
.Moving() ) 
4517         m_dragRowOrCol 
= XToEdgeOfCol( x 
); 
4518         if ( m_dragRowOrCol 
>= 0 ) 
4520             if ( m_cursorMode 
== WXGRID_CURSOR_SELECT_CELL 
) 
4522                 // don't capture the cursor yet 
4523                 if ( CanDragColSize() ) 
4524                     ChangeCursorMode(WXGRID_CURSOR_RESIZE_COL
, m_colLabelWin
, FALSE
); 
4527         else if ( m_cursorMode 
!= WXGRID_CURSOR_SELECT_CELL 
) 
4529             ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
, m_colLabelWin
, FALSE
); 
4535 void wxGrid::ProcessCornerLabelMouseEvent( wxMouseEvent
& event 
) 
4537     if ( event
.LeftDown() ) 
4539         // indicate corner label by having both row and 
4542         if ( !SendEvent( wxEVT_GRID_LABEL_LEFT_CLICK
, -1, -1, event 
) ) 
4548     else if ( event
.LeftDClick() ) 
4550         SendEvent( wxEVT_GRID_LABEL_LEFT_DCLICK
, -1, -1, event 
); 
4553     else if ( event
.RightDown() ) 
4555         if ( !SendEvent( wxEVT_GRID_LABEL_RIGHT_CLICK
, -1, -1, event 
) ) 
4557             // no default action at the moment 
4561     else if ( event
.RightDClick() ) 
4563         if ( !SendEvent( wxEVT_GRID_LABEL_RIGHT_DCLICK
, -1, -1, event 
) ) 
4565             // no default action at the moment 
4570 void wxGrid::ChangeCursorMode(CursorMode mode
, 
4575     static const wxChar 
*cursorModes
[] = 
4584     wxLogTrace(_T("grid"), 
4585                _T("wxGrid cursor mode (mouse capture for %s): %s -> %s"), 
4586                win 
== m_colLabelWin 
? _T("colLabelWin") 
4587                                     : win 
? _T("rowLabelWin") 
4589                cursorModes
[m_cursorMode
], cursorModes
[mode
]); 
4590 #endif // __WXDEBUG__ 
4592     if ( mode 
== m_cursorMode 
) 
4597         // by default use the grid itself 
4603         m_winCapture
->ReleaseMouse(); 
4604         m_winCapture 
= (wxWindow 
*)NULL
; 
4607     m_cursorMode 
= mode
; 
4609     switch ( m_cursorMode 
) 
4611         case WXGRID_CURSOR_RESIZE_ROW
: 
4612             win
->SetCursor( m_rowResizeCursor 
); 
4615         case WXGRID_CURSOR_RESIZE_COL
: 
4616             win
->SetCursor( m_colResizeCursor 
); 
4620             win
->SetCursor( *wxSTANDARD_CURSOR 
); 
4623     // we need to capture mouse when resizing 
4624     bool resize 
= m_cursorMode 
== WXGRID_CURSOR_RESIZE_ROW 
|| 
4625                   m_cursorMode 
== WXGRID_CURSOR_RESIZE_COL
; 
4627     if ( captureMouse 
&& resize 
) 
4629         win
->CaptureMouse(); 
4634 void wxGrid::ProcessGridCellMouseEvent( wxMouseEvent
& event 
) 
4637     wxPoint 
pos( event
.GetPosition() ); 
4638     CalcUnscrolledPosition( pos
.x
, pos
.y
, &x
, &y 
); 
4640     wxGridCellCoords coords
; 
4641     XYToCell( x
, y
, coords 
); 
4643     if ( event
.Dragging() ) 
4645         //wxLogDebug("pos(%d, %d) coords(%d, %d)", pos.x, pos.y, coords.GetRow(), coords.GetCol()); 
4647         // Don't start doing anything until the mouse has been drug at 
4648         // least 3 pixels in any direction... 
4651             if (m_startDragPos 
== wxDefaultPosition
) 
4653                 m_startDragPos 
= pos
; 
4656             if (abs(m_startDragPos
.x 
- pos
.x
) < 4 && abs(m_startDragPos
.y 
- pos
.y
) < 4) 
4660         m_isDragging 
= TRUE
; 
4661         if ( m_cursorMode 
== WXGRID_CURSOR_SELECT_CELL 
) 
4663             // Hide the edit control, so it 
4664             // won't interfer with drag-shrinking. 
4665             if ( IsCellEditControlShown() ) 
4667                 HideCellEditControl(); 
4668                 SaveEditControlValue(); 
4671             // Have we captured the mouse yet? 
4674                 m_winCapture 
= m_gridWin
; 
4675                 m_winCapture
->CaptureMouse(); 
4678             if ( coords 
!= wxGridNoCellCoords 
) 
4680                 if ( event
.ControlDown() ) 
4682                     if ( m_selectingKeyboard 
== wxGridNoCellCoords
) 
4683                         m_selectingKeyboard 
= coords
; 
4684                     HighlightBlock ( m_selectingKeyboard
, coords 
); 
4688                     if ( !IsSelection() ) 
4690                         HighlightBlock( coords
, coords 
); 
4694                         HighlightBlock( m_currentCellCoords
, coords 
); 
4698                 if (! IsVisible(coords
)) 
4700                     MakeCellVisible(coords
); 
4701                     // TODO: need to introduce a delay or something here.  The 
4702                     // scrolling is way to fast, at least on MSW - also on GTK. 
4706         else if ( m_cursorMode 
== WXGRID_CURSOR_RESIZE_ROW 
) 
4708             int cw
, ch
, left
, dummy
; 
4709             m_gridWin
->GetClientSize( &cw
, &ch 
); 
4710             CalcUnscrolledPosition( 0, 0, &left
, &dummy 
); 
4712             wxClientDC 
dc( m_gridWin 
); 
4714             y 
= wxMax( y
, GetRowTop(m_dragRowOrCol
) + 
4715                           GetRowMinimalHeight(m_dragRowOrCol
) ); 
4716             dc
.SetLogicalFunction(wxINVERT
); 
4717             if ( m_dragLastPos 
>= 0 ) 
4719                 dc
.DrawLine( left
, m_dragLastPos
, left
+cw
, m_dragLastPos 
); 
4721             dc
.DrawLine( left
, y
, left
+cw
, y 
); 
4724         else if ( m_cursorMode 
== WXGRID_CURSOR_RESIZE_COL 
) 
4726             int cw
, ch
, dummy
, top
; 
4727             m_gridWin
->GetClientSize( &cw
, &ch 
); 
4728             CalcUnscrolledPosition( 0, 0, &dummy
, &top 
); 
4730             wxClientDC 
dc( m_gridWin 
); 
4732             x 
= wxMax( x
, GetColLeft(m_dragRowOrCol
) + 
4733                           GetColMinimalWidth(m_dragRowOrCol
) ); 
4734             dc
.SetLogicalFunction(wxINVERT
); 
4735             if ( m_dragLastPos 
>= 0 ) 
4737                 dc
.DrawLine( m_dragLastPos
, top
, m_dragLastPos
, top
+ch 
); 
4739             dc
.DrawLine( x
, top
, x
, top
+ch 
); 
4746     m_isDragging 
= FALSE
; 
4747     m_startDragPos 
= wxDefaultPosition
; 
4749     // VZ: if we do this, the mode is reset to WXGRID_CURSOR_SELECT_CELL 
4750     //     immediately after it becomes WXGRID_CURSOR_RESIZE_ROW/COL under 
4753     if ( event
.Entering() || event
.Leaving() ) 
4755         ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
); 
4756         m_gridWin
->SetCursor( *wxSTANDARD_CURSOR 
); 
4761     // ------------ Left button pressed 
4763     if ( event
.LeftDown() && coords 
!= wxGridNoCellCoords 
) 
4765         if ( !SendEvent( wxEVT_GRID_CELL_LEFT_CLICK
, 
4770             if ( !event
.ControlDown() ) 
4772             if ( event
.ShiftDown() ) 
4774                 m_selection
->SelectBlock( m_currentCellCoords
.GetRow(), 
4775                                           m_currentCellCoords
.GetCol(), 
4778                                           event
.ControlDown(), 
4783             else if ( XToEdgeOfCol(x
) < 0  && 
4784                       YToEdgeOfRow(y
) < 0 ) 
4786                 DisableCellEditControl(); 
4787                 MakeCellVisible( coords 
); 
4789                 // if this is the second click on this cell then start 
4791                 if ( m_waitForSlowClick 
&& 
4792                      (coords 
== m_currentCellCoords
) && 
4793                      CanEnableCellControl()) 
4795                     EnableCellEditControl(); 
4797                     wxGridCellAttr
* attr 
= GetCellAttr(m_currentCellCoords
); 
4798                     wxGridCellEditor 
*editor 
= attr
->GetEditor(this, 
4801                     editor
->StartingClick(); 
4805                     m_waitForSlowClick 
= FALSE
; 
4809                     if ( event
.ControlDown() ) 
4811                         m_selection
->ToggleCellSelection( coords
.GetRow(), 
4813                                                           event
.ControlDown(), 
4817                         m_selectingTopLeft 
= wxGridNoCellCoords
; 
4818                         m_selectingBottomRight 
= wxGridNoCellCoords
; 
4819                         m_selectingKeyboard 
= coords
; 
4823                         SetCurrentCell( coords 
); 
4824                         if ( m_selection
->GetSelectionMode() 
4825                              != wxGrid::wxGridSelectCells
) 
4826                             HighlightBlock( coords
, coords 
); 
4828                     m_waitForSlowClick 
= TRUE
; 
4835     // ------------ Left double click 
4837     else if ( event
.LeftDClick() && coords 
!= wxGridNoCellCoords 
) 
4839         DisableCellEditControl(); 
4841         if ( XToEdgeOfCol(x
) < 0  &&  YToEdgeOfRow(y
) < 0 ) 
4843             SendEvent( wxEVT_GRID_CELL_LEFT_DCLICK
, 
4851     // ------------ Left button released 
4853     else if ( event
.LeftUp() ) 
4855         if ( m_cursorMode 
== WXGRID_CURSOR_SELECT_CELL 
) 
4857             if ( m_selectingTopLeft 
!= wxGridNoCellCoords 
&& 
4858                  m_selectingBottomRight 
!= wxGridNoCellCoords 
) 
4862                     m_winCapture
->ReleaseMouse(); 
4863                     m_winCapture 
= NULL
; 
4865                 m_selection
->SelectBlock( m_selectingTopLeft
.GetRow(), 
4866                                           m_selectingTopLeft
.GetCol(), 
4867                                           m_selectingBottomRight
.GetRow(), 
4868                                           m_selectingBottomRight
.GetCol(), 
4869                                           event
.ControlDown(), 
4873                 m_selectingTopLeft 
= wxGridNoCellCoords
; 
4874                 m_selectingBottomRight 
= wxGridNoCellCoords
; 
4877             // Show the edit control, if it has been hidden for 
4879             ShowCellEditControl(); 
4881         else if ( m_cursorMode 
== WXGRID_CURSOR_RESIZE_ROW 
) 
4883             ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
); 
4884             DoEndDragResizeRow(); 
4886             // Note: we are ending the event *after* doing 
4887             // default processing in this case 
4889             SendEvent( wxEVT_GRID_ROW_SIZE
, m_dragRowOrCol
, -1, event 
); 
4891         else if ( m_cursorMode 
== WXGRID_CURSOR_RESIZE_COL 
) 
4893             ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
); 
4894             DoEndDragResizeCol(); 
4896             // Note: we are ending the event *after* doing 
4897             // default processing in this case 
4899             SendEvent( wxEVT_GRID_COL_SIZE
, -1, m_dragRowOrCol
, event 
); 
4906     // ------------ Right button down 
4908     else if ( event
.RightDown() && coords 
!= wxGridNoCellCoords 
) 
4910         DisableCellEditControl(); 
4911         if ( !SendEvent( wxEVT_GRID_CELL_RIGHT_CLICK
, 
4916             // no default action at the moment 
4921     // ------------ Right double click 
4923     else if ( event
.RightDClick() && coords 
!= wxGridNoCellCoords 
) 
4925         DisableCellEditControl(); 
4926         if ( !SendEvent( wxEVT_GRID_CELL_RIGHT_DCLICK
, 
4931             // no default action at the moment 
4935     // ------------ Moving and no button action 
4937     else if ( event
.Moving() && !event
.IsButton() ) 
4939         int dragRow 
= YToEdgeOfRow( y 
); 
4940         int dragCol 
= XToEdgeOfCol( x 
); 
4942         // Dragging on the corner of a cell to resize in both 
4943         // directions is not implemented yet... 
4945         if ( dragRow 
>= 0  &&  dragCol 
>= 0 ) 
4947             ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
); 
4953             m_dragRowOrCol 
= dragRow
; 
4955             if ( m_cursorMode 
== WXGRID_CURSOR_SELECT_CELL 
) 
4957                 if ( CanDragRowSize() && CanDragGridSize() ) 
4958                     ChangeCursorMode(WXGRID_CURSOR_RESIZE_ROW
); 
4963                 m_dragRowOrCol 
= dragCol
; 
4971             m_dragRowOrCol 
= dragCol
; 
4973             if ( m_cursorMode 
== WXGRID_CURSOR_SELECT_CELL 
) 
4975                 if ( CanDragColSize() && CanDragGridSize() ) 
4976                     ChangeCursorMode(WXGRID_CURSOR_RESIZE_COL
); 
4982         // Neither on a row or col edge 
4984         if ( m_cursorMode 
!= WXGRID_CURSOR_SELECT_CELL 
) 
4986             ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
); 
4992 void wxGrid::DoEndDragResizeRow() 
4994     if ( m_dragLastPos 
>= 0 ) 
4996         // erase the last line and resize the row 
4998         int cw
, ch
, left
, dummy
; 
4999         m_gridWin
->GetClientSize( &cw
, &ch 
); 
5000         CalcUnscrolledPosition( 0, 0, &left
, &dummy 
); 
5002         wxClientDC 
dc( m_gridWin 
); 
5004         dc
.SetLogicalFunction( wxINVERT 
); 
5005         dc
.DrawLine( left
, m_dragLastPos
, left
+cw
, m_dragLastPos 
); 
5006         HideCellEditControl(); 
5007         SaveEditControlValue(); 
5009         int rowTop 
= GetRowTop(m_dragRowOrCol
); 
5010         SetRowSize( m_dragRowOrCol
, 
5011                     wxMax( m_dragLastPos 
- rowTop
, WXGRID_MIN_ROW_HEIGHT 
) ); 
5013         if ( !GetBatchCount() ) 
5015             // Only needed to get the correct rect.y: 
5016             wxRect 
rect ( CellToRect( m_dragRowOrCol
, 0 ) ); 
5018             CalcScrolledPosition(0, rect
.y
, &dummy
, &rect
.y
); 
5019             rect
.width 
= m_rowLabelWidth
; 
5020             rect
.height 
= ch 
- rect
.y
; 
5021             m_rowLabelWin
->Refresh( TRUE
, &rect 
); 
5023             m_gridWin
->Refresh( FALSE
, &rect 
); 
5026         ShowCellEditControl(); 
5031 void wxGrid::DoEndDragResizeCol() 
5033     if ( m_dragLastPos 
>= 0 ) 
5035         // erase the last line and resize the col 
5037         int cw
, ch
, dummy
, top
; 
5038         m_gridWin
->GetClientSize( &cw
, &ch 
); 
5039         CalcUnscrolledPosition( 0, 0, &dummy
, &top 
); 
5041         wxClientDC 
dc( m_gridWin 
); 
5043         dc
.SetLogicalFunction( wxINVERT 
); 
5044         dc
.DrawLine( m_dragLastPos
, top
, m_dragLastPos
, top
+ch 
); 
5045         HideCellEditControl(); 
5046         SaveEditControlValue(); 
5048         int colLeft 
= GetColLeft(m_dragRowOrCol
); 
5049         SetColSize( m_dragRowOrCol
, 
5050                     wxMax( m_dragLastPos 
- colLeft
, 
5051                            GetColMinimalWidth(m_dragRowOrCol
) ) ); 
5053         if ( !GetBatchCount() ) 
5055             // Only needed to get the correct rect.x: 
5056             wxRect 
rect ( CellToRect( 0, m_dragRowOrCol 
) ); 
5058             CalcScrolledPosition(rect
.x
, 0, &rect
.x
, &dummy
); 
5059             rect
.width 
= cw 
- rect
.x
; 
5060             rect
.height 
= m_colLabelHeight
; 
5061             m_colLabelWin
->Refresh( TRUE
, &rect 
); 
5063             m_gridWin
->Refresh( FALSE
, &rect 
); 
5066         ShowCellEditControl(); 
5073 // ------ interaction with data model 
5075 bool wxGrid::ProcessTableMessage( wxGridTableMessage
& msg 
) 
5077     switch ( msg
.GetId() ) 
5079         case wxGRIDTABLE_REQUEST_VIEW_GET_VALUES
: 
5080             return GetModelValues(); 
5082         case wxGRIDTABLE_REQUEST_VIEW_SEND_VALUES
: 
5083             return SetModelValues(); 
5085         case wxGRIDTABLE_NOTIFY_ROWS_INSERTED
: 
5086         case wxGRIDTABLE_NOTIFY_ROWS_APPENDED
: 
5087         case wxGRIDTABLE_NOTIFY_ROWS_DELETED
: 
5088         case wxGRIDTABLE_NOTIFY_COLS_INSERTED
: 
5089         case wxGRIDTABLE_NOTIFY_COLS_APPENDED
: 
5090         case wxGRIDTABLE_NOTIFY_COLS_DELETED
: 
5091             return Redimension( msg 
); 
5100 // The behaviour of this function depends on the grid table class 
5101 // Clear() function.  For the default wxGridStringTable class the 
5102 // behavious is to replace all cell contents with wxEmptyString but 
5103 // not to change the number of rows or cols. 
5105 void wxGrid::ClearGrid() 
5109         if (IsCellEditControlEnabled()) 
5110             DisableCellEditControl(); 
5113         if ( !GetBatchCount() ) m_gridWin
->Refresh(); 
5118 bool wxGrid::InsertRows( int pos
, int numRows
, bool WXUNUSED(updateLabels
) ) 
5120     // TODO: something with updateLabels flag 
5124         wxFAIL_MSG( wxT("Called wxGrid::InsertRows() before calling CreateGrid()") ); 
5130         if (IsCellEditControlEnabled()) 
5131             DisableCellEditControl(); 
5133         return m_table
->InsertRows( pos
, numRows 
); 
5135         // the table will have sent the results of the insert row 
5136         // operation to this view object as a grid table message 
5142 bool wxGrid::AppendRows( int numRows
, bool WXUNUSED(updateLabels
) ) 
5144     // TODO: something with updateLabels flag 
5148         wxFAIL_MSG( wxT("Called wxGrid::AppendRows() before calling CreateGrid()") ); 
5152     return ( m_table 
&& m_table
->AppendRows( numRows 
) ); 
5153     // the table will have sent the results of the append row 
5154     // operation to this view object as a grid table message 
5158 bool wxGrid::DeleteRows( int pos
, int numRows
, bool WXUNUSED(updateLabels
) ) 
5160     // TODO: something with updateLabels flag 
5164         wxFAIL_MSG( wxT("Called wxGrid::DeleteRows() before calling CreateGrid()") ); 
5170         if (IsCellEditControlEnabled()) 
5171             DisableCellEditControl(); 
5173         return (m_table
->DeleteRows( pos
, numRows 
)); 
5174         // the table will have sent the results of the delete row 
5175         // operation to this view object as a grid table message 
5181 bool wxGrid::InsertCols( int pos
, int numCols
, bool WXUNUSED(updateLabels
) ) 
5183     // TODO: something with updateLabels flag 
5187         wxFAIL_MSG( wxT("Called wxGrid::InsertCols() before calling CreateGrid()") ); 
5193         if (IsCellEditControlEnabled()) 
5194             DisableCellEditControl(); 
5196         return m_table
->InsertCols( pos
, numCols 
); 
5197         // the table will have sent the results of the insert col 
5198         // operation to this view object as a grid table message 
5204 bool wxGrid::AppendCols( int numCols
, bool WXUNUSED(updateLabels
) ) 
5206     // TODO: something with updateLabels flag 
5210         wxFAIL_MSG( wxT("Called wxGrid::AppendCols() before calling CreateGrid()") ); 
5214     return ( m_table 
&& m_table
->AppendCols( numCols 
) ); 
5215     // the table will have sent the results of the append col 
5216     // operation to this view object as a grid table message 
5220 bool wxGrid::DeleteCols( int pos
, int numCols
, bool WXUNUSED(updateLabels
) ) 
5222     // TODO: something with updateLabels flag 
5226         wxFAIL_MSG( wxT("Called wxGrid::DeleteCols() before calling CreateGrid()") ); 
5232         if (IsCellEditControlEnabled()) 
5233             DisableCellEditControl(); 
5235         return ( m_table
->DeleteCols( pos
, numCols 
) ); 
5236         // the table will have sent the results of the delete col 
5237         // operation to this view object as a grid table message 
5245 // ----- event handlers 
5248 // Generate a grid event based on a mouse event and 
5249 // return the result of ProcessEvent() 
5251 bool wxGrid::SendEvent( const wxEventType type
, 
5253                         wxMouseEvent
& mouseEv 
) 
5255     if ( type 
== wxEVT_GRID_ROW_SIZE 
|| type 
== wxEVT_GRID_COL_SIZE 
) 
5257         int rowOrCol 
= (row 
== -1 ? col 
: row
); 
5259         wxGridSizeEvent 
gridEvt( GetId(), 
5263                                  mouseEv
.GetX() + GetColLabelSize(), 
5264                                  mouseEv
.GetY() + GetRowLabelSize(), 
5265                                  mouseEv
.ControlDown(), 
5266                                  mouseEv
.ShiftDown(), 
5268                                  mouseEv
.MetaDown() ); 
5270         return GetEventHandler()->ProcessEvent(gridEvt
); 
5272     else if ( type 
== wxEVT_GRID_RANGE_SELECT 
) 
5274         // Right now, it should _never_ end up here! 
5275         wxGridRangeSelectEvent 
gridEvt( GetId(), 
5279                                         m_selectingBottomRight
, 
5281                                         mouseEv
.ControlDown(), 
5282                                         mouseEv
.ShiftDown(), 
5284                                         mouseEv
.MetaDown() ); 
5286         return GetEventHandler()->ProcessEvent(gridEvt
); 
5290         wxGridEvent 
gridEvt( GetId(), 
5294                              mouseEv
.GetX() + GetColLabelSize(), 
5295                              mouseEv
.GetY() + GetRowLabelSize(), 
5297                              mouseEv
.ControlDown(), 
5298                              mouseEv
.ShiftDown(), 
5300                              mouseEv
.MetaDown() ); 
5302         return GetEventHandler()->ProcessEvent(gridEvt
); 
5307 // Generate a grid event of specified type and return the result 
5308 // of ProcessEvent(). 
5310 bool wxGrid::SendEvent( const wxEventType type
, 
5313     if ( type 
== wxEVT_GRID_ROW_SIZE 
|| type 
== wxEVT_GRID_COL_SIZE 
) 
5315         int rowOrCol 
= (row 
== -1 ? col 
: row
); 
5317         wxGridSizeEvent 
gridEvt( GetId(), 
5322         return GetEventHandler()->ProcessEvent(gridEvt
); 
5326         wxGridEvent 
gridEvt( GetId(), 
5331         return GetEventHandler()->ProcessEvent(gridEvt
); 
5336 void wxGrid::OnPaint( wxPaintEvent
& WXUNUSED(event
) ) 
5338     wxPaintDC 
dc(this);  // needed to prevent zillions of paint events on MSW 
5342 // This is just here to make sure that CalcDimensions gets called when 
5343 // the grid view is resized... then the size event is skipped to allow 
5344 // the box sizers to handle everything 
5346 void wxGrid::OnSize( wxSizeEvent
& WXUNUSED(event
) ) 
5353 void wxGrid::OnKeyDown( wxKeyEvent
& event 
) 
5355     if ( m_inOnKeyDown 
) 
5357         // shouldn't be here - we are going round in circles... 
5359         wxFAIL_MSG( wxT("wxGrid::OnKeyDown called while already active") ); 
5362     m_inOnKeyDown 
= TRUE
; 
5364     // propagate the event up and see if it gets processed 
5366     wxWindow 
*parent 
= GetParent(); 
5367     wxKeyEvent 
keyEvt( event 
); 
5368     keyEvt
.SetEventObject( parent 
); 
5370     if ( !parent
->GetEventHandler()->ProcessEvent( keyEvt 
) ) 
5373         // try local handlers 
5375         switch ( event
.KeyCode() ) 
5378                 if ( event
.ControlDown() ) 
5380                     MoveCursorUpBlock( event
.ShiftDown() ); 
5384                     MoveCursorUp( event
.ShiftDown() ); 
5389                 if ( event
.ControlDown() ) 
5391                     MoveCursorDownBlock( event
.ShiftDown() ); 
5395                     MoveCursorDown( event
.ShiftDown() ); 
5400                 if ( event
.ControlDown() ) 
5402                     MoveCursorLeftBlock( event
.ShiftDown() ); 
5406                     MoveCursorLeft( event
.ShiftDown() ); 
5411                 if ( event
.ControlDown() ) 
5413                     MoveCursorRightBlock( event
.ShiftDown() ); 
5417                     MoveCursorRight( event
.ShiftDown() ); 
5422                 if ( event
.ControlDown() ) 
5424                     event
.Skip();  // to let the edit control have the return 
5428                     if ( GetGridCursorRow() < GetNumberRows()-1 ) 
5430                         MoveCursorDown( event
.ShiftDown() ); 
5434                         // at the bottom of a column 
5435                         HideCellEditControl(); 
5436                         SaveEditControlValue(); 
5446                 if (event
.ShiftDown()) 
5448                     if ( GetGridCursorCol() > 0 ) 
5450                         MoveCursorLeft( FALSE 
); 
5455                         HideCellEditControl(); 
5456                         SaveEditControlValue(); 
5461                     if ( GetGridCursorCol() < GetNumberCols()-1 ) 
5463                         MoveCursorRight( FALSE 
); 
5468                         HideCellEditControl(); 
5469                         SaveEditControlValue(); 
5475                 if ( event
.ControlDown() ) 
5477                     MakeCellVisible( 0, 0 ); 
5478                     SetCurrentCell( 0, 0 ); 
5487                 if ( event
.ControlDown() ) 
5489                     MakeCellVisible( m_numRows
-1, m_numCols
-1 ); 
5490                     SetCurrentCell( m_numRows
-1, m_numCols
-1 ); 
5507                 if ( event
.ControlDown() ) 
5509                     m_selection
->ToggleCellSelection( m_currentCellCoords
.GetRow(), 
5510                                                       m_currentCellCoords
.GetCol(), 
5511                                                       event
.ControlDown(), 
5517                 if ( !IsEditable() ) 
5519                     MoveCursorRight( FALSE 
); 
5522                 // Otherwise fall through to default 
5525                 // is it possible to edit the current cell at all? 
5526                 if ( !IsCellEditControlEnabled() && CanEnableCellControl() ) 
5528                     // yes, now check whether the cells editor accepts the key 
5529                     int row 
= m_currentCellCoords
.GetRow(); 
5530                     int col 
= m_currentCellCoords
.GetCol(); 
5531                     wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
5532                     wxGridCellEditor 
*editor 
= attr
->GetEditor(this, row
, col
); 
5534                     // <F2> is special and will always start editing, for 
5535                     // other keys - ask the editor itself 
5536                     if ( (event
.KeyCode() == WXK_F2 
&& !event
.HasModifiers()) 
5537                          || editor
->IsAcceptedKey(event
) ) 
5539                         EnableCellEditControl(); 
5540                         editor
->StartingKey(event
); 
5552                     // let others process char events with modifiers or all 
5553                     // char events for readonly cells 
5560     m_inOnKeyDown 
= FALSE
; 
5563 void wxGrid::OnKeyUp( wxKeyEvent
& event 
) 
5565     // try local handlers 
5567     if ( event
.KeyCode() == WXK_SHIFT 
) 
5569         if ( m_selectingTopLeft 
!= wxGridNoCellCoords 
&& 
5570              m_selectingBottomRight 
!= wxGridNoCellCoords 
) 
5571             m_selection
->SelectBlock( m_selectingTopLeft
.GetRow(), 
5572                                       m_selectingTopLeft
.GetCol(), 
5573                                       m_selectingBottomRight
.GetRow(), 
5574                                       m_selectingBottomRight
.GetCol(), 
5575                                       event
.ControlDown(), 
5579         m_selectingTopLeft 
= wxGridNoCellCoords
; 
5580         m_selectingBottomRight 
= wxGridNoCellCoords
; 
5581         m_selectingKeyboard 
= wxGridNoCellCoords
; 
5585 void wxGrid::OnEraseBackground(wxEraseEvent
&) 
5589 void wxGrid::SetCurrentCell( const wxGridCellCoords
& coords 
) 
5591     if ( SendEvent( wxEVT_GRID_SELECT_CELL
, coords
.GetRow(), coords
.GetCol() ) ) 
5593         // the event has been intercepted - do nothing 
5597     wxClientDC 
dc(m_gridWin
); 
5600     if ( m_currentCellCoords 
!= wxGridNoCellCoords 
) 
5602         HideCellEditControl(); 
5603         DisableCellEditControl(); 
5605         if ( IsVisible( m_currentCellCoords
, FALSE 
) ) 
5608             r 
= BlockToDeviceRect(m_currentCellCoords
, m_currentCellCoords
); 
5609             if ( !m_gridLinesEnabled 
) 
5617             CalcCellsExposed( r 
); 
5619             // Otherwise refresh redraws the highlight! 
5620             m_currentCellCoords 
= coords
; 
5622             DrawGridCellArea(dc
); 
5623             DrawAllGridLines( dc
, r 
); 
5627     m_currentCellCoords 
= coords
; 
5629     wxGridCellAttr
* attr 
= GetCellAttr(coords
); 
5630     DrawCellHighlight(dc
, attr
); 
5635 void wxGrid::HighlightBlock( int topRow
, int leftCol
, int bottomRow
, int rightCol 
) 
5638     wxGridCellCoords updateTopLeft
, updateBottomRight
; 
5640     if ( m_selection
->GetSelectionMode() == wxGrid::wxGridSelectRows 
) 
5643         rightCol 
= GetNumberCols() - 1; 
5645     else if ( m_selection
->GetSelectionMode() == wxGrid::wxGridSelectColumns 
) 
5648         bottomRow 
= GetNumberRows() - 1; 
5650     if ( topRow 
> bottomRow 
) 
5657     if ( leftCol 
> rightCol 
) 
5664     updateTopLeft 
= wxGridCellCoords( topRow
, leftCol 
); 
5665     updateBottomRight 
= wxGridCellCoords( bottomRow
, rightCol 
); 
5667     if ( m_selectingTopLeft 
!= updateTopLeft 
|| 
5668          m_selectingBottomRight 
!= updateBottomRight 
) 
5670         // Compute two optimal update rectangles: 
5671         // Either one rectangle is a real subset of the 
5672         // other, or they are (almost) disjoint! 
5674         bool    need_refresh
[4]; 
5678         need_refresh
[3] = FALSE
; 
5681         // Store intermediate values 
5682         wxCoord oldLeft   
= m_selectingTopLeft
.GetCol(); 
5683         wxCoord oldTop    
= m_selectingTopLeft
.GetRow(); 
5684         wxCoord oldRight  
= m_selectingBottomRight
.GetCol(); 
5685         wxCoord oldBottom 
= m_selectingBottomRight
.GetRow(); 
5687         // Determine the outer/inner coordinates. 
5688         if (oldLeft 
> leftCol
) 
5694         if (oldTop 
> topRow 
) 
5700         if (oldRight 
< rightCol 
) 
5703             oldRight 
= rightCol
; 
5706         if (oldBottom 
< bottomRow
) 
5709             oldBottom 
= bottomRow
; 
5713         // Now, either the stuff marked old is the outer 
5714         // rectangle or we don't have a situation where one 
5715         // is contained in the other. 
5717         if ( oldLeft 
< leftCol 
) 
5719             need_refresh
[0] = TRUE
; 
5720             rect
[0] = BlockToDeviceRect( wxGridCellCoords ( oldTop
, 
5722                                          wxGridCellCoords ( oldBottom
, 
5726         if ( oldTop  
< topRow 
) 
5728             need_refresh
[1] = TRUE
; 
5729             rect
[1] = BlockToDeviceRect( wxGridCellCoords ( oldTop
, 
5731                                          wxGridCellCoords ( topRow 
- 1, 
5735         if ( oldRight 
> rightCol 
) 
5737             need_refresh
[2] = TRUE
; 
5738             rect
[2] = BlockToDeviceRect( wxGridCellCoords ( oldTop
, 
5740                                          wxGridCellCoords ( oldBottom
, 
5744         if ( oldBottom 
> bottomRow 
) 
5746             need_refresh
[3] = TRUE
; 
5747             rect
[3] = BlockToDeviceRect( wxGridCellCoords ( bottomRow 
+ 1, 
5749                                          wxGridCellCoords ( oldBottom
, 
5755         m_selectingTopLeft 
= updateTopLeft
; 
5756         m_selectingBottomRight 
= updateBottomRight
; 
5758         // various Refresh() calls 
5759         for (i 
= 0; i 
< 4; i
++ ) 
5760             if ( need_refresh
[i
] && rect
[i
] != wxGridNoCellRect 
) 
5761                 m_gridWin
->Refresh( FALSE
, &(rect
[i
]) ); 
5764     // never generate an event as it will be generated from 
5765     // wxGridSelection::SelectBlock! 
5766     // (old comment from when this was the body of SelectBlock) 
5771 // ------ functions to get/send data (see also public functions) 
5774 bool wxGrid::GetModelValues() 
5778         // all we need to do is repaint the grid 
5780         m_gridWin
->Refresh(); 
5788 bool wxGrid::SetModelValues() 
5794         for ( row 
= 0;  row 
< m_numRows
;  row
++ ) 
5796             for ( col 
= 0;  col 
< m_numCols
;  col
++ ) 
5798                 m_table
->SetValue( row
, col
, GetCellValue(row
, col
) ); 
5810 // Note - this function only draws cells that are in the list of 
5811 // exposed cells (usually set from the update region by 
5812 // CalcExposedCells) 
5814 void wxGrid::DrawGridCellArea( wxDC
& dc 
) 
5816     if ( !m_numRows 
|| !m_numCols 
) return; 
5819     size_t numCells 
= m_cellsExposed
.GetCount(); 
5821     for ( i 
= 0;  i 
< numCells
;  i
++ ) 
5823         DrawCell( dc
, m_cellsExposed
[i
] ); 
5828 void wxGrid::DrawGridSpace( wxDC
& dc 
) 
5831   m_gridWin
->GetClientSize( &cw
, &ch 
); 
5834   CalcUnscrolledPosition( cw
, ch
, &right
, &bottom 
); 
5836   int rightCol 
= m_numCols 
> 0 ? GetColRight(m_numCols 
- 1) : 0; 
5837   int bottomRow 
= m_numRows 
> 0 ? GetRowBottom(m_numRows 
- 1) : 0 ; 
5839   if ( right 
> rightCol 
|| bottom 
> bottomRow 
) 
5842       CalcUnscrolledPosition( 0, 0, &left
, &top 
); 
5844       dc
.SetBrush( wxBrush(GetDefaultCellBackgroundColour(), wxSOLID
) ); 
5845       dc
.SetPen( *wxTRANSPARENT_PEN 
); 
5847       if ( right 
> rightCol 
) 
5849           dc
.DrawRectangle( rightCol
, top
, right 
- rightCol
, ch
); 
5852       if ( bottom 
> bottomRow 
) 
5854           dc
.DrawRectangle( left
, bottomRow
, cw
, bottom 
- bottomRow
); 
5860 void wxGrid::DrawCell( wxDC
& dc
, const wxGridCellCoords
& coords 
) 
5862     int row 
= coords
.GetRow(); 
5863     int col 
= coords
.GetCol(); 
5865     if ( GetColWidth(col
) <= 0 || GetRowHeight(row
) <= 0 ) 
5868     // we draw the cell border ourselves 
5869 #if !WXGRID_DRAW_LINES 
5870     if ( m_gridLinesEnabled 
) 
5871         DrawCellBorder( dc
, coords 
); 
5874     wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
5876     bool isCurrent 
= coords 
== m_currentCellCoords
; 
5878     wxRect rect 
= CellToRect( row
, col 
); 
5880     // if the editor is shown, we should use it and not the renderer 
5881     // Note: However, only if it is really _shown_, i.e. not hidden! 
5882     if ( isCurrent 
&& IsCellEditControlShown() ) 
5884         wxGridCellEditor 
*editor 
= attr
->GetEditor(this, row
, col
); 
5885         editor
->PaintBackground(rect
, attr
); 
5890         // but all the rest is drawn by the cell renderer and hence may be 
5892         wxGridCellRenderer 
*renderer 
= attr
->GetRenderer(this, row
, col
); 
5893         renderer
->Draw(*this, *attr
, dc
, rect
, row
, col
, IsInSelection(coords
)); 
5900 void wxGrid::DrawCellHighlight( wxDC
& dc
, const wxGridCellAttr 
*attr 
) 
5902     int row 
= m_currentCellCoords
.GetRow(); 
5903     int col 
= m_currentCellCoords
.GetCol(); 
5905     if ( GetColWidth(col
) <= 0 || GetRowHeight(row
) <= 0 ) 
5908     wxRect rect 
= CellToRect(row
, col
); 
5910     // hmmm... what could we do here to show that the cell is disabled? 
5911     // for now, I just draw a thinner border than for the other ones, but 
5912     // it doesn't look really good 
5913     dc
.SetPen(wxPen(m_cellHighlightColour
, attr
->IsReadOnly() ? 1 : 3, wxSOLID
)); 
5914     dc
.SetBrush(*wxTRANSPARENT_BRUSH
); 
5916     dc
.DrawRectangle(rect
); 
5919         // VZ: my experiments with 3d borders... 
5921         // how to properly set colours for arbitrary bg? 
5922         wxCoord x1 
= rect
.x
, 
5924                 x2 
= rect
.x 
+ rect
.width 
-1, 
5925                 y2 
= rect
.y 
+ rect
.height 
-1; 
5927         dc
.SetPen(*wxWHITE_PEN
); 
5928         dc
.DrawLine(x1
, y1
, x2
, y1
); 
5929         dc
.DrawLine(x1
, y1
, x1
, y2
); 
5931         dc
.DrawLine(x1 
+ 1, y2 
- 1, x2 
- 1, y2 
- 1); 
5932         dc
.DrawLine(x2 
- 1, y1 
+ 1, x2 
- 1, y2 
); 
5934         dc
.SetPen(*wxBLACK_PEN
); 
5935         dc
.DrawLine(x1
, y2
, x2
, y2
); 
5936         dc
.DrawLine(x2
, y1
, x2
, y2
+1); 
5941 void wxGrid::DrawCellBorder( wxDC
& dc
, const wxGridCellCoords
& coords 
) 
5943     int row 
= coords
.GetRow(); 
5944     int col 
= coords
.GetCol(); 
5945     if ( GetColWidth(col
) <= 0 || GetRowHeight(row
) <= 0 ) 
5948     dc
.SetPen( wxPen(GetGridLineColour(), 1, wxSOLID
) ); 
5950     // right hand border 
5952     dc
.DrawLine( GetColRight(col
), GetRowTop(row
), 
5953                  GetColRight(col
), GetRowBottom(row
) ); 
5957     dc
.DrawLine( GetColLeft(col
), GetRowBottom(row
), 
5958                  GetColRight(col
), GetRowBottom(row
) ); 
5961 void wxGrid::DrawHighlight(wxDC
& dc
) 
5963     // This if block was previously in wxGrid::OnPaint but that doesn't 
5964     // seem to get called under wxGTK - MB 
5966     if ( m_currentCellCoords 
== wxGridNoCellCoords  
&& 
5967          m_numRows 
&& m_numCols 
) 
5969         m_currentCellCoords
.Set(0, 0); 
5972     if ( IsCellEditControlShown() ) 
5974         // don't show highlight when the edit control is shown 
5978     // if the active cell was repainted, repaint its highlight too because it 
5979     // might have been damaged by the grid lines 
5980     size_t count 
= m_cellsExposed
.GetCount(); 
5981     for ( size_t n 
= 0; n 
< count
; n
++ ) 
5983         if ( m_cellsExposed
[n
] == m_currentCellCoords 
) 
5985             wxGridCellAttr
* attr 
= GetCellAttr(m_currentCellCoords
); 
5986             DrawCellHighlight(dc
, attr
); 
5994 // TODO: remove this ??? 
5995 // This is used to redraw all grid lines e.g. when the grid line colour 
5998 void wxGrid::DrawAllGridLines( wxDC
& dc
, const wxRegion 
& WXUNUSED_GTK(reg
) ) 
6000     if ( !m_gridLinesEnabled 
|| 
6002          !m_numCols 
) return; 
6004     int top
, bottom
, left
, right
; 
6006 #if 0  //#ifndef __WXGTK__ 
6010       m_gridWin
->GetClientSize(&cw
, &ch
); 
6012       // virtual coords of visible area 
6014       CalcUnscrolledPosition( 0, 0, &left
, &top 
); 
6015       CalcUnscrolledPosition( cw
, ch
, &right
, &bottom 
); 
6020       reg
.GetBox(x
, y
, w
, h
); 
6021       CalcUnscrolledPosition( x
, y
, &left
, &top 
); 
6022       CalcUnscrolledPosition( x 
+ w
, y 
+ h
, &right
, &bottom 
); 
6026       m_gridWin
->GetClientSize(&cw
, &ch
); 
6027       CalcUnscrolledPosition( 0, 0, &left
, &top 
); 
6028       CalcUnscrolledPosition( cw
, ch
, &right
, &bottom 
); 
6031     // avoid drawing grid lines past the last row and col 
6033     right 
= wxMin( right
, GetColRight(m_numCols 
- 1) ); 
6034     bottom 
= wxMin( bottom
, GetRowBottom(m_numRows 
- 1) ); 
6036     dc
.SetPen( wxPen(GetGridLineColour(), 1, wxSOLID
) ); 
6038     // horizontal grid lines 
6041     for ( i 
= 0; i 
< m_numRows
; i
++ ) 
6043         int bot 
= GetRowBottom(i
) - 1; 
6052             dc
.DrawLine( left
, bot
, right
, bot 
); 
6057     // vertical grid lines 
6059     for ( i 
= 0; i 
< m_numCols
; i
++ ) 
6061         int colRight 
= GetColRight(i
) - 1; 
6062         if ( colRight 
> right 
) 
6067         if ( colRight 
>= left 
) 
6069             dc
.DrawLine( colRight
, top
, colRight
, bottom 
); 
6075 void wxGrid::DrawRowLabels( wxDC
& dc 
) 
6077     if ( !m_numRows 
) return; 
6080     size_t numLabels 
= m_rowLabelsExposed
.GetCount(); 
6082     for ( i 
= 0;  i 
< numLabels
;  i
++ ) 
6084         DrawRowLabel( dc
, m_rowLabelsExposed
[i
] ); 
6089 void wxGrid::DrawRowLabel( wxDC
& dc
, int row 
) 
6091     if ( GetRowHeight(row
) <= 0 ) 
6094     int rowTop 
= GetRowTop(row
), 
6095         rowBottom 
= GetRowBottom(row
) - 1; 
6097     dc
.SetPen( *wxBLACK_PEN 
); 
6098     dc
.DrawLine( m_rowLabelWidth
-1, rowTop
, 
6099                  m_rowLabelWidth
-1, rowBottom 
); 
6101     dc
.DrawLine( 0, rowBottom
, m_rowLabelWidth
-1, rowBottom 
); 
6103     dc
.SetPen( *wxWHITE_PEN 
); 
6104     dc
.DrawLine( 0, rowTop
, 0, rowBottom 
); 
6105     dc
.DrawLine( 0, rowTop
, m_rowLabelWidth
-1, rowTop 
); 
6107     dc
.SetBackgroundMode( wxTRANSPARENT 
); 
6108     dc
.SetTextForeground( GetLabelTextColour() ); 
6109     dc
.SetFont( GetLabelFont() ); 
6112     GetRowLabelAlignment( &hAlign
, &vAlign 
); 
6116     rect
.SetY( GetRowTop(row
) + 2 ); 
6117     rect
.SetWidth( m_rowLabelWidth 
- 4 ); 
6118     rect
.SetHeight( GetRowHeight(row
) - 4 ); 
6119     DrawTextRectangle( dc
, GetRowLabelValue( row 
), rect
, hAlign
, vAlign 
); 
6123 void wxGrid::DrawColLabels( wxDC
& dc 
) 
6125     if ( !m_numCols 
) return; 
6128     size_t numLabels 
= m_colLabelsExposed
.GetCount(); 
6130     for ( i 
= 0;  i 
< numLabels
;  i
++ ) 
6132         DrawColLabel( dc
, m_colLabelsExposed
[i
] ); 
6137 void wxGrid::DrawColLabel( wxDC
& dc
, int col 
) 
6139     if ( GetColWidth(col
) <= 0 ) 
6142     int colLeft 
= GetColLeft(col
), 
6143         colRight 
= GetColRight(col
) - 1; 
6145     dc
.SetPen( *wxBLACK_PEN 
); 
6146     dc
.DrawLine( colRight
, 0, 
6147                  colRight
, m_colLabelHeight
-1 ); 
6149     dc
.DrawLine( colLeft
, m_colLabelHeight
-1, 
6150                  colRight
, m_colLabelHeight
-1 ); 
6152     dc
.SetPen( *wxWHITE_PEN 
); 
6153     dc
.DrawLine( colLeft
, 0, colLeft
, m_colLabelHeight
-1 ); 
6154     dc
.DrawLine( colLeft
, 0, colRight
, 0 ); 
6156     dc
.SetBackgroundMode( wxTRANSPARENT 
); 
6157     dc
.SetTextForeground( GetLabelTextColour() ); 
6158     dc
.SetFont( GetLabelFont() ); 
6160     dc
.SetBackgroundMode( wxTRANSPARENT 
); 
6161     dc
.SetTextForeground( GetLabelTextColour() ); 
6162     dc
.SetFont( GetLabelFont() ); 
6165     GetColLabelAlignment( &hAlign
, &vAlign 
); 
6168     rect
.SetX( colLeft 
+ 2 ); 
6170     rect
.SetWidth( GetColWidth(col
) - 4 ); 
6171     rect
.SetHeight( m_colLabelHeight 
- 4 ); 
6172     DrawTextRectangle( dc
, GetColLabelValue( col 
), rect
, hAlign
, vAlign 
); 
6176 void wxGrid::DrawTextRectangle( wxDC
& dc
, 
6177                                 const wxString
& value
, 
6182     long textWidth
, textHeight
; 
6183     long lineWidth
, lineHeight
; 
6184     wxArrayString lines
; 
6186     dc
.SetClippingRegion( rect 
); 
6187     StringToLines( value
, lines 
); 
6188     if ( lines
.GetCount() ) 
6190         GetTextBoxSize( dc
, lines
, &textWidth
, &textHeight 
); 
6191         dc
.GetTextExtent( lines
[0], &lineWidth
, &lineHeight 
); 
6194         switch ( horizAlign 
) 
6197                 x 
= rect
.x 
+ (rect
.width 
- textWidth 
- 1); 
6200             case wxALIGN_CENTRE
: 
6201                 x 
= rect
.x 
+ ((rect
.width 
- textWidth
)/2); 
6210         switch ( vertAlign 
) 
6212             case wxALIGN_BOTTOM
: 
6213                 y 
= rect
.y 
+ (rect
.height 
- textHeight 
- 1); 
6216             case wxALIGN_CENTRE
: 
6217                 y 
= rect
.y 
+ ((rect
.height 
- textHeight
)/2); 
6226         for ( size_t i 
= 0;  i 
< lines
.GetCount();  i
++ ) 
6228             dc
.DrawText( lines
[i
], (int)x
, (int)y 
); 
6233     dc
.DestroyClippingRegion(); 
6237 // Split multi line text up into an array of strings.  Any existing 
6238 // contents of the string array are preserved. 
6240 void wxGrid::StringToLines( const wxString
& value
, wxArrayString
& lines 
) 
6244     wxString eol 
= wxTextFile::GetEOL( wxTextFileType_Unix 
); 
6245     wxString tVal 
= wxTextFile::Translate( value
, wxTextFileType_Unix 
); 
6247     while ( startPos 
< (int)tVal
.Length() ) 
6249         pos 
= tVal
.Mid(startPos
).Find( eol 
); 
6254         else if ( pos 
== 0 ) 
6256             lines
.Add( wxEmptyString 
); 
6260             lines
.Add( value
.Mid(startPos
, pos
) ); 
6264     if ( startPos 
< (int)value
.Length() ) 
6266         lines
.Add( value
.Mid( startPos 
) ); 
6271 void wxGrid::GetTextBoxSize( wxDC
& dc
, 
6272                              wxArrayString
& lines
, 
6273                              long *width
, long *height 
) 
6280     for ( i 
= 0;  i 
< lines
.GetCount();  i
++ ) 
6282         dc
.GetTextExtent( lines
[i
], &lineW
, &lineH 
); 
6283         w 
= wxMax( w
, lineW 
); 
6292 // ------ Batch processing. 
6294 void wxGrid::EndBatch() 
6296     if ( m_batchCount 
> 0 ) 
6299         if ( !m_batchCount 
) 
6302             m_rowLabelWin
->Refresh(); 
6303             m_colLabelWin
->Refresh(); 
6304             m_cornerLabelWin
->Refresh(); 
6305             m_gridWin
->Refresh(); 
6310 // Use this, rather than wxWindow::Refresh(), to force an immediate 
6311 // repainting of the grid. Has no effect if you are already inside a 
6312 // BeginBatch / EndBatch block. 
6314 void wxGrid::ForceRefresh() 
6322 // ------ Edit control functions 
6326 void wxGrid::EnableEditing( bool edit 
) 
6328     // TODO: improve this ? 
6330     if ( edit 
!= m_editable 
) 
6332         if(!edit
) EnableCellEditControl(edit
); 
6338 void wxGrid::EnableCellEditControl( bool enable 
) 
6343     if ( m_currentCellCoords 
== wxGridNoCellCoords 
) 
6344         SetCurrentCell( 0, 0 ); 
6346     if ( enable 
!= m_cellEditCtrlEnabled 
) 
6348         // TODO allow the app to Veto() this event? 
6349         SendEvent(enable 
? wxEVT_GRID_EDITOR_SHOWN 
: wxEVT_GRID_EDITOR_HIDDEN
); 
6353             // this should be checked by the caller! 
6354             wxASSERT_MSG( CanEnableCellControl(), 
6355                           _T("can't enable editing for this cell!") ); 
6357             // do it before ShowCellEditControl() 
6358             m_cellEditCtrlEnabled 
= enable
; 
6360             ShowCellEditControl(); 
6364             HideCellEditControl(); 
6365             SaveEditControlValue(); 
6367             // do it after HideCellEditControl() 
6368             m_cellEditCtrlEnabled 
= enable
; 
6373 bool wxGrid::IsCurrentCellReadOnly() const 
6376     wxGridCellAttr
* attr 
= ((wxGrid 
*)this)->GetCellAttr(m_currentCellCoords
); 
6377     bool readonly 
= attr
->IsReadOnly(); 
6383 bool wxGrid::CanEnableCellControl() const 
6385     return m_editable 
&& !IsCurrentCellReadOnly(); 
6388 bool wxGrid::IsCellEditControlEnabled() const 
6390     // the cell edit control might be disable for all cells or just for the 
6391     // current one if it's read only 
6392     return m_cellEditCtrlEnabled 
? !IsCurrentCellReadOnly() : FALSE
; 
6395 bool wxGrid::IsCellEditControlShown() const 
6397     bool isShown 
= FALSE
; 
6399     if ( m_cellEditCtrlEnabled 
) 
6401         int row 
= m_currentCellCoords
.GetRow(); 
6402         int col 
= m_currentCellCoords
.GetCol(); 
6403         wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
6404         wxGridCellEditor
* editor 
= attr
->GetEditor((wxGrid
*) this, row
, col
); 
6409             if ( editor
->IsCreated() ) 
6411                 isShown 
= editor
->GetControl()->IsShown(); 
6421 void wxGrid::ShowCellEditControl() 
6423     if ( IsCellEditControlEnabled() ) 
6425         if ( !IsVisible( m_currentCellCoords 
) ) 
6427             m_cellEditCtrlEnabled 
= FALSE
; 
6432             wxRect rect 
= CellToRect( m_currentCellCoords 
); 
6433             int row 
= m_currentCellCoords
.GetRow(); 
6434             int col 
= m_currentCellCoords
.GetCol(); 
6436             // convert to scrolled coords 
6438             CalcScrolledPosition( rect
.x
, rect
.y
, &rect
.x
, &rect
.y 
); 
6440             // done in PaintBackground() 
6442             // erase the highlight and the cell contents because the editor 
6443             // might not cover the entire cell 
6444             wxClientDC 
dc( m_gridWin 
); 
6446             dc
.SetBrush(*wxLIGHT_GREY_BRUSH
); //wxBrush(attr->GetBackgroundColour(), wxSOLID)); 
6447             dc
.SetPen(*wxTRANSPARENT_PEN
); 
6448             dc
.DrawRectangle(rect
); 
6451             // cell is shifted by one pixel 
6455             wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
6456             wxGridCellEditor
* editor 
= attr
->GetEditor(this, row
, col
); 
6457             if ( !editor
->IsCreated() ) 
6459                 editor
->Create(m_gridWin
, -1, 
6460                                new wxGridCellEditorEvtHandler(this, editor
)); 
6463             editor
->Show( TRUE
, attr 
); 
6465             editor
->SetSize( rect 
); 
6467             editor
->BeginEdit(row
, col
, this); 
6476 void wxGrid::HideCellEditControl() 
6478     if ( IsCellEditControlEnabled() ) 
6480         int row 
= m_currentCellCoords
.GetRow(); 
6481         int col 
= m_currentCellCoords
.GetCol(); 
6483         wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
6484         wxGridCellEditor 
*editor 
= attr
->GetEditor(this, row
, col
); 
6485         editor
->Show( FALSE 
); 
6488         m_gridWin
->SetFocus(); 
6489         wxRect 
rect( CellToRect( row
, col 
) ); 
6490         m_gridWin
->Refresh( FALSE
, &rect 
); 
6495 void wxGrid::SaveEditControlValue() 
6497     if ( IsCellEditControlEnabled() ) 
6499         int row 
= m_currentCellCoords
.GetRow(); 
6500         int col 
= m_currentCellCoords
.GetCol(); 
6502         wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
6503         wxGridCellEditor
* editor 
= attr
->GetEditor(this, row
, col
); 
6504         bool changed 
= editor
->EndEdit(row
, col
, this); 
6511             SendEvent( wxEVT_GRID_CELL_CHANGE
, 
6512                        m_currentCellCoords
.GetRow(), 
6513                        m_currentCellCoords
.GetCol() ); 
6520 // ------ Grid location functions 
6521 //  Note that all of these functions work with the logical coordinates of 
6522 //  grid cells and labels so you will need to convert from device 
6523 //  coordinates for mouse events etc. 
6526 void wxGrid::XYToCell( int x
, int y
, wxGridCellCoords
& coords 
) 
6528     int row 
= YToRow(y
); 
6529     int col 
= XToCol(x
); 
6531     if ( row 
== -1  ||  col 
== -1 ) 
6533         coords 
= wxGridNoCellCoords
; 
6537         coords
.Set( row
, col 
); 
6542 int wxGrid::YToRow( int y 
) 
6546     for ( i 
= 0;  i 
< m_numRows
;  i
++ ) 
6548         if ( y 
< GetRowBottom(i
) ) 
6556 int wxGrid::XToCol( int x 
) 
6560     for ( i 
= 0;  i 
< m_numCols
;  i
++ ) 
6562         if ( x 
< GetColRight(i
) ) 
6570 // return the row number that that the y coord is near the edge of, or 
6571 // -1 if not near an edge 
6573 int wxGrid::YToEdgeOfRow( int y 
) 
6577     for ( i 
= 0;  i 
< m_numRows
;  i
++ ) 
6579         if ( GetRowHeight(i
) > WXGRID_LABEL_EDGE_ZONE 
) 
6581             d 
= abs( y 
- GetRowBottom(i
) ); 
6582             if ( d 
< WXGRID_LABEL_EDGE_ZONE 
) 
6591 // return the col number that that the x coord is near the edge of, or 
6592 // -1 if not near an edge 
6594 int wxGrid::XToEdgeOfCol( int x 
) 
6598     for ( i 
= 0;  i 
< m_numCols
;  i
++ ) 
6600         if ( GetColWidth(i
) > WXGRID_LABEL_EDGE_ZONE 
) 
6602             d 
= abs( x 
- GetColRight(i
) ); 
6603             if ( d 
< WXGRID_LABEL_EDGE_ZONE 
) 
6612 wxRect 
wxGrid::CellToRect( int row
, int col 
) 
6614     wxRect 
rect( -1, -1, -1, -1 ); 
6616     if ( row 
>= 0  &&  row 
< m_numRows  
&& 
6617          col 
>= 0  &&  col 
< m_numCols 
) 
6619         rect
.x 
= GetColLeft(col
); 
6620         rect
.y 
= GetRowTop(row
); 
6621         rect
.width 
= GetColWidth(col
); 
6622         rect
.height 
= GetRowHeight(row
); 
6625     // if grid lines are enabled, then the area of the cell is a bit smaller 
6626     if (m_gridLinesEnabled
) { 
6634 bool wxGrid::IsVisible( int row
, int col
, bool wholeCellVisible 
) 
6636     // get the cell rectangle in logical coords 
6638     wxRect 
r( CellToRect( row
, col 
) ); 
6640     // convert to device coords 
6642     int left
, top
, right
, bottom
; 
6643     CalcScrolledPosition( r
.GetLeft(), r
.GetTop(), &left
, &top 
); 
6644     CalcScrolledPosition( r
.GetRight(), r
.GetBottom(), &right
, &bottom 
); 
6646     // check against the client area of the grid window 
6649     m_gridWin
->GetClientSize( &cw
, &ch 
); 
6651     if ( wholeCellVisible 
) 
6653         // is the cell wholly visible ? 
6655         return ( left 
>= 0  &&  right 
<= cw  
&& 
6656                  top 
>= 0  &&  bottom 
<= ch 
); 
6660         // is the cell partly visible ? 
6662         return ( ((left 
>=0 && left 
< cw
) || (right 
> 0 && right 
<= cw
))  && 
6663                  ((top 
>=0 && top 
< ch
) || (bottom 
> 0 && bottom 
<= ch
)) ); 
6668 // make the specified cell location visible by doing a minimal amount 
6671 void wxGrid::MakeCellVisible( int row
, int col 
) 
6674     int xpos 
= -1, ypos 
= -1; 
6676     if ( row 
>= 0  &&  row 
< m_numRows  
&& 
6677          col 
>= 0  &&  col 
< m_numCols 
) 
6679         // get the cell rectangle in logical coords 
6681         wxRect 
r( CellToRect( row
, col 
) ); 
6683         // convert to device coords 
6685         int left
, top
, right
, bottom
; 
6686         CalcScrolledPosition( r
.GetLeft(), r
.GetTop(), &left
, &top 
); 
6687         CalcScrolledPosition( r
.GetRight(), r
.GetBottom(), &right
, &bottom 
); 
6690         m_gridWin
->GetClientSize( &cw
, &ch 
); 
6696         else if ( bottom 
> ch 
) 
6698             int h 
= r
.GetHeight(); 
6700             for ( i 
= row
-1;  i 
>= 0;  i
-- ) 
6702                 int rowHeight 
= GetRowHeight(i
); 
6703                 if ( h 
+ rowHeight 
> ch 
) 
6710             // we divide it later by GRID_SCROLL_LINE, make sure that we don't 
6711             // have rounding errors (this is important, because if we do, we 
6712             // might not scroll at all and some cells won't be redrawn) 
6713             ypos 
+= GRID_SCROLL_LINE 
/ 2; 
6720         else if ( right 
> cw 
) 
6722             int w 
= r
.GetWidth(); 
6724             for ( i 
= col
-1;  i 
>= 0;  i
-- ) 
6726                 int colWidth 
= GetColWidth(i
); 
6727                 if ( w 
+ colWidth 
> cw 
) 
6734             // see comment for ypos above 
6735             xpos 
+= GRID_SCROLL_LINE 
/ 2; 
6738         if ( xpos 
!= -1  ||  ypos 
!= -1 ) 
6740             if ( xpos 
!= -1 ) xpos 
/= GRID_SCROLL_LINE
; 
6741             if ( ypos 
!= -1 ) ypos 
/= GRID_SCROLL_LINE
; 
6742             Scroll( xpos
, ypos 
); 
6750 // ------ Grid cursor movement functions 
6753 bool wxGrid::MoveCursorUp( bool expandSelection 
) 
6755     if ( m_currentCellCoords 
!= wxGridNoCellCoords  
&& 
6756          m_currentCellCoords
.GetRow() >= 0 ) 
6758         if ( expandSelection
) 
6760             if ( m_selectingKeyboard 
== wxGridNoCellCoords 
) 
6761                 m_selectingKeyboard 
= m_currentCellCoords
; 
6762             if ( m_selectingKeyboard
.GetRow() > 0 ) 
6764                 m_selectingKeyboard
.SetRow( m_selectingKeyboard
.GetRow() - 1 ); 
6765                 MakeCellVisible( m_selectingKeyboard
.GetRow(), 
6766                                  m_selectingKeyboard
.GetCol() ); 
6767                 HighlightBlock( m_currentCellCoords
, m_selectingKeyboard 
); 
6770         else if ( m_currentCellCoords
.GetRow() > 0 ) 
6773             MakeCellVisible( m_currentCellCoords
.GetRow() - 1, 
6774                              m_currentCellCoords
.GetCol() ); 
6775             SetCurrentCell( m_currentCellCoords
.GetRow() - 1, 
6776                             m_currentCellCoords
.GetCol() ); 
6787 bool wxGrid::MoveCursorDown( bool expandSelection 
) 
6789     if ( m_currentCellCoords 
!= wxGridNoCellCoords  
&& 
6790          m_currentCellCoords
.GetRow() < m_numRows 
) 
6792         if ( expandSelection 
) 
6794             if ( m_selectingKeyboard 
== wxGridNoCellCoords 
) 
6795                 m_selectingKeyboard 
= m_currentCellCoords
; 
6796             if ( m_selectingKeyboard
.GetRow() < m_numRows
-1 ) 
6798                 m_selectingKeyboard
.SetRow( m_selectingKeyboard
.GetRow() + 1 ); 
6799                 MakeCellVisible( m_selectingKeyboard
.GetRow(), 
6800                         m_selectingKeyboard
.GetCol() ); 
6801                 HighlightBlock( m_currentCellCoords
, m_selectingKeyboard 
); 
6804         else if ( m_currentCellCoords
.GetRow() < m_numRows 
- 1 ) 
6807             MakeCellVisible( m_currentCellCoords
.GetRow() + 1, 
6808                              m_currentCellCoords
.GetCol() ); 
6809             SetCurrentCell( m_currentCellCoords
.GetRow() + 1, 
6810                             m_currentCellCoords
.GetCol() ); 
6821 bool wxGrid::MoveCursorLeft( bool expandSelection 
) 
6823     if ( m_currentCellCoords 
!= wxGridNoCellCoords  
&& 
6824          m_currentCellCoords
.GetCol() >= 0 ) 
6826         if ( expandSelection 
) 
6828             if ( m_selectingKeyboard 
== wxGridNoCellCoords 
) 
6829                 m_selectingKeyboard 
= m_currentCellCoords
; 
6830             if ( m_selectingKeyboard
.GetCol() > 0 ) 
6832                 m_selectingKeyboard
.SetCol( m_selectingKeyboard
.GetCol() - 1 ); 
6833                 MakeCellVisible( m_selectingKeyboard
.GetRow(), 
6834                         m_selectingKeyboard
.GetCol() ); 
6835                 HighlightBlock( m_currentCellCoords
, m_selectingKeyboard 
); 
6838         else if ( m_currentCellCoords
.GetCol() > 0 ) 
6841             MakeCellVisible( m_currentCellCoords
.GetRow(), 
6842                              m_currentCellCoords
.GetCol() - 1 ); 
6843             SetCurrentCell( m_currentCellCoords
.GetRow(), 
6844                             m_currentCellCoords
.GetCol() - 1 ); 
6855 bool wxGrid::MoveCursorRight( bool expandSelection 
) 
6857     if ( m_currentCellCoords 
!= wxGridNoCellCoords  
&& 
6858          m_currentCellCoords
.GetCol() < m_numCols 
) 
6860         if ( expandSelection 
) 
6862             if ( m_selectingKeyboard 
== wxGridNoCellCoords 
) 
6863                 m_selectingKeyboard 
= m_currentCellCoords
; 
6864             if ( m_selectingKeyboard
.GetCol() < m_numCols 
- 1 ) 
6866                 m_selectingKeyboard
.SetCol( m_selectingKeyboard
.GetCol() + 1 ); 
6867                 MakeCellVisible( m_selectingKeyboard
.GetRow(), 
6868                         m_selectingKeyboard
.GetCol() ); 
6869                 HighlightBlock( m_currentCellCoords
, m_selectingKeyboard 
); 
6872         else if ( m_currentCellCoords
.GetCol() < m_numCols 
- 1 ) 
6875             MakeCellVisible( m_currentCellCoords
.GetRow(), 
6876                              m_currentCellCoords
.GetCol() + 1 ); 
6877             SetCurrentCell( m_currentCellCoords
.GetRow(), 
6878                             m_currentCellCoords
.GetCol() + 1 ); 
6889 bool wxGrid::MovePageUp() 
6891     if ( m_currentCellCoords 
== wxGridNoCellCoords 
) return FALSE
; 
6893     int row 
= m_currentCellCoords
.GetRow(); 
6897         m_gridWin
->GetClientSize( &cw
, &ch 
); 
6899         int y 
= GetRowTop(row
); 
6900         int newRow 
= YToRow( y 
- ch 
+ 1 ); 
6905         else if ( newRow 
== row 
) 
6910         MakeCellVisible( newRow
, m_currentCellCoords
.GetCol() ); 
6911         SetCurrentCell( newRow
, m_currentCellCoords
.GetCol() ); 
6919 bool wxGrid::MovePageDown() 
6921     if ( m_currentCellCoords 
== wxGridNoCellCoords 
) return FALSE
; 
6923     int row 
= m_currentCellCoords
.GetRow(); 
6924     if ( row 
< m_numRows 
) 
6927         m_gridWin
->GetClientSize( &cw
, &ch 
); 
6929         int y 
= GetRowTop(row
); 
6930         int newRow 
= YToRow( y 
+ ch 
); 
6933             newRow 
= m_numRows 
- 1; 
6935         else if ( newRow 
== row 
) 
6940         MakeCellVisible( newRow
, m_currentCellCoords
.GetCol() ); 
6941         SetCurrentCell( newRow
, m_currentCellCoords
.GetCol() ); 
6949 bool wxGrid::MoveCursorUpBlock( bool expandSelection 
) 
6952          m_currentCellCoords 
!= wxGridNoCellCoords  
&& 
6953          m_currentCellCoords
.GetRow() > 0 ) 
6955         int row 
= m_currentCellCoords
.GetRow(); 
6956         int col 
= m_currentCellCoords
.GetCol(); 
6958         if ( m_table
->IsEmptyCell(row
, col
) ) 
6960             // starting in an empty cell: find the next block of 
6966                 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break; 
6969         else if ( m_table
->IsEmptyCell(row
-1, col
) ) 
6971             // starting at the top of a block: find the next block 
6977                 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break; 
6982             // starting within a block: find the top of the block 
6987                 if ( m_table
->IsEmptyCell(row
, col
) ) 
6995         MakeCellVisible( row
, col 
); 
6996         if ( expandSelection 
) 
6998             m_selectingKeyboard 
= wxGridCellCoords( row
, col 
); 
6999             HighlightBlock( m_currentCellCoords
, m_selectingKeyboard 
); 
7004             SetCurrentCell( row
, col 
); 
7012 bool wxGrid::MoveCursorDownBlock( bool expandSelection 
) 
7015          m_currentCellCoords 
!= wxGridNoCellCoords  
&& 
7016          m_currentCellCoords
.GetRow() < m_numRows
-1 ) 
7018         int row 
= m_currentCellCoords
.GetRow(); 
7019         int col 
= m_currentCellCoords
.GetCol(); 
7021         if ( m_table
->IsEmptyCell(row
, col
) ) 
7023             // starting in an empty cell: find the next block of 
7026             while ( row 
< m_numRows
-1 ) 
7029                 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break; 
7032         else if ( m_table
->IsEmptyCell(row
+1, col
) ) 
7034             // starting at the bottom of a block: find the next block 
7037             while ( row 
< m_numRows
-1 ) 
7040                 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break; 
7045             // starting within a block: find the bottom of the block 
7047             while ( row 
< m_numRows
-1 ) 
7050                 if ( m_table
->IsEmptyCell(row
, col
) ) 
7058         MakeCellVisible( row
, col 
); 
7059         if ( expandSelection 
) 
7061             m_selectingKeyboard 
= wxGridCellCoords( row
, col 
); 
7062             HighlightBlock( m_currentCellCoords
, m_selectingKeyboard 
); 
7067             SetCurrentCell( row
, col 
); 
7076 bool wxGrid::MoveCursorLeftBlock( bool expandSelection 
) 
7079          m_currentCellCoords 
!= wxGridNoCellCoords  
&& 
7080          m_currentCellCoords
.GetCol() > 0 ) 
7082         int row 
= m_currentCellCoords
.GetRow(); 
7083         int col 
= m_currentCellCoords
.GetCol(); 
7085         if ( m_table
->IsEmptyCell(row
, col
) ) 
7087             // starting in an empty cell: find the next block of 
7093                 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break; 
7096         else if ( m_table
->IsEmptyCell(row
, col
-1) ) 
7098             // starting at the left of a block: find the next block 
7104                 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break; 
7109             // starting within a block: find the left of the block 
7114                 if ( m_table
->IsEmptyCell(row
, col
) ) 
7122         MakeCellVisible( row
, col 
); 
7123         if ( expandSelection 
) 
7125             m_selectingKeyboard 
= wxGridCellCoords( row
, col 
); 
7126             HighlightBlock( m_currentCellCoords
, m_selectingKeyboard 
); 
7131             SetCurrentCell( row
, col 
); 
7140 bool wxGrid::MoveCursorRightBlock( bool expandSelection 
) 
7143          m_currentCellCoords 
!= wxGridNoCellCoords  
&& 
7144          m_currentCellCoords
.GetCol() < m_numCols
-1 ) 
7146         int row 
= m_currentCellCoords
.GetRow(); 
7147         int col 
= m_currentCellCoords
.GetCol(); 
7149         if ( m_table
->IsEmptyCell(row
, col
) ) 
7151             // starting in an empty cell: find the next block of 
7154             while ( col 
< m_numCols
-1 ) 
7157                 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break; 
7160         else if ( m_table
->IsEmptyCell(row
, col
+1) ) 
7162             // starting at the right of a block: find the next block 
7165             while ( col 
< m_numCols
-1 ) 
7168                 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break; 
7173             // starting within a block: find the right of the block 
7175             while ( col 
< m_numCols
-1 ) 
7178                 if ( m_table
->IsEmptyCell(row
, col
) ) 
7186         MakeCellVisible( row
, col 
); 
7187         if ( expandSelection 
) 
7189             m_selectingKeyboard 
= wxGridCellCoords( row
, col 
); 
7190             HighlightBlock( m_currentCellCoords
, m_selectingKeyboard 
); 
7195             SetCurrentCell( row
, col 
); 
7207 // ------ Label values and formatting 
7210 void wxGrid::GetRowLabelAlignment( int *horiz
, int *vert 
) 
7212     *horiz 
= m_rowLabelHorizAlign
; 
7213     *vert  
= m_rowLabelVertAlign
; 
7216 void wxGrid::GetColLabelAlignment( int *horiz
, int *vert 
) 
7218     *horiz 
= m_colLabelHorizAlign
; 
7219     *vert  
= m_colLabelVertAlign
; 
7222 wxString 
wxGrid::GetRowLabelValue( int row 
) 
7226         return m_table
->GetRowLabelValue( row 
); 
7236 wxString 
wxGrid::GetColLabelValue( int col 
) 
7240         return m_table
->GetColLabelValue( col 
); 
7251 void wxGrid::SetRowLabelSize( int width 
) 
7253     width 
= wxMax( width
, 0 ); 
7254     if ( width 
!= m_rowLabelWidth 
) 
7258             m_rowLabelWin
->Show( FALSE 
); 
7259             m_cornerLabelWin
->Show( FALSE 
); 
7261         else if ( m_rowLabelWidth 
== 0 ) 
7263             m_rowLabelWin
->Show( TRUE 
); 
7264             if ( m_colLabelHeight 
> 0 ) m_cornerLabelWin
->Show( TRUE 
); 
7267         m_rowLabelWidth 
= width
; 
7274 void wxGrid::SetColLabelSize( int height 
) 
7276     height 
= wxMax( height
, 0 ); 
7277     if ( height 
!= m_colLabelHeight 
) 
7281             m_colLabelWin
->Show( FALSE 
); 
7282             m_cornerLabelWin
->Show( FALSE 
); 
7284         else if ( m_colLabelHeight 
== 0 ) 
7286             m_colLabelWin
->Show( TRUE 
); 
7287             if ( m_rowLabelWidth 
> 0 ) m_cornerLabelWin
->Show( TRUE 
); 
7290         m_colLabelHeight 
= height
; 
7297 void wxGrid::SetLabelBackgroundColour( const wxColour
& colour 
) 
7299     if ( m_labelBackgroundColour 
!= colour 
) 
7301         m_labelBackgroundColour 
= colour
; 
7302         m_rowLabelWin
->SetBackgroundColour( colour 
); 
7303         m_colLabelWin
->SetBackgroundColour( colour 
); 
7304         m_cornerLabelWin
->SetBackgroundColour( colour 
); 
7306         if ( !GetBatchCount() ) 
7308             m_rowLabelWin
->Refresh(); 
7309             m_colLabelWin
->Refresh(); 
7310             m_cornerLabelWin
->Refresh(); 
7315 void wxGrid::SetLabelTextColour( const wxColour
& colour 
) 
7317     if ( m_labelTextColour 
!= colour 
) 
7319         m_labelTextColour 
= colour
; 
7320         if ( !GetBatchCount() ) 
7322             m_rowLabelWin
->Refresh(); 
7323             m_colLabelWin
->Refresh(); 
7328 void wxGrid::SetLabelFont( const wxFont
& font 
) 
7331     if ( !GetBatchCount() ) 
7333         m_rowLabelWin
->Refresh(); 
7334         m_colLabelWin
->Refresh(); 
7338 void wxGrid::SetRowLabelAlignment( int horiz
, int vert 
) 
7340     // allow old (incorrect) defs to be used 
7343         case wxLEFT
:   horiz 
= wxALIGN_LEFT
; break; 
7344         case wxRIGHT
:  horiz 
= wxALIGN_RIGHT
; break; 
7345         case wxCENTRE
: horiz 
= wxALIGN_CENTRE
; break; 
7350         case wxTOP
:    vert 
= wxALIGN_TOP
;    break; 
7351         case wxBOTTOM
: vert 
= wxALIGN_BOTTOM
; break; 
7352         case wxCENTRE
: vert 
= wxALIGN_CENTRE
; break; 
7355     if ( horiz 
== wxALIGN_LEFT 
|| horiz 
== wxALIGN_CENTRE 
|| horiz 
== wxALIGN_RIGHT 
) 
7357         m_rowLabelHorizAlign 
= horiz
; 
7360     if ( vert 
== wxALIGN_TOP 
|| vert 
== wxALIGN_CENTRE 
|| vert 
== wxALIGN_BOTTOM 
) 
7362         m_rowLabelVertAlign 
= vert
; 
7365     if ( !GetBatchCount() ) 
7367         m_rowLabelWin
->Refresh(); 
7371 void wxGrid::SetColLabelAlignment( int horiz
, int vert 
) 
7373     // allow old (incorrect) defs to be used 
7376         case wxLEFT
:   horiz 
= wxALIGN_LEFT
; break; 
7377         case wxRIGHT
:  horiz 
= wxALIGN_RIGHT
; break; 
7378         case wxCENTRE
: horiz 
= wxALIGN_CENTRE
; break; 
7383         case wxTOP
:    vert 
= wxALIGN_TOP
;    break; 
7384         case wxBOTTOM
: vert 
= wxALIGN_BOTTOM
; break; 
7385         case wxCENTRE
: vert 
= wxALIGN_CENTRE
; break; 
7388     if ( horiz 
== wxALIGN_LEFT 
|| horiz 
== wxALIGN_CENTRE 
|| horiz 
== wxALIGN_RIGHT 
) 
7390         m_colLabelHorizAlign 
= horiz
; 
7393     if ( vert 
== wxALIGN_TOP 
|| vert 
== wxALIGN_CENTRE 
|| vert 
== wxALIGN_BOTTOM 
) 
7395         m_colLabelVertAlign 
= vert
; 
7398     if ( !GetBatchCount() ) 
7400         m_colLabelWin
->Refresh(); 
7404 void wxGrid::SetRowLabelValue( int row
, const wxString
& s 
) 
7408         m_table
->SetRowLabelValue( row
, s 
); 
7409         if ( !GetBatchCount() ) 
7411             wxRect rect 
= CellToRect( row
, 0); 
7412             if ( rect
.height 
> 0 ) 
7414                 CalcScrolledPosition(0, rect
.y
, &rect
.x
, &rect
.y
); 
7416                 rect
.width 
= m_rowLabelWidth
; 
7417                 m_rowLabelWin
->Refresh( TRUE
, &rect 
); 
7423 void wxGrid::SetColLabelValue( int col
, const wxString
& s 
) 
7427         m_table
->SetColLabelValue( col
, s 
); 
7428         if ( !GetBatchCount() ) 
7430             wxRect rect 
= CellToRect( 0, col 
); 
7431             if ( rect
.width 
> 0 ) 
7433                 CalcScrolledPosition(rect
.x
, 0, &rect
.x
, &rect
.y
); 
7435                 rect
.height 
= m_colLabelHeight
; 
7436                 m_colLabelWin
->Refresh( TRUE
, &rect 
); 
7442 void wxGrid::SetGridLineColour( const wxColour
& colour 
) 
7444     if ( m_gridLineColour 
!= colour 
) 
7446         m_gridLineColour 
= colour
; 
7448         wxClientDC 
dc( m_gridWin 
); 
7450         DrawAllGridLines( dc
, wxRegion() ); 
7455 void wxGrid::SetCellHighlightColour( const wxColour
& colour 
) 
7457     if ( m_cellHighlightColour 
!= colour 
) 
7459         m_cellHighlightColour 
= colour
; 
7461         wxClientDC 
dc( m_gridWin 
); 
7463         wxGridCellAttr
* attr 
= GetCellAttr(m_currentCellCoords
); 
7464         DrawCellHighlight(dc
, attr
); 
7469 void wxGrid::EnableGridLines( bool enable 
) 
7471     if ( enable 
!= m_gridLinesEnabled 
) 
7473         m_gridLinesEnabled 
= enable
; 
7475         if ( !GetBatchCount() ) 
7479                 wxClientDC 
dc( m_gridWin 
); 
7481                 DrawAllGridLines( dc
, wxRegion() ); 
7485                 m_gridWin
->Refresh(); 
7492 int wxGrid::GetDefaultRowSize() 
7494     return m_defaultRowHeight
; 
7497 int wxGrid::GetRowSize( int row 
) 
7499     wxCHECK_MSG( row 
>= 0 && row 
< m_numRows
, 0, _T("invalid row index") ); 
7501     return GetRowHeight(row
); 
7504 int wxGrid::GetDefaultColSize() 
7506     return m_defaultColWidth
; 
7509 int wxGrid::GetColSize( int col 
) 
7511     wxCHECK_MSG( col 
>= 0 && col 
< m_numCols
, 0, _T("invalid column index") ); 
7513     return GetColWidth(col
); 
7516 // ============================================================================ 
7517 // access to the grid attributes: each of them has a default value in the grid 
7518 // itself and may be overidden on a per-cell basis 
7519 // ============================================================================ 
7521 // ---------------------------------------------------------------------------- 
7522 // setting default attributes 
7523 // ---------------------------------------------------------------------------- 
7525 void wxGrid::SetDefaultCellBackgroundColour( const wxColour
& col 
) 
7527     m_defaultCellAttr
->SetBackgroundColour(col
); 
7529     m_gridWin
->SetBackgroundColour(col
); 
7533 void wxGrid::SetDefaultCellTextColour( const wxColour
& col 
) 
7535     m_defaultCellAttr
->SetTextColour(col
); 
7538 void wxGrid::SetDefaultCellAlignment( int horiz
, int vert 
) 
7540     m_defaultCellAttr
->SetAlignment(horiz
, vert
); 
7543 void wxGrid::SetDefaultCellFont( const wxFont
& font 
) 
7545     m_defaultCellAttr
->SetFont(font
); 
7548 void wxGrid::SetDefaultRenderer(wxGridCellRenderer 
*renderer
) 
7550     m_defaultCellAttr
->SetRenderer(renderer
); 
7553 void wxGrid::SetDefaultEditor(wxGridCellEditor 
*editor
) 
7555     m_defaultCellAttr
->SetEditor(editor
); 
7558 // ---------------------------------------------------------------------------- 
7559 // access to the default attrbiutes 
7560 // ---------------------------------------------------------------------------- 
7562 wxColour 
wxGrid::GetDefaultCellBackgroundColour() 
7564     return m_defaultCellAttr
->GetBackgroundColour(); 
7567 wxColour 
wxGrid::GetDefaultCellTextColour() 
7569     return m_defaultCellAttr
->GetTextColour(); 
7572 wxFont 
wxGrid::GetDefaultCellFont() 
7574     return m_defaultCellAttr
->GetFont(); 
7577 void wxGrid::GetDefaultCellAlignment( int *horiz
, int *vert 
) 
7579     m_defaultCellAttr
->GetAlignment(horiz
, vert
); 
7582 wxGridCellRenderer 
*wxGrid::GetDefaultRenderer() const 
7584     return m_defaultCellAttr
->GetRenderer(NULL
, 0, 0); 
7587 wxGridCellEditor 
*wxGrid::GetDefaultEditor() const 
7589     return m_defaultCellAttr
->GetEditor(NULL
,0,0); 
7592 // ---------------------------------------------------------------------------- 
7593 // access to cell attributes 
7594 // ---------------------------------------------------------------------------- 
7596 wxColour 
wxGrid::GetCellBackgroundColour(int row
, int col
) 
7598     wxGridCellAttr 
*attr 
= GetCellAttr(row
, col
); 
7599     wxColour colour 
= attr
->GetBackgroundColour(); 
7604 wxColour 
wxGrid::GetCellTextColour( int row
, int col 
) 
7606     wxGridCellAttr 
*attr 
= GetCellAttr(row
, col
); 
7607     wxColour colour 
= attr
->GetTextColour(); 
7612 wxFont 
wxGrid::GetCellFont( int row
, int col 
) 
7614     wxGridCellAttr 
*attr 
= GetCellAttr(row
, col
); 
7615     wxFont font 
= attr
->GetFont(); 
7620 void wxGrid::GetCellAlignment( int row
, int col
, int *horiz
, int *vert 
) 
7622     wxGridCellAttr 
*attr 
= GetCellAttr(row
, col
); 
7623     attr
->GetAlignment(horiz
, vert
); 
7627 wxGridCellRenderer
* wxGrid::GetCellRenderer(int row
, int col
) 
7629     wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
7630     wxGridCellRenderer
* renderer 
= attr
->GetRenderer(this, row
, col
); 
7636 wxGridCellEditor
* wxGrid::GetCellEditor(int row
, int col
) 
7638     wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
7639     wxGridCellEditor
* editor 
= attr
->GetEditor(this, row
, col
); 
7645 bool wxGrid::IsReadOnly(int row
, int col
) const 
7647     wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
7648     bool isReadOnly 
= attr
->IsReadOnly(); 
7653 // ---------------------------------------------------------------------------- 
7654 // attribute support: cache, automatic provider creation, ... 
7655 // ---------------------------------------------------------------------------- 
7657 bool wxGrid::CanHaveAttributes() 
7664     return m_table
->CanHaveAttributes(); 
7667 void wxGrid::ClearAttrCache() 
7669     if ( m_attrCache
.row 
!= -1 ) 
7671         wxSafeDecRef(m_attrCache
.attr
); 
7672         m_attrCache
.row 
= -1; 
7676 void wxGrid::CacheAttr(int row
, int col
, wxGridCellAttr 
*attr
) const 
7678     wxGrid 
*self 
= (wxGrid 
*)this;  // const_cast 
7680     self
->ClearAttrCache(); 
7681     self
->m_attrCache
.row 
= row
; 
7682     self
->m_attrCache
.col 
= col
; 
7683     self
->m_attrCache
.attr 
= attr
; 
7687 bool wxGrid::LookupAttr(int row
, int col
, wxGridCellAttr 
**attr
) const 
7689     if ( row 
== m_attrCache
.row 
&& col 
== m_attrCache
.col 
) 
7691         *attr 
= m_attrCache
.attr
; 
7692         wxSafeIncRef(m_attrCache
.attr
); 
7694 #ifdef DEBUG_ATTR_CACHE 
7695         gs_nAttrCacheHits
++; 
7702 #ifdef DEBUG_ATTR_CACHE 
7703         gs_nAttrCacheMisses
++; 
7709 wxGridCellAttr 
*wxGrid::GetCellAttr(int row
, int col
) const 
7711     wxGridCellAttr 
*attr
; 
7712     if ( !LookupAttr(row
, col
, &attr
) ) 
7714         attr 
= m_table 
? m_table
->GetAttr(row
, col
) : (wxGridCellAttr 
*)NULL
; 
7715         CacheAttr(row
, col
, attr
); 
7719         attr
->SetDefAttr(m_defaultCellAttr
); 
7723         attr 
= m_defaultCellAttr
; 
7730 wxGridCellAttr 
*wxGrid::GetOrCreateCellAttr(int row
, int col
) const 
7732     wxGridCellAttr 
*attr
; 
7733     if ( !LookupAttr(row
, col
, &attr
) || !attr 
) 
7735         wxASSERT_MSG( m_table
, 
7736                       _T("we may only be called if CanHaveAttributes() returned TRUE and then m_table should be !NULL") ); 
7738         attr 
= m_table
->GetAttr(row
, col
); 
7741             attr 
= new wxGridCellAttr
; 
7743             // artificially inc the ref count to match DecRef() in caller 
7746             m_table
->SetAttr(attr
, row
, col
); 
7749         CacheAttr(row
, col
, attr
); 
7751     attr
->SetDefAttr(m_defaultCellAttr
); 
7755 // ---------------------------------------------------------------------------- 
7756 // setting column attributes (wrappers around SetColAttr) 
7757 // ---------------------------------------------------------------------------- 
7759 void wxGrid::SetColFormatBool(int col
) 
7761     SetColFormatCustom(col
, wxGRID_VALUE_BOOL
); 
7764 void wxGrid::SetColFormatNumber(int col
) 
7766     SetColFormatCustom(col
, wxGRID_VALUE_NUMBER
); 
7769 void wxGrid::SetColFormatFloat(int col
, int width
, int precision
) 
7771     wxString typeName 
= wxGRID_VALUE_FLOAT
; 
7772     if ( (width 
!= -1) || (precision 
!= -1) ) 
7774         typeName 
<< _T(':') << width 
<< _T(',') << precision
; 
7777     SetColFormatCustom(col
, typeName
); 
7780 void wxGrid::SetColFormatCustom(int col
, const wxString
& typeName
) 
7782     wxGridCellAttr 
*attr 
= new wxGridCellAttr
; 
7783     wxGridCellRenderer 
*renderer 
= GetDefaultRendererForType(typeName
); 
7784     attr
->SetRenderer(renderer
); 
7786     SetColAttr(col
, attr
); 
7789 // ---------------------------------------------------------------------------- 
7790 // setting cell attributes: this is forwarded to the table 
7791 // ---------------------------------------------------------------------------- 
7793 void wxGrid::SetRowAttr(int row
, wxGridCellAttr 
*attr
) 
7795     if ( CanHaveAttributes() ) 
7797         m_table
->SetRowAttr(attr
, row
); 
7805 void wxGrid::SetColAttr(int col
, wxGridCellAttr 
*attr
) 
7807     if ( CanHaveAttributes() ) 
7809         m_table
->SetColAttr(attr
, col
); 
7817 void wxGrid::SetCellBackgroundColour( int row
, int col
, const wxColour
& colour 
) 
7819     if ( CanHaveAttributes() ) 
7821         wxGridCellAttr 
*attr 
= GetOrCreateCellAttr(row
, col
); 
7822         attr
->SetBackgroundColour(colour
); 
7827 void wxGrid::SetCellTextColour( int row
, int col
, const wxColour
& colour 
) 
7829     if ( CanHaveAttributes() ) 
7831         wxGridCellAttr 
*attr 
= GetOrCreateCellAttr(row
, col
); 
7832         attr
->SetTextColour(colour
); 
7837 void wxGrid::SetCellFont( int row
, int col
, const wxFont
& font 
) 
7839     if ( CanHaveAttributes() ) 
7841         wxGridCellAttr 
*attr 
= GetOrCreateCellAttr(row
, col
); 
7842         attr
->SetFont(font
); 
7847 void wxGrid::SetCellAlignment( int row
, int col
, int horiz
, int vert 
) 
7849     if ( CanHaveAttributes() ) 
7851         wxGridCellAttr 
*attr 
= GetOrCreateCellAttr(row
, col
); 
7852         attr
->SetAlignment(horiz
, vert
); 
7857 void wxGrid::SetCellRenderer(int row
, int col
, wxGridCellRenderer 
*renderer
) 
7859     if ( CanHaveAttributes() ) 
7861         wxGridCellAttr 
*attr 
= GetOrCreateCellAttr(row
, col
); 
7862         attr
->SetRenderer(renderer
); 
7867 void wxGrid::SetCellEditor(int row
, int col
, wxGridCellEditor
* editor
) 
7869     if ( CanHaveAttributes() ) 
7871         wxGridCellAttr 
*attr 
= GetOrCreateCellAttr(row
, col
); 
7872         attr
->SetEditor(editor
); 
7877 void wxGrid::SetReadOnly(int row
, int col
, bool isReadOnly
) 
7879     if ( CanHaveAttributes() ) 
7881         wxGridCellAttr 
*attr 
= GetOrCreateCellAttr(row
, col
); 
7882         attr
->SetReadOnly(isReadOnly
); 
7887 // ---------------------------------------------------------------------------- 
7888 // Data type registration 
7889 // ---------------------------------------------------------------------------- 
7891 void wxGrid::RegisterDataType(const wxString
& typeName
, 
7892                               wxGridCellRenderer
* renderer
, 
7893                               wxGridCellEditor
* editor
) 
7895     m_typeRegistry
->RegisterDataType(typeName
, renderer
, editor
); 
7899 wxGridCellEditor
* wxGrid::GetDefaultEditorForCell(int row
, int col
) const 
7901     wxString typeName 
= m_table
->GetTypeName(row
, col
); 
7902     return GetDefaultEditorForType(typeName
); 
7905 wxGridCellRenderer
* wxGrid::GetDefaultRendererForCell(int row
, int col
) const 
7907     wxString typeName 
= m_table
->GetTypeName(row
, col
); 
7908     return GetDefaultRendererForType(typeName
); 
7912 wxGrid::GetDefaultEditorForType(const wxString
& typeName
) const 
7914     int index 
= m_typeRegistry
->FindOrCloneDataType(typeName
); 
7915     if ( index 
== wxNOT_FOUND 
) 
7917         wxFAIL_MSG(wxT("Unknown data type name")); 
7922     return m_typeRegistry
->GetEditor(index
); 
7926 wxGrid::GetDefaultRendererForType(const wxString
& typeName
) const 
7928     int index 
= m_typeRegistry
->FindOrCloneDataType(typeName
); 
7929     if ( index 
== wxNOT_FOUND 
) 
7931         wxFAIL_MSG(wxT("Unknown data type name")); 
7936     return m_typeRegistry
->GetRenderer(index
); 
7940 // ---------------------------------------------------------------------------- 
7942 // ---------------------------------------------------------------------------- 
7944 void wxGrid::EnableDragRowSize( bool enable 
) 
7946     m_canDragRowSize 
= enable
; 
7950 void wxGrid::EnableDragColSize( bool enable 
) 
7952     m_canDragColSize 
= enable
; 
7955 void wxGrid::EnableDragGridSize( bool enable 
) 
7957     m_canDragGridSize 
= enable
; 
7961 void wxGrid::SetDefaultRowSize( int height
, bool resizeExistingRows 
) 
7963     m_defaultRowHeight 
= wxMax( height
, WXGRID_MIN_ROW_HEIGHT 
); 
7965     if ( resizeExistingRows 
) 
7973 void wxGrid::SetRowSize( int row
, int height 
) 
7975     wxCHECK_RET( row 
>= 0 && row 
< m_numRows
, _T("invalid row index") ); 
7977     if ( m_rowHeights
.IsEmpty() ) 
7979         // need to really create the array 
7983     int h 
= wxMax( 0, height 
); 
7984     int diff 
= h 
- m_rowHeights
[row
]; 
7986     m_rowHeights
[row
] = h
; 
7988     for ( i 
= row
;  i 
< m_numRows
;  i
++ ) 
7990         m_rowBottoms
[i
] += diff
; 
7995 void wxGrid::SetDefaultColSize( int width
, bool resizeExistingCols 
) 
7997     m_defaultColWidth 
= wxMax( width
, WXGRID_MIN_COL_WIDTH 
); 
7999     if ( resizeExistingCols 
) 
8007 void wxGrid::SetColSize( int col
, int width 
) 
8009     wxCHECK_RET( col 
>= 0 && col 
< m_numCols
, _T("invalid column index") ); 
8011     // should we check that it's bigger than GetColMinimalWidth(col) here? 
8013     if ( m_colWidths
.IsEmpty() ) 
8015         // need to really create the array 
8019     int w 
= wxMax( 0, width 
); 
8020     int diff 
= w 
- m_colWidths
[col
]; 
8021     m_colWidths
[col
] = w
; 
8024     for ( i 
= col
;  i 
< m_numCols
;  i
++ ) 
8026         m_colRights
[i
] += diff
; 
8032 void wxGrid::SetColMinimalWidth( int col
, int width 
) 
8034     m_colMinWidths
.Put(col
, width
); 
8037 void wxGrid::SetRowMinimalHeight( int row
, int width 
) 
8039     m_rowMinHeights
.Put(row
, width
); 
8042 int wxGrid::GetColMinimalWidth(int col
) const 
8044     long value 
= m_colMinWidths
.Get(col
); 
8045     return value 
!= wxNOT_FOUND 
? (int)value 
: WXGRID_MIN_COL_WIDTH
; 
8048 int wxGrid::GetRowMinimalHeight(int row
) const 
8050     long value 
= m_rowMinHeights
.Get(row
); 
8051     return value 
!= wxNOT_FOUND 
? (int)value 
: WXGRID_MIN_ROW_HEIGHT
; 
8054 // ---------------------------------------------------------------------------- 
8056 // ---------------------------------------------------------------------------- 
8058 void wxGrid::AutoSizeColOrRow( int colOrRow
, bool setAsMin
, bool column 
) 
8060     wxClientDC 
dc(m_gridWin
); 
8062     // init both of them to avoid compiler warnings, even if weo nly need one 
8070     wxCoord extent
, extentMax 
= 0; 
8071     int max 
= column 
? m_numRows 
: m_numCols
; 
8072     for ( int rowOrCol 
= 0; rowOrCol 
< max
; rowOrCol
++ ) 
8079         wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
8080         wxGridCellRenderer
* renderer 
= attr
->GetRenderer(this, row
, col
); 
8083             wxSize size 
= renderer
->GetBestSize(*this, *attr
, dc
, row
, col
); 
8084             extent 
= column 
? size
.x 
: size
.y
; 
8085             if ( extent 
> extentMax 
) 
8096     // now also compare with the column label extent 
8098     dc
.SetFont( GetLabelFont() ); 
8101         dc
.GetTextExtent( GetColLabelValue(col
), &w
, &h 
); 
8103         dc
.GetTextExtent( GetRowLabelValue(col
), &w
, &h 
); 
8105     extent 
= column 
? w 
: h
; 
8106     if ( extent 
> extentMax 
) 
8113         // empty column - give default extent (notice that if extentMax is less 
8114         // than default extent but != 0, it's ok) 
8115         extentMax 
= column 
? m_defaultColWidth 
: m_defaultRowHeight
; 
8121             // leave some space around text 
8131         SetColSize(col
, extentMax
); 
8133         SetRowSize(row
, extentMax
); 
8138             SetColMinimalWidth(col
, extentMax
); 
8140             SetRowMinimalHeight(row
, extentMax
); 
8144 int wxGrid::SetOrCalcColumnSizes(bool calcOnly
, bool setAsMin
) 
8146     int width 
= m_rowLabelWidth
; 
8148     for ( int col 
= 0; col 
< m_numCols
; col
++ ) 
8152             AutoSizeColumn(col
, setAsMin
); 
8155         width 
+= GetColWidth(col
); 
8161 int wxGrid::SetOrCalcRowSizes(bool calcOnly
, bool setAsMin
) 
8163     int height 
= m_colLabelHeight
; 
8165     for ( int row 
= 0; row 
< m_numRows
; row
++ ) 
8169             AutoSizeRow(row
, setAsMin
); 
8172         height 
+= GetRowHeight(row
); 
8178 void wxGrid::AutoSize() 
8181     SetSize(SetOrCalcColumnSizes(FALSE
), SetOrCalcRowSizes(FALSE
)); 
8184 wxSize 
wxGrid::DoGetBestSize() const 
8186     // don't set sizes, only calculate them 
8187     wxGrid 
*self 
= (wxGrid 
*)this;  // const_cast 
8189     return wxSize(self
->SetOrCalcColumnSizes(TRUE
), 
8190                   self
->SetOrCalcRowSizes(TRUE
)); 
8199 wxPen
& wxGrid::GetDividerPen() const 
8204 // ---------------------------------------------------------------------------- 
8205 // cell value accessor functions 
8206 // ---------------------------------------------------------------------------- 
8208 void wxGrid::SetCellValue( int row
, int col
, const wxString
& s 
) 
8212         m_table
->SetValue( row
, col
, s 
); 
8213         if ( !GetBatchCount() ) 
8215             wxClientDC 
dc( m_gridWin 
); 
8217             DrawCell( dc
, wxGridCellCoords(row
, col
) ); 
8220         if ( m_currentCellCoords
.GetRow() == row 
&& 
8221              m_currentCellCoords
.GetCol() == col 
&& 
8222              IsCellEditControlShown()) 
8223              // Note: If we are using IsCellEditControlEnabled, 
8224              // this interacts badly with calling SetCellValue from 
8225              // an EVT_GRID_CELL_CHANGE handler. 
8227             HideCellEditControl(); 
8228             ShowCellEditControl(); // will reread data from table 
8235 // ------ Block, row and col selection 
8238 void wxGrid::SelectRow( int row
, bool addToSelected 
) 
8240     if ( IsSelection() && !addToSelected 
) 
8243     m_selection
->SelectRow( row
, FALSE
, addToSelected 
); 
8247 void wxGrid::SelectCol( int col
, bool addToSelected 
) 
8249     if ( IsSelection() && !addToSelected 
) 
8252     m_selection
->SelectCol( col
, FALSE
, addToSelected 
); 
8256 void wxGrid::SelectBlock( int topRow
, int leftCol
, int bottomRow
, int rightCol
,  
8257                           bool addToSelected 
) 
8259     if ( IsSelection() && !addToSelected 
) 
8262     m_selection
->SelectBlock( topRow
, leftCol
, bottomRow
, rightCol
,  
8263                               FALSE
, addToSelected 
);     
8267 void wxGrid::SelectAll() 
8269     m_selection
->SelectBlock( 0, 0, m_numRows
-1, m_numCols
-1 ); 
8272 bool wxGrid::IsSelection() 
8274     return ( m_selection
->IsSelection() || 
8275              ( m_selectingTopLeft 
!= wxGridNoCellCoords 
&& 
8276                m_selectingBottomRight 
!= wxGridNoCellCoords 
) ); 
8279 bool wxGrid::IsInSelection( int row
, int col 
) 
8281     return ( m_selection
->IsInSelection( row
, col 
) || 
8282              ( row 
>= m_selectingTopLeft
.GetRow() && 
8283                col 
>= m_selectingTopLeft
.GetCol() && 
8284                row 
<= m_selectingBottomRight
.GetRow() && 
8285                col 
<= m_selectingBottomRight
.GetCol() ) ); 
8288 void wxGrid::ClearSelection() 
8290     m_selectingTopLeft 
= wxGridNoCellCoords
; 
8291     m_selectingBottomRight 
= wxGridNoCellCoords
; 
8292     m_selection
->ClearSelection(); 
8296 // This function returns the rectangle that encloses the given block 
8297 // in device coords clipped to the client size of the grid window. 
8299 wxRect 
wxGrid::BlockToDeviceRect( const wxGridCellCoords 
&topLeft
, 
8300                                   const wxGridCellCoords 
&bottomRight 
) 
8302     wxRect 
rect( wxGridNoCellRect 
); 
8305     cellRect 
= CellToRect( topLeft 
); 
8306     if ( cellRect 
!= wxGridNoCellRect 
) 
8312         rect 
= wxRect( 0, 0, 0, 0 ); 
8315     cellRect 
= CellToRect( bottomRight 
); 
8316     if ( cellRect 
!= wxGridNoCellRect 
) 
8322         return wxGridNoCellRect
; 
8325     // convert to scrolled coords 
8327     int left
, top
, right
, bottom
; 
8328     CalcScrolledPosition( rect
.GetLeft(), rect
.GetTop(), &left
, &top 
); 
8329     CalcScrolledPosition( rect
.GetRight(), rect
.GetBottom(), &right
, &bottom 
); 
8332     m_gridWin
->GetClientSize( &cw
, &ch 
); 
8334     if (right 
< 0 || bottom 
< 0 || left 
> cw 
|| top 
> ch
) 
8335         return wxRect( 0, 0, 0, 0); 
8337     rect
.SetLeft( wxMax(0, left
) ); 
8338     rect
.SetTop( wxMax(0, top
) ); 
8339     rect
.SetRight( wxMin(cw
, right
) ); 
8340     rect
.SetBottom( wxMin(ch
, bottom
) ); 
8348 // ------ Grid event classes 
8351 IMPLEMENT_DYNAMIC_CLASS( wxGridEvent
, wxEvent 
) 
8353 wxGridEvent::wxGridEvent( int id
, wxEventType type
, wxObject
* obj
, 
8354                           int row
, int col
, int x
, int y
, bool sel
, 
8355                           bool control
, bool shift
, bool alt
, bool meta 
) 
8356         : wxNotifyEvent( type
, id 
) 
8363     m_control 
= control
; 
8368     SetEventObject(obj
); 
8372 IMPLEMENT_DYNAMIC_CLASS( wxGridSizeEvent
, wxEvent 
) 
8374 wxGridSizeEvent::wxGridSizeEvent( int id
, wxEventType type
, wxObject
* obj
, 
8375                                   int rowOrCol
, int x
, int y
, 
8376                                   bool control
, bool shift
, bool alt
, bool meta 
) 
8377         : wxNotifyEvent( type
, id 
) 
8379     m_rowOrCol 
= rowOrCol
; 
8382     m_control 
= control
; 
8387     SetEventObject(obj
); 
8391 IMPLEMENT_DYNAMIC_CLASS( wxGridRangeSelectEvent
, wxEvent 
) 
8393 wxGridRangeSelectEvent::wxGridRangeSelectEvent(int id
, wxEventType type
, wxObject
* obj
, 
8394                                                const wxGridCellCoords
& topLeft
, 
8395                                                const wxGridCellCoords
& bottomRight
, 
8396                                                bool sel
, bool control
, 
8397                                                bool shift
, bool alt
, bool meta 
) 
8398         : wxNotifyEvent( type
, id 
) 
8400     m_topLeft     
= topLeft
; 
8401     m_bottomRight 
= bottomRight
; 
8403     m_control     
= control
; 
8408     SetEventObject(obj
); 
8412 #endif // ifndef wxUSE_NEW_GRID